summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2015-02-25 22:44:55 -0500
committerGravatar bunnei2015-03-03 18:26:03 -0500
commit34c31db14a98013ee802bd5ae31c775768f12439 (patch)
tree20a611dd0e2d30203d756f79d86838ad22e01f02 /src/core/hw/gpu.cpp
parentMerge pull request #622 from Subv/titles (diff)
downloadyuzu-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.cpp75
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());