summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/fermi_2d.cpp62
-rw-r--r--src/video_core/engines/fermi_2d.h29
-rw-r--r--src/video_core/rasterizer_interface.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp12
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp141
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h4
7 files changed, 188 insertions, 68 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 9f1533263..ec1a57226 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -21,7 +21,9 @@ void Fermi2D::CallMethod(const GPU::MethodCall& method_call) {
21 regs.reg_array[method_call.method] = method_call.argument; 21 regs.reg_array[method_call.method] = method_call.argument;
22 22
23 switch (method_call.method) { 23 switch (method_call.method) {
24 case FERMI2D_REG_INDEX(trigger): { 24 // Trigger the surface copy on the last register write. This is blit_src_y, but this is 64-bit,
25 // so trigger on the second 32-bit write.
26 case FERMI2D_REG_INDEX(blit_src_y) + 1: {
25 HandleSurfaceCopy(); 27 HandleSurfaceCopy();
26 break; 28 break;
27 } 29 }
@@ -32,57 +34,23 @@ void Fermi2D::HandleSurfaceCopy() {
32 LOG_WARNING(HW_GPU, "Requested a surface copy with operation {}", 34 LOG_WARNING(HW_GPU, "Requested a surface copy with operation {}",
33 static_cast<u32>(regs.operation)); 35 static_cast<u32>(regs.operation));
34 36
35 const GPUVAddr source = regs.src.Address();
36 const GPUVAddr dest = regs.dst.Address();
37
38 // TODO(Subv): Only same-format and same-size copies are allowed for now.
39 ASSERT(regs.src.format == regs.dst.format);
40 ASSERT(regs.src.width * regs.src.height == regs.dst.width * regs.dst.height);
41
42 // TODO(Subv): Only raw copies are implemented. 37 // TODO(Subv): Only raw copies are implemented.
43 ASSERT(regs.operation == Regs::Operation::SrcCopy); 38 ASSERT(regs.operation == Regs::Operation::SrcCopy);
44 39
45 const auto source_cpu = memory_manager.GpuToCpuAddress(source); 40 const u32 src_blit_x1{static_cast<u32>(regs.blit_src_x >> 32)};
46 const auto dest_cpu = memory_manager.GpuToCpuAddress(dest); 41 const u32 src_blit_y1{static_cast<u32>(regs.blit_src_y >> 32)};
47 ASSERT_MSG(source_cpu, "Invalid source GPU address"); 42 const u32 src_blit_x2{
48 ASSERT_MSG(dest_cpu, "Invalid destination GPU address"); 43 static_cast<u32>((regs.blit_src_x + (regs.blit_dst_width * regs.blit_du_dx)) >> 32)};
49 44 const u32 src_blit_y2{
50 u32 src_bytes_per_pixel = RenderTargetBytesPerPixel(regs.src.format); 45 static_cast<u32>((regs.blit_src_y + (regs.blit_dst_height * regs.blit_dv_dy)) >> 32)};
51 u32 dst_bytes_per_pixel = RenderTargetBytesPerPixel(regs.dst.format);
52
53 if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst)) {
54 // All copies here update the main memory, so mark all rasterizer states as invalid.
55 Core::System::GetInstance().GPU().Maxwell3D().dirty_flags.OnMemoryWrite();
56 46
57 rasterizer.FlushRegion(*source_cpu, src_bytes_per_pixel * regs.src.width * regs.src.height); 47 const MathUtil::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2};
58 // We have to invalidate the destination region to evict any outdated surfaces from the 48 const MathUtil::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y,
59 // cache. We do this before actually writing the new data because the destination address 49 regs.blit_dst_x + regs.blit_dst_width,
60 // might contain a dirty surface that will have to be written back to memory. 50 regs.blit_dst_y + regs.blit_dst_height};
61 rasterizer.InvalidateRegion(*dest_cpu,
62 dst_bytes_per_pixel * regs.dst.width * regs.dst.height);
63 51
64 if (regs.src.linear == regs.dst.linear) { 52 if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, src_rect, dst_rect)) {
65 // If the input layout and the output layout are the same, just perform a raw copy. 53 UNIMPLEMENTED();
66 ASSERT(regs.src.BlockHeight() == regs.dst.BlockHeight());
67 Memory::CopyBlock(*dest_cpu, *source_cpu,
68 src_bytes_per_pixel * regs.dst.width * regs.dst.height);
69 return;
70 }
71 u8* src_buffer = Memory::GetPointer(*source_cpu);
72 u8* dst_buffer = Memory::GetPointer(*dest_cpu);
73 if (!regs.src.linear && regs.dst.linear) {
74 // If the input is tiled and the output is linear, deswizzle the input and copy it over.
75 Texture::CopySwizzledData(regs.src.width, regs.src.height, regs.src.depth,
76 src_bytes_per_pixel, dst_bytes_per_pixel, src_buffer,
77 dst_buffer, true, regs.src.BlockHeight(),
78 regs.src.BlockDepth(), 0);
79 } else {
80 // If the input is linear and the output is tiled, swizzle the input and copy it over.
81 Texture::CopySwizzledData(regs.src.width, regs.src.height, regs.src.depth,
82 src_bytes_per_pixel, dst_bytes_per_pixel, dst_buffer,
83 src_buffer, false, regs.dst.BlockHeight(),
84 regs.dst.BlockDepth(), 0);
85 }
86 } 54 }
87} 55}
88 56
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 50009bf75..c69f74cc5 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -94,12 +94,22 @@ public:
94 94
95 Operation operation; 95 Operation operation;
96 96
97 INSERT_PADDING_WORDS(0x9); 97 INSERT_PADDING_WORDS(0x177);
98 98
99 // TODO(Subv): This is only a guess. 99 u32 blit_control;
100 u32 trigger;
101 100
102 INSERT_PADDING_WORDS(0x1A3); 101 INSERT_PADDING_WORDS(0x8);
102
103 u32 blit_dst_x;
104 u32 blit_dst_y;
105 u32 blit_dst_width;
106 u32 blit_dst_height;
107 u64 blit_du_dx;
108 u64 blit_dv_dy;
109 u64 blit_src_x;
110 u64 blit_src_y;
111
112 INSERT_PADDING_WORDS(0x21);
103 }; 113 };
104 std::array<u32, NUM_REGS> reg_array; 114 std::array<u32, NUM_REGS> reg_array;
105 }; 115 };
@@ -122,7 +132,16 @@ private:
122ASSERT_REG_POSITION(dst, 0x80); 132ASSERT_REG_POSITION(dst, 0x80);
123ASSERT_REG_POSITION(src, 0x8C); 133ASSERT_REG_POSITION(src, 0x8C);
124ASSERT_REG_POSITION(operation, 0xAB); 134ASSERT_REG_POSITION(operation, 0xAB);
125ASSERT_REG_POSITION(trigger, 0xB5); 135ASSERT_REG_POSITION(blit_control, 0x223);
136ASSERT_REG_POSITION(blit_dst_x, 0x22c);
137ASSERT_REG_POSITION(blit_dst_y, 0x22d);
138ASSERT_REG_POSITION(blit_dst_width, 0x22e);
139ASSERT_REG_POSITION(blit_dst_height, 0x22f);
140ASSERT_REG_POSITION(blit_du_dx, 0x230);
141ASSERT_REG_POSITION(blit_dv_dy, 0x232);
142ASSERT_REG_POSITION(blit_src_x, 0x234);
143ASSERT_REG_POSITION(blit_src_y, 0x236);
144
126#undef ASSERT_REG_POSITION 145#undef ASSERT_REG_POSITION
127 146
128} // namespace Tegra::Engines 147} // namespace Tegra::Engines
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 77da135a0..b2a223705 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -46,7 +46,9 @@ public:
46 46
47 /// Attempt to use a faster method to perform a surface copy 47 /// Attempt to use a faster method to perform a surface copy
48 virtual bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, 48 virtual bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
49 const Tegra::Engines::Fermi2D::Regs::Surface& dst) { 49 const Tegra::Engines::Fermi2D::Regs::Surface& dst,
50 const MathUtil::Rectangle<u32>& src_rect,
51 const MathUtil::Rectangle<u32>& dst_rect) {
50 return false; 52 return false;
51 } 53 }
52 54
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 974ca6a20..12d876120 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -778,15 +778,11 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
778} 778}
779 779
780bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, 780bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
781 const Tegra::Engines::Fermi2D::Regs::Surface& dst) { 781 const Tegra::Engines::Fermi2D::Regs::Surface& dst,
782 const MathUtil::Rectangle<u32>& src_rect,
783 const MathUtil::Rectangle<u32>& dst_rect) {
782 MICROPROFILE_SCOPE(OpenGL_Blits); 784 MICROPROFILE_SCOPE(OpenGL_Blits);
783 785 res_cache.FermiCopySurface(src, dst, src_rect, dst_rect);
784 if (Settings::values.use_accurate_gpu_emulation) {
785 // Skip the accelerated copy and perform a slow but more accurate copy
786 return false;
787 }
788
789 res_cache.FermiCopySurface(src, dst);
790 return true; 786 return true;
791} 787}
792 788
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index f3b607f4d..258d62259 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -61,7 +61,9 @@ public:
61 void InvalidateRegion(VAddr addr, u64 size) override; 61 void InvalidateRegion(VAddr addr, u64 size) override;
62 void FlushAndInvalidateRegion(VAddr addr, u64 size) override; 62 void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
63 bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, 63 bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
64 const Tegra::Engines::Fermi2D::Regs::Surface& dst) override; 64 const Tegra::Engines::Fermi2D::Regs::Surface& dst,
65 const MathUtil::Rectangle<u32>& src_rect,
66 const MathUtil::Rectangle<u32>& dst_rect) override;
65 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 67 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
66 u32 pixel_stride) override; 68 u32 pixel_stride) override;
67 bool AccelerateDrawBatch(bool is_indexed) override; 69 bool AccelerateDrawBatch(bool is_indexed) override;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index a79eee03e..f585c8884 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -1021,24 +1021,155 @@ void RasterizerCacheOpenGL::FastLayeredCopySurface(const Surface& src_surface,
1021 } 1021 }
1022} 1022}
1023 1023
1024static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
1025 const MathUtil::Rectangle<u32>& src_rect,
1026 const MathUtil::Rectangle<u32>& dst_rect, GLuint read_fb_handle,
1027 GLuint draw_fb_handle, GLenum src_attachment = 0, GLenum dst_attachment = 0,
1028 std::size_t cubemap_face = 0) {
1029
1030 const auto& src_params{src_surface->GetSurfaceParams()};
1031 const auto& dst_params{dst_surface->GetSurfaceParams()};
1032
1033 OpenGLState prev_state{OpenGLState::GetCurState()};
1034 SCOPE_EXIT({ prev_state.Apply(); });
1035
1036 OpenGLState state;
1037 state.draw.read_framebuffer = read_fb_handle;
1038 state.draw.draw_framebuffer = draw_fb_handle;
1039 state.Apply();
1040
1041 u32 buffers{};
1042
1043 if (src_params.type == SurfaceType::ColorTexture) {
1044 switch (src_params.target) {
1045 case SurfaceTarget::Texture2D:
1046 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1047 GL_TEXTURE_2D, src_surface->Texture().handle, 0);
1048 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1049 0, 0);
1050 break;
1051 case SurfaceTarget::TextureCubemap:
1052 glFramebufferTexture2D(
1053 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1054 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
1055 src_surface->Texture().handle, 0);
1056 glFramebufferTexture2D(
1057 GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
1058 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
1059 break;
1060 case SurfaceTarget::Texture2DArray:
1061 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1062 src_surface->Texture().handle, 0, 0);
1063 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
1064 break;
1065 case SurfaceTarget::Texture3D:
1066 glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1067 SurfaceTargetToGL(src_params.target),
1068 src_surface->Texture().handle, 0, 0);
1069 glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
1070 SurfaceTargetToGL(src_params.target), 0, 0, 0);
1071 break;
1072 default:
1073 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1074 GL_TEXTURE_2D, src_surface->Texture().handle, 0);
1075 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1076 0, 0);
1077 break;
1078 }
1079
1080 switch (dst_params.target) {
1081 case SurfaceTarget::Texture2D:
1082 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1083 GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
1084 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1085 0, 0);
1086 break;
1087 case SurfaceTarget::TextureCubemap:
1088 glFramebufferTexture2D(
1089 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1090 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
1091 dst_surface->Texture().handle, 0);
1092 glFramebufferTexture2D(
1093 GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
1094 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
1095 break;
1096 case SurfaceTarget::Texture2DArray:
1097 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1098 dst_surface->Texture().handle, 0, 0);
1099 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
1100 break;
1101
1102 case SurfaceTarget::Texture3D:
1103 glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1104 SurfaceTargetToGL(dst_params.target),
1105 dst_surface->Texture().handle, 0, 0);
1106 glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
1107 SurfaceTargetToGL(dst_params.target), 0, 0, 0);
1108 break;
1109 default:
1110 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1111 GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
1112 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1113 0, 0);
1114 break;
1115 }
1116
1117 buffers = GL_COLOR_BUFFER_BIT;
1118 } else if (src_params.type == SurfaceType::Depth) {
1119 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1120 GL_TEXTURE_2D, 0, 0);
1121 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
1122 src_surface->Texture().handle, 0);
1123 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
1124
1125 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1126 GL_TEXTURE_2D, 0, 0);
1127 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
1128 dst_surface->Texture().handle, 0);
1129 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
1130
1131 buffers = GL_DEPTH_BUFFER_BIT;
1132 } else if (src_params.type == SurfaceType::DepthStencil) {
1133 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
1134 GL_TEXTURE_2D, 0, 0);
1135 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1136 src_surface->Texture().handle, 0);
1137
1138 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
1139 GL_TEXTURE_2D, 0, 0);
1140 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1141 dst_surface->Texture().handle, 0);
1142
1143 buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
1144 }
1145
1146 glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
1147 dst_rect.top, dst_rect.right, dst_rect.bottom, buffers,
1148 buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST);
1149
1150 return true;
1151}
1152
1024void RasterizerCacheOpenGL::FermiCopySurface( 1153void RasterizerCacheOpenGL::FermiCopySurface(
1025 const Tegra::Engines::Fermi2D::Regs::Surface& src_config, 1154 const Tegra::Engines::Fermi2D::Regs::Surface& src_config,
1026 const Tegra::Engines::Fermi2D::Regs::Surface& dst_config) { 1155 const Tegra::Engines::Fermi2D::Regs::Surface& dst_config,
1156 const MathUtil::Rectangle<u32>& src_rect, const MathUtil::Rectangle<u32>& dst_rect) {
1027 1157
1028 const auto& src_params = SurfaceParams::CreateForFermiCopySurface(src_config); 1158 const auto& src_params = SurfaceParams::CreateForFermiCopySurface(src_config);
1029 const auto& dst_params = SurfaceParams::CreateForFermiCopySurface(dst_config); 1159 const auto& dst_params = SurfaceParams::CreateForFermiCopySurface(dst_config);
1030 1160
1031 ASSERT(src_params.width == dst_params.width);
1032 ASSERT(src_params.height == dst_params.height);
1033 ASSERT(src_params.pixel_format == dst_params.pixel_format); 1161 ASSERT(src_params.pixel_format == dst_params.pixel_format);
1034 ASSERT(src_params.block_height == dst_params.block_height); 1162 ASSERT(src_params.block_height == dst_params.block_height);
1035 ASSERT(src_params.is_tiled == dst_params.is_tiled); 1163 ASSERT(src_params.is_tiled == dst_params.is_tiled);
1036 ASSERT(src_params.depth == dst_params.depth); 1164 ASSERT(src_params.depth == dst_params.depth);
1037 ASSERT(src_params.depth == 1); // Currently, FastCopySurface only works with 2D surfaces
1038 ASSERT(src_params.target == dst_params.target); 1165 ASSERT(src_params.target == dst_params.target);
1039 ASSERT(src_params.rt.index == dst_params.rt.index); 1166 ASSERT(src_params.rt.index == dst_params.rt.index);
1040 1167
1041 FastCopySurface(GetSurface(src_params, true), GetSurface(dst_params, false)); 1168 auto src_surface = GetSurface(src_params, true);
1169 auto dst_surface = GetSurface(dst_params, true);
1170
1171 BlitSurface(src_surface, dst_surface, src_rect, dst_rect, read_framebuffer.handle,
1172 draw_framebuffer.handle);
1042} 1173}
1043 1174
1044void RasterizerCacheOpenGL::AccurateCopySurface(const Surface& src_surface, 1175void RasterizerCacheOpenGL::AccurateCopySurface(const Surface& src_surface,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 490b8252e..c742f4a93 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -421,7 +421,9 @@ public:
421 421
422 /// Copies the contents of one surface to another 422 /// Copies the contents of one surface to another
423 void FermiCopySurface(const Tegra::Engines::Fermi2D::Regs::Surface& src_config, 423 void FermiCopySurface(const Tegra::Engines::Fermi2D::Regs::Surface& src_config,
424 const Tegra::Engines::Fermi2D::Regs::Surface& dst_config); 424 const Tegra::Engines::Fermi2D::Regs::Surface& dst_config,
425 const MathUtil::Rectangle<u32>& src_rect,
426 const MathUtil::Rectangle<u32>& dst_rect);
425 427
426private: 428private:
427 void LoadSurface(const Surface& surface); 429 void LoadSurface(const Surface& surface);