diff options
| author | 2024-01-03 22:46:59 -0500 | |
|---|---|---|
| committer | 2024-01-31 11:27:20 -0500 | |
| commit | 80de01a5b4a7f57ec7850079fbd38fac76b9d08f (patch) | |
| tree | 18086d7a71ffcd9f5bc6651aec20de37e3b1c33d /src/video_core/renderer_opengl | |
| parent | Merge pull request #12760 from liamwhite/mp-am (diff) | |
| download | yuzu-80de01a5b4a7f57ec7850079fbd38fac76b9d08f.tar.gz yuzu-80de01a5b4a7f57ec7850079fbd38fac76b9d08f.tar.xz yuzu-80de01a5b4a7f57ec7850079fbd38fac76b9d08f.zip | |
video_core: simplify accelerated surface fetch and crop handling between APIs
Diffstat (limited to 'src/video_core/renderer_opengl')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_fsr.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_fsr.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 235 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 32 |
6 files changed, 142 insertions, 189 deletions
diff --git a/src/video_core/renderer_opengl/gl_fsr.cpp b/src/video_core/renderer_opengl/gl_fsr.cpp index 77262dcf1..429dcdc6c 100644 --- a/src/video_core/renderer_opengl/gl_fsr.cpp +++ b/src/video_core/renderer_opengl/gl_fsr.cpp | |||
| @@ -25,7 +25,7 @@ FSR::~FSR() = default; | |||
| 25 | 25 | ||
| 26 | void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, | 26 | void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, |
| 27 | u32 input_image_width, u32 input_image_height, | 27 | u32 input_image_width, u32 input_image_height, |
| 28 | const Common::Rectangle<int>& crop_rect) { | 28 | const Common::Rectangle<f32>& crop_rect) { |
| 29 | 29 | ||
| 30 | const auto output_image_width = screen.GetWidth(); | 30 | const auto output_image_width = screen.GetWidth(); |
| 31 | const auto output_image_height = screen.GetHeight(); | 31 | const auto output_image_height = screen.GetHeight(); |
| @@ -57,14 +57,19 @@ void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& sc | |||
| 57 | glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width), | 57 | glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width), |
| 58 | static_cast<GLfloat>(output_image_height)); | 58 | static_cast<GLfloat>(output_image_height)); |
| 59 | 59 | ||
| 60 | FsrConstants constants; | 60 | const f32 input_width = static_cast<f32>(input_image_width); |
| 61 | FsrEasuConOffset( | 61 | const f32 input_height = static_cast<f32>(input_image_height); |
| 62 | constants.data() + 0, constants.data() + 4, constants.data() + 8, constants.data() + 12, | 62 | const f32 output_width = static_cast<f32>(screen.GetWidth()); |
| 63 | const f32 output_height = static_cast<f32>(screen.GetHeight()); | ||
| 64 | const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width; | ||
| 65 | const f32 viewport_x = crop_rect.left * input_width; | ||
| 66 | const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height; | ||
| 67 | const f32 viewport_y = crop_rect.top * input_height; | ||
| 63 | 68 | ||
| 64 | static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()), | 69 | FsrConstants constants; |
| 65 | static_cast<f32>(input_image_width), static_cast<f32>(input_image_height), | 70 | FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8, |
| 66 | static_cast<f32>(output_image_width), static_cast<f32>(output_image_height), | 71 | constants.data() + 12, viewport_width, viewport_height, input_width, |
| 67 | static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top)); | 72 | input_height, output_width, output_height, viewport_x, viewport_y); |
| 68 | 73 | ||
| 69 | glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants)); | 74 | glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants)); |
| 70 | 75 | ||
diff --git a/src/video_core/renderer_opengl/gl_fsr.h b/src/video_core/renderer_opengl/gl_fsr.h index 1f6ae3115..a5092e396 100644 --- a/src/video_core/renderer_opengl/gl_fsr.h +++ b/src/video_core/renderer_opengl/gl_fsr.h | |||
| @@ -22,7 +22,7 @@ public: | |||
| 22 | 22 | ||
| 23 | void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, | 23 | void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, |
| 24 | u32 input_image_width, u32 input_image_height, | 24 | u32 input_image_width, u32 input_image_height, |
| 25 | const Common::Rectangle<int>& crop_rect); | 25 | const Common::Rectangle<f32>& crop_rect); |
| 26 | 26 | ||
| 27 | void InitBuffers(); | 27 | void InitBuffers(); |
| 28 | 28 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d5354ef2d..050a74cca 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -71,10 +71,10 @@ std::optional<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryTy | |||
| 71 | 71 | ||
| 72 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 72 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 73 | Tegra::MaxwellDeviceMemoryManager& device_memory_, | 73 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 74 | const Device& device_, ScreenInfo& screen_info_, | 74 | const Device& device_, ProgramManager& program_manager_, |
| 75 | ProgramManager& program_manager_, StateTracker& state_tracker_) | 75 | StateTracker& state_tracker_) |
| 76 | : gpu(gpu_), device_memory(device_memory_), device(device_), screen_info(screen_info_), | 76 | : gpu(gpu_), device_memory(device_memory_), device(device_), program_manager(program_manager_), |
| 77 | program_manager(program_manager_), state_tracker(state_tracker_), | 77 | state_tracker(state_tracker_), |
| 78 | texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), | 78 | texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), |
| 79 | texture_cache(texture_cache_runtime, device_memory_), | 79 | texture_cache(texture_cache_runtime, device_memory_), |
| 80 | buffer_cache_runtime(device, staging_buffer_pool), | 80 | buffer_cache_runtime(device, staging_buffer_pool), |
| @@ -739,10 +739,10 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si | |||
| 739 | query_cache.InvalidateRegion(*cpu_addr, copy_size); | 739 | query_cache.InvalidateRegion(*cpu_addr, copy_size); |
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 742 | std::optional<FramebufferTextureInfo> RasterizerOpenGL::AccelerateDisplay( |
| 743 | DAddr framebuffer_addr, u32 pixel_stride) { | 743 | const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) { |
| 744 | if (framebuffer_addr == 0) { | 744 | if (framebuffer_addr == 0) { |
| 745 | return false; | 745 | return {}; |
| 746 | } | 746 | } |
| 747 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 747 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 748 | 748 | ||
| @@ -750,16 +750,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | |||
| 750 | ImageView* const image_view{ | 750 | ImageView* const image_view{ |
| 751 | texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)}; | 751 | texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)}; |
| 752 | if (!image_view) { | 752 | if (!image_view) { |
| 753 | return false; | 753 | return {}; |
| 754 | } | 754 | } |
| 755 | // Verify that the cached surface is the same size and format as the requested framebuffer | ||
| 756 | // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different"); | ||
| 757 | // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different"); | ||
| 758 | 755 | ||
| 759 | screen_info.texture.width = image_view->size.width; | 756 | FramebufferTextureInfo info{}; |
| 760 | screen_info.texture.height = image_view->size.height; | 757 | info.display_texture = image_view->Handle(Shader::TextureType::Color2D); |
| 761 | screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D); | 758 | info.width = image_view->size.width; |
| 762 | return true; | 759 | info.height = image_view->size.height; |
| 760 | return info; | ||
| 763 | } | 761 | } |
| 764 | 762 | ||
| 765 | void RasterizerOpenGL::SyncState() { | 763 | void RasterizerOpenGL::SyncState() { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 34aa73526..ee82d9f3a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -37,7 +37,7 @@ class MemoryManager; | |||
| 37 | 37 | ||
| 38 | namespace OpenGL { | 38 | namespace OpenGL { |
| 39 | 39 | ||
| 40 | struct ScreenInfo; | 40 | struct FramebufferTextureInfo; |
| 41 | struct ShaderEntries; | 41 | struct ShaderEntries; |
| 42 | 42 | ||
| 43 | struct BindlessSSBO { | 43 | struct BindlessSSBO { |
| @@ -76,8 +76,8 @@ class RasterizerOpenGL : public VideoCore::RasterizerInterface, | |||
| 76 | public: | 76 | public: |
| 77 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 77 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 78 | Tegra::MaxwellDeviceMemoryManager& device_memory_, | 78 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 79 | const Device& device_, ScreenInfo& screen_info_, | 79 | const Device& device_, ProgramManager& program_manager_, |
| 80 | ProgramManager& program_manager_, StateTracker& state_tracker_); | 80 | StateTracker& state_tracker_); |
| 81 | ~RasterizerOpenGL() override; | 81 | ~RasterizerOpenGL() override; |
| 82 | 82 | ||
| 83 | void Draw(bool is_indexed, u32 instance_count) override; | 83 | void Draw(bool is_indexed, u32 instance_count) override; |
| @@ -122,8 +122,6 @@ public: | |||
| 122 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | 122 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; |
| 123 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 123 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 124 | std::span<const u8> memory) override; | 124 | std::span<const u8> memory) override; |
| 125 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, | ||
| 126 | u32 pixel_stride) override; | ||
| 127 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 125 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 128 | const VideoCore::DiskResourceLoadCallback& callback) override; | 126 | const VideoCore::DiskResourceLoadCallback& callback) override; |
| 129 | 127 | ||
| @@ -144,6 +142,10 @@ public: | |||
| 144 | return true; | 142 | return true; |
| 145 | } | 143 | } |
| 146 | 144 | ||
| 145 | std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config, | ||
| 146 | VAddr framebuffer_addr, | ||
| 147 | u32 pixel_stride); | ||
| 148 | |||
| 147 | private: | 149 | private: |
| 148 | static constexpr size_t MAX_TEXTURES = 192; | 150 | static constexpr size_t MAX_TEXTURES = 192; |
| 149 | static constexpr size_t MAX_IMAGES = 48; | 151 | static constexpr size_t MAX_IMAGES = 48; |
| @@ -237,7 +239,6 @@ private: | |||
| 237 | Tegra::MaxwellDeviceMemoryManager& device_memory; | 239 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 238 | 240 | ||
| 239 | const Device& device; | 241 | const Device& device; |
| 240 | ScreenInfo& screen_info; | ||
| 241 | ProgramManager& program_manager; | 242 | ProgramManager& program_manager; |
| 242 | StateTracker& state_tracker; | 243 | StateTracker& state_tracker; |
| 243 | 244 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index b75376fdb..ea5ed3e2f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -148,8 +148,7 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, | |||
| 148 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, | 148 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, |
| 149 | emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_}, | 149 | emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_}, |
| 150 | state_tracker{}, program_manager{device}, | 150 | state_tracker{}, program_manager{device}, |
| 151 | rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager, | 151 | rasterizer(emu_window, gpu, device_memory, device, program_manager, state_tracker) { |
| 152 | state_tracker) { | ||
| 153 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { | 152 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { |
| 154 | glEnable(GL_DEBUG_OUTPUT); | 153 | glEnable(GL_DEBUG_OUTPUT); |
| 155 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | 154 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); |
| @@ -184,11 +183,11 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 184 | if (!framebuffer) { | 183 | if (!framebuffer) { |
| 185 | return; | 184 | return; |
| 186 | } | 185 | } |
| 187 | PrepareRendertarget(framebuffer); | 186 | |
| 188 | RenderScreenshot(); | 187 | RenderScreenshot(*framebuffer); |
| 189 | 188 | ||
| 190 | state_tracker.BindFramebuffer(0); | 189 | state_tracker.BindFramebuffer(0); |
| 191 | DrawScreen(emu_window.GetFramebufferLayout()); | 190 | DrawScreen(*framebuffer, emu_window.GetFramebufferLayout()); |
| 192 | 191 | ||
| 193 | ++m_current_frame; | 192 | ++m_current_frame; |
| 194 | 193 | ||
| @@ -199,41 +198,37 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 199 | render_window.OnFrameDisplayed(); | 198 | render_window.OnFrameDisplayed(); |
| 200 | } | 199 | } |
| 201 | 200 | ||
| 202 | void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { | 201 | FramebufferTextureInfo RendererOpenGL::PrepareRenderTarget( |
| 203 | if (!framebuffer) { | 202 | const Tegra::FramebufferConfig& framebuffer) { |
| 204 | return; | ||
| 205 | } | ||
| 206 | // If framebuffer is provided, reload it from memory to a texture | 203 | // If framebuffer is provided, reload it from memory to a texture |
| 207 | if (screen_info.texture.width != static_cast<GLsizei>(framebuffer->width) || | 204 | if (framebuffer_texture.width != static_cast<GLsizei>(framebuffer.width) || |
| 208 | screen_info.texture.height != static_cast<GLsizei>(framebuffer->height) || | 205 | framebuffer_texture.height != static_cast<GLsizei>(framebuffer.height) || |
| 209 | screen_info.texture.pixel_format != framebuffer->pixel_format || | 206 | framebuffer_texture.pixel_format != framebuffer.pixel_format || |
| 210 | gl_framebuffer_data.empty()) { | 207 | gl_framebuffer_data.empty()) { |
| 211 | // Reallocate texture if the framebuffer size has changed. | 208 | // Reallocate texture if the framebuffer size has changed. |
| 212 | // This is expected to not happen very often and hence should not be a | 209 | // This is expected to not happen very often and hence should not be a |
| 213 | // performance problem. | 210 | // performance problem. |
| 214 | ConfigureFramebufferTexture(screen_info.texture, *framebuffer); | 211 | ConfigureFramebufferTexture(framebuffer); |
| 215 | } | 212 | } |
| 216 | 213 | ||
| 217 | // Load the framebuffer from memory, draw it to the screen, and swap buffers | 214 | // Load the framebuffer from memory if needed |
| 218 | LoadFBToScreenInfo(*framebuffer); | 215 | return LoadFBToScreenInfo(framebuffer); |
| 219 | } | 216 | } |
| 220 | 217 | ||
| 221 | void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) { | 218 | FramebufferTextureInfo RendererOpenGL::LoadFBToScreenInfo( |
| 222 | // Framebuffer orientation handling | 219 | const Tegra::FramebufferConfig& framebuffer) { |
| 223 | framebuffer_transform_flags = framebuffer.transform_flags; | ||
| 224 | framebuffer_crop_rect = framebuffer.crop_rect; | ||
| 225 | framebuffer_width = framebuffer.width; | ||
| 226 | framebuffer_height = framebuffer.height; | ||
| 227 | |||
| 228 | const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; | 220 | const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; |
| 229 | screen_info.was_accelerated = | 221 | const auto accelerated_info = |
| 230 | rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride); | 222 | rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride); |
| 231 | if (screen_info.was_accelerated) { | 223 | if (accelerated_info) { |
| 232 | return; | 224 | return *accelerated_info; |
| 233 | } | 225 | } |
| 234 | 226 | ||
| 235 | // Reset the screen info's display texture to its own permanent texture | 227 | // Reset the screen info's display texture to its own permanent texture |
| 236 | screen_info.display_texture = screen_info.texture.resource.handle; | 228 | FramebufferTextureInfo info{}; |
| 229 | info.display_texture = framebuffer_texture.resource.handle; | ||
| 230 | info.width = framebuffer.width; | ||
| 231 | info.height = framebuffer.height; | ||
| 237 | 232 | ||
| 238 | // TODO(Rodrigo): Read this from HLE | 233 | // TODO(Rodrigo): Read this from HLE |
| 239 | constexpr u32 block_height_log2 = 4; | 234 | constexpr u32 block_height_log2 = 4; |
| @@ -256,17 +251,13 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf | |||
| 256 | // they differ from the LCD resolution. | 251 | // they differ from the LCD resolution. |
| 257 | // TODO: Applications could theoretically crash yuzu here by specifying too large | 252 | // TODO: Applications could theoretically crash yuzu here by specifying too large |
| 258 | // framebuffer sizes. We should make sure that this cannot happen. | 253 | // framebuffer sizes. We should make sure that this cannot happen. |
| 259 | glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width, | 254 | glTextureSubImage2D(framebuffer_texture.resource.handle, 0, 0, 0, framebuffer.width, |
| 260 | framebuffer.height, screen_info.texture.gl_format, | 255 | framebuffer.height, framebuffer_texture.gl_format, |
| 261 | screen_info.texture.gl_type, gl_framebuffer_data.data()); | 256 | framebuffer_texture.gl_type, gl_framebuffer_data.data()); |
| 262 | 257 | ||
| 263 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 258 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 264 | } | ||
| 265 | 259 | ||
| 266 | void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, | 260 | return info; |
| 267 | const TextureInfo& texture) { | ||
| 268 | const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; | ||
| 269 | glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); | ||
| 270 | } | 261 | } |
| 271 | 262 | ||
| 272 | void RendererOpenGL::InitOpenGLObjects() { | 263 | void RendererOpenGL::InitOpenGLObjects() { |
| @@ -343,15 +334,15 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 343 | glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); | 334 | glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); |
| 344 | 335 | ||
| 345 | // Allocate textures for the screen | 336 | // Allocate textures for the screen |
| 346 | screen_info.texture.resource.Create(GL_TEXTURE_2D); | 337 | framebuffer_texture.resource.Create(GL_TEXTURE_2D); |
| 347 | 338 | ||
| 348 | const GLuint texture = screen_info.texture.resource.handle; | 339 | const GLuint texture = framebuffer_texture.resource.handle; |
| 349 | glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); | 340 | glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); |
| 350 | 341 | ||
| 351 | screen_info.display_texture = screen_info.texture.resource.handle; | ||
| 352 | |||
| 353 | // Clear screen to black | 342 | // Clear screen to black |
| 354 | LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); | 343 | const u8 framebuffer_data[4] = {0, 0, 0, 0}; |
| 344 | glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, | ||
| 345 | framebuffer_data); | ||
| 355 | 346 | ||
| 356 | aa_framebuffer.Create(); | 347 | aa_framebuffer.Create(); |
| 357 | 348 | ||
| @@ -380,60 +371,65 @@ void RendererOpenGL::AddTelemetryFields() { | |||
| 380 | telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); | 371 | telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); |
| 381 | } | 372 | } |
| 382 | 373 | ||
| 383 | void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | 374 | void RendererOpenGL::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer) { |
| 384 | const Tegra::FramebufferConfig& framebuffer) { | 375 | framebuffer_texture.width = framebuffer.width; |
| 385 | texture.width = framebuffer.width; | 376 | framebuffer_texture.height = framebuffer.height; |
| 386 | texture.height = framebuffer.height; | 377 | framebuffer_texture.pixel_format = framebuffer.pixel_format; |
| 387 | texture.pixel_format = framebuffer.pixel_format; | ||
| 388 | 378 | ||
| 389 | const auto pixel_format{ | 379 | const auto pixel_format{ |
| 390 | VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; | 380 | VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; |
| 391 | const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; | 381 | const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; |
| 392 | gl_framebuffer_data.resize(texture.width * texture.height * bytes_per_pixel); | 382 | gl_framebuffer_data.resize(framebuffer_texture.width * framebuffer_texture.height * |
| 383 | bytes_per_pixel); | ||
| 393 | 384 | ||
| 394 | GLint internal_format; | 385 | GLint internal_format; |
| 395 | switch (framebuffer.pixel_format) { | 386 | switch (framebuffer.pixel_format) { |
| 396 | case Service::android::PixelFormat::Rgba8888: | 387 | case Service::android::PixelFormat::Rgba8888: |
| 397 | internal_format = GL_RGBA8; | 388 | internal_format = GL_RGBA8; |
| 398 | texture.gl_format = GL_RGBA; | 389 | framebuffer_texture.gl_format = GL_RGBA; |
| 399 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; | 390 | framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
| 400 | break; | 391 | break; |
| 401 | case Service::android::PixelFormat::Rgb565: | 392 | case Service::android::PixelFormat::Rgb565: |
| 402 | internal_format = GL_RGB565; | 393 | internal_format = GL_RGB565; |
| 403 | texture.gl_format = GL_RGB; | 394 | framebuffer_texture.gl_format = GL_RGB; |
| 404 | texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; | 395 | framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; |
| 405 | break; | 396 | break; |
| 406 | default: | 397 | default: |
| 407 | internal_format = GL_RGBA8; | 398 | internal_format = GL_RGBA8; |
| 408 | texture.gl_format = GL_RGBA; | 399 | framebuffer_texture.gl_format = GL_RGBA; |
| 409 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; | 400 | framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
| 410 | // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", | 401 | // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", |
| 411 | // static_cast<u32>(framebuffer.pixel_format)); | 402 | // static_cast<u32>(framebuffer.pixel_format)); |
| 412 | break; | 403 | break; |
| 413 | } | 404 | } |
| 414 | 405 | ||
| 415 | texture.resource.Release(); | 406 | framebuffer_texture.resource.Release(); |
| 416 | texture.resource.Create(GL_TEXTURE_2D); | 407 | framebuffer_texture.resource.Create(GL_TEXTURE_2D); |
| 417 | glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); | 408 | glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, |
| 409 | framebuffer_texture.width, framebuffer_texture.height); | ||
| 418 | aa_texture.Release(); | 410 | aa_texture.Release(); |
| 419 | aa_texture.Create(GL_TEXTURE_2D); | 411 | aa_texture.Create(GL_TEXTURE_2D); |
| 420 | glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F, | 412 | glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F, |
| 421 | Settings::values.resolution_info.ScaleUp(screen_info.texture.width), | 413 | Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), |
| 422 | Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); | 414 | Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); |
| 423 | glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); | 415 | glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); |
| 424 | smaa_edges_tex.Release(); | 416 | smaa_edges_tex.Release(); |
| 425 | smaa_edges_tex.Create(GL_TEXTURE_2D); | 417 | smaa_edges_tex.Create(GL_TEXTURE_2D); |
| 426 | glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, | 418 | glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, |
| 427 | Settings::values.resolution_info.ScaleUp(screen_info.texture.width), | 419 | Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), |
| 428 | Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); | 420 | Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); |
| 429 | smaa_blend_tex.Release(); | 421 | smaa_blend_tex.Release(); |
| 430 | smaa_blend_tex.Create(GL_TEXTURE_2D); | 422 | smaa_blend_tex.Create(GL_TEXTURE_2D); |
| 431 | glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, | 423 | glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, |
| 432 | Settings::values.resolution_info.ScaleUp(screen_info.texture.width), | 424 | Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), |
| 433 | Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); | 425 | Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); |
| 434 | } | 426 | } |
| 435 | 427 | ||
| 436 | void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | 428 | void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer, |
| 429 | const Layout::FramebufferLayout& layout) { | ||
| 430 | FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); | ||
| 431 | const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); | ||
| 432 | |||
| 437 | // TODO: Signal state tracker about these changes | 433 | // TODO: Signal state tracker about these changes |
| 438 | state_tracker.NotifyScreenDrawVertexArray(); | 434 | state_tracker.NotifyScreenDrawVertexArray(); |
| 439 | state_tracker.NotifyPolygonModes(); | 435 | state_tracker.NotifyPolygonModes(); |
| @@ -469,7 +465,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 469 | glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | 465 | glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| 470 | glDepthRangeIndexed(0, 0.0, 0.0); | 466 | glDepthRangeIndexed(0, 0.0, 0.0); |
| 471 | 467 | ||
| 472 | glBindTextureUnit(0, screen_info.display_texture); | 468 | glBindTextureUnit(0, info.display_texture); |
| 473 | 469 | ||
| 474 | auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); | 470 | auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); |
| 475 | if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { | 471 | if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { |
| @@ -480,22 +476,22 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 480 | 476 | ||
| 481 | if (anti_aliasing != Settings::AntiAliasing::None) { | 477 | if (anti_aliasing != Settings::AntiAliasing::None) { |
| 482 | glEnablei(GL_SCISSOR_TEST, 0); | 478 | glEnablei(GL_SCISSOR_TEST, 0); |
| 483 | auto viewport_width = screen_info.texture.width; | 479 | auto viewport_width = info.width; |
| 484 | auto scissor_width = framebuffer_crop_rect.GetWidth(); | 480 | auto scissor_width = static_cast<u32>(crop.GetWidth()); |
| 485 | if (scissor_width <= 0) { | 481 | if (scissor_width <= 0) { |
| 486 | scissor_width = viewport_width; | 482 | scissor_width = viewport_width; |
| 487 | } | 483 | } |
| 488 | auto viewport_height = screen_info.texture.height; | 484 | auto viewport_height = info.height; |
| 489 | auto scissor_height = framebuffer_crop_rect.GetHeight(); | 485 | auto scissor_height = static_cast<u32>(crop.GetHeight()); |
| 490 | if (scissor_height <= 0) { | 486 | if (scissor_height <= 0) { |
| 491 | scissor_height = viewport_height; | 487 | scissor_height = viewport_height; |
| 492 | } | 488 | } |
| 493 | if (screen_info.was_accelerated) { | 489 | |
| 494 | viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width); | 490 | viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width); |
| 495 | scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width); | 491 | scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width); |
| 496 | viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height); | 492 | viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height); |
| 497 | scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height); | 493 | scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height); |
| 498 | } | 494 | |
| 499 | glScissorIndexed(0, 0, 0, scissor_width, scissor_height); | 495 | glScissorIndexed(0, 0, 0, scissor_width, scissor_height); |
| 500 | glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width), | 496 | glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width), |
| 501 | static_cast<GLfloat>(viewport_height)); | 497 | static_cast<GLfloat>(viewport_height)); |
| @@ -536,7 +532,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 536 | smaa_blending_weight_calculation_frag.handle); | 532 | smaa_blending_weight_calculation_frag.handle); |
| 537 | glDrawArrays(GL_TRIANGLES, 0, 3); | 533 | glDrawArrays(GL_TRIANGLES, 0, 3); |
| 538 | 534 | ||
| 539 | glBindTextureUnit(0, screen_info.display_texture); | 535 | glBindTextureUnit(0, info.display_texture); |
| 540 | glBindTextureUnit(1, smaa_blend_tex.handle); | 536 | glBindTextureUnit(1, smaa_blend_tex.handle); |
| 541 | glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, | 537 | glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, |
| 542 | aa_texture.handle, 0); | 538 | aa_texture.handle, 0); |
| @@ -561,18 +557,10 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 561 | fsr->InitBuffers(); | 557 | fsr->InitBuffers(); |
| 562 | } | 558 | } |
| 563 | 559 | ||
| 564 | auto crop_rect = framebuffer_crop_rect; | 560 | const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width); |
| 565 | if (crop_rect.GetWidth() == 0) { | 561 | const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height); |
| 566 | crop_rect.right = framebuffer_width; | ||
| 567 | } | ||
| 568 | if (crop_rect.GetHeight() == 0) { | ||
| 569 | crop_rect.bottom = framebuffer_height; | ||
| 570 | } | ||
| 571 | crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor); | ||
| 572 | const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width); | ||
| 573 | const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height); | ||
| 574 | glBindSampler(0, present_sampler.handle); | 562 | glBindSampler(0, present_sampler.handle); |
| 575 | fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect); | 563 | fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop); |
| 576 | } else { | 564 | } else { |
| 577 | if (fsr->AreBuffersInitialized()) { | 565 | if (fsr->AreBuffersInitialized()) { |
| 578 | fsr->ReleaseBuffers(); | 566 | fsr->ReleaseBuffers(); |
| @@ -603,61 +591,34 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 603 | glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, | 591 | glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, |
| 604 | ortho_matrix.data()); | 592 | ortho_matrix.data()); |
| 605 | 593 | ||
| 606 | const auto& texcoords = screen_info.display_texcoords; | 594 | f32 left, top, right, bottom; |
| 607 | auto left = texcoords.left; | 595 | if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { |
| 608 | auto right = texcoords.right; | 596 | // FSR has already applied the crop, so we just want to render the image |
| 609 | if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) { | 597 | // it has produced. |
| 610 | if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) { | 598 | left = 0; |
| 611 | // Flip the framebuffer vertically | 599 | top = 0; |
| 612 | left = texcoords.right; | 600 | right = 1; |
| 613 | right = texcoords.left; | 601 | bottom = 1; |
| 614 | } else { | 602 | } else { |
| 615 | // Other transformations are unsupported | 603 | // Apply the precomputed crop. |
| 616 | LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}", | 604 | left = crop.left; |
| 617 | framebuffer_transform_flags); | 605 | top = crop.top; |
| 618 | UNIMPLEMENTED(); | 606 | right = crop.right; |
| 619 | } | 607 | bottom = crop.bottom; |
| 620 | } | ||
| 621 | |||
| 622 | ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented"); | ||
| 623 | |||
| 624 | f32 left_start{}; | ||
| 625 | if (framebuffer_crop_rect.Top() > 0) { | ||
| 626 | left_start = static_cast<f32>(framebuffer_crop_rect.Top()) / | ||
| 627 | static_cast<f32>(framebuffer_crop_rect.Bottom()); | ||
| 628 | } | ||
| 629 | f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width); | ||
| 630 | f32 scale_v = | ||
| 631 | static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height); | ||
| 632 | |||
| 633 | if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) { | ||
| 634 | // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering | ||
| 635 | // (e.g. handheld mode) on a 1920x1080 framebuffer. | ||
| 636 | if (framebuffer_crop_rect.GetWidth() > 0) { | ||
| 637 | scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) / | ||
| 638 | static_cast<f32>(screen_info.texture.width); | ||
| 639 | } | ||
| 640 | if (framebuffer_crop_rect.GetHeight() > 0) { | ||
| 641 | scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) / | ||
| 642 | static_cast<f32>(screen_info.texture.height); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa && | ||
| 646 | !screen_info.was_accelerated) { | ||
| 647 | scale_u /= Settings::values.resolution_info.up_factor; | ||
| 648 | scale_v /= Settings::values.resolution_info.up_factor; | ||
| 649 | } | 608 | } |
| 650 | 609 | ||
| 610 | // Map the coordinates to the screen. | ||
| 651 | const auto& screen = layout.screen; | 611 | const auto& screen = layout.screen; |
| 612 | const auto x = screen.left; | ||
| 613 | const auto y = screen.top; | ||
| 614 | const auto w = screen.GetWidth(); | ||
| 615 | const auto h = screen.GetHeight(); | ||
| 616 | |||
| 652 | const std::array vertices = { | 617 | const std::array vertices = { |
| 653 | ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u, | 618 | ScreenRectVertex(x, y, left, top), |
| 654 | left_start + left * scale_v), | 619 | ScreenRectVertex(x + w, y, right, top), |
| 655 | ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u, | 620 | ScreenRectVertex(x, y + h, left, bottom), |
| 656 | left_start + left * scale_v), | 621 | ScreenRectVertex(x + w, y + h, right, bottom), |
| 657 | ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u, | ||
| 658 | left_start + right * scale_v), | ||
| 659 | ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u, | ||
| 660 | left_start + right * scale_v), | ||
| 661 | }; | 622 | }; |
| 662 | glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); | 623 | glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); |
| 663 | 624 | ||
| @@ -701,7 +662,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 701 | // program_manager.RestoreGuestPipeline(); | 662 | // program_manager.RestoreGuestPipeline(); |
| 702 | } | 663 | } |
| 703 | 664 | ||
| 704 | void RendererOpenGL::RenderScreenshot() { | 665 | void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) { |
| 705 | if (!renderer_settings.screenshot_requested) { | 666 | if (!renderer_settings.screenshot_requested) { |
| 706 | return; | 667 | return; |
| 707 | } | 668 | } |
| @@ -723,7 +684,7 @@ void RendererOpenGL::RenderScreenshot() { | |||
| 723 | glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height); | 684 | glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height); |
| 724 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); | 685 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); |
| 725 | 686 | ||
| 726 | DrawScreen(layout); | 687 | DrawScreen(framebuffer, layout); |
| 727 | 688 | ||
| 728 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); | 689 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); |
| 729 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); | 690 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 18699610a..cde8c5702 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -50,11 +50,10 @@ struct TextureInfo { | |||
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | /// Structure used for storing information about the display target for the Switch screen | 52 | /// Structure used for storing information about the display target for the Switch screen |
| 53 | struct ScreenInfo { | 53 | struct FramebufferTextureInfo { |
| 54 | GLuint display_texture{}; | 54 | GLuint display_texture{}; |
| 55 | bool was_accelerated = false; | 55 | u32 width; |
| 56 | const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f}; | 56 | u32 height; |
| 57 | TextureInfo texture; | ||
| 58 | }; | 57 | }; |
| 59 | 58 | ||
| 60 | class RendererOpenGL final : public VideoCore::RendererBase { | 59 | class RendererOpenGL final : public VideoCore::RendererBase { |
| @@ -81,23 +80,18 @@ private: | |||
| 81 | 80 | ||
| 82 | void AddTelemetryFields(); | 81 | void AddTelemetryFields(); |
| 83 | 82 | ||
| 84 | void ConfigureFramebufferTexture(TextureInfo& texture, | 83 | void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer); |
| 85 | const Tegra::FramebufferConfig& framebuffer); | ||
| 86 | 84 | ||
| 87 | /// Draws the emulated screens to the emulator window. | 85 | /// Draws the emulated screens to the emulator window. |
| 88 | void DrawScreen(const Layout::FramebufferLayout& layout); | 86 | void DrawScreen(const Tegra::FramebufferConfig& framebuffer, |
| 87 | const Layout::FramebufferLayout& layout); | ||
| 89 | 88 | ||
| 90 | void RenderScreenshot(); | 89 | void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer); |
| 91 | 90 | ||
| 92 | /// Loads framebuffer from emulated memory into the active OpenGL texture. | 91 | /// Loads framebuffer from emulated memory into the active OpenGL texture. |
| 93 | void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); | 92 | FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); |
| 94 | 93 | ||
| 95 | /// Fills active OpenGL texture with the given RGB color.Since the color is solid, the texture | 94 | FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer); |
| 96 | /// can be 1x1 but will stretch across whatever it's rendered on. | ||
| 97 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, | ||
| 98 | const TextureInfo& texture); | ||
| 99 | |||
| 100 | void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer); | ||
| 101 | 95 | ||
| 102 | Core::TelemetrySession& telemetry_session; | 96 | Core::TelemetrySession& telemetry_session; |
| 103 | Core::Frontend::EmuWindow& emu_window; | 97 | Core::Frontend::EmuWindow& emu_window; |
| @@ -126,7 +120,7 @@ private: | |||
| 126 | GLuint64EXT vertex_buffer_address = 0; | 120 | GLuint64EXT vertex_buffer_address = 0; |
| 127 | 121 | ||
| 128 | /// Display information for Switch screen | 122 | /// Display information for Switch screen |
| 129 | ScreenInfo screen_info; | 123 | TextureInfo framebuffer_texture; |
| 130 | OGLTexture aa_texture; | 124 | OGLTexture aa_texture; |
| 131 | OGLFramebuffer aa_framebuffer; | 125 | OGLFramebuffer aa_framebuffer; |
| 132 | 126 | ||
| @@ -145,12 +139,6 @@ private: | |||
| 145 | 139 | ||
| 146 | /// OpenGL framebuffer data | 140 | /// OpenGL framebuffer data |
| 147 | std::vector<u8> gl_framebuffer_data; | 141 | std::vector<u8> gl_framebuffer_data; |
| 148 | |||
| 149 | /// Used for transforming the framebuffer orientation | ||
| 150 | Service::android::BufferTransformFlags framebuffer_transform_flags{}; | ||
| 151 | Common::Rectangle<int> framebuffer_crop_rect; | ||
| 152 | u32 framebuffer_width; | ||
| 153 | u32 framebuffer_height; | ||
| 154 | }; | 142 | }; |
| 155 | 143 | ||
| 156 | } // namespace OpenGL | 144 | } // namespace OpenGL |