From 4319ba5edcfeb066d712cdb5a851f155a87ed71b Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Mon, 13 Mar 2023 16:46:39 -0700
Subject: SL-19331: Improve performance of setSubImage (ex: media updates)

---
 indra/llrender/llimagegl.cpp | 59 ++++++++++++++++++++++++++++++--------------
 indra/llrender/llimagegl.h   |  1 +
 2 files changed, 41 insertions(+), 19 deletions(-)

(limited to 'indra/llrender')

diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 7c1cf2ba33..c42688e95b 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -732,21 +732,8 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
 BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
-	bool is_compressed = false;
 
-    switch (mFormatPrimary)
-    {
-    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
-    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
-    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-        is_compressed = true;
-        break;
-    default:
-        break;
-    }
+	const bool is_compressed = isCompressed();
 	
 	if (mUseMipMaps)
 	{
@@ -1232,11 +1219,23 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
 		if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL;
 		stop_glerror();
 
-        // *TODO: glTexSubImage2D may not work on a subset of the texture if
-        // the texture is compressed. Make sure the image isn't compressed
-        // when using this function, then it's safe to replace this call with
-        // subImageLines, when it is performant to do so (see setManualImage)
-		glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap);
+#if LL_DARWIN
+        const bool use_sub_image = false;
+#else
+        const bool use_sub_image = !isCompressed();
+#endif
+        if (!use_sub_image)
+        {
+            // *TODO: Why does this work here, in setSubImage, but not in
+            // setManualImage? Maybe because it only gets called with the
+            // dimensions of the full image?  Or because the image is never
+            // compressed?
+            glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap);
+        }
+        else
+        {
+            subImageLines(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap);
+        }
 		gGL.getTexUnit(0)->disable();
 		stop_glerror();
 
@@ -1456,6 +1455,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
         const bool use_sub_image = false;
 #else
         // glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08
+        // *TODO: Small chance that glCompressedTexImage2D/glCompressedTexSubImage2D may work better here
         const bool use_sub_image = !compress;
 #endif
         if (!use_sub_image)
@@ -2296,6 +2296,27 @@ void LLImageGL::freePickMask()
 	mPickMaskWidth = mPickMaskHeight = 0;
 }
 
+bool LLImageGL::isCompressed()
+{
+    llassert(mFormatPrimary != 0);
+    // *NOTE: Not all compressed formats are included here.
+    bool is_compressed = false;
+    switch (mFormatPrimary)
+    {
+    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+        is_compressed = true;
+        break;
+    default:
+        break;
+    }
+    return is_compressed;
+}
+
 //----------------------------------------------------------------------------
 void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 {
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 08d8f60979..42f6efef77 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -214,6 +214,7 @@ public:
 private:
 	U32 createPickMask(S32 pWidth, S32 pHeight);
 	void freePickMask();
+    bool isCompressed();
 
 	LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
 	LL::WorkQueue::weak_t mMainQueue;
-- 
cgit v1.2.3