diff options
| -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, | |||
| 698 | void Image::DownloadMemory(ImageBufferMap& map, | 698 | void Image::DownloadMemory(ImageBufferMap& map, |
| 699 | std::span<const VideoCommon::BufferImageCopy> copies) { | 699 | std::span<const VideoCommon::BufferImageCopy> copies) { |
| 700 | glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API | 700 | glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API |
| 701 | 701 | const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); | |
| 702 | if (is_rescaled) { | ||
| 703 | ScaleDown(); | ||
| 704 | } | ||
| 702 | glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer); | 705 | glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer); |
| 703 | glPixelStorei(GL_PACK_ALIGNMENT, 1); | 706 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
| 704 | 707 | ||
| @@ -716,6 +719,9 @@ void Image::DownloadMemory(ImageBufferMap& map, | |||
| 716 | } | 719 | } |
| 717 | CopyImageToBuffer(copy, map.offset); | 720 | CopyImageToBuffer(copy, map.offset); |
| 718 | } | 721 | } |
| 722 | if (is_rescaled) { | ||
| 723 | ScaleUp(); | ||
| 724 | } | ||
| 719 | } | 725 | } |
| 720 | 726 | ||
| 721 | GLuint Image::StorageHandle() noexcept { | 727 | GLuint Image::StorageHandle() noexcept { |
| @@ -849,12 +855,70 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b | |||
| 849 | } | 855 | } |
| 850 | } | 856 | } |
| 851 | 857 | ||
| 858 | void Image::Scale() { | ||
| 859 | // TODO: Pass scaling factor? | ||
| 860 | if (gl_format == 0 || gl_type == 0) { | ||
| 861 | // compressed textures | ||
| 862 | return; | ||
| 863 | } | ||
| 864 | if (info.type == ImageType::Linear) { | ||
| 865 | UNIMPLEMENTED(); | ||
| 866 | return; | ||
| 867 | } | ||
| 868 | GLint prev_draw_fbo; | ||
| 869 | GLint prev_read_fbo; | ||
| 870 | glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo); | ||
| 871 | glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo); | ||
| 872 | const GLenum attachment = [this] { | ||
| 873 | switch (GetFormatType(info.format)) { | ||
| 874 | case SurfaceType::ColorTexture: | ||
| 875 | return GL_COLOR_ATTACHMENT0; | ||
| 876 | case SurfaceType::Depth: | ||
| 877 | return GL_DEPTH_ATTACHMENT; | ||
| 878 | case SurfaceType::DepthStencil: | ||
| 879 | return GL_DEPTH_STENCIL_ATTACHMENT; | ||
| 880 | default: | ||
| 881 | UNREACHABLE(); | ||
| 882 | return GL_COLOR_ATTACHMENT0; | ||
| 883 | } | ||
| 884 | }(); | ||
| 885 | const GLenum mask = [this] { | ||
| 886 | switch (GetFormatType(info.format)) { | ||
| 887 | case SurfaceType::ColorTexture: | ||
| 888 | return GL_COLOR_BUFFER_BIT; | ||
| 889 | case SurfaceType::Depth: | ||
| 890 | return GL_DEPTH_BUFFER_BIT; | ||
| 891 | case SurfaceType::DepthStencil: | ||
| 892 | return GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; | ||
| 893 | default: | ||
| 894 | UNREACHABLE(); | ||
| 895 | return GL_COLOR_BUFFER_BIT; | ||
| 896 | } | ||
| 897 | }(); | ||
| 898 | const GLenum filter = (mask & GL_COLOR_BUFFER_BIT) != 0 ? GL_LINEAR : GL_NEAREST; | ||
| 899 | GLuint fbo_handle; | ||
| 900 | glGenFramebuffers(1, &fbo_handle); | ||
| 901 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_handle); | ||
| 902 | glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle); | ||
| 903 | glNamedFramebufferTexture(fbo_handle, attachment, texture.handle, 0); | ||
| 904 | |||
| 905 | const size_t scaled_width = info.size.width; | ||
| 906 | const size_t scaled_height = info.size.height * 2; | ||
| 907 | glBlitNamedFramebuffer(fbo_handle, fbo_handle, 0, 0, info.size.width, info.size.height, 0, 0, | ||
| 908 | scaled_width, scaled_height, mask, filter); | ||
| 909 | // TODO: resize texture? | ||
| 910 | glCopyTextureSubImage3D(texture.handle, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height / 2); | ||
| 911 | // Restore previous framebuffers | ||
| 912 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo); | ||
| 913 | glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo); | ||
| 914 | } | ||
| 915 | |||
| 852 | bool Image::ScaleUp() { | 916 | bool Image::ScaleUp() { |
| 853 | if (True(flags & ImageFlagBits::Rescaled)) { | 917 | if (True(flags & ImageFlagBits::Rescaled)) { |
| 854 | return false; | 918 | return false; |
| 855 | } | 919 | } |
| 856 | flags |= ImageFlagBits::Rescaled; | 920 | flags |= ImageFlagBits::Rescaled; |
| 857 | UNIMPLEMENTED(); | 921 | Scale(); |
| 858 | return true; | 922 | return true; |
| 859 | } | 923 | } |
| 860 | 924 | ||
| @@ -863,7 +927,7 @@ bool Image::ScaleDown() { | |||
| 863 | return false; | 927 | return false; |
| 864 | } | 928 | } |
| 865 | flags &= ~ImageFlagBits::Rescaled; | 929 | flags &= ~ImageFlagBits::Rescaled; |
| 866 | UNIMPLEMENTED(); | 930 | Scale(); |
| 867 | return true; | 931 | return true; |
| 868 | } | 932 | } |
| 869 | 933 | ||
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: | |||
| 198 | 198 | ||
| 199 | void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); | 199 | void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); |
| 200 | 200 | ||
| 201 | void Scale(); | ||
| 202 | |||
| 201 | OGLTexture texture; | 203 | OGLTexture texture; |
| 202 | OGLTextureView store_view; | 204 | OGLTextureView store_view; |
| 203 | GLenum gl_internal_format = GL_NONE; | 205 | GLenum gl_internal_format = GL_NONE; |