diff options
| author | 2015-02-25 22:44:55 -0500 | |
|---|---|---|
| committer | 2015-03-03 18:26:03 -0500 | |
| commit | 34c31db14a98013ee802bd5ae31c775768f12439 (patch) | |
| tree | 20a611dd0e2d30203d756f79d86838ad22e01f02 /src/core/hw/gpu.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/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 75 |
1 files changed, 25 insertions, 50 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 2f1a69d90..424ce2ca7 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -113,8 +113,8 @@ inline void Write(u32 addr, const T data) { | |||
| 113 | { | 113 | { |
| 114 | const auto& config = g_regs.display_transfer_config; | 114 | const auto& config = g_regs.display_transfer_config; |
| 115 | if (config.trigger & 1) { | 115 | if (config.trigger & 1) { |
| 116 | u8* source_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress())); | 116 | u8* src_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress())); |
| 117 | u8* dest_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress())); | 117 | u8* dst_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress())); |
| 118 | 118 | ||
| 119 | unsigned horizontal_scale = (config.scale_horizontally != 0) ? 2 : 1; | 119 | unsigned horizontal_scale = (config.scale_horizontally != 0) ? 2 : 1; |
| 120 | unsigned vertical_scale = (config.scale_vertically != 0) ? 2 : 1; | 120 | unsigned vertical_scale = (config.scale_vertically != 0) ? 2 : 1; |
| @@ -125,7 +125,7 @@ inline void Write(u32 addr, const T data) { | |||
| 125 | if (config.raw_copy) { | 125 | if (config.raw_copy) { |
| 126 | // Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions | 126 | // Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions |
| 127 | // TODO(Subv): Verify if raw copies perform scaling | 127 | // TODO(Subv): Verify if raw copies perform scaling |
| 128 | memcpy(dest_pointer, source_pointer, config.output_width * config.output_height * | 128 | memcpy(dst_pointer, src_pointer, config.output_width * config.output_height * |
| 129 | GPU::Regs::BytesPerPixel(config.output_format)); | 129 | GPU::Regs::BytesPerPixel(config.output_format)); |
| 130 | 130 | ||
| 131 | LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), flags 0x%08X, Raw copy", | 131 | LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), flags 0x%08X, Raw copy", |
| @@ -142,9 +142,7 @@ inline void Write(u32 addr, const T data) { | |||
| 142 | // right now we're just skipping the extra pixels. | 142 | // right now we're just skipping the extra pixels. |
| 143 | for (u32 y = 0; y < output_height; ++y) { | 143 | for (u32 y = 0; y < output_height; ++y) { |
| 144 | for (u32 x = 0; x < output_width; ++x) { | 144 | for (u32 x = 0; x < output_width; ++x) { |
| 145 | struct { | 145 | Math::Vec4<u8> src_color = { 0, 0, 0, 0 }; |
| 146 | int r, g, b, a; | ||
| 147 | } source_color = { 0, 0, 0, 0 }; | ||
| 148 | 146 | ||
| 149 | u32 scaled_x = x * horizontal_scale; | 147 | u32 scaled_x = x * horizontal_scale; |
| 150 | u32 scaled_y = y * vertical_scale; | 148 | u32 scaled_y = y * vertical_scale; |
| @@ -170,77 +168,54 @@ inline void Write(u32 addr, const T data) { | |||
| 170 | dst_offset = (x + y * output_width) * dst_bytes_per_pixel; | 168 | dst_offset = (x + y * output_width) * dst_bytes_per_pixel; |
| 171 | } | 169 | } |
| 172 | 170 | ||
| 171 | const u8* src_pixel = src_pointer + src_offset; | ||
| 173 | switch (config.input_format) { | 172 | switch (config.input_format) { |
| 174 | case Regs::PixelFormat::RGBA8: | 173 | case Regs::PixelFormat::RGBA8: |
| 175 | { | 174 | src_color = Color::DecodeRGBA8(src_pixel); |
| 176 | u8* srcptr = source_pointer + src_offset; | 175 | break; |
| 177 | source_color.r = srcptr[3]; // red | 176 | |
| 178 | source_color.g = srcptr[2]; // green | 177 | case Regs::PixelFormat::RGB8: |
| 179 | source_color.b = srcptr[1]; // blue | 178 | src_color = Color::DecodeRGB8(src_pixel); |
| 180 | source_color.a = srcptr[0]; // alpha | 179 | break; |
| 180 | |||
| 181 | case Regs::PixelFormat::RGB565: | ||
| 182 | src_color = Color::DecodeRGB565(src_pixel); | ||
| 181 | break; | 183 | break; |
| 182 | } | ||
| 183 | 184 | ||
| 184 | case Regs::PixelFormat::RGB5A1: | 185 | case Regs::PixelFormat::RGB5A1: |
| 185 | { | 186 | src_color = Color::DecodeRGB5A1(src_pixel); |
| 186 | u16 srcval = *(u16*)(source_pointer + src_offset); | ||
| 187 | source_color.r = Color::Convert5To8((srcval >> 11) & 0x1F); // red | ||
| 188 | source_color.g = Color::Convert5To8((srcval >> 6) & 0x1F); // green | ||
| 189 | source_color.b = Color::Convert5To8((srcval >> 1) & 0x1F); // blue | ||
| 190 | source_color.a = Color::Convert1To8(srcval & 0x1); // alpha | ||
| 191 | break; | 187 | break; |
| 192 | } | ||
| 193 | 188 | ||
| 194 | case Regs::PixelFormat::RGBA4: | 189 | case Regs::PixelFormat::RGBA4: |
| 195 | { | 190 | src_color = Color::DecodeRGBA4(src_pixel); |
| 196 | u16 srcval = *(u16*)(source_pointer + src_offset); | ||
| 197 | source_color.r = Color::Convert4To8((srcval >> 12) & 0xF); // red | ||
| 198 | source_color.g = Color::Convert4To8((srcval >> 8) & 0xF); // green | ||
| 199 | source_color.b = Color::Convert4To8((srcval >> 4) & 0xF); // blue | ||
| 200 | source_color.a = Color::Convert4To8( srcval & 0xF); // alpha | ||
| 201 | break; | 191 | break; |
| 202 | } | ||
| 203 | 192 | ||
| 204 | default: | 193 | default: |
| 205 | LOG_ERROR(HW_GPU, "Unknown source framebuffer format %x", config.input_format.Value()); | 194 | LOG_ERROR(HW_GPU, "Unknown source framebuffer format %x", config.input_format.Value()); |
| 206 | break; | 195 | break; |
| 207 | } | 196 | } |
| 208 | 197 | ||
| 198 | u8* dst_pixel = dst_pointer + dst_offset; | ||
| 209 | switch (config.output_format) { | 199 | switch (config.output_format) { |
| 210 | case Regs::PixelFormat::RGBA8: | 200 | case Regs::PixelFormat::RGBA8: |
| 211 | { | 201 | Color::EncodeRGBA8(src_color, dst_pixel); |
| 212 | u8* dstptr = dest_pointer + dst_offset; | ||
| 213 | dstptr[3] = source_color.r; | ||
| 214 | dstptr[2] = source_color.g; | ||
| 215 | dstptr[1] = source_color.b; | ||
| 216 | dstptr[0] = source_color.a; | ||
| 217 | break; | 202 | break; |
| 218 | } | ||
| 219 | 203 | ||
| 220 | case Regs::PixelFormat::RGB8: | 204 | case Regs::PixelFormat::RGB8: |
| 221 | { | 205 | Color::EncodeRGB8(src_color, dst_pixel); |
| 222 | u8* dstptr = dest_pointer + dst_offset; | 206 | break; |
| 223 | dstptr[2] = source_color.r; // red | 207 | |
| 224 | dstptr[1] = source_color.g; // green | 208 | case Regs::PixelFormat::RGB565: |
| 225 | dstptr[0] = source_color.b; // blue | 209 | Color::EncodeRGB565(src_color, dst_pixel); |
| 226 | break; | 210 | break; |
| 227 | } | ||
| 228 | 211 | ||
| 229 | case Regs::PixelFormat::RGB5A1: | 212 | case Regs::PixelFormat::RGB5A1: |
| 230 | { | 213 | Color::EncodeRGB5A1(src_color, dst_pixel); |
| 231 | u16* dstptr = (u16*)(dest_pointer + dst_offset); | ||
| 232 | *dstptr = ((source_color.r >> 3) << 11) | ((source_color.g >> 3) << 6) | ||
| 233 | | ((source_color.b >> 3) << 1) | ( source_color.a >> 7); | ||
| 234 | break; | 214 | break; |
| 235 | } | ||
| 236 | 215 | ||
| 237 | case Regs::PixelFormat::RGBA4: | 216 | case Regs::PixelFormat::RGBA4: |
| 238 | { | 217 | Color::EncodeRGBA4(src_color, dst_pixel); |
| 239 | u16* dstptr = (u16*)(dest_pointer + dst_offset); | ||
| 240 | *dstptr = ((source_color.r >> 4) << 12) | ((source_color.g >> 4) << 8) | ||
| 241 | | ((source_color.b >> 4) << 4) | ( source_color.a >> 4); | ||
| 242 | break; | 218 | break; |
| 243 | } | ||
| 244 | 219 | ||
| 245 | default: | 220 | default: |
| 246 | LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); | 221 | LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); |