From ebf57683405c12ce7c56d07bed1c040b149ef31f Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 21 Aug 2018 01:04:46 -0400
Subject: [PATCH] gl_rasterizer_cache: Implement compressed texture copies.

---
 .../renderer_opengl/gl_rasterizer_cache.cpp   | 26 +++++++++++++------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index b1769c99b..dc582b2df 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -800,8 +800,6 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
     // Verify surface is compatible for blitting
     const auto& params{surface->GetSurfaceParams()};
     ASSERT(params.type == new_params.type);
-    ASSERT_MSG(params.GetCompressionFactor(params.pixel_format) == 1,
-               "Compressed texture reinterpretation is not supported");
 
     // Create a new surface with the new parameters, and blit the previous surface to it
     Surface new_surface{std::make_shared<CachedSurface>(new_params)};
@@ -818,9 +816,13 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
 
     glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle);
     glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
-    glGetTextureImage(surface->Texture().handle, 0, source_format.format, source_format.type,
-                      params.SizeInBytes(), nullptr);
-
+    if (source_format.compressed) {
+        glGetCompressedTextureImage(surface->Texture().handle, 0,
+                                    static_cast<GLsizei>(params.SizeInBytes()), nullptr);
+    } else {
+        glGetTextureImage(surface->Texture().handle, 0, source_format.format, source_format.type,
+                          static_cast<GLsizei>(params.SizeInBytes()), nullptr);
+    }
     // If the new texture is bigger than the previous one, we need to fill in the rest with data
     // from the CPU.
     if (params.SizeInBytes() < new_params.SizeInBytes()) {
@@ -846,9 +848,17 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
     const auto& dest_rect{new_params.GetRect()};
 
     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.handle);
-    glTextureSubImage2D(
-        new_surface->Texture().handle, 0, 0, 0, static_cast<GLsizei>(dest_rect.GetWidth()),
-        static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format, dest_format.type, nullptr);
+    if (dest_format.compressed) {
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+                                  static_cast<GLsizei>(dest_rect.GetWidth()),
+                                  static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
+                                  static_cast<GLsizei>(new_params.SizeInBytes()), nullptr);
+    } else {
+        glTextureSubImage2D(new_surface->Texture().handle, 0, 0, 0,
+                            static_cast<GLsizei>(dest_rect.GetWidth()),
+                            static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
+                            dest_format.type, nullptr);
+    }
     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
     pbo.Release();