summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp70
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
2 files changed, 69 insertions, 3 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index cdd352aef..9b2a09007 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -698,7 +698,10 @@ void Image::UploadMemory(const ImageBufferMap& map,
void Image::DownloadMemory(ImageBufferMap& map,
std::span<const VideoCommon::BufferImageCopy> copies) {
glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API
-
+ const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
+ if (is_rescaled) {
+ ScaleDown();
+ }
glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
@@ -716,6 +719,9 @@ void Image::DownloadMemory(ImageBufferMap& map,
}
CopyImageToBuffer(copy, map.offset);
}
+ if (is_rescaled) {
+ ScaleUp();
+ }
}
GLuint Image::StorageHandle() noexcept {
@@ -849,12 +855,70 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b
}
}
+void Image::Scale() {
+ // TODO: Pass scaling factor?
+ if (gl_format == 0 || gl_type == 0) {
+ // compressed textures
+ return;
+ }
+ if (info.type == ImageType::Linear) {
+ UNIMPLEMENTED();
+ return;
+ }
+ GLint prev_draw_fbo;
+ GLint prev_read_fbo;
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo);
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo);
+ const GLenum attachment = [this] {
+ switch (GetFormatType(info.format)) {
+ case SurfaceType::ColorTexture:
+ return GL_COLOR_ATTACHMENT0;
+ case SurfaceType::Depth:
+ return GL_DEPTH_ATTACHMENT;
+ case SurfaceType::DepthStencil:
+ return GL_DEPTH_STENCIL_ATTACHMENT;
+ default:
+ UNREACHABLE();
+ return GL_COLOR_ATTACHMENT0;
+ }
+ }();
+ const GLenum mask = [this] {
+ switch (GetFormatType(info.format)) {
+ case SurfaceType::ColorTexture:
+ return GL_COLOR_BUFFER_BIT;
+ case SurfaceType::Depth:
+ return GL_DEPTH_BUFFER_BIT;
+ case SurfaceType::DepthStencil:
+ return GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ default:
+ UNREACHABLE();
+ return GL_COLOR_BUFFER_BIT;
+ }
+ }();
+ const GLenum filter = (mask & GL_COLOR_BUFFER_BIT) != 0 ? GL_LINEAR : GL_NEAREST;
+ GLuint fbo_handle;
+ glGenFramebuffers(1, &fbo_handle);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_handle);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle);
+ glNamedFramebufferTexture(fbo_handle, attachment, texture.handle, 0);
+
+ const size_t scaled_width = info.size.width;
+ const size_t scaled_height = info.size.height * 2;
+ glBlitNamedFramebuffer(fbo_handle, fbo_handle, 0, 0, info.size.width, info.size.height, 0, 0,
+ scaled_width, scaled_height, mask, filter);
+ // TODO: resize texture?
+ glCopyTextureSubImage3D(texture.handle, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height / 2);
+ // Restore previous framebuffers
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo);
+}
+
bool Image::ScaleUp() {
if (True(flags & ImageFlagBits::Rescaled)) {
return false;
}
flags |= ImageFlagBits::Rescaled;
- UNIMPLEMENTED();
+ Scale();
return true;
}
@@ -863,7 +927,7 @@ bool Image::ScaleDown() {
return false;
}
flags &= ~ImageFlagBits::Rescaled;
- UNIMPLEMENTED();
+ Scale();
return true;
}
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 58b36494b..324a0f1cb 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -198,6 +198,8 @@ private:
void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);
+ void Scale();
+
OGLTexture texture;
OGLTextureView store_view;
GLenum gl_internal_format = GL_NONE;