diff options
| author | Rye Mutt <rye@alchemyviewer.org> | 2024-08-22 11:25:25 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-22 10:25:25 -0500 | 
| commit | 28331b2385a8de2a0fde67329127c1694e3f219f (patch) | |
| tree | 83b63b6329b508dd2d943b8bb2d16d77b3faefba | |
| parent | f7bb097247e5ccbd699a76e872913e557c545d3a (diff) | |
Do deprecated texture swizzle on GPU using GL texture swizzling functions (#2389)
* Use GL texture swizzling instead of scratch buffer for deprecated formats when GL 3.3 is available
Fix crash when GL texture compression is enabled
* Fix UI font atlas being eligible for texture compression
| -rw-r--r-- | indra/llrender/llfontbitmapcache.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 216 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.h | 8 | 
3 files changed, 135 insertions, 91 deletions
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index 46c2e89797..ee9cfd0719 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -117,7 +117,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp              }              // Make corresponding GL image. -            mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false)); +            mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false, false));              LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);              // Start at beginning of the new image. diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index be30807e7f..d5f7949051 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -277,6 +277,15 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)  {      switch (dataformat)      { +    case GL_COMPRESSED_RED:                         return 8; +    case GL_COMPRESSED_RG:                          return 16; +    case GL_COMPRESSED_RGB:                         return 24; +    case GL_COMPRESSED_SRGB:                        return 32; +    case GL_COMPRESSED_RGBA:                        return 32; +    case GL_COMPRESSED_SRGB_ALPHA:                  return 32; +    case GL_COMPRESSED_LUMINANCE:                   return 8; +    case GL_COMPRESSED_LUMINANCE_ALPHA:             return 16; +    case GL_COMPRESSED_ALPHA:                       return 8;      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:          return 4;      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:    return 4;      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:          return 8; @@ -288,9 +297,12 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)      case GL_ALPHA:                                  return 8;      case GL_ALPHA8:                                 return 8;      case GL_RED:                                    return 8; +    case GL_R8:                                     return 8;      case GL_COLOR_INDEX:                            return 8;      case GL_LUMINANCE_ALPHA:                        return 16;      case GL_LUMINANCE8_ALPHA8:                      return 16; +    case GL_RG:                                     return 16; +    case GL_RG8:                                    return 16;      case GL_RGB:                                    return 24;      case GL_SRGB:                                   return 24;      case GL_RGB8:                                   return 24; @@ -348,6 +360,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)        case GL_RED:                              return 1;        case GL_COLOR_INDEX:                      return 1;        case GL_LUMINANCE_ALPHA:                  return 2; +      case GL_RG:                               return 2;        case GL_RGB:                              return 3;        case GL_SRGB:                             return 3;        case GL_RGBA:                             return 4; @@ -415,29 +428,29 @@ bool LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, b  //---------------------------------------------------------------------------- -LLImageGL::LLImageGL(bool usemipmaps) +LLImageGL::LLImageGL(bool usemipmaps/* = true*/, bool allow_compression/* = true*/)  :   mSaveData(0), mExternalTexture(false)  { -    init(usemipmaps); +    init(usemipmaps, allow_compression);      setSize(0, 0, 0);      sImageList.insert(this);      sCount++;  } -LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps) +LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)  :   mSaveData(0), mExternalTexture(false)  {      llassert( components <= 4 ); -    init(usemipmaps); +    init(usemipmaps, allow_compression);      setSize(width, height, components);      sImageList.insert(this);      sCount++;  } -LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps) +LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)  :   mSaveData(0), mExternalTexture(false)  { -    init(usemipmaps); +    init(usemipmaps, allow_compression);      setSize(0, 0, 0);      sImageList.insert(this);      sCount++; @@ -454,7 +467,7 @@ LLImageGL::LLImageGL(      LLGLenum formatType,      LLTexUnit::eTextureAddressMode addressMode)  { -    init(false); +    init(false, true);      mTexName = texName;      mTarget = target;      mComponents = components; @@ -476,7 +489,7 @@ LLImageGL::~LLImageGL()      }  } -void LLImageGL::init(bool usemipmaps) +void LLImageGL::init(bool usemipmaps, bool allow_compression)  {  #if LL_IMAGEGL_THREAD_CHECK      mActiveThread = LLThread::currentID(); @@ -506,7 +519,7 @@ void LLImageGL::init(bool usemipmaps)      mHeight = 0;      mCurrentDiscardLevel = -1; -    mAllowCompression = true; +    mAllowCompression = allow_compression;      mTarget = GL_TEXTURE_2D;      mBindTarget = LLTexUnit::TT_TEXTURE; @@ -1234,90 +1247,122 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)  void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -    bool use_scratch = false; -    U32* scratch = NULL; +    std::unique_ptr<U32[]> scratch;      if (LLRender::sGLCoreProfile)      { -        if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) -        { //GL_ALPHA is deprecated, convert to RGBA -            if (pixels != nullptr) -            { -                use_scratch = true; -                scratch = new(std::nothrow) U32[width * height]; -                if (!scratch) -                { -                    LLError::LLUserWarningMsg::showOutOfMemory(); -                    LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) -                              << " bytes for a manual image W" << width << " H" << height << LL_ENDL; -                } +        LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; +        if (gGLManager.mGLVersion >= 3.29f) +        { +            if (pixformat == GL_ALPHA) +            { //GL_ALPHA is deprecated, convert to RGBA +                const GLint mask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; +                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); +                pixformat = GL_RED; +                intformat = GL_R8; +            } -                U32 pixel_count = (U32)(width * height); -                for (U32 i = 0; i < pixel_count; i++) -                { -                    U8* pix = (U8*)&scratch[i]; -                    pix[0] = pix[1] = pix[2] = 0; -                    pix[3] = ((U8*)pixels)[i]; -                } +            if (pixformat == GL_LUMINANCE) +            { //GL_LUMINANCE is deprecated, convert to GL_RGBA +                const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; +                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); +                pixformat = GL_RED; +                intformat = GL_R8;              } -            pixformat = GL_RGBA; -            intformat = GL_RGBA8; +            if (pixformat == GL_LUMINANCE_ALPHA) +            { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA +                const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; +                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); +                pixformat = GL_RG; +                intformat = GL_RG8; +            }          } - -        if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) -        { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA -            if (pixels != nullptr) -            { -                use_scratch = true; -                scratch = new(std::nothrow) U32[width * height]; -                if (!scratch) +        else +        { +            if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) +            { //GL_ALPHA is deprecated, convert to RGBA +                if (pixels != nullptr)                  { -                    LLError::LLUserWarningMsg::showOutOfMemory(); -                    LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) -                        << " bytes for a manual image W" << width << " H" << height << LL_ENDL; -                } +                    scratch.reset(new(std::nothrow) U32[width * height]); +                    if (!scratch) +                    { +                        LLError::LLUserWarningMsg::showOutOfMemory(); +                        LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) +                            << " bytes for a manual image W" << width << " H" << height << LL_ENDL; +                    } -                U32 pixel_count = (U32)(width * height); -                for (U32 i = 0; i < pixel_count; i++) -                { -                    U8 lum = ((U8*)pixels)[i * 2 + 0]; -                    U8 alpha = ((U8*)pixels)[i * 2 + 1]; +                    U32 pixel_count = (U32)(width * height); +                    for (U32 i = 0; i < pixel_count; i++) +                    { +                        U8* pix = (U8*)&scratch[i]; +                        pix[0] = pix[1] = pix[2] = 0; +                        pix[3] = ((U8*)pixels)[i]; +                    } -                    U8* pix = (U8*)&scratch[i]; -                    pix[0] = pix[1] = pix[2] = lum; -                    pix[3] = alpha; +                    pixels = scratch.get();                  } -            } -            pixformat = GL_RGBA; -            intformat = GL_RGBA8; -        } +                pixformat = GL_RGBA; +                intformat = GL_RGBA8; +            } -        if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) -        { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB -            if (pixels != nullptr) -            { -                use_scratch = true; -                scratch = new(std::nothrow) U32[width * height]; -                if (!scratch) +            if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) +            { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA +                if (pixels != nullptr)                  { -                    LLError::LLUserWarningMsg::showOutOfMemory(); -                    LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) -                        << " bytes for a manual image W" << width << " H" << height << LL_ENDL; +                    scratch.reset(new(std::nothrow) U32[width * height]); +                    if (!scratch) +                    { +                        LLError::LLUserWarningMsg::showOutOfMemory(); +                        LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) +                            << " bytes for a manual image W" << width << " H" << height << LL_ENDL; +                    } + +                    U32 pixel_count = (U32)(width * height); +                    for (U32 i = 0; i < pixel_count; i++) +                    { +                        U8 lum = ((U8*)pixels)[i * 2 + 0]; +                        U8 alpha = ((U8*)pixels)[i * 2 + 1]; + +                        U8* pix = (U8*)&scratch[i]; +                        pix[0] = pix[1] = pix[2] = lum; +                        pix[3] = alpha; +                    } + +                    pixels = scratch.get();                  } -                U32 pixel_count = (U32)(width * height); -                for (U32 i = 0; i < pixel_count; i++) +                pixformat = GL_RGBA; +                intformat = GL_RGBA8; +            } + +            if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) +            { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB +                if (pixels != nullptr)                  { -                    U8 lum = ((U8*)pixels)[i]; +                    scratch.reset(new(std::nothrow) U32[width * height]); +                    if (!scratch) +                    { +                        LLError::LLUserWarningMsg::showOutOfMemory(); +                        LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) +                            << " bytes for a manual image W" << width << " H" << height << LL_ENDL; +                    } + +                    U32 pixel_count = (U32)(width * height); +                    for (U32 i = 0; i < pixel_count; i++) +                    { +                        U8 lum = ((U8*)pixels)[i]; + +                        U8* pix = (U8*)&scratch[i]; +                        pix[0] = pix[1] = pix[2] = lum; +                        pix[3] = 255; +                    } -                    U8* pix = (U8*)&scratch[i]; -                    pix[0] = pix[1] = pix[2] = lum; -                    pix[3] = 255; +                    pixels = scratch.get();                  } +                pixformat = GL_RGBA; +                intformat = GL_RGB8;              } -            pixformat = GL_RGBA; -            intformat = GL_RGB8;          }      } @@ -1326,6 +1371,14 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt      {          switch (intformat)          { +        case GL_RED: +        case GL_R8: +            intformat = GL_COMPRESSED_RED; +            break; +        case GL_RG: +        case GL_RG8: +            intformat = GL_COMPRESSED_RG; +            break;          case GL_RGB:          case GL_RGB8:              intformat = GL_COMPRESSED_RGB; @@ -1354,12 +1407,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt          case GL_ALPHA8:              intformat = GL_COMPRESSED_ALPHA;              break; -        case GL_RED: -        case GL_R8: -            intformat = GL_COMPRESSED_RED; -            break;          default: -            LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; +            LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL;              break;          }      } @@ -1375,7 +1424,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt          if (!use_sub_image)          {              LL_PROFILE_ZONE_NAMED("glTexImage2D alloc + copy"); -            glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); +            glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels);          }          else          { @@ -1385,7 +1434,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt                  glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);              } -            U8* src = (U8*)(use_scratch ? scratch : pixels); +            U8* src = (U8*)(pixels);              if (src)              {                  LL_PROFILE_ZONE_NAMED("glTexImage2D copy"); @@ -1395,11 +1444,6 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt          alloc_tex_image(width, height, intformat, 1);      }      stop_glerror(); - -    if (use_scratch) -    { -        delete[] scratch; -    }  }  //create an empty GL texture: just create a texture name diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 9a8d935b89..a8b94bd5b0 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -101,9 +101,9 @@ public:      static bool create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, bool usemipmaps = true);  public: -    LLImageGL(bool usemipmaps = true); -    LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true); -    LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true); +    LLImageGL(bool usemipmaps = true, bool allow_compression = true); +    LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true, bool allow_compression = true); +    LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true, bool allow_compression = true);      // For wrapping textures created via GL elsewhere with our API only. Use with caution.      LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint  formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode); @@ -203,7 +203,7 @@ public:      LLGLenum getTexTarget()const { return mTarget; } -    void init(bool usemipmaps); +    void init(bool usemipmaps, bool allow_compression);      virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized.  Be careful when using this in derived class destructors      void setNeedsAlphaAndPickMask(bool need_mask);  | 
