/** * Renders external framebuffer (XFB) * @param src_rect Source rectangle in XFB to copy * @param dst_rect Destination rectangle in output framebuffer to copy to */ void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) { FlipFramebuffer(LCD::GetFramebufferPointer(LCD::g_regs.framebuffer_top_left_1), m_xfb_top_flipped); FlipFramebuffer(LCD::GetFramebufferPointer(LCD::g_regs.framebuffer_sub_left_1), m_xfb_bottom_flipped); // Blit the top framebuffer // ------------------------ // Update textures with contents of XFB in RAM - top glBindTexture(GL_TEXTURE_2D, m_xfb_texture_top); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight, GL_BGR, GL_UNSIGNED_BYTE, m_xfb_top_flipped); glBindTexture(GL_TEXTURE_2D, 0); // Render target is destination framebuffer glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo[kFramebuffer_VirtualXFB]); glViewport(0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight); // Render source is our EFB glBindFramebuffer(GL_READ_FRAMEBUFFER, m_xfb_top); glReadBuffer(GL_COLOR_ATTACHMENT0); // Blit glBlitFramebuffer(src_rect.x0_, src_rect.y0_, src_rect.x1_, src_rect.y1_, dst_rect.x0_, dst_rect.y1_, dst_rect.x1_, dst_rect.y0_, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); // Blit the bottom framebuffer // --------------------------- // Update textures with contents of XFB in RAM - bottom glBindTexture(GL_TEXTURE_2D, m_xfb_texture_bottom); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight, GL_RGB, GL_UNSIGNED_BYTE, m_xfb_bottom_flipped); glBindTexture(GL_TEXTURE_2D, 0); // Render target is destination framebuffer glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo[kFramebuffer_VirtualXFB]); glViewport(0, 0, VideoCore::kScreenBottomWidth, VideoCore::kScreenBottomHeight); // Render source is our EFB glBindFramebuffer(GL_READ_FRAMEBUFFER, m_xfb_bottom); glReadBuffer(GL_COLOR_ATTACHMENT0); // Blit int offset = (VideoCore::kScreenTopWidth - VideoCore::kScreenBottomWidth) / 2; glBlitFramebuffer(0,0, VideoCore::kScreenBottomWidth, VideoCore::kScreenBottomHeight, offset, VideoCore::kScreenBottomHeight, VideoCore::kScreenBottomWidth + offset, 0, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); }
/** * Renders external framebuffer (XFB) * @param src_rect Source rectangle in XFB to copy * @param dst_rect Destination rectangle in output framebuffer to copy to */ void RendererOpenGL::RenderXFB(const common::Rect& src_rect, const common::Rect& dst_rect) { const auto& framebuffer_top = GPU::g_regs.framebuffer_config[0]; const auto& framebuffer_sub = GPU::g_regs.framebuffer_config[1]; const u32 active_fb_top = (framebuffer_top.active_fb == 1) ? Memory::PhysicalToVirtualAddress(framebuffer_top.address_left2) : Memory::PhysicalToVirtualAddress(framebuffer_top.address_left1); const u32 active_fb_sub = (framebuffer_sub.active_fb == 1) ? Memory::PhysicalToVirtualAddress(framebuffer_sub.address_left2) : Memory::PhysicalToVirtualAddress(framebuffer_sub.address_left1); DEBUG_LOG(GPU, "RenderXFB: 0x%08x bytes from 0x%08x(%dx%d), fmt %x", framebuffer_top.stride * framebuffer_top.height, active_fb_top, (int)framebuffer_top.width, (int)framebuffer_top.height, (int)framebuffer_top.format); FlipFramebuffer(Memory::GetPointer(active_fb_top), screen_info.Top()); FlipFramebuffer(Memory::GetPointer(active_fb_sub), screen_info.Bottom()); for (int i = 0; i < 2; i++) { ScreenInfo* current_screen = &screen_info[i]; glBindTexture(GL_TEXTURE_2D, current_screen->texture_id); // TODO: This should consider the GPU registers for framebuffer width, height and stride. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, current_screen->width, current_screen->height, GL_RGB, GL_UNSIGNED_BYTE, current_screen->flipped_xfb_data); } glBindTexture(GL_TEXTURE_2D, 0); // TODO(princesspeachum): // Only the subset src_rect of the GPU buffer // should be copied into the texture of the relevant screen. // // The method's parameters also only include src_rect and dest_rec for one screen, // so this may need to be changed (pair for each screen). }