diff options
| -rw-r--r-- | src/video_core/engines/fermi_2d.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/engines/fermi_2d.h | 44 | ||||
| -rw-r--r-- | src/video_core/rasterizer_interface.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_framebuffer_cache.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 54 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 6 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 15 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.h | 14 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 40 |
11 files changed, 125 insertions, 77 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 55966eef1..d63b82838 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/math_util.h" | ||
| 8 | #include "video_core/engines/fermi_2d.h" | 7 | #include "video_core/engines/fermi_2d.h" |
| 9 | #include "video_core/memory_manager.h" | 8 | #include "video_core/memory_manager.h" |
| 10 | #include "video_core/rasterizer_interface.h" | 9 | #include "video_core/rasterizer_interface.h" |
| @@ -35,7 +34,7 @@ void Fermi2D::HandleSurfaceCopy() { | |||
| 35 | static_cast<u32>(regs.operation)); | 34 | static_cast<u32>(regs.operation)); |
| 36 | 35 | ||
| 37 | // TODO(Subv): Only raw copies are implemented. | 36 | // TODO(Subv): Only raw copies are implemented. |
| 38 | ASSERT(regs.operation == Regs::Operation::SrcCopy); | 37 | ASSERT(regs.operation == Operation::SrcCopy); |
| 39 | 38 | ||
| 40 | const u32 src_blit_x1{static_cast<u32>(regs.blit_src_x >> 32)}; | 39 | const u32 src_blit_x1{static_cast<u32>(regs.blit_src_x >> 32)}; |
| 41 | const u32 src_blit_y1{static_cast<u32>(regs.blit_src_y >> 32)}; | 40 | const u32 src_blit_y1{static_cast<u32>(regs.blit_src_y >> 32)}; |
| @@ -48,8 +47,13 @@ void Fermi2D::HandleSurfaceCopy() { | |||
| 48 | const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, | 47 | const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, |
| 49 | regs.blit_dst_x + regs.blit_dst_width, | 48 | regs.blit_dst_x + regs.blit_dst_width, |
| 50 | regs.blit_dst_y + regs.blit_dst_height}; | 49 | regs.blit_dst_y + regs.blit_dst_height}; |
| 50 | Config copy_config; | ||
| 51 | copy_config.operation = regs.operation; | ||
| 52 | copy_config.filter = regs.blit_control.filter; | ||
| 53 | copy_config.src_rect = src_rect; | ||
| 54 | copy_config.dst_rect = dst_rect; | ||
| 51 | 55 | ||
| 52 | if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, src_rect, dst_rect)) { | 56 | if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { |
| 53 | UNIMPLEMENTED(); | 57 | UNIMPLEMENTED(); |
| 54 | } | 58 | } |
| 55 | } | 59 | } |
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 3d28afa91..0a4c7c5ad 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/math_util.h" | ||
| 12 | #include "video_core/gpu.h" | 13 | #include "video_core/gpu.h" |
| 13 | 14 | ||
| 14 | namespace Tegra { | 15 | namespace Tegra { |
| @@ -38,6 +39,26 @@ public: | |||
| 38 | /// Write the value to the register identified by method. | 39 | /// Write the value to the register identified by method. |
| 39 | void CallMethod(const GPU::MethodCall& method_call); | 40 | void CallMethod(const GPU::MethodCall& method_call); |
| 40 | 41 | ||
| 42 | enum class Origin : u32 { | ||
| 43 | Center = 0, | ||
| 44 | Corner = 1, | ||
| 45 | }; | ||
| 46 | |||
| 47 | enum class Filter : u32 { | ||
| 48 | PointSample = 0, // Nearest | ||
| 49 | Linear = 1, | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum class Operation : u32 { | ||
| 53 | SrcCopyAnd = 0, | ||
| 54 | ROPAnd = 1, | ||
| 55 | Blend = 2, | ||
| 56 | SrcCopy = 3, | ||
| 57 | ROP = 4, | ||
| 58 | SrcCopyPremult = 5, | ||
| 59 | BlendPremult = 6, | ||
| 60 | }; | ||
| 61 | |||
| 41 | struct Regs { | 62 | struct Regs { |
| 42 | static constexpr std::size_t NUM_REGS = 0x258; | 63 | static constexpr std::size_t NUM_REGS = 0x258; |
| 43 | 64 | ||
| @@ -76,16 +97,6 @@ public: | |||
| 76 | }; | 97 | }; |
| 77 | static_assert(sizeof(Surface) == 0x28, "Surface has incorrect size"); | 98 | static_assert(sizeof(Surface) == 0x28, "Surface has incorrect size"); |
| 78 | 99 | ||
| 79 | enum class Operation : u32 { | ||
| 80 | SrcCopyAnd = 0, | ||
| 81 | ROPAnd = 1, | ||
| 82 | Blend = 2, | ||
| 83 | SrcCopy = 3, | ||
| 84 | ROP = 4, | ||
| 85 | SrcCopyPremult = 5, | ||
| 86 | BlendPremult = 6, | ||
| 87 | }; | ||
| 88 | |||
| 89 | union { | 100 | union { |
| 90 | struct { | 101 | struct { |
| 91 | INSERT_PADDING_WORDS(0x80); | 102 | INSERT_PADDING_WORDS(0x80); |
| @@ -102,7 +113,11 @@ public: | |||
| 102 | 113 | ||
| 103 | INSERT_PADDING_WORDS(0x177); | 114 | INSERT_PADDING_WORDS(0x177); |
| 104 | 115 | ||
| 105 | u32 blit_control; | 116 | union { |
| 117 | u32 raw; | ||
| 118 | BitField<0, 1, Origin> origin; | ||
| 119 | BitField<4, 1, Filter> filter; | ||
| 120 | } blit_control; | ||
| 106 | 121 | ||
| 107 | INSERT_PADDING_WORDS(0x8); | 122 | INSERT_PADDING_WORDS(0x8); |
| 108 | 123 | ||
| @@ -121,6 +136,13 @@ public: | |||
| 121 | }; | 136 | }; |
| 122 | } regs{}; | 137 | } regs{}; |
| 123 | 138 | ||
| 139 | struct Config { | ||
| 140 | Operation operation; | ||
| 141 | Filter filter; | ||
| 142 | Common::Rectangle<u32> src_rect; | ||
| 143 | Common::Rectangle<u32> dst_rect; | ||
| 144 | }; | ||
| 145 | |||
| 124 | private: | 146 | private: |
| 125 | VideoCore::RasterizerInterface& rasterizer; | 147 | VideoCore::RasterizerInterface& rasterizer; |
| 126 | MemoryManager& memory_manager; | 148 | MemoryManager& memory_manager; |
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 3c18d3b1f..6007e8c2e 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -52,8 +52,7 @@ public: | |||
| 52 | /// Attempt to use a faster method to perform a surface copy | 52 | /// Attempt to use a faster method to perform a surface copy |
| 53 | virtual bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, | 53 | virtual bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, |
| 54 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, | 54 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, |
| 55 | const Common::Rectangle<u32>& src_rect, | 55 | const Tegra::Engines::Fermi2D::Config& copy_config) { |
| 56 | const Common::Rectangle<u32>& dst_rect) { | ||
| 57 | return false; | 56 | return false; |
| 58 | } | 57 | } |
| 59 | 58 | ||
diff --git a/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp b/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp index bb9f9b81f..7c926bd48 100644 --- a/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp | |||
| @@ -37,7 +37,7 @@ OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheK | |||
| 37 | 37 | ||
| 38 | if (key.is_single_buffer) { | 38 | if (key.is_single_buffer) { |
| 39 | if (key.color_attachments[0] != GL_NONE && key.colors[0]) { | 39 | if (key.color_attachments[0] != GL_NONE && key.colors[0]) { |
| 40 | key.colors[0]->Attach(key.color_attachments[0]); | 40 | key.colors[0]->Attach(key.color_attachments[0], GL_DRAW_FRAMEBUFFER); |
| 41 | glDrawBuffer(key.color_attachments[0]); | 41 | glDrawBuffer(key.color_attachments[0]); |
| 42 | } else { | 42 | } else { |
| 43 | glDrawBuffer(GL_NONE); | 43 | glDrawBuffer(GL_NONE); |
| @@ -45,14 +45,16 @@ OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheK | |||
| 45 | } else { | 45 | } else { |
| 46 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { | 46 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { |
| 47 | if (key.colors[index]) { | 47 | if (key.colors[index]) { |
| 48 | key.colors[index]->Attach(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index)); | 48 | key.colors[index]->Attach(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), |
| 49 | GL_DRAW_FRAMEBUFFER); | ||
| 49 | } | 50 | } |
| 50 | } | 51 | } |
| 51 | glDrawBuffers(key.colors_count, key.color_attachments.data()); | 52 | glDrawBuffers(key.colors_count, key.color_attachments.data()); |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | if (key.zeta) { | 55 | if (key.zeta) { |
| 55 | key.zeta->Attach(key.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT); | 56 | key.zeta->Attach(key.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, |
| 57 | GL_DRAW_FRAMEBUFFER); | ||
| 56 | } | 58 | } |
| 57 | 59 | ||
| 58 | return framebuffer; | 60 | return framebuffer; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4f7eeb22c..d613cb1dc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -696,10 +696,9 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { | |||
| 696 | 696 | ||
| 697 | bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, | 697 | bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, |
| 698 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, | 698 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, |
| 699 | const Common::Rectangle<u32>& src_rect, | 699 | const Tegra::Engines::Fermi2D::Config& copy_config) { |
| 700 | const Common::Rectangle<u32>& dst_rect) { | ||
| 701 | MICROPROFILE_SCOPE(OpenGL_Blits); | 700 | MICROPROFILE_SCOPE(OpenGL_Blits); |
| 702 | texture_cache.DoFermiCopy(src, dst, src_rect, dst_rect); | 701 | texture_cache.DoFermiCopy(src, dst, copy_config); |
| 703 | return true; | 702 | return true; |
| 704 | } | 703 | } |
| 705 | 704 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 64c27660f..33582ac42 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -67,8 +67,7 @@ public: | |||
| 67 | void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; | 67 | void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; |
| 68 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, | 68 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, |
| 69 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, | 69 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, |
| 70 | const Common::Rectangle<u32>& src_rect, | 70 | const Tegra::Engines::Fermi2D::Config& copy_config) override; |
| 71 | const Common::Rectangle<u32>& dst_rect) override; | ||
| 72 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 71 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, |
| 73 | u32 pixel_stride) override; | 72 | u32 pixel_stride) override; |
| 74 | bool AccelerateDrawBatch(bool is_indexed) override; | 73 | bool AccelerateDrawBatch(bool is_indexed) override; |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 197c9f02c..9e9734f9e 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -378,26 +378,26 @@ CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& p | |||
| 378 | 378 | ||
| 379 | CachedSurfaceView::~CachedSurfaceView() = default; | 379 | CachedSurfaceView::~CachedSurfaceView() = default; |
| 380 | 380 | ||
| 381 | void CachedSurfaceView::Attach(GLenum attachment) const { | 381 | void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { |
| 382 | ASSERT(params.num_layers == 1 && params.num_levels == 1); | 382 | ASSERT(params.num_layers == 1 && params.num_levels == 1); |
| 383 | 383 | ||
| 384 | const auto& owner_params = surface.GetSurfaceParams(); | 384 | const auto& owner_params = surface.GetSurfaceParams(); |
| 385 | 385 | ||
| 386 | switch (owner_params.target) { | 386 | switch (owner_params.target) { |
| 387 | case SurfaceTarget::Texture1D: | 387 | case SurfaceTarget::Texture1D: |
| 388 | glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, attachment, surface.GetTarget(), | 388 | glFramebufferTexture1D(target, attachment, surface.GetTarget(), surface.GetTexture(), |
| 389 | surface.GetTexture(), params.base_level); | 389 | params.base_level); |
| 390 | break; | 390 | break; |
| 391 | case SurfaceTarget::Texture2D: | 391 | case SurfaceTarget::Texture2D: |
| 392 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, surface.GetTarget(), | 392 | glFramebufferTexture2D(target, attachment, surface.GetTarget(), surface.GetTexture(), |
| 393 | surface.GetTexture(), params.base_level); | 393 | params.base_level); |
| 394 | break; | 394 | break; |
| 395 | case SurfaceTarget::Texture1DArray: | 395 | case SurfaceTarget::Texture1DArray: |
| 396 | case SurfaceTarget::Texture2DArray: | 396 | case SurfaceTarget::Texture2DArray: |
| 397 | case SurfaceTarget::TextureCubemap: | 397 | case SurfaceTarget::TextureCubemap: |
| 398 | case SurfaceTarget::TextureCubeArray: | 398 | case SurfaceTarget::TextureCubeArray: |
| 399 | glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, surface.GetTexture(), | 399 | glFramebufferTextureLayer(target, attachment, surface.GetTexture(), params.base_level, |
| 400 | params.base_level, params.base_layer); | 400 | params.base_layer); |
| 401 | break; | 401 | break; |
| 402 | default: | 402 | default: |
| 403 | UNIMPLEMENTED(); | 403 | UNIMPLEMENTED(); |
| @@ -460,11 +460,10 @@ void TextureCacheOpenGL::ImageCopy(Surface src_surface, Surface dst_surface, | |||
| 460 | copy_params.depth); | 460 | copy_params.depth); |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | void TextureCacheOpenGL::ImageBlit(Surface src_surface, Surface dst_surface, | 463 | void TextureCacheOpenGL::ImageBlit(View src_view, View dst_view, |
| 464 | const Common::Rectangle<u32>& src_rect, | 464 | const Tegra::Engines::Fermi2D::Config& copy_config) { |
| 465 | const Common::Rectangle<u32>& dst_rect) { | 465 | const auto& src_params{src_view->GetSurfaceParams()}; |
| 466 | const auto& src_params{src_surface->GetSurfaceParams()}; | 466 | const auto& dst_params{dst_view->GetSurfaceParams()}; |
| 467 | const auto& dst_params{dst_surface->GetSurfaceParams()}; | ||
| 468 | 467 | ||
| 469 | OpenGLState prev_state{OpenGLState::GetCurState()}; | 468 | OpenGLState prev_state{OpenGLState::GetCurState()}; |
| 470 | SCOPE_EXIT({ prev_state.Apply(); }); | 469 | SCOPE_EXIT({ prev_state.Apply(); }); |
| @@ -476,51 +475,46 @@ void TextureCacheOpenGL::ImageBlit(Surface src_surface, Surface dst_surface, | |||
| 476 | 475 | ||
| 477 | u32 buffers{}; | 476 | u32 buffers{}; |
| 478 | 477 | ||
| 479 | UNIMPLEMENTED_IF(src_params.target != SurfaceTarget::Texture2D); | 478 | UNIMPLEMENTED_IF(src_params.target == SurfaceTarget::Texture3D); |
| 480 | UNIMPLEMENTED_IF(dst_params.target != SurfaceTarget::Texture2D); | 479 | UNIMPLEMENTED_IF(dst_params.target == SurfaceTarget::Texture3D); |
| 481 | |||
| 482 | const GLuint src_texture{src_surface->GetTexture()}; | ||
| 483 | const GLuint dst_texture{dst_surface->GetTexture()}; | ||
| 484 | 480 | ||
| 485 | if (src_params.type == SurfaceType::ColorTexture) { | 481 | if (src_params.type == SurfaceType::ColorTexture) { |
| 486 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | 482 | src_view->Attach(GL_COLOR_ATTACHMENT0, GL_READ_FRAMEBUFFER); |
| 487 | src_texture, 0); | ||
| 488 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | 483 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, |
| 489 | 0); | 484 | 0); |
| 490 | 485 | ||
| 491 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | 486 | dst_view->Attach(GL_COLOR_ATTACHMENT0, GL_DRAW_FRAMEBUFFER); |
| 492 | dst_texture, 0); | ||
| 493 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | 487 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, |
| 494 | 0); | 488 | 0); |
| 495 | 489 | ||
| 496 | buffers = GL_COLOR_BUFFER_BIT; | 490 | buffers = GL_COLOR_BUFFER_BIT; |
| 497 | } else if (src_params.type == SurfaceType::Depth) { | 491 | } else if (src_params.type == SurfaceType::Depth) { |
| 498 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | 492 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |
| 499 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, src_texture, | 493 | src_view->Attach(GL_DEPTH_ATTACHMENT, GL_READ_FRAMEBUFFER); |
| 500 | 0); | ||
| 501 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | 494 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); |
| 502 | 495 | ||
| 503 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | 496 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |
| 504 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dst_texture, | 497 | dst_view->Attach(GL_DEPTH_ATTACHMENT, GL_DRAW_FRAMEBUFFER); |
| 505 | 0); | ||
| 506 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | 498 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); |
| 507 | 499 | ||
| 508 | buffers = GL_DEPTH_BUFFER_BIT; | 500 | buffers = GL_DEPTH_BUFFER_BIT; |
| 509 | } else if (src_params.type == SurfaceType::DepthStencil) { | 501 | } else if (src_params.type == SurfaceType::DepthStencil) { |
| 510 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | 502 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |
| 511 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | 503 | src_view->Attach(GL_DEPTH_STENCIL_ATTACHMENT, GL_READ_FRAMEBUFFER); |
| 512 | src_texture, 0); | ||
| 513 | 504 | ||
| 514 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | 505 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |
| 515 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | 506 | dst_view->Attach(GL_DEPTH_STENCIL_ATTACHMENT, GL_DRAW_FRAMEBUFFER); |
| 516 | dst_texture, 0); | ||
| 517 | 507 | ||
| 518 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | 508 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; |
| 519 | } | 509 | } |
| 520 | 510 | ||
| 511 | const Common::Rectangle<u32>& src_rect = copy_config.src_rect; | ||
| 512 | const Common::Rectangle<u32>& dst_rect = copy_config.dst_rect; | ||
| 513 | const bool is_linear = copy_config.filter == Tegra::Engines::Fermi2D::Filter::Linear; | ||
| 514 | |||
| 521 | glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left, | 515 | glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left, |
| 522 | dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, | 516 | dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, |
| 523 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | 517 | is_linear ? GL_LINEAR : GL_NEAREST); |
| 524 | } | 518 | } |
| 525 | 519 | ||
| 526 | } // namespace OpenGL | 520 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 0ba42dbab..0b333e9e3 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -73,7 +73,7 @@ public: | |||
| 73 | ~CachedSurfaceView(); | 73 | ~CachedSurfaceView(); |
| 74 | 74 | ||
| 75 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER | 75 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER |
| 76 | void Attach(GLenum attachment) const; | 76 | void Attach(GLenum attachment, GLenum target) const; |
| 77 | 77 | ||
| 78 | GLuint GetTexture() { | 78 | GLuint GetTexture() { |
| 79 | if (is_proxy) { | 79 | if (is_proxy) { |
| @@ -138,8 +138,8 @@ protected: | |||
| 138 | void ImageCopy(Surface src_surface, Surface dst_surface, | 138 | void ImageCopy(Surface src_surface, Surface dst_surface, |
| 139 | const VideoCommon::CopyParams& copy_params) override; | 139 | const VideoCommon::CopyParams& copy_params) override; |
| 140 | 140 | ||
| 141 | void ImageBlit(Surface src_surface, Surface dst_surface, const Common::Rectangle<u32>& src_rect, | 141 | void ImageBlit(View src_view, View dst_view, |
| 142 | const Common::Rectangle<u32>& dst_rect) override; | 142 | const Tegra::Engines::Fermi2D::Config& copy_config) override; |
| 143 | 143 | ||
| 144 | private: | 144 | private: |
| 145 | OGLFramebuffer src_framebuffer; | 145 | OGLFramebuffer src_framebuffer; |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index cb7f22706..a3dd1c607 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -126,14 +126,19 @@ public: | |||
| 126 | return MatchStructureResult::None; | 126 | return MatchStructureResult::None; |
| 127 | } | 127 | } |
| 128 | // Tiled surface | 128 | // Tiled surface |
| 129 | if (std::tie(params.height, params.depth, params.block_width, params.block_height, | 129 | if (std::tie(params.depth, params.block_width, params.block_height, params.block_depth, |
| 130 | params.block_depth, params.tile_width_spacing, params.num_levels) == | 130 | params.tile_width_spacing, params.num_levels) == |
| 131 | std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, | 131 | std::tie(rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, |
| 132 | rhs.tile_width_spacing, rhs.num_levels)) { | 132 | rhs.tile_width_spacing, rhs.num_levels)) { |
| 133 | if (params.width == rhs.width) { | 133 | if (std::tie(params.width, params.height) == std::tie(rhs.width, rhs.height)) { |
| 134 | return MatchStructureResult::FullMatch; | 134 | return MatchStructureResult::FullMatch; |
| 135 | } | 135 | } |
| 136 | if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { | 136 | const u32 ws = SurfaceParams::ConvertWidth(rhs.GetBlockAlignedWidth(), |
| 137 | params.pixel_format, rhs.pixel_format); | ||
| 138 | const u32 hs = | ||
| 139 | SurfaceParams::ConvertHeight(rhs.height, params.pixel_format, rhs.pixel_format); | ||
| 140 | const u32 w1 = params.GetBlockAlignedWidth(); | ||
| 141 | if (std::tie(w1, params.height) == std::tie(ws, hs)) { | ||
| 137 | return MatchStructureResult::SemiMatch; | 142 | return MatchStructureResult::SemiMatch; |
| 138 | } | 143 | } |
| 139 | } | 144 | } |
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index b3082173f..13a08a60f 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h | |||
| @@ -126,6 +126,20 @@ public: | |||
| 126 | /// Returns the size of a layer in bytes in host memory for a given mipmap level. | 126 | /// Returns the size of a layer in bytes in host memory for a given mipmap level. |
| 127 | std::size_t GetHostLayerSize(u32 level) const; | 127 | std::size_t GetHostLayerSize(u32 level) const; |
| 128 | 128 | ||
| 129 | static u32 ConvertWidth(u32 width, VideoCore::Surface::PixelFormat pixel_format_from, | ||
| 130 | VideoCore::Surface::PixelFormat pixel_format_to) { | ||
| 131 | const u32 bw1 = VideoCore::Surface::GetDefaultBlockWidth(pixel_format_from); | ||
| 132 | const u32 bw2 = VideoCore::Surface::GetDefaultBlockWidth(pixel_format_to); | ||
| 133 | return (width * bw2 + bw1 - 1) / bw1; | ||
| 134 | } | ||
| 135 | |||
| 136 | static u32 ConvertHeight(u32 height, VideoCore::Surface::PixelFormat pixel_format_from, | ||
| 137 | VideoCore::Surface::PixelFormat pixel_format_to) { | ||
| 138 | const u32 bh1 = VideoCore::Surface::GetDefaultBlockHeight(pixel_format_from); | ||
| 139 | const u32 bh2 = VideoCore::Surface::GetDefaultBlockHeight(pixel_format_to); | ||
| 140 | return (height * bh2 + bh1 - 1) / bh1; | ||
| 141 | } | ||
| 142 | |||
| 129 | /// Returns the default block width. | 143 | /// Returns the default block width. |
| 130 | u32 GetDefaultBlockWidth() const { | 144 | u32 GetDefaultBlockWidth() const { |
| 131 | return VideoCore::Surface::GetDefaultBlockWidth(pixel_format); | 145 | return VideoCore::Surface::GetDefaultBlockWidth(pixel_format); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 85c9160e0..593ceeaf6 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -141,11 +141,6 @@ public: | |||
| 141 | return {}; | 141 | return {}; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | if (regs.color_mask[index].raw == 0) { | ||
| 145 | SetEmptyColorBuffer(index); | ||
| 146 | return {}; | ||
| 147 | } | ||
| 148 | |||
| 149 | const auto& config{regs.rt[index]}; | 144 | const auto& config{regs.rt[index]}; |
| 150 | const auto gpu_addr{config.Address()}; | 145 | const auto gpu_addr{config.Address()}; |
| 151 | if (!gpu_addr) { | 146 | if (!gpu_addr) { |
| @@ -192,11 +187,11 @@ public: | |||
| 192 | 187 | ||
| 193 | void DoFermiCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src_config, | 188 | void DoFermiCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src_config, |
| 194 | const Tegra::Engines::Fermi2D::Regs::Surface& dst_config, | 189 | const Tegra::Engines::Fermi2D::Regs::Surface& dst_config, |
| 195 | const Common::Rectangle<u32>& src_rect, | 190 | const Tegra::Engines::Fermi2D::Config& copy_config) { |
| 196 | const Common::Rectangle<u32>& dst_rect) { | 191 | std::pair<TSurface, TView> dst_surface = GetFermiSurface(dst_config); |
| 197 | TSurface dst_surface = GetFermiSurface(dst_config); | 192 | std::pair<TSurface, TView> src_surface = GetFermiSurface(src_config); |
| 198 | ImageBlit(GetFermiSurface(src_config), dst_surface, src_rect, dst_rect); | 193 | ImageBlit(src_surface.second, dst_surface.second, copy_config); |
| 199 | dst_surface->MarkAsModified(true, Tick()); | 194 | dst_surface.first->MarkAsModified(true, Tick()); |
| 200 | } | 195 | } |
| 201 | 196 | ||
| 202 | TSurface TryFindFramebufferSurface(const u8* host_ptr) { | 197 | TSurface TryFindFramebufferSurface(const u8* host_ptr) { |
| @@ -234,8 +229,8 @@ protected: | |||
| 234 | virtual void ImageCopy(TSurface src_surface, TSurface dst_surface, | 229 | virtual void ImageCopy(TSurface src_surface, TSurface dst_surface, |
| 235 | const CopyParams& copy_params) = 0; | 230 | const CopyParams& copy_params) = 0; |
| 236 | 231 | ||
| 237 | virtual void ImageBlit(TSurface src, TSurface dst, const Common::Rectangle<u32>& src_rect, | 232 | virtual void ImageBlit(TView src_view, TView dst_view, |
| 238 | const Common::Rectangle<u32>& dst_rect) = 0; | 233 | const Tegra::Engines::Fermi2D::Config& copy_config) = 0; |
| 239 | 234 | ||
| 240 | void Register(TSurface surface) { | 235 | void Register(TSurface surface) { |
| 241 | std::lock_guard lock{mutex}; | 236 | std::lock_guard lock{mutex}; |
| @@ -282,10 +277,11 @@ protected: | |||
| 282 | return new_surface; | 277 | return new_surface; |
| 283 | } | 278 | } |
| 284 | 279 | ||
| 285 | TSurface GetFermiSurface(const Tegra::Engines::Fermi2D::Regs::Surface& config) { | 280 | std::pair<TSurface, TView> GetFermiSurface( |
| 281 | const Tegra::Engines::Fermi2D::Regs::Surface& config) { | ||
| 286 | SurfaceParams params = SurfaceParams::CreateForFermiCopySurface(config); | 282 | SurfaceParams params = SurfaceParams::CreateForFermiCopySurface(config); |
| 287 | const GPUVAddr gpu_addr = config.Address(); | 283 | const GPUVAddr gpu_addr = config.Address(); |
| 288 | return GetSurface(gpu_addr, params, true).first; | 284 | return GetSurface(gpu_addr, params, true); |
| 289 | } | 285 | } |
| 290 | 286 | ||
| 291 | Core::System& system; | 287 | Core::System& system; |
| @@ -551,7 +547,21 @@ private: | |||
| 551 | if (view.has_value()) { | 547 | if (view.has_value()) { |
| 552 | const bool is_mirage = !current_surface->MatchFormat(params.pixel_format); | 548 | const bool is_mirage = !current_surface->MatchFormat(params.pixel_format); |
| 553 | if (is_mirage) { | 549 | if (is_mirage) { |
| 554 | LOG_CRITICAL(HW_GPU, "Mirage View Unsupported"); | 550 | // On a mirage view, we need to recreate the surface under this new view |
| 551 | // and then obtain a view again. | ||
| 552 | SurfaceParams new_params = current_surface->GetSurfaceParams(); | ||
| 553 | const u32 wh = SurfaceParams::ConvertWidth( | ||
| 554 | new_params.width, new_params.pixel_format, params.pixel_format); | ||
| 555 | const u32 hh = SurfaceParams::ConvertHeight( | ||
| 556 | new_params.height, new_params.pixel_format, params.pixel_format); | ||
| 557 | new_params.width = wh; | ||
| 558 | new_params.height = hh; | ||
| 559 | new_params.pixel_format = params.pixel_format; | ||
| 560 | std::pair<TSurface, TView> pair = RebuildSurface(current_surface, new_params); | ||
| 561 | std::optional<TView> mirage_view = | ||
| 562 | pair.first->EmplaceView(params, gpu_addr, candidate_size); | ||
| 563 | if (mirage_view) | ||
| 564 | return {pair.first, *mirage_view}; | ||
| 555 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); | 565 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
| 556 | } | 566 | } |
| 557 | return {current_surface, *view}; | 567 | return {current_surface, *view}; |