Skip to content

Commit 28331b2

Browse files
authored
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
1 parent f7bb097 commit 28331b2

File tree

3 files changed

+135
-91
lines changed

3 files changed

+135
-91
lines changed

indra/llrender/llfontbitmapcache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
117117
}
118118

119119
// Make corresponding GL image.
120-
mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false));
120+
mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false, false));
121121
LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
122122

123123
// Start at beginning of the new image.

indra/llrender/llimagegl.cpp

Lines changed: 130 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,15 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
277277
{
278278
switch (dataformat)
279279
{
280+
case GL_COMPRESSED_RED: return 8;
281+
case GL_COMPRESSED_RG: return 16;
282+
case GL_COMPRESSED_RGB: return 24;
283+
case GL_COMPRESSED_SRGB: return 32;
284+
case GL_COMPRESSED_RGBA: return 32;
285+
case GL_COMPRESSED_SRGB_ALPHA: return 32;
286+
case GL_COMPRESSED_LUMINANCE: return 8;
287+
case GL_COMPRESSED_LUMINANCE_ALPHA: return 16;
288+
case GL_COMPRESSED_ALPHA: return 8;
280289
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4;
281290
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4;
282291
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8;
@@ -288,9 +297,12 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
288297
case GL_ALPHA: return 8;
289298
case GL_ALPHA8: return 8;
290299
case GL_RED: return 8;
300+
case GL_R8: return 8;
291301
case GL_COLOR_INDEX: return 8;
292302
case GL_LUMINANCE_ALPHA: return 16;
293303
case GL_LUMINANCE8_ALPHA8: return 16;
304+
case GL_RG: return 16;
305+
case GL_RG8: return 16;
294306
case GL_RGB: return 24;
295307
case GL_SRGB: return 24;
296308
case GL_RGB8: return 24;
@@ -348,6 +360,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
348360
case GL_RED: return 1;
349361
case GL_COLOR_INDEX: return 1;
350362
case GL_LUMINANCE_ALPHA: return 2;
363+
case GL_RG: return 2;
351364
case GL_RGB: return 3;
352365
case GL_SRGB: return 3;
353366
case GL_RGBA: return 4;
@@ -415,29 +428,29 @@ bool LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, b
415428

416429
//----------------------------------------------------------------------------
417430

418-
LLImageGL::LLImageGL(bool usemipmaps)
431+
LLImageGL::LLImageGL(bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
419432
: mSaveData(0), mExternalTexture(false)
420433
{
421-
init(usemipmaps);
434+
init(usemipmaps, allow_compression);
422435
setSize(0, 0, 0);
423436
sImageList.insert(this);
424437
sCount++;
425438
}
426439

427-
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps)
440+
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
428441
: mSaveData(0), mExternalTexture(false)
429442
{
430443
llassert( components <= 4 );
431-
init(usemipmaps);
444+
init(usemipmaps, allow_compression);
432445
setSize(width, height, components);
433446
sImageList.insert(this);
434447
sCount++;
435448
}
436449

437-
LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps)
450+
LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
438451
: mSaveData(0), mExternalTexture(false)
439452
{
440-
init(usemipmaps);
453+
init(usemipmaps, allow_compression);
441454
setSize(0, 0, 0);
442455
sImageList.insert(this);
443456
sCount++;
@@ -454,7 +467,7 @@ LLImageGL::LLImageGL(
454467
LLGLenum formatType,
455468
LLTexUnit::eTextureAddressMode addressMode)
456469
{
457-
init(false);
470+
init(false, true);
458471
mTexName = texName;
459472
mTarget = target;
460473
mComponents = components;
@@ -476,7 +489,7 @@ LLImageGL::~LLImageGL()
476489
}
477490
}
478491

479-
void LLImageGL::init(bool usemipmaps)
492+
void LLImageGL::init(bool usemipmaps, bool allow_compression)
480493
{
481494
#if LL_IMAGEGL_THREAD_CHECK
482495
mActiveThread = LLThread::currentID();
@@ -506,7 +519,7 @@ void LLImageGL::init(bool usemipmaps)
506519
mHeight = 0;
507520
mCurrentDiscardLevel = -1;
508521

509-
mAllowCompression = true;
522+
mAllowCompression = allow_compression;
510523

511524
mTarget = GL_TEXTURE_2D;
512525
mBindTarget = LLTexUnit::TT_TEXTURE;
@@ -1234,90 +1247,122 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
12341247
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression)
12351248
{
12361249
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
1237-
bool use_scratch = false;
1238-
U32* scratch = NULL;
1250+
std::unique_ptr<U32[]> scratch;
12391251
if (LLRender::sGLCoreProfile)
12401252
{
1241-
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
1242-
{ //GL_ALPHA is deprecated, convert to RGBA
1243-
if (pixels != nullptr)
1244-
{
1245-
use_scratch = true;
1246-
scratch = new(std::nothrow) U32[width * height];
1247-
if (!scratch)
1248-
{
1249-
LLError::LLUserWarningMsg::showOutOfMemory();
1250-
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
1251-
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
1252-
}
1253+
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
1254+
if (gGLManager.mGLVersion >= 3.29f)
1255+
{
1256+
if (pixformat == GL_ALPHA)
1257+
{ //GL_ALPHA is deprecated, convert to RGBA
1258+
const GLint mask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED };
1259+
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask);
1260+
pixformat = GL_RED;
1261+
intformat = GL_R8;
1262+
}
12531263

1254-
U32 pixel_count = (U32)(width * height);
1255-
for (U32 i = 0; i < pixel_count; i++)
1256-
{
1257-
U8* pix = (U8*)&scratch[i];
1258-
pix[0] = pix[1] = pix[2] = 0;
1259-
pix[3] = ((U8*)pixels)[i];
1260-
}
1264+
if (pixformat == GL_LUMINANCE)
1265+
{ //GL_LUMINANCE is deprecated, convert to GL_RGBA
1266+
const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
1267+
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask);
1268+
pixformat = GL_RED;
1269+
intformat = GL_R8;
12611270
}
12621271

1263-
pixformat = GL_RGBA;
1264-
intformat = GL_RGBA8;
1272+
if (pixformat == GL_LUMINANCE_ALPHA)
1273+
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
1274+
const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
1275+
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask);
1276+
pixformat = GL_RG;
1277+
intformat = GL_RG8;
1278+
}
12651279
}
1266-
1267-
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
1268-
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
1269-
if (pixels != nullptr)
1270-
{
1271-
use_scratch = true;
1272-
scratch = new(std::nothrow) U32[width * height];
1273-
if (!scratch)
1280+
else
1281+
{
1282+
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
1283+
{ //GL_ALPHA is deprecated, convert to RGBA
1284+
if (pixels != nullptr)
12741285
{
1275-
LLError::LLUserWarningMsg::showOutOfMemory();
1276-
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
1277-
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
1278-
}
1286+
scratch.reset(new(std::nothrow) U32[width * height]);
1287+
if (!scratch)
1288+
{
1289+
LLError::LLUserWarningMsg::showOutOfMemory();
1290+
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
1291+
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
1292+
}
12791293

1280-
U32 pixel_count = (U32)(width * height);
1281-
for (U32 i = 0; i < pixel_count; i++)
1282-
{
1283-
U8 lum = ((U8*)pixels)[i * 2 + 0];
1284-
U8 alpha = ((U8*)pixels)[i * 2 + 1];
1294+
U32 pixel_count = (U32)(width * height);
1295+
for (U32 i = 0; i < pixel_count; i++)
1296+
{
1297+
U8* pix = (U8*)&scratch[i];
1298+
pix[0] = pix[1] = pix[2] = 0;
1299+
pix[3] = ((U8*)pixels)[i];
1300+
}
12851301

1286-
U8* pix = (U8*)&scratch[i];
1287-
pix[0] = pix[1] = pix[2] = lum;
1288-
pix[3] = alpha;
1302+
pixels = scratch.get();
12891303
}
1290-
}
12911304

1292-
pixformat = GL_RGBA;
1293-
intformat = GL_RGBA8;
1294-
}
1305+
pixformat = GL_RGBA;
1306+
intformat = GL_RGBA8;
1307+
}
12951308

1296-
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
1297-
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
1298-
if (pixels != nullptr)
1299-
{
1300-
use_scratch = true;
1301-
scratch = new(std::nothrow) U32[width * height];
1302-
if (!scratch)
1309+
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
1310+
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
1311+
if (pixels != nullptr)
13031312
{
1304-
LLError::LLUserWarningMsg::showOutOfMemory();
1305-
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
1306-
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
1313+
scratch.reset(new(std::nothrow) U32[width * height]);
1314+
if (!scratch)
1315+
{
1316+
LLError::LLUserWarningMsg::showOutOfMemory();
1317+
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
1318+
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
1319+
}
1320+
1321+
U32 pixel_count = (U32)(width * height);
1322+
for (U32 i = 0; i < pixel_count; i++)
1323+
{
1324+
U8 lum = ((U8*)pixels)[i * 2 + 0];
1325+
U8 alpha = ((U8*)pixels)[i * 2 + 1];
1326+
1327+
U8* pix = (U8*)&scratch[i];
1328+
pix[0] = pix[1] = pix[2] = lum;
1329+
pix[3] = alpha;
1330+
}
1331+
1332+
pixels = scratch.get();
13071333
}
13081334

1309-
U32 pixel_count = (U32)(width * height);
1310-
for (U32 i = 0; i < pixel_count; i++)
1335+
pixformat = GL_RGBA;
1336+
intformat = GL_RGBA8;
1337+
}
1338+
1339+
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
1340+
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
1341+
if (pixels != nullptr)
13111342
{
1312-
U8 lum = ((U8*)pixels)[i];
1343+
scratch.reset(new(std::nothrow) U32[width * height]);
1344+
if (!scratch)
1345+
{
1346+
LLError::LLUserWarningMsg::showOutOfMemory();
1347+
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
1348+
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
1349+
}
1350+
1351+
U32 pixel_count = (U32)(width * height);
1352+
for (U32 i = 0; i < pixel_count; i++)
1353+
{
1354+
U8 lum = ((U8*)pixels)[i];
1355+
1356+
U8* pix = (U8*)&scratch[i];
1357+
pix[0] = pix[1] = pix[2] = lum;
1358+
pix[3] = 255;
1359+
}
13131360

1314-
U8* pix = (U8*)&scratch[i];
1315-
pix[0] = pix[1] = pix[2] = lum;
1316-
pix[3] = 255;
1361+
pixels = scratch.get();
13171362
}
1363+
pixformat = GL_RGBA;
1364+
intformat = GL_RGB8;
13181365
}
1319-
pixformat = GL_RGBA;
1320-
intformat = GL_RGB8;
13211366
}
13221367
}
13231368

@@ -1326,6 +1371,14 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
13261371
{
13271372
switch (intformat)
13281373
{
1374+
case GL_RED:
1375+
case GL_R8:
1376+
intformat = GL_COMPRESSED_RED;
1377+
break;
1378+
case GL_RG:
1379+
case GL_RG8:
1380+
intformat = GL_COMPRESSED_RG;
1381+
break;
13291382
case GL_RGB:
13301383
case GL_RGB8:
13311384
intformat = GL_COMPRESSED_RGB;
@@ -1354,12 +1407,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
13541407
case GL_ALPHA8:
13551408
intformat = GL_COMPRESSED_ALPHA;
13561409
break;
1357-
case GL_RED:
1358-
case GL_R8:
1359-
intformat = GL_COMPRESSED_RED;
1360-
break;
13611410
default:
1362-
LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL;
1411+
LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL;
13631412
break;
13641413
}
13651414
}
@@ -1375,7 +1424,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
13751424
if (!use_sub_image)
13761425
{
13771426
LL_PROFILE_ZONE_NAMED("glTexImage2D alloc + copy");
1378-
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
1427+
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels);
13791428
}
13801429
else
13811430
{
@@ -1385,7 +1434,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
13851434
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);
13861435
}
13871436

1388-
U8* src = (U8*)(use_scratch ? scratch : pixels);
1437+
U8* src = (U8*)(pixels);
13891438
if (src)
13901439
{
13911440
LL_PROFILE_ZONE_NAMED("glTexImage2D copy");
@@ -1395,11 +1444,6 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
13951444
alloc_tex_image(width, height, intformat, 1);
13961445
}
13971446
stop_glerror();
1398-
1399-
if (use_scratch)
1400-
{
1401-
delete[] scratch;
1402-
}
14031447
}
14041448

14051449
//create an empty GL texture: just create a texture name

indra/llrender/llimagegl.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ class LLImageGL : public LLRefCount
101101
static bool create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, bool usemipmaps = true);
102102

103103
public:
104-
LLImageGL(bool usemipmaps = true);
105-
LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true);
106-
LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true);
104+
LLImageGL(bool usemipmaps = true, bool allow_compression = true);
105+
LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true, bool allow_compression = true);
106+
LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true, bool allow_compression = true);
107107

108108
// For wrapping textures created via GL elsewhere with our API only. Use with caution.
109109
LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode);
@@ -203,7 +203,7 @@ class LLImageGL : public LLRefCount
203203

204204
LLGLenum getTexTarget()const { return mTarget; }
205205

206-
void init(bool usemipmaps);
206+
void init(bool usemipmaps, bool allow_compression);
207207
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
208208

209209
void setNeedsAlphaAndPickMask(bool need_mask);

0 commit comments

Comments
 (0)