From bfe45774f16e958bf34ed0d58a1d31e2325df47d Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 Mar 2018 21:04:30 -0400 Subject: video_core: Move FramebufferInfo to FramebufferConfig in GPU. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 56 ++++++++++++---------- 1 file changed, 30 insertions(+), 26 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 65d38ade5..2ea5e91e3 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -98,22 +98,22 @@ RendererOpenGL::RendererOpenGL() = default; RendererOpenGL::~RendererOpenGL() = default; /// Swap buffers (render frame) -void RendererOpenGL::SwapBuffers(boost::optional framebuffer_info) { +void RendererOpenGL::SwapBuffers(boost::optional framebuffer) { // Maintain the rasterizer's state as a priority OpenGLState prev_state = OpenGLState::GetCurState(); state.Apply(); - if (framebuffer_info != boost::none) { - // If framebuffer_info is provided, reload it from memory to a texture - if (screen_info.texture.width != (GLsizei)framebuffer_info->width || - screen_info.texture.height != (GLsizei)framebuffer_info->height || - screen_info.texture.pixel_format != framebuffer_info->pixel_format) { + if (framebuffer != boost::none) { + // If framebuffer is provided, reload it from memory to a texture + if (screen_info.texture.width != (GLsizei)framebuffer->width || + screen_info.texture.height != (GLsizei)framebuffer->height || + screen_info.texture.pixel_format != framebuffer->pixel_format) { // Reallocate texture if the framebuffer size has changed. // This is expected to not happen very often and hence should not be a // performance problem. - ConfigureFramebufferTexture(screen_info.texture, *framebuffer_info); + ConfigureFramebufferTexture(screen_info.texture, *framebuffer); } - LoadFBToScreenInfo(*framebuffer_info, screen_info); + LoadFBToScreenInfo(*framebuffer, screen_info); } DrawScreens(); @@ -245,43 +245,47 @@ static void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32 /** * Loads framebuffer from emulated memory into the active OpenGL texture. */ -void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, +void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer, ScreenInfo& screen_info) { - const u32 bpp{FramebufferInfo::BytesPerPixel(framebuffer_info.pixel_format)}; - const u32 size_in_bytes{framebuffer_info.stride * framebuffer_info.height * bpp}; + const u32 bpp{Tegra::FramebufferConfig::BytesPerPixel(framebuffer.pixel_format)}; + const u32 size_in_bytes{framebuffer.stride * framebuffer.height * bpp}; + const VAddr framebuffer_addr{framebuffer.address}; + const size_t pixel_stride{framebuffer.stride / bpp}; - MortonCopyPixels128(framebuffer_info.width, framebuffer_info.height, bpp, 4, - Memory::GetPointer(framebuffer_info.address), gl_framebuffer_data.data(), - true); + // OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately + ASSERT(pixel_stride * bpp == framebuffer.stride); + + MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4, + Memory::GetPointer(framebuffer.address), gl_framebuffer_data.data(), true); LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%llx(%dx%d), fmt %x", size_in_bytes, - framebuffer_info.address, framebuffer_info.width, framebuffer_info.height, - (int)framebuffer_info.pixel_format); + framebuffer.address, framebuffer.width, framebuffer.height, + (int)framebuffer.pixel_format); // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default // only allows rows to have a memory alignement of 4. - ASSERT(framebuffer_info.stride % 4 == 0); + ASSERT(framebuffer.stride % 4 == 0); - framebuffer_flip_vertical = framebuffer_info.flip_vertical; + framebuffer_flip_vertical = framebuffer.flip_vertical; // Reset the screen info's display texture to its own permanent texture screen_info.display_texture = screen_info.texture.resource.handle; screen_info.display_texcoords = MathUtil::Rectangle(0.f, 0.f, 1.f, 1.f); - // Memory::RasterizerFlushRegion(framebuffer_info.address, size_in_bytes); + Rasterizer()->FlushRegion(framebuffer.address, size_in_bytes); state.texture_units[0].texture_2d = screen_info.texture.resource.handle; state.Apply(); glActiveTexture(GL_TEXTURE0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer_info.stride); + glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer.stride); // Update existing texture // TODO: Test what happens on hardware when you change the framebuffer dimensions so that // they differ from the LCD resolution. // 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_info.width, framebuffer_info.height, + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, screen_info.texture.gl_format, screen_info.texture.gl_type, gl_framebuffer_data.data()); @@ -372,14 +376,14 @@ void RendererOpenGL::InitOpenGLObjects() { } void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, - const FramebufferInfo& framebuffer_info) { + const Tegra::FramebufferConfig& framebuffer) { - texture.width = framebuffer_info.width; - texture.height = framebuffer_info.height; + texture.width = framebuffer.width; + texture.height = framebuffer.height; GLint internal_format; - switch (framebuffer_info.pixel_format) { - case FramebufferInfo::PixelFormat::ABGR8: + switch (framebuffer.pixel_format) { + case Tegra::FramebufferConfig::PixelFormat::ABGR8: // Use RGBA8 and swap in the fragment shader internal_format = GL_RGBA; texture.gl_format = GL_RGBA; -- cgit v1.2.3 From 740310113b626cc1918213dd569d3a9a644d9280 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 Mar 2018 22:52:40 -0400 Subject: video_core: Move MortonCopyPixels128 to utils header. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 112 +-------------------- 1 file changed, 1 insertion(+), 111 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 2ea5e91e3..a65270222 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -20,6 +20,7 @@ #include "core/settings.h" #include "core/tracer/recorder.h" #include "video_core/renderer_opengl/renderer_opengl.h" +#include "video_core/utils.h" #include "video_core/video_core.h" static const char vertex_shader[] = R"( @@ -131,117 +132,6 @@ void RendererOpenGL::SwapBuffers(boost::optional Date: Thu, 22 Mar 2018 23:28:37 -0400 Subject: renderer_opengl: Use accelerated framebuffer load with LoadFBToScreenInfo. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 56 ++++++++++------------ 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index a65270222..047389fee 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -140,49 +140,43 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf const u32 bpp{Tegra::FramebufferConfig::BytesPerPixel(framebuffer.pixel_format)}; const u32 size_in_bytes{framebuffer.stride * framebuffer.height * bpp}; const VAddr framebuffer_addr{framebuffer.address}; - const size_t pixel_stride{framebuffer.stride / bpp}; - - // OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately - ASSERT(pixel_stride * bpp == framebuffer.stride); - - MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4, - Memory::GetPointer(framebuffer.address), gl_framebuffer_data.data(), true); - - LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%llx(%dx%d), fmt %x", size_in_bytes, - framebuffer.address, framebuffer.width, framebuffer.height, - (int)framebuffer.pixel_format); // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default // only allows rows to have a memory alignement of 4. ASSERT(framebuffer.stride % 4 == 0); - framebuffer_flip_vertical = framebuffer.flip_vertical; + if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride, + screen_info)) { + // Reset the screen info's display texture to its own permanent texture + screen_info.display_texture = screen_info.texture.resource.handle; + screen_info.display_texcoords = MathUtil::Rectangle(0.f, 0.f, 1.f, 1.f); - // Reset the screen info's display texture to its own permanent texture - screen_info.display_texture = screen_info.texture.resource.handle; - screen_info.display_texcoords = MathUtil::Rectangle(0.f, 0.f, 1.f, 1.f); + Rasterizer()->FlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); - Rasterizer()->FlushRegion(framebuffer.address, size_in_bytes); + VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4, + Memory::GetPointer(framebuffer.address), + gl_framebuffer_data.data(), true); - state.texture_units[0].texture_2d = screen_info.texture.resource.handle; - state.Apply(); + state.texture_units[0].texture_2d = screen_info.texture.resource.handle; + state.Apply(); - glActiveTexture(GL_TEXTURE0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer.stride); + glActiveTexture(GL_TEXTURE0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(framebuffer.stride)); - // Update existing texture - // TODO: Test what happens on hardware when you change the framebuffer dimensions so that - // they differ from the LCD resolution. - // 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, - screen_info.texture.gl_format, screen_info.texture.gl_type, - gl_framebuffer_data.data()); + // Update existing texture + // TODO: Test what happens on hardware when you change the framebuffer dimensions so that + // they differ from the LCD resolution. + // TODO: Applications could theoretically crash yuzu 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, + screen_info.texture.gl_format, screen_info.texture.gl_type, + gl_framebuffer_data.data()); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - state.texture_units[0].texture_2d = 0; - state.Apply(); + state.texture_units[0].texture_2d = 0; + state.Apply(); + } } /** -- cgit v1.2.3 From ec4e1a3685d458147ac76f4cf53ea86632d0debd Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 14:58:27 -0400 Subject: renderer_opengl: Better handling of framebuffer transform flags. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 047389fee..ef63cbcf0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -141,6 +141,9 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf const u32 size_in_bytes{framebuffer.stride * framebuffer.height * bpp}; const VAddr framebuffer_addr{framebuffer.address}; + // Framebuffer orientation handling + framebuffer_transform_flags = framebuffer.transform_flags; + // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default // only allows rows to have a memory alignement of 4. ASSERT(framebuffer.stride % 4 == 0); @@ -292,8 +295,19 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h) { const auto& texcoords = screen_info.display_texcoords; - const auto& left = framebuffer_flip_vertical ? texcoords.right : texcoords.left; - const auto& right = framebuffer_flip_vertical ? texcoords.left : texcoords.right; + auto left = texcoords.left; + auto right = texcoords.right; + if (framebuffer_transform_flags != Tegra::FramebufferConfig::TransformFlags::Unset) + if (framebuffer_transform_flags == Tegra::FramebufferConfig::TransformFlags::FlipV) { + // Flip the framebuffer vertically + left = texcoords.right; + right = texcoords.left; + } else { + // Other transformations are unsupported + LOG_CRITICAL(HW_GPU, "unsupported framebuffer_transform_flags=%d", + framebuffer_transform_flags); + UNIMPLEMENTED(); + } std::array vertices = {{ ScreenRectVertex(x, y, texcoords.top, right), -- cgit v1.2.3 From 054393917e99d307eea0aabc78c0c6e5e709b2c7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 15:49:04 -0400 Subject: renderer_opengl: Fixes for properly flushing & rendering the framebuffer. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index ef63cbcf0..4628f6db0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -137,9 +137,15 @@ void RendererOpenGL::SwapBuffers(boost::optional(0.f, 0.f, 1.f, 1.f); - Rasterizer()->FlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); + Rasterizer()->FlushRegion(framebuffer_addr, size_in_bytes); - VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4, - Memory::GetPointer(framebuffer.address), + VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bytes_per_pixel, 4, + Memory::GetPointer(framebuffer_addr), gl_framebuffer_data.data(), true); state.texture_units[0].texture_2d = screen_info.texture.resource.handle; -- cgit v1.2.3 From 0f8401906b9616f853bb8baf43424dc354f736e2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 15:52:14 -0400 Subject: renderer_opengl: Only invalidate the framebuffer region, not flush. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 4628f6db0..1a24855d7 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -141,11 +141,10 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf const u64 size_in_bytes{framebuffer.stride * framebuffer.height * bytes_per_pixel}; const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; - // TODO(bunnei): The framebuffer region should only be flushed and invalidated if it is - // written to, not every frame. When we find the right place for this, the below line can be - // removed. + // TODO(bunnei): The framebuffer region should only be invalidated if it is written to, not + // every frame. When we find the right place for this, the below line can be removed. Memory::RasterizerFlushVirtualRegion(framebuffer_addr, size_in_bytes, - Memory::FlushMode::FlushAndInvalidate); + Memory::FlushMode::Invalidate); // Framebuffer orientation handling framebuffer_transform_flags = framebuffer.transform_flags; -- cgit v1.2.3