summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/fermi_2d.cpp10
-rw-r--r--src/video_core/engines/fermi_2d.h44
-rw-r--r--src/video_core/rasterizer_interface.h3
-rw-r--r--src/video_core/renderer_opengl/gl_framebuffer_cache.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp54
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h6
-rw-r--r--src/video_core/texture_cache/surface_base.h15
-rw-r--r--src/video_core/texture_cache/surface_params.h14
-rw-r--r--src/video_core/texture_cache/texture_cache.h40
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
14namespace Tegra { 15namespace 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
124private: 146private:
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
697bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, 697bool 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
379CachedSurfaceView::~CachedSurfaceView() = default; 379CachedSurfaceView::~CachedSurfaceView() = default;
380 380
381void CachedSurfaceView::Attach(GLenum attachment) const { 381void 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
463void TextureCacheOpenGL::ImageBlit(Surface src_surface, Surface dst_surface, 463void 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
144private: 144private:
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};