From f5d95dcc861031dac4de98d95117afe1c43b166c Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 16 Apr 2017 20:34:02 +1000 Subject: [PATCH] OGL: Use native compressed textures on supported drivers --- Source/Core/VideoBackends/OGL/Render.cpp | 2 + .../Core/VideoBackends/OGL/TextureCache.cpp | 89 +++++++++++++++++-- 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index ce58be68cc..360bc76a70 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -462,6 +462,8 @@ Renderer::Renderer() g_ogl_config.bSupportsConservativeDepth = GLExtensions::Supports("GL_ARB_conservative_depth"); g_ogl_config.bSupportsAniso = GLExtensions::Supports("GL_EXT_texture_filter_anisotropic"); g_Config.backend_info.bSupportsComputeShaders = GLExtensions::Supports("GL_ARB_compute_shader"); + g_Config.backend_info.bSupportsST3CTextures = + GLExtensions::Supports("GL_EXT_texture_compression_s3tc"); if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) { diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index e49483a593..05261f1d33 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -11,6 +11,7 @@ #include #include +#include "Common/Assert.h" #include "Common/GL/GLInterfaceBase.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" @@ -87,6 +88,53 @@ bool SaveTexture(const std::string& filename, u32 textarget, u32 tex, int virtua return TextureToPng(data.data(), width * 4, filename, width, height, true); } +static bool IsCompressedTextureFormat(HostTextureFormat format) +{ + return format >= HostTextureFormat::DXT1 && format <= HostTextureFormat::DXT5; +} + +static GLenum GetGLInternalFormatForTextureFormat(HostTextureFormat format, bool storage) +{ + switch (format) + { + case HostTextureFormat::DXT1: + return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + case HostTextureFormat::DXT3: + return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + case HostTextureFormat::DXT5: + return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + case HostTextureFormat::RGBA8: + default: + return storage ? GL_RGBA8 : GL_RGBA; + } +} + +static GLenum GetGLFormatForTextureFormat(HostTextureFormat format) +{ + switch (format) + { + case HostTextureFormat::RGBA8: + return GL_RGBA; + + // Compressed texture formats don't use this parameter. + default: + return GL_UNSIGNED_BYTE; + } +} + +static GLenum GetGLTypeForTextureFormat(HostTextureFormat format) +{ + switch (format) + { + case HostTextureFormat::RGBA8: + return GL_UNSIGNED_BYTE; + + // Compressed texture formats don't use this parameter. + default: + return GL_UNSIGNED_BYTE; + } +} + TextureCache::TCacheEntry::~TCacheEntry() { if (texture) @@ -129,6 +177,11 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) { + // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 + // framebuffer, and saving that). TextureCache does not call Save for custom textures + // anyway, so this is fine for now. + _assert_(config.format == HostTextureFormat::RGBA8); + return SaveTexture(filename, GL_TEXTURE_2D_ARRAY, texture, config.width, config.height, level); } @@ -143,12 +196,15 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConf if (g_ogl_config.bSupportsTextureStorage) { - glTexStorage3D(GL_TEXTURE_2D_ARRAY, config.levels, GL_RGBA8, config.width, config.height, - config.layers); + GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(config.format, true); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, config.levels, gl_internal_format, config.width, + config.height, config.layers); } if (config.rendertarget) { + // We can't render to compressed formats. + _assert_(!IsCompressedTextureFormat(config.format)); if (!g_ogl_config.bSupportsTextureStorage) { for (u32 level = 0; level < config.levels; level++) @@ -219,15 +275,34 @@ void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_l if (row_length != width) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - if (g_ogl_config.bSupportsTextureStorage) + GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(config.format, false); + if (IsCompressedTextureFormat(config.format)) { - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0, width, height, 1, GL_RGBA, - GL_UNSIGNED_BYTE, buffer); + if (g_ogl_config.bSupportsTextureStorage) + { + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0, width, height, 1, + gl_internal_format, static_cast(buffer_size), buffer); + } + else + { + glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_internal_format, width, height, 1, 0, + static_cast(buffer_size), buffer); + } } else { - glTexImage3D(GL_TEXTURE_2D_ARRAY, level, GL_RGBA, width, height, 1, 0, GL_RGBA, - GL_UNSIGNED_BYTE, buffer); + GLenum gl_format = GetGLFormatForTextureFormat(config.format); + GLenum gl_type = GetGLTypeForTextureFormat(config.format); + if (g_ogl_config.bSupportsTextureStorage) + { + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0, width, height, 1, gl_format, gl_type, + buffer); + } + else + { + glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_internal_format, width, height, 1, 0, gl_format, + gl_type, buffer); + } } if (row_length != width)