diff options
Diffstat (limited to 'src/video_core')
-rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 70 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 2 |
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; |