diff options
| author | 2015-02-25 22:44:55 -0500 | |
|---|---|---|
| committer | 2015-03-03 18:26:03 -0500 | |
| commit | 34c31db14a98013ee802bd5ae31c775768f12439 (patch) | |
| tree | 20a611dd0e2d30203d756f79d86838ad22e01f02 /src/video_core/rasterizer.cpp | |
| parent | Merge pull request #622 from Subv/titles (diff) | |
| download | yuzu-34c31db14a98013ee802bd5ae31c775768f12439.tar.gz yuzu-34c31db14a98013ee802bd5ae31c775768f12439.tar.xz yuzu-34c31db14a98013ee802bd5ae31c775768f12439.zip | |
GPU: Added RGB565/RGB8 framebuffer support and various cleanups.
- Centralizes color format encode/decode functions.
- Fixes endianness issues.
- Implements remaining framebuffer formats in the debugger.
Diffstat (limited to 'src/video_core/rasterizer.cpp')
| -rw-r--r-- | src/video_core/rasterizer.cpp | 76 |
1 files changed, 26 insertions, 50 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 8c370781a..5861c1926 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -22,7 +22,6 @@ namespace Rasterizer { | |||
| 22 | 22 | ||
| 23 | static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | 23 | static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { |
| 24 | const PAddr addr = registers.framebuffer.GetColorBufferPhysicalAddress(); | 24 | const PAddr addr = registers.framebuffer.GetColorBufferPhysicalAddress(); |
| 25 | u8* color_buffer = Memory::GetPointer(PAddrToVAddr(addr)); | ||
| 26 | 25 | ||
| 27 | // Similarly to textures, the render framebuffer is laid out from bottom to top, too. | 26 | // Similarly to textures, the render framebuffer is laid out from bottom to top, too. |
| 28 | // NOTE: The framebuffer height register contains the actual FB height minus one. | 27 | // NOTE: The framebuffer height register contains the actual FB height minus one. |
| @@ -31,35 +30,28 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | |||
| 31 | const u32 coarse_y = y & ~7; | 30 | const u32 coarse_y = y & ~7; |
| 32 | u32 bytes_per_pixel = GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(registers.framebuffer.color_format.Value())); | 31 | u32 bytes_per_pixel = GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(registers.framebuffer.color_format.Value())); |
| 33 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * registers.framebuffer.width * bytes_per_pixel; | 32 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * registers.framebuffer.width * bytes_per_pixel; |
| 33 | u8* dst_pixel = Memory::GetPointer(PAddrToVAddr(addr)) + dst_offset; | ||
| 34 | 34 | ||
| 35 | switch (registers.framebuffer.color_format) { | 35 | switch (registers.framebuffer.color_format) { |
| 36 | case registers.framebuffer.RGBA8: | 36 | case registers.framebuffer.RGBA8: |
| 37 | { | 37 | Color::EncodeRGBA8(color, dst_pixel); |
| 38 | u8* pixel = color_buffer + dst_offset; | ||
| 39 | pixel[3] = color.r(); | ||
| 40 | pixel[2] = color.g(); | ||
| 41 | pixel[1] = color.b(); | ||
| 42 | pixel[0] = color.a(); | ||
| 43 | break; | 38 | break; |
| 44 | } | ||
| 45 | 39 | ||
| 46 | case registers.framebuffer.RGBA4: | 40 | case registers.framebuffer.RGB8: |
| 47 | { | 41 | Color::EncodeRGB8(color, dst_pixel); |
| 48 | u8* pixel = color_buffer + dst_offset; | ||
| 49 | pixel[1] = (color.r() & 0xF0) | (color.g() >> 4); | ||
| 50 | pixel[0] = (color.b() & 0xF0) | (color.a() >> 4); | ||
| 51 | break; | 42 | break; |
| 52 | } | ||
| 53 | 43 | ||
| 54 | case registers.framebuffer.RGBA5551: | 44 | case registers.framebuffer.RGB5A1: |
| 55 | { | 45 | Color::EncodeRGB5A1(color, dst_pixel); |
| 56 | u16_le* pixel = (u16_le*)(color_buffer + dst_offset); | 46 | break; |
| 57 | *pixel = (Color::Convert8To5(color.r()) << 11) | | 47 | |
| 58 | (Color::Convert8To5(color.g()) << 6) | | 48 | case registers.framebuffer.RGB565: |
| 59 | (Color::Convert8To5(color.b()) << 1) | | 49 | Color::EncodeRGB565(color, dst_pixel); |
| 60 | Color::Convert8To1(color.a()); | 50 | break; |
| 51 | |||
| 52 | case registers.framebuffer.RGBA4: | ||
| 53 | Color::EncodeRGBA4(color, dst_pixel); | ||
| 61 | break; | 54 | break; |
| 62 | } | ||
| 63 | 55 | ||
| 64 | default: | 56 | default: |
| 65 | LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", registers.framebuffer.color_format.Value()); | 57 | LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", registers.framebuffer.color_format.Value()); |
| @@ -69,45 +61,29 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | |||
| 69 | 61 | ||
| 70 | static const Math::Vec4<u8> GetPixel(int x, int y) { | 62 | static const Math::Vec4<u8> GetPixel(int x, int y) { |
| 71 | const PAddr addr = registers.framebuffer.GetColorBufferPhysicalAddress(); | 63 | const PAddr addr = registers.framebuffer.GetColorBufferPhysicalAddress(); |
| 72 | u8* color_buffer = Memory::GetPointer(PAddrToVAddr(addr)); | ||
| 73 | 64 | ||
| 74 | y = (registers.framebuffer.height - y); | 65 | y = (registers.framebuffer.height - y); |
| 75 | 66 | ||
| 76 | const u32 coarse_y = y & ~7; | 67 | const u32 coarse_y = y & ~7; |
| 77 | u32 bytes_per_pixel = GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(registers.framebuffer.color_format.Value())); | 68 | u32 bytes_per_pixel = GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(registers.framebuffer.color_format.Value())); |
| 78 | u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * registers.framebuffer.width * bytes_per_pixel; | 69 | u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * registers.framebuffer.width * bytes_per_pixel; |
| 79 | Math::Vec4<u8> ret; | 70 | u8* src_pixel = Memory::GetPointer(PAddrToVAddr(addr)) + src_offset; |
| 80 | 71 | ||
| 81 | switch (registers.framebuffer.color_format) { | 72 | switch (registers.framebuffer.color_format) { |
| 82 | case registers.framebuffer.RGBA8: | 73 | case registers.framebuffer.RGBA8: |
| 83 | { | 74 | return Color::DecodeRGBA8(src_pixel); |
| 84 | u8* pixel = color_buffer + src_offset; | ||
| 85 | ret.r() = pixel[3]; | ||
| 86 | ret.g() = pixel[2]; | ||
| 87 | ret.b() = pixel[1]; | ||
| 88 | ret.a() = pixel[0]; | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | 75 | ||
| 92 | case registers.framebuffer.RGBA4: | 76 | case registers.framebuffer.RGB8: |
| 93 | { | 77 | return Color::DecodeRGB8(src_pixel); |
| 94 | u8* pixel = color_buffer + src_offset; | ||
| 95 | ret.r() = Color::Convert4To8(pixel[1] >> 4); | ||
| 96 | ret.g() = Color::Convert4To8(pixel[1] & 0x0F); | ||
| 97 | ret.b() = Color::Convert4To8(pixel[0] >> 4); | ||
| 98 | ret.a() = Color::Convert4To8(pixel[0] & 0x0F); | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | 78 | ||
| 102 | case registers.framebuffer.RGBA5551: | 79 | case registers.framebuffer.RGB5A1: |
| 103 | { | 80 | return Color::DecodeRGB5A1(src_pixel); |
| 104 | u16_le pixel = *(u16_le*)(color_buffer + src_offset); | 81 | |
| 105 | ret.r() = Color::Convert5To8((pixel >> 11) & 0x1F); | 82 | case registers.framebuffer.RGB565: |
| 106 | ret.g() = Color::Convert5To8((pixel >> 6) & 0x1F); | 83 | return Color::DecodeRGB565(src_pixel); |
| 107 | ret.b() = Color::Convert5To8((pixel >> 1) & 0x1F); | 84 | |
| 108 | ret.a() = Color::Convert1To8(pixel & 0x1); | 85 | case registers.framebuffer.RGBA4: |
| 109 | return ret; | 86 | return Color::DecodeRGBA4(src_pixel); |
| 110 | } | ||
| 111 | 87 | ||
| 112 | default: | 88 | default: |
| 113 | LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", registers.framebuffer.color_format.Value()); | 89 | LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", registers.framebuffer.color_format.Value()); |