SL-16928 Fix for broken bumpmaps on Intel GPUs
parent
97a103255e
commit
9dc8fee0f5
|
|
@ -211,6 +211,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
|
|||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8;
|
||||
case GL_LUMINANCE: return 8;
|
||||
case GL_ALPHA: return 8;
|
||||
case GL_RED: return 8;
|
||||
case GL_COLOR_INDEX: return 8;
|
||||
case GL_LUMINANCE_ALPHA: return 16;
|
||||
case GL_RGB: return 24;
|
||||
|
|
@ -260,6 +261,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
|
|||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
|
||||
case GL_LUMINANCE: return 1;
|
||||
case GL_ALPHA: return 1;
|
||||
case GL_RED: return 1;
|
||||
case GL_COLOR_INDEX: return 1;
|
||||
case GL_LUMINANCE_ALPHA: return 2;
|
||||
case GL_RGB: return 3;
|
||||
|
|
@ -1199,7 +1201,29 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
|
|||
void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
glGenTextures(numTextures, textures);
|
||||
static constexpr U32 pool_size = 1024;
|
||||
static thread_local U32 name_pool[pool_size]; // pool of texture names
|
||||
static thread_local U32 name_count = 0; // number of available names in the pool
|
||||
|
||||
if (name_count == 0)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("iglgt - reup pool");
|
||||
// pool is emtpy, refill it
|
||||
glGenTextures(pool_size, name_pool);
|
||||
name_count = pool_size;
|
||||
}
|
||||
|
||||
if (numTextures <= name_count)
|
||||
{
|
||||
//copy teture names off the end of the pool
|
||||
memcpy(textures, name_pool + name_count - numTextures, sizeof(U32) * numTextures);
|
||||
name_count -= numTextures;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("iglgt - pool miss");
|
||||
glGenTextures(numTextures, textures);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -1221,15 +1245,18 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
{
|
||||
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_ALPHA is deprecated, convert to RGBA
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = 0;
|
||||
pix[3] = ((U8*)pixels)[i];
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
|
|
@ -1238,18 +1265,21 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
|
||||
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i * 2 + 0];
|
||||
U8 alpha = ((U8*)pixels)[i * 2 + 1];
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = alpha;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
|
|
@ -1258,19 +1288,21 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
|
||||
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i];
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = 255;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGB8;
|
||||
}
|
||||
|
|
@ -1308,6 +1340,10 @@ 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;
|
||||
break;
|
||||
|
|
@ -2010,6 +2046,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
|
|||
case GL_LUMINANCE_ALPHA:
|
||||
mAlphaStride = 2;
|
||||
break;
|
||||
case GL_RED:
|
||||
case GL_RGB:
|
||||
case GL_SRGB:
|
||||
mNeedsAlphaAndPickMask = FALSE;
|
||||
|
|
|
|||
|
|
@ -170,6 +170,53 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
|
|||
return addColorAttachment(color_fmt);
|
||||
}
|
||||
|
||||
void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
llassert(img != nullptr); // img must not be null
|
||||
llassert(sUseFBO); // FBO support must be enabled
|
||||
llassert(mDepth == 0); // depth buffers not supported with this mode
|
||||
llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL)
|
||||
|
||||
if (mFBO == 0)
|
||||
{
|
||||
glGenFramebuffers(1, (GLuint*)&mFBO);
|
||||
}
|
||||
|
||||
mResX = img->getWidth();
|
||||
mResY = img->getHeight();
|
||||
mUsage = img->getTarget();
|
||||
|
||||
if (use_name == 0)
|
||||
{
|
||||
use_name = img->getTexName();
|
||||
}
|
||||
|
||||
mTex.push_back(use_name);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
LLTexUnit::getInternalType(mUsage), use_name, 0);
|
||||
stop_glerror();
|
||||
|
||||
check_framebuffer_status();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
|
||||
void LLRenderTarget::releaseColorAttachment()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets
|
||||
llassert(mFBO != 0); // mFBO must be valid
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
|
||||
mTex.clear();
|
||||
}
|
||||
|
||||
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
||||
{
|
||||
if (color_fmt == 0)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,24 @@ public:
|
|||
// DO use for render targets that resize often and aren't likely to ruin someone's day if they break
|
||||
void resize(U32 resx, U32 resy);
|
||||
|
||||
//point this render target at a particular LLImageGL
|
||||
// Intended usage:
|
||||
// LLRenderTarget target;
|
||||
// target.addColorAttachment(image);
|
||||
// target.bindTarget();
|
||||
// < issue GL calls>
|
||||
// target.flush();
|
||||
// target.releaseColorAttachment();
|
||||
//
|
||||
// attachment -- LLImageGL to render into
|
||||
// use_name -- optional texture name to target instead of attachment->getTexName()
|
||||
// NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with
|
||||
// addColorAttachment, allocateDepth, resize, etc.
|
||||
void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0);
|
||||
|
||||
// detach from current color attachment
|
||||
void releaseColorAttachment();
|
||||
|
||||
//add color buffer attachment
|
||||
//limit of 4 color attachments per render target
|
||||
bool addColorAttachment(U32 color_fmt);
|
||||
|
|
|
|||
|
|
@ -43,18 +43,18 @@ uniform float norm_scale;
|
|||
|
||||
void main()
|
||||
{
|
||||
float alpha = texture2D(alphaMap, vary_texcoord0).a;
|
||||
float c = texture2D(alphaMap, vary_texcoord0).r;
|
||||
|
||||
vec3 right = vec3(norm_scale, 0, (texture2D(alphaMap, vary_texcoord0+vec2(stepX, 0)).a-alpha)*255);
|
||||
vec3 left = vec3(-norm_scale, 0, (texture2D(alphaMap, vary_texcoord0-vec2(stepX, 0)).a-alpha)*255);
|
||||
vec3 up = vec3(0, -norm_scale, (texture2D(alphaMap, vary_texcoord0-vec2(0, stepY)).a-alpha)*255);
|
||||
vec3 down = vec3(0, norm_scale, (texture2D(alphaMap, vary_texcoord0+vec2(0, stepY)).a-alpha)*255);
|
||||
vec3 right = vec3(norm_scale, 0, (texture2D(alphaMap, vary_texcoord0+vec2(stepX, 0)).r-c)*255);
|
||||
vec3 left = vec3(-norm_scale, 0, (texture2D(alphaMap, vary_texcoord0-vec2(stepX, 0)).r-c)*255);
|
||||
vec3 up = vec3(0, -norm_scale, (texture2D(alphaMap, vary_texcoord0-vec2(0, stepY)).r-c)*255);
|
||||
vec3 down = vec3(0, norm_scale, (texture2D(alphaMap, vary_texcoord0+vec2(0, stepY)).r-c)*255);
|
||||
|
||||
vec3 norm = cross(right, down) + cross(down, left) + cross(left,up) + cross(up, right);
|
||||
|
||||
norm = normalize(norm);
|
||||
norm *= 0.5;
|
||||
norm += 0.5;
|
||||
|
||||
frag_color = vec4(norm, alpha);
|
||||
|
||||
frag_color = vec4(norm, c);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT];
|
||||
LL::WorkQueue::weak_t LLBumpImageList::sMainQueue;
|
||||
LL::WorkQueue::weak_t LLBumpImageList::sTexUpdateQueue;
|
||||
LLRenderTarget LLBumpImageList::sRenderTarget;
|
||||
|
||||
// static
|
||||
U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
|
||||
|
|
@ -76,7 +77,7 @@ static S32 cube_channel = -1;
|
|||
static S32 diffuse_channel = -1;
|
||||
static S32 bump_channel = -1;
|
||||
|
||||
#define LL_BUMPLIST_MULTITHREADED 0
|
||||
#define LL_BUMPLIST_MULTITHREADED 0 // TODO -- figure out why this doesn't work
|
||||
|
||||
// static
|
||||
void LLStandardBumpmap::init()
|
||||
|
|
@ -776,6 +777,8 @@ void LLBumpImageList::clear()
|
|||
mBrightnessEntries.clear();
|
||||
mDarknessEntries.clear();
|
||||
|
||||
sRenderTarget.release();
|
||||
|
||||
LLStandardBumpmap::clear();
|
||||
}
|
||||
|
||||
|
|
@ -1032,6 +1035,8 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr
|
|||
// static
|
||||
void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if( success )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
|
||||
|
|
@ -1201,145 +1206,111 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
|
|||
}
|
||||
else
|
||||
{ //convert to normal map
|
||||
|
||||
//disable compression on normal maps to prevent errors below
|
||||
bump->getGLTexture()->setAllowCompression(false);
|
||||
bump->getGLTexture()->setUseMipMaps(TRUE);
|
||||
LL_PROFILE_ZONE_NAMED("bil - create normal map");
|
||||
LLImageGL* img = bump->getGLTexture();
|
||||
LLImageRaw* dst_ptr = dst_image.get();
|
||||
LLGLTexture* bump_ptr = bump.get();
|
||||
|
||||
auto* bump_ptr = bump.get();
|
||||
auto* dst_ptr = dst_image.get();
|
||||
|
||||
#if LL_BUMPLIST_MULTITHREADED
|
||||
bump_ptr->ref();
|
||||
dst_ptr->ref();
|
||||
#endif
|
||||
|
||||
bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA);
|
||||
|
||||
auto create_texture = [=]()
|
||||
img->ref();
|
||||
bump_ptr->ref();
|
||||
auto create_func = [=]()
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID();
|
||||
#endif
|
||||
LL_PROFILE_ZONE_NAMED("bil - create texture deferred");
|
||||
img->setUseMipMaps(TRUE);
|
||||
// upload dst_image to GPU (greyscale in red channel)
|
||||
img->setExplicitFormat(GL_RED, GL_RED);
|
||||
|
||||
bump_ptr->createGLTexture(0, dst_ptr);
|
||||
};
|
||||
|
||||
auto gen_normal_map = [=]()
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID();
|
||||
#endif
|
||||
LL_PROFILE_ZONE_NAMED("bil - generate normal map");
|
||||
if (gNormalMapGenProgram.mProgramObject == 0)
|
||||
{
|
||||
#if LL_BUMPLIST_MULTITHREADED
|
||||
bump_ptr->unref();
|
||||
dst_ptr->unref();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
gPipeline.mScreen.bindTarget();
|
||||
|
||||
LLGLDepthTest depth(GL_FALSE);
|
||||
LLGLDisable cull(GL_CULL_FACE);
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
gGL.setColorMask(TRUE, TRUE);
|
||||
gNormalMapGenProgram.bind();
|
||||
|
||||
static LLStaticHashedString sNormScale("norm_scale");
|
||||
static LLStaticHashedString sStepX("stepX");
|
||||
static LLStaticHashedString sStepY("stepY");
|
||||
|
||||
gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
|
||||
gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
|
||||
gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
|
||||
|
||||
LLVector2 v((F32)bump_ptr->getWidth() / gPipeline.mScreen.getWidth(),
|
||||
(F32)bump_ptr->getHeight() / gPipeline.mScreen.getHeight());
|
||||
|
||||
gGL.getTexUnit(0)->bind(bump_ptr);
|
||||
|
||||
S32 width = bump_ptr->getWidth();
|
||||
S32 height = bump_ptr->getHeight();
|
||||
|
||||
S32 screen_width = gPipeline.mScreen.getWidth();
|
||||
S32 screen_height = gPipeline.mScreen.getHeight();
|
||||
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
|
||||
for (S32 left = 0; left < width; left += screen_width)
|
||||
{
|
||||
S32 right = left + screen_width;
|
||||
right = llmin(right, width);
|
||||
|
||||
F32 left_tc = (F32)left / width;
|
||||
F32 right_tc = (F32)right / width;
|
||||
|
||||
for (S32 bottom = 0; bottom < height; bottom += screen_height)
|
||||
{
|
||||
S32 top = bottom + screen_height;
|
||||
top = llmin(top, height);
|
||||
|
||||
F32 bottom_tc = (F32)bottom / height;
|
||||
F32 top_tc = (F32)(bottom + screen_height) / height;
|
||||
top_tc = llmin(top_tc, 1.f);
|
||||
|
||||
F32 screen_right = (F32)(right - left) / screen_width;
|
||||
F32 screen_top = (F32)(top - bottom) / screen_height;
|
||||
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.texCoord2f(left_tc, bottom_tc);
|
||||
gGL.vertex2f(0, 0);
|
||||
|
||||
gGL.texCoord2f(left_tc, top_tc);
|
||||
gGL.vertex2f(0, screen_top);
|
||||
|
||||
gGL.texCoord2f(right_tc, bottom_tc);
|
||||
gGL.vertex2f(screen_right, 0);
|
||||
|
||||
gGL.texCoord2f(right_tc, top_tc);
|
||||
gGL.vertex2f(screen_right, screen_top);
|
||||
|
||||
gGL.end();
|
||||
|
||||
gGL.flush();
|
||||
|
||||
S32 w = right - left;
|
||||
S32 h = top - bottom;
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
gPipeline.mScreen.flush();
|
||||
|
||||
gNormalMapGenProgram.unbind();
|
||||
|
||||
//generateNormalMapFromAlpha(dst_image, nrm_image);
|
||||
#if LL_BUMPLIST_MULTITHREADED
|
||||
bump_ptr->unref();
|
||||
dst_ptr->unref();
|
||||
#endif
|
||||
};
|
||||
|
||||
auto generate_func = [=]()
|
||||
{
|
||||
// Allocate an empty RGBA texture at "tex_name" the same size as bump
|
||||
// Note: bump will still point at GPU copy of dst_image
|
||||
bump_ptr->setExplicitFormat(GL_RGBA, GL_RGBA);
|
||||
LLGLuint tex_name;
|
||||
img->createGLTexture(0, nullptr, 0, 0, true, &tex_name);
|
||||
|
||||
// point render target at empty buffer
|
||||
sRenderTarget.setColorAttachment(img, tex_name);
|
||||
|
||||
// generate normal map in empty texture
|
||||
{
|
||||
sRenderTarget.bindTarget();
|
||||
|
||||
LLGLDepthTest depth(GL_FALSE);
|
||||
LLGLDisable cull(GL_CULL_FACE);
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
gGL.setColorMask(TRUE, TRUE);
|
||||
|
||||
gNormalMapGenProgram.bind();
|
||||
|
||||
static LLStaticHashedString sNormScale("norm_scale");
|
||||
static LLStaticHashedString sStepX("stepX");
|
||||
static LLStaticHashedString sStepY("stepY");
|
||||
|
||||
gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
|
||||
gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
|
||||
gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
|
||||
|
||||
gGL.getTexUnit(0)->bind(bump_ptr);
|
||||
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.texCoord2f(0, 0);
|
||||
gGL.vertex2f(0, 0);
|
||||
|
||||
gGL.texCoord2f(0, 1);
|
||||
gGL.vertex2f(0, 1);
|
||||
|
||||
gGL.texCoord2f(1, 0);
|
||||
gGL.vertex2f(1, 0);
|
||||
|
||||
gGL.texCoord2f(1, 1);
|
||||
gGL.vertex2f(1, 1);
|
||||
|
||||
gGL.end();
|
||||
|
||||
gGL.flush();
|
||||
|
||||
gNormalMapGenProgram.unbind();
|
||||
|
||||
sRenderTarget.flush();
|
||||
sRenderTarget.releaseColorAttachment();
|
||||
}
|
||||
|
||||
// point bump at normal map and free gpu copy of dst_image
|
||||
img->syncTexName(tex_name);
|
||||
|
||||
// generate mipmap
|
||||
gGL.getTexUnit(0)->bind(img);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
gGL.getTexUnit(0)->disable();
|
||||
|
||||
bump_ptr->unref();
|
||||
img->unref();
|
||||
};
|
||||
|
||||
#if LL_BUMPLIST_MULTITHREADED
|
||||
auto main_queue = sMainQueue.lock();
|
||||
auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr;
|
||||
|
||||
if (LLImageGLThread::sEnabled)
|
||||
{ //dispatch creation to background thread
|
||||
main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map);
|
||||
if (main_queue)
|
||||
{ //dispatch texture upload to background thread, issue GPU commands to generate normal map on main thread
|
||||
main_queue->postTo(
|
||||
sTexUpdateQueue,
|
||||
create_func,
|
||||
generate_func);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
create_texture();
|
||||
gen_normal_map();
|
||||
{ // immediate upload texture and generate normal map
|
||||
create_func();
|
||||
generate_func();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
iter->second = bump; // derefs (and deletes) old image
|
||||
//---------------------------------------------------
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ private:
|
|||
bump_image_map_t mDarknessEntries;
|
||||
static LL::WorkQueue::weak_t sMainQueue;
|
||||
static LL::WorkQueue::weak_t sTexUpdateQueue;
|
||||
static LLRenderTarget sRenderTarget;
|
||||
};
|
||||
|
||||
extern LLBumpImageList gBumpImageList;
|
||||
|
|
|
|||
Loading…
Reference in New Issue