diff options
| author | 2018-01-10 22:43:17 -0500 | |
|---|---|---|
| committer | 2018-01-10 23:28:59 -0500 | |
| commit | ee4691297f2f030cb112b2467db4ada142e2ba80 (patch) | |
| tree | 55c36da6343dd4e70641bc11cf4340013406b81c /src | |
| parent | render_base: Add a struct describing framebuffer metadata. (diff) | |
| download | yuzu-ee4691297f2f030cb112b2467db4ada142e2ba80.tar.gz yuzu-ee4691297f2f030cb112b2467db4ada142e2ba80.tar.xz yuzu-ee4691297f2f030cb112b2467db4ada142e2ba80.zip | |
renderer_opengl: Support rendering Switch framebuffer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_base.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 197 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 17 |
3 files changed, 83 insertions, 138 deletions
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index f18917da3..28015aba9 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -15,7 +15,10 @@ public: | |||
| 15 | /// Used to reference a framebuffer | 15 | /// Used to reference a framebuffer |
| 16 | enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture }; | 16 | enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture }; |
| 17 | 17 | ||
| 18 | /// Struct describing framebuffer metadata | 18 | /** |
| 19 | * Struct describing framebuffer metadata | ||
| 20 | * TODO(bunnei): This struct belongs in the GPU code, but we don't have a good place for it yet. | ||
| 21 | */ | ||
| 19 | struct FramebufferInfo { | 22 | struct FramebufferInfo { |
| 20 | enum class PixelFormat : u32 { | 23 | enum class PixelFormat : u32 { |
| 21 | ABGR8 = 1, | 24 | ABGR8 = 1, |
| @@ -44,7 +47,7 @@ public: | |||
| 44 | virtual ~RendererBase() {} | 47 | virtual ~RendererBase() {} |
| 45 | 48 | ||
| 46 | /// Swap buffers (render frame) | 49 | /// Swap buffers (render frame) |
| 47 | virtual void SwapBuffers() = 0; | 50 | virtual void SwapBuffers(const FramebufferInfo& framebuffer_info) = 0; |
| 48 | 51 | ||
| 49 | /** | 52 | /** |
| 50 | * Set the emulator window to use for renderer | 53 | * Set the emulator window to use for renderer |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index c481d1d76..de61987a8 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -56,7 +56,9 @@ out vec4 color; | |||
| 56 | uniform sampler2D color_texture; | 56 | uniform sampler2D color_texture; |
| 57 | 57 | ||
| 58 | void main() { | 58 | void main() { |
| 59 | color = texture(color_texture, frag_tex_coord); | 59 | // Swap RGBA -> ABGR so we don't have to do this on the CPU. This needs to change if we have to |
| 60 | // support more framebuffer pixel formats. | ||
| 61 | color = texture(color_texture, frag_tex_coord).abgr; | ||
| 60 | } | 62 | } |
| 61 | )"; | 63 | )"; |
| 62 | 64 | ||
| @@ -98,44 +100,20 @@ RendererOpenGL::RendererOpenGL() = default; | |||
| 98 | RendererOpenGL::~RendererOpenGL() = default; | 100 | RendererOpenGL::~RendererOpenGL() = default; |
| 99 | 101 | ||
| 100 | /// Swap buffers (render frame) | 102 | /// Swap buffers (render frame) |
| 101 | void RendererOpenGL::SwapBuffers() { | 103 | void RendererOpenGL::SwapBuffers(const FramebufferInfo& framebuffer_info) { |
| 102 | // Maintain the rasterizer's state as a priority | 104 | // Maintain the rasterizer's state as a priority |
| 103 | OpenGLState prev_state = OpenGLState::GetCurState(); | 105 | OpenGLState prev_state = OpenGLState::GetCurState(); |
| 104 | state.Apply(); | 106 | state.Apply(); |
| 105 | 107 | ||
| 106 | for (int i : {0, 1}) { | 108 | if (screen_info.texture.width != (GLsizei)framebuffer_info.width || |
| 107 | const auto& framebuffer = GPU::g_regs.framebuffer_config[i]; | 109 | screen_info.texture.height != (GLsizei)framebuffer_info.height || |
| 108 | 110 | screen_info.texture.pixel_format != framebuffer_info.pixel_format) { | |
| 109 | // Main LCD (0): 0x1ED02204, Sub LCD (1): 0x1ED02A04 | 111 | // Reallocate texture if the framebuffer size has changed. |
| 110 | u32 lcd_color_addr = | 112 | // This is expected to not happen very often and hence should not be a |
| 111 | (i == 0) ? LCD_REG_INDEX(color_fill_top) : LCD_REG_INDEX(color_fill_bottom); | 113 | // performance problem. |
| 112 | lcd_color_addr = HW::VADDR_LCD + 4 * lcd_color_addr; | 114 | ConfigureFramebufferTexture(screen_info.texture, framebuffer_info); |
| 113 | LCD::Regs::ColorFill color_fill = {0}; | ||
| 114 | LCD::Read(color_fill.raw, lcd_color_addr); | ||
| 115 | |||
| 116 | if (color_fill.is_enabled) { | ||
| 117 | LoadColorToActiveGLTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b, | ||
| 118 | screen_infos[i].texture); | ||
| 119 | |||
| 120 | // Resize the texture in case the framebuffer size has changed | ||
| 121 | screen_infos[i].texture.width = 1; | ||
| 122 | screen_infos[i].texture.height = 1; | ||
| 123 | } else { | ||
| 124 | if (screen_infos[i].texture.width != (GLsizei)framebuffer.width || | ||
| 125 | screen_infos[i].texture.height != (GLsizei)framebuffer.height || | ||
| 126 | screen_infos[i].texture.format != framebuffer.color_format) { | ||
| 127 | // Reallocate texture if the framebuffer size has changed. | ||
| 128 | // This is expected to not happen very often and hence should not be a | ||
| 129 | // performance problem. | ||
| 130 | ConfigureFramebufferTexture(screen_infos[i].texture, framebuffer); | ||
| 131 | } | ||
| 132 | LoadFBToScreenInfo(framebuffer, screen_infos[i]); | ||
| 133 | |||
| 134 | // Resize the texture in case the framebuffer size has changed | ||
| 135 | screen_infos[i].texture.width = framebuffer.width; | ||
| 136 | screen_infos[i].texture.height = framebuffer.height; | ||
| 137 | } | ||
| 138 | } | 115 | } |
| 116 | LoadFBToScreenInfo(framebuffer_info, screen_info); | ||
| 139 | 117 | ||
| 140 | DrawScreens(); | 118 | DrawScreens(); |
| 141 | 119 | ||
| @@ -270,56 +248,48 @@ static void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32 | |||
| 270 | /** | 248 | /** |
| 271 | * Loads framebuffer from emulated memory into the active OpenGL texture. | 249 | * Loads framebuffer from emulated memory into the active OpenGL texture. |
| 272 | */ | 250 | */ |
| 273 | void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer, | 251 | void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, |
| 274 | ScreenInfo& screen_info) { | 252 | ScreenInfo& screen_info) { |
| 253 | const u32 bpp{FramebufferInfo::BytesPerPixel(framebuffer_info.pixel_format)}; | ||
| 254 | const u32 size_in_bytes{framebuffer_info.stride * framebuffer_info.height * bpp}; | ||
| 275 | 255 | ||
| 276 | const PAddr framebuffer_addr = | 256 | MortonCopyPixels128(framebuffer_info.width, framebuffer_info.height, bpp, 4, |
| 277 | framebuffer.active_fb == 0 ? framebuffer.address_left1 : framebuffer.address_left2; | 257 | Memory::GetPointer(framebuffer_info.address), gl_framebuffer_data.data(), |
| 278 | 258 | true); | |
| 279 | LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%08x(%dx%d), fmt %x", | ||
| 280 | framebuffer.stride * framebuffer.height, framebuffer_addr, (int)framebuffer.width, | ||
| 281 | (int)framebuffer.height, (int)framebuffer.format); | ||
| 282 | 259 | ||
| 283 | int bpp = GPU::Regs::BytesPerPixel(framebuffer.color_format); | 260 | LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%llx(%dx%d), fmt %x", size_in_bytes, |
| 284 | size_t pixel_stride = framebuffer.stride / bpp; | 261 | framebuffer_info.address, framebuffer_info.width, framebuffer_info.height, |
| 285 | 262 | (int)framebuffer_info.format); | |
| 286 | // OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately | ||
| 287 | ASSERT(pixel_stride * bpp == framebuffer.stride); | ||
| 288 | 263 | ||
| 289 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default | 264 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default |
| 290 | // only allows rows to have a memory alignement of 4. | 265 | // only allows rows to have a memory alignement of 4. |
| 291 | ASSERT(pixel_stride % 4 == 0); | 266 | ASSERT(framebuffer_info.stride % 4 == 0); |
| 292 | |||
| 293 | if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr, | ||
| 294 | static_cast<u32>(pixel_stride), screen_info)) { | ||
| 295 | // Reset the screen info's display texture to its own permanent texture | ||
| 296 | screen_info.display_texture = screen_info.texture.resource.handle; | ||
| 297 | screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); | ||
| 298 | 267 | ||
| 299 | Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); | 268 | // Reset the screen info's display texture to its own permanent texture |
| 269 | screen_info.display_texture = screen_info.texture.resource.handle; | ||
| 270 | screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); | ||
| 300 | 271 | ||
| 301 | const u8* framebuffer_data = Memory::GetPhysicalPointer(framebuffer_addr); | 272 | Memory::RasterizerFlushRegion(framebuffer_info.address, size_in_bytes); |
| 302 | 273 | ||
| 303 | state.texture_units[0].texture_2d = screen_info.texture.resource.handle; | 274 | state.texture_units[0].texture_2d = screen_info.texture.resource.handle; |
| 304 | state.Apply(); | 275 | state.Apply(); |
| 305 | 276 | ||
| 306 | glActiveTexture(GL_TEXTURE0); | 277 | glActiveTexture(GL_TEXTURE0); |
| 307 | glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride); | 278 | glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer_info.stride); |
| 308 | 279 | ||
| 309 | // Update existing texture | 280 | // Update existing texture |
| 310 | // TODO: Test what happens on hardware when you change the framebuffer dimensions so that | 281 | // TODO: Test what happens on hardware when you change the framebuffer dimensions so that |
| 311 | // they differ from the LCD resolution. | 282 | // they differ from the LCD resolution. |
| 312 | // TODO: Applications could theoretically crash Citra here by specifying too large | 283 | // TODO: Applications could theoretically crash Citra here by specifying too large |
| 313 | // framebuffer sizes. We should make sure that this cannot happen. | 284 | // framebuffer sizes. We should make sure that this cannot happen. |
| 314 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, | 285 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer_info.width, framebuffer_info.height, |
| 315 | screen_info.texture.gl_format, screen_info.texture.gl_type, | 286 | screen_info.texture.gl_format, screen_info.texture.gl_type, |
| 316 | framebuffer_data); | 287 | gl_framebuffer_data.data()); |
| 317 | 288 | ||
| 318 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 289 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 319 | 290 | ||
| 320 | state.texture_units[0].texture_2d = 0; | 291 | state.texture_units[0].texture_2d = 0; |
| 321 | state.Apply(); | 292 | state.Apply(); |
| 322 | } | ||
| 323 | } | 293 | } |
| 324 | 294 | ||
| 325 | /** | 295 | /** |
| @@ -377,74 +347,43 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 377 | glEnableVertexAttribArray(attrib_position); | 347 | glEnableVertexAttribArray(attrib_position); |
| 378 | glEnableVertexAttribArray(attrib_tex_coord); | 348 | glEnableVertexAttribArray(attrib_tex_coord); |
| 379 | 349 | ||
| 380 | // Allocate textures for each screen | 350 | // Allocate textures for the screen |
| 381 | for (auto& screen_info : screen_infos) { | 351 | screen_info.texture.resource.Create(); |
| 382 | screen_info.texture.resource.Create(); | ||
| 383 | 352 | ||
| 384 | // Allocation of storage is deferred until the first frame, when we | 353 | // Allocation of storage is deferred until the first frame, when we |
| 385 | // know the framebuffer size. | 354 | // know the framebuffer size. |
| 386 | 355 | ||
| 387 | state.texture_units[0].texture_2d = screen_info.texture.resource.handle; | 356 | state.texture_units[0].texture_2d = screen_info.texture.resource.handle; |
| 388 | state.Apply(); | 357 | state.Apply(); |
| 389 | 358 | ||
| 390 | glActiveTexture(GL_TEXTURE0); | 359 | glActiveTexture(GL_TEXTURE0); |
| 391 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); | 360 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); |
| 392 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 361 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 393 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 362 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 394 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 363 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 395 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 364 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 396 | 365 | ||
| 397 | screen_info.display_texture = screen_info.texture.resource.handle; | 366 | screen_info.display_texture = screen_info.texture.resource.handle; |
| 398 | } | ||
| 399 | 367 | ||
| 400 | state.texture_units[0].texture_2d = 0; | 368 | state.texture_units[0].texture_2d = 0; |
| 401 | state.Apply(); | 369 | state.Apply(); |
| 402 | } | 370 | } |
| 403 | 371 | ||
| 404 | void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | 372 | void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, |
| 405 | const GPU::Regs::FramebufferConfig& framebuffer) { | 373 | const FramebufferInfo& framebuffer_info) { |
| 406 | GPU::Regs::PixelFormat format = framebuffer.color_format; | ||
| 407 | GLint internal_format; | ||
| 408 | 374 | ||
| 409 | texture.format = format; | 375 | texture.width = framebuffer_info.width; |
| 410 | texture.width = framebuffer.width; | 376 | texture.height = framebuffer_info.height; |
| 411 | texture.height = framebuffer.height; | ||
| 412 | 377 | ||
| 413 | switch (format) { | 378 | GLint internal_format; |
| 414 | case GPU::Regs::PixelFormat::RGBA8: | 379 | switch (framebuffer_info.pixel_format) { |
| 380 | case FramebufferInfo::PixelFormat::ABGR8: | ||
| 381 | // Use RGBA8 and swap in the fragment shader | ||
| 415 | internal_format = GL_RGBA; | 382 | internal_format = GL_RGBA; |
| 416 | texture.gl_format = GL_RGBA; | 383 | texture.gl_format = GL_RGBA; |
| 417 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8; | 384 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8; |
| 385 | gl_framebuffer_data.resize(texture.width * texture.height * 4); | ||
| 418 | break; | 386 | break; |
| 419 | |||
| 420 | case GPU::Regs::PixelFormat::RGB8: | ||
| 421 | // This pixel format uses BGR since GL_UNSIGNED_BYTE specifies byte-order, unlike every | ||
| 422 | // specific OpenGL type used in this function using native-endian (that is, little-endian | ||
| 423 | // mostly everywhere) for words or half-words. | ||
| 424 | // TODO: check how those behave on big-endian processors. | ||
| 425 | internal_format = GL_RGB; | ||
| 426 | texture.gl_format = GL_BGR; | ||
| 427 | texture.gl_type = GL_UNSIGNED_BYTE; | ||
| 428 | break; | ||
| 429 | |||
| 430 | case GPU::Regs::PixelFormat::RGB565: | ||
| 431 | internal_format = GL_RGB; | ||
| 432 | texture.gl_format = GL_RGB; | ||
| 433 | texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; | ||
| 434 | break; | ||
| 435 | |||
| 436 | case GPU::Regs::PixelFormat::RGB5A1: | ||
| 437 | internal_format = GL_RGBA; | ||
| 438 | texture.gl_format = GL_RGBA; | ||
| 439 | texture.gl_type = GL_UNSIGNED_SHORT_5_5_5_1; | ||
| 440 | break; | ||
| 441 | |||
| 442 | case GPU::Regs::PixelFormat::RGBA4: | ||
| 443 | internal_format = GL_RGBA; | ||
| 444 | texture.gl_format = GL_RGBA; | ||
| 445 | texture.gl_type = GL_UNSIGNED_SHORT_4_4_4_4; | ||
| 446 | break; | ||
| 447 | |||
| 448 | default: | 387 | default: |
| 449 | UNIMPLEMENTED(); | 388 | UNIMPLEMENTED(); |
| 450 | } | 389 | } |
| @@ -465,10 +404,10 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl | |||
| 465 | auto& texcoords = screen_info.display_texcoords; | 404 | auto& texcoords = screen_info.display_texcoords; |
| 466 | 405 | ||
| 467 | std::array<ScreenRectVertex, 4> vertices = {{ | 406 | std::array<ScreenRectVertex, 4> vertices = {{ |
| 468 | ScreenRectVertex(x, y, texcoords.top, texcoords.left), | 407 | ScreenRectVertex(x, y, texcoords.top, texcoords.right), |
| 469 | ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.left), | 408 | ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right), |
| 470 | ScreenRectVertex(x, y + h, texcoords.top, texcoords.right), | 409 | ScreenRectVertex(x, y + h, texcoords.top, texcoords.left), |
| 471 | ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.right), | 410 | ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left), |
| 472 | }}; | 411 | }}; |
| 473 | 412 | ||
| 474 | state.texture_units[0].texture_2d = screen_info.display_texture; | 413 | state.texture_units[0].texture_2d = screen_info.display_texture; |
| @@ -500,8 +439,8 @@ void RendererOpenGL::DrawScreens() { | |||
| 500 | glActiveTexture(GL_TEXTURE0); | 439 | glActiveTexture(GL_TEXTURE0); |
| 501 | glUniform1i(uniform_color_texture, 0); | 440 | glUniform1i(uniform_color_texture, 0); |
| 502 | 441 | ||
| 503 | DrawSingleScreen(screen_infos[0], (float)screen.left, (float)screen.top, | 442 | DrawSingleScreen(screen_info, (float)screen.left, (float)screen.top, (float)screen.GetWidth(), |
| 504 | (float)screen.GetWidth(), (float)screen.GetHeight()); | 443 | (float)screen.GetHeight()); |
| 505 | 444 | ||
| 506 | m_current_frame++; | 445 | m_current_frame++; |
| 507 | } | 446 | } |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 111b78466..9d2bb8423 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <vector> |
| 8 | #include <glad/glad.h> | 8 | #include <glad/glad.h> |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/math_util.h" | 10 | #include "common/math_util.h" |
| @@ -20,9 +20,9 @@ struct TextureInfo { | |||
| 20 | OGLTexture resource; | 20 | OGLTexture resource; |
| 21 | GLsizei width; | 21 | GLsizei width; |
| 22 | GLsizei height; | 22 | GLsizei height; |
| 23 | GPU::Regs::PixelFormat format; | ||
| 24 | GLenum gl_format; | 23 | GLenum gl_format; |
| 25 | GLenum gl_type; | 24 | GLenum gl_type; |
| 25 | RendererBase::FramebufferInfo::PixelFormat pixel_format; | ||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /// Structure used for storing information about the display target for each 3DS screen | 28 | /// Structure used for storing information about the display target for each 3DS screen |
| @@ -38,7 +38,7 @@ public: | |||
| 38 | ~RendererOpenGL() override; | 38 | ~RendererOpenGL() override; |
| 39 | 39 | ||
| 40 | /// Swap buffers (render frame) | 40 | /// Swap buffers (render frame) |
| 41 | void SwapBuffers() override; | 41 | void SwapBuffers(const FramebufferInfo& framebuffer_info) override; |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Set the emulator window to use for renderer | 44 | * Set the emulator window to use for renderer |
| @@ -55,13 +55,13 @@ public: | |||
| 55 | private: | 55 | private: |
| 56 | void InitOpenGLObjects(); | 56 | void InitOpenGLObjects(); |
| 57 | void ConfigureFramebufferTexture(TextureInfo& texture, | 57 | void ConfigureFramebufferTexture(TextureInfo& texture, |
| 58 | const GPU::Regs::FramebufferConfig& framebuffer); | 58 | const FramebufferInfo& framebuffer_info); |
| 59 | void DrawScreens(); | 59 | void DrawScreens(); |
| 60 | void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); | 60 | void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); |
| 61 | void UpdateFramerate(); | 61 | void UpdateFramerate(); |
| 62 | 62 | ||
| 63 | // Loads framebuffer from emulated memory into the display information structure | 63 | // Loads framebuffer from emulated memory into the display information structure |
| 64 | void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer, | 64 | void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, |
| 65 | ScreenInfo& screen_info); | 65 | ScreenInfo& screen_info); |
| 66 | // Fills active OpenGL texture with the given RGB color. | 66 | // Fills active OpenGL texture with the given RGB color. |
| 67 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture); | 67 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture); |
| @@ -75,8 +75,11 @@ private: | |||
| 75 | OGLBuffer vertex_buffer; | 75 | OGLBuffer vertex_buffer; |
| 76 | OGLShader shader; | 76 | OGLShader shader; |
| 77 | 77 | ||
| 78 | /// Display information for top and bottom screens respectively | 78 | /// Display information for Switch screen |
| 79 | std::array<ScreenInfo, 2> screen_infos; | 79 | ScreenInfo screen_info; |
| 80 | |||
| 81 | /// OpenGL framebuffer data | ||
| 82 | std::vector<u8> gl_framebuffer_data; | ||
| 80 | 83 | ||
| 81 | // Shader uniform location indices | 84 | // Shader uniform location indices |
| 82 | GLuint uniform_modelview_matrix; | 85 | GLuint uniform_modelview_matrix; |