Last active
August 29, 2015 14:11
-
-
Save Subv/294f4328bfc9c2d5f493 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp | |
index 93d7ac3..c21376f 100644 | |
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp | |
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp | |
@@ -242,6 +242,42 @@ void GraphicsFramebufferWidget::OnUpdate() | |
break; | |
} | |
+ case Format::RGB565: | |
+ { | |
+ QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); | |
+ u32* color_buffer = (u32*)Memory::GetPointer(framebuffer_address); | |
+ for (int y = 0; y < framebuffer_height; ++y) { | |
+ for (int x = 0; x < framebuffer_width; ++x) { | |
+ u16 value = *(u16*)(((u8*)color_buffer) + x * 2 + y * framebuffer_width * 2); | |
+ u8 r = (value >> 11) & 0x1F; | |
+ u8 g = (value >> 5) & 0x3F; | |
+ u8 b = (value >> 1) & 0x1F; | |
+ | |
+ decoded_image.setPixel(x, y, qRgba(r, g, b, 255)); | |
+ } | |
+ } | |
+ pixmap = QPixmap::fromImage(decoded_image); | |
+ break; | |
+ } | |
+ | |
+ case Format::RGBA4: | |
+ { | |
+ QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); | |
+ u32* color_buffer = (u32*)Memory::GetPointer(framebuffer_address); | |
+ for (int y = 0; y < framebuffer_height; ++y) { | |
+ for (int x = 0; x < framebuffer_width; ++x) { | |
+ u16 value = *(u16*)(((u8*)color_buffer) + x * 2 + y * framebuffer_width * 2); | |
+ u8 r = (value >> 12) & 0xF; | |
+ u8 g = (value >> 8) & 0xF; | |
+ u8 b = (value >> 4) & 0xF; | |
+ u8 a = value & 0xF; | |
+ | |
+ decoded_image.setPixel(x, y, qRgba(r, g, b, 255)); | |
+ } | |
+ } | |
+ pixmap = QPixmap::fromImage(decoded_image); | |
+ break; | |
+ } | |
default: | |
qDebug() << "Unknown fb color format " << static_cast<int>(framebuffer_format); | |
break; | |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp | |
index da78b85..6e26f24 100644 | |
--- a/src/core/hw/gpu.cpp | |
+++ b/src/core/hw/gpu.cpp | |
@@ -103,23 +103,40 @@ inline void Write(u32 addr, const T data) { | |
source_color.a = srcptr[3]; // alpha | |
break; | |
} | |
- | |
+ case Regs::PixelFormat::RGB5A1: | |
+ { | |
+ u16 value = *(u16*)(source_pointer + x * 2 + y * config.input_width * 2); | |
+ source_color.r = (value >> 11) & 0x1F; | |
+ source_color.g = (value >> 6) & 0x1F; | |
+ source_color.b = (value >> 1) & 0x1F; | |
+ source_color.a = value & 1; | |
+ break; | |
+ } | |
+ case Regs::PixelFormat::RGBA4: | |
+ { | |
+ u16 value = *(u16*)(source_pointer + x * 2 + y * config.input_width * 2); | |
+ source_color.r = (value >> 12) & 0xF; | |
+ source_color.g = (value >> 8) & 0xF; | |
+ source_color.b = (value >> 4) & 0xF; | |
+ source_color.a = value & 0xF; | |
+ break; | |
+ } | |
default: | |
LOG_ERROR(HW_GPU, "Unknown source framebuffer format %x", config.input_format.Value()); | |
break; | |
} | |
switch (config.output_format) { | |
- /*case Regs::PixelFormat::RGBA8: | |
+ case Regs::PixelFormat::RGBA8: | |
{ | |
// TODO: Untested | |
- u8* dstptr = (u32*)(dest_pointer + x * 4 + y * config.output_width * 4); | |
+ u8* dstptr = (u8*)(dest_pointer + x * 4 + y * config.output_width * 4); | |
dstptr[0] = source_color.r; | |
dstptr[1] = source_color.g; | |
dstptr[2] = source_color.b; | |
dstptr[3] = source_color.a; | |
break; | |
- }*/ | |
+ } | |
case Regs::PixelFormat::RGB8: | |
{ | |
@@ -130,7 +147,18 @@ inline void Write(u32 addr, const T data) { | |
dstptr[2] = source_color.b; // red | |
break; | |
} | |
- | |
+ case Regs::PixelFormat::RGB5A1: | |
+ { | |
+ u16* value = (u16*)(dest_pointer + x * 2 + y * config.input_width * 2); | |
+ *value = (source_color.r << 11) | (source_color.g << 6) | (source_color.b << 1) | source_color.a; | |
+ break; | |
+ } | |
+ case Regs::PixelFormat::RGBA4: | |
+ { | |
+ u16* value = (u16*)(source_pointer + x * 2 + y * config.input_width * 2); | |
+ *value = (source_color.r << 12) | (source_color.g << 8) | (source_color.b << 4) | source_color.a; | |
+ break; | |
+ } | |
default: | |
LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); | |
break; | |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h | |
index 5090c24..e932e11 100644 | |
--- a/src/video_core/pica.h | |
+++ b/src/video_core/pica.h | |
@@ -227,13 +227,16 @@ struct Regs { | |
SourceAlpha = 2, | |
OneMinusSourceAlpha = 3, | |
+ Unknown1 = 5, | |
+ | |
// Other values seem to be non-standard extensions | |
}; | |
enum class AlphaModifier : u32 { | |
SourceAlpha = 0, | |
OneMinusSourceAlpha = 1, | |
- | |
+ Unknown0 = 2, | |
+ Unknown1 = 5, | |
// Other values seem to be non-standard extensions | |
}; | |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp | |
index 20a3a3c..1e44a34 100644 | |
--- a/src/video_core/rasterizer.cpp | |
+++ b/src/video_core/rasterizer.cpp | |
@@ -286,11 +286,14 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |
case ColorModifier::SourceAlpha: | |
return { values.a(), values.a(), values.a() }; | |
- | |
+ case ColorModifier::OneMinusSourceColor: | |
+ return { 255 - values.r(), 255 - values.g(), 255 - values.b() }; | |
+ case ColorModifier::Unknown1: | |
+ return values.rgb(); | |
default: | |
LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); | |
- _dbg_assert_(HW_GPU, 0); | |
- return {}; | |
+ //_dbg_assert_(HW_GPU, 0); | |
+ return values.rgb(); | |
} | |
}; | |
@@ -301,11 +304,13 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |
case AlphaModifier::OneMinusSourceAlpha: | |
return 255 - value; | |
- | |
+ case AlphaModifier::Unknown1: | |
+ case AlphaModifier::Unknown0: | |
+ return value; | |
default: | |
LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); | |
- _dbg_assert_(HW_GPU, 0); | |
- return 0; | |
+ //_dbg_assert_(HW_GPU, 0); | |
+ return value; | |
} | |
}; | |
@@ -350,6 +355,8 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |
case Operation::Lerp: | |
return (input[0] * input[2] + input[1] * (255 - input[2])) / 255; | |
+ case Operation::Subtract: | |
+ return std::max(0, (s8)input[0] - (s8)input[1]); | |
default: | |
LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op); | |
_dbg_assert_(HW_GPU, 0); | |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp | |
index e2caeeb..94449af 100644 | |
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp | |
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |
@@ -98,8 +98,32 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& | |
const u8* framebuffer_data = Memory::GetPointer(framebuffer_vaddr); | |
// TODO: Handle other pixel formats | |
- _dbg_assert_msg_(Render_OpenGL, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8, | |
- "Unsupported 3DS pixel format."); | |
+ int glformat = 0; | |
+ int gltype = GL_BGR; | |
+ //_dbg_assert_msg_(Render_OpenGL, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8, | |
+ // "Unsupported 3DS pixel format."); | |
+ switch (framebuffer.color_format) { | |
+ case GPU::Regs::PixelFormat::RGB8: | |
+ glformat = GL_UNSIGNED_BYTE; | |
+ gltype = GL_BGR; | |
+ break; | |
+ case GPU::Regs::PixelFormat::RGBA4: | |
+ glformat = GL_UNSIGNED_SHORT_4_4_4_4; | |
+ gltype = GL_BGRA; | |
+ break; | |
+ case GPU::Regs::PixelFormat::RGB5A1: | |
+ glformat = GL_UNSIGNED_SHORT_5_5_5_1; | |
+ gltype = GL_BGRA; | |
+ break; | |
+ case GPU::Regs::PixelFormat::RGB565: | |
+ glformat = GL_UNSIGNED_SHORT_5_6_5; | |
+ gltype = GL_BGR; | |
+ break; | |
+ case GPU::Regs::PixelFormat::RGBA8: | |
+ glformat = GL_UNSIGNED_INT_8_8_8_8; | |
+ gltype = GL_BGRA; | |
+ break; | |
+ } | |
size_t pixel_stride = framebuffer.stride / 3; | |
// OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately | |
@@ -117,7 +141,7 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& | |
// TODO: Applications could theoretically crash Citra here by specifying too large | |
// framebuffer sizes. We should make sure that this cannot happen. | |
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, | |
- GL_BGR, GL_UNSIGNED_BYTE, framebuffer_data); | |
+ gltype, glformat, framebuffer_data); | |
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | |
@@ -211,6 +235,7 @@ void RendererOpenGL::DrawScreens() { | |
DrawSingleScreenRotated(textures[0], top_x, 0, | |
(float)VideoCore::kScreenTopWidth, (float)VideoCore::kScreenTopHeight); | |
+ glFlush(); | |
DrawSingleScreenRotated(textures[1], bottom_x, (float)VideoCore::kScreenTopHeight, | |
(float)VideoCore::kScreenBottomWidth, (float)VideoCore::kScreenBottomHeight); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment