Skip to content
Snippets Groups Projects
Commit 946da4e5 authored by Graham Linden's avatar Graham Linden
Browse files

SL-10761

Add work-around for broken intel drivers which can't use glReadPixels from RGBA FBOs to get alpha without locking up.
parent ddf70361
No related branches found
No related tags found
No related merge requests found
......@@ -137,7 +137,7 @@ void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
popProjection();
}
BOOL LLTexLayerSetBuffer::renderTexLayerSet()
BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target)
{
// Default color mask for tex layer render
gGL.setColorMask(true, true);
......@@ -161,7 +161,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet()
// Composite the color data
LLGLSUIDefault gls_ui;
success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(),
getCompositeWidth(), getCompositeHeight() );
getCompositeWidth(), getCompositeHeight(), bound_target );
gGL.flush();
midRenderTexLayerSet(success);
......@@ -375,7 +375,7 @@ void LLTexLayerSet::deleteCaches()
}
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target )
{
BOOL success = TRUE;
mIsVisible = TRUE;
......@@ -427,7 +427,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
{
gGL.flush();
success &= layer->render(x, y, width, height);
success &= layer->render(x, y, width, height, bound_target);
gGL.flush();
}
}
......@@ -523,7 +523,7 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const
}
static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha");
void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height)
void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target)
{
LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA);
memset(data, 255, width * height);
......@@ -531,15 +531,15 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
layer->gatherAlphaMasks(data, origin_x, origin_y, width, height);
layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target);
}
// Set alpha back to that of our alpha masks.
renderAlphaMaskTextures(origin_x, origin_y, width, height, true);
renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true);
}
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures");
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES);
const LLTexLayerSetInfo *info = getInfo();
......@@ -1124,7 +1124,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LL
}
}
BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
{
LLGLEnable color_mat(GL_COLOR_MATERIAL);
// *TODO: Is this correct?
......@@ -1185,7 +1185,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
}//*/
const bool force_render = true;
renderMorphMasks(x, y, width, height, net_color, force_render);
renderMorphMasks(x, y, width, height, net_color, bound_target, force_render);
alpha_mask_specified = TRUE;
gGL.flush();
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA);
......@@ -1428,13 +1428,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
return success;
}
/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
{
addAlphaMask(data, originX, originY, width, height);
addAlphaMask(data, originX, originY, width, height, bound_target);
}
static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks");
void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render)
void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render)
{
if (!force_render && !hasMorph())
{
......@@ -1586,11 +1586,42 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
alpha_data = (U8*)ll_aligned_malloc_32(mem_size);
bool skip_readback = LLRender::sNsightDebugSupport || gGLManager.mIsIntel; // nSight doesn't support use of glReadPixels
bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels
if (!skip_readback)
{
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
if (gGLManager.mIsIntel)
{ // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO
// returning only the alpha portion without locking up downstream
U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA
if (bound_target)
{
gGL.getTexUnit(0)->bind(bound_target);
}
else
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0);
}
glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
U8* alpha_cursor = alpha_data;
U8* pixel = temp;
for (int i = 0; i < pixels; i++)
{
*alpha_cursor++ = pixel[3];
pixel += 4;
}
gGL.getTexUnit(0)->disable();
ll_aligned_free_32(temp);
}
else
{ // platforms with working drivers...
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
}
}
else
{
......@@ -1609,7 +1640,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask");
void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
{
LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK);
S32 size = width * height;
......@@ -1621,7 +1652,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
// TODO: eliminate need for layer morph mask valid flag
invalidateMorphMasks();
const bool force_render = false;
renderMorphMasks(originX, originY, width, height, net_color, force_render);
renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render);
alphaData = getAlphaData();
}
if (alphaData)
......@@ -1755,7 +1786,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
return layer;
}
/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height)
/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
{
if(!mInfo)
{
......@@ -1782,7 +1813,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
{
wearable->writeToAvatar(mAvatarAppearance);
layer->setLTO(lto);
success &= layer->render(x,y,width,height);
success &= layer->render(x, y, width, height, bound_target);
}
}
......@@ -1804,14 +1835,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
return success;
}
/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
{
U32 num_wearables = updateWearableCache();
U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
LLTexLayer *layer = getLayer(i);
if (layer)
{
layer->addAlphaMask(data, originX, originY, width, height);
layer->addAlphaMask(data, originX, originY, width, height, bound_target);
}
}
......
......@@ -65,7 +65,7 @@ class LLTexLayerInterface
LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
virtual ~LLTexLayerInterface() {}
virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0;
virtual BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0;
virtual void deleteCaches() = 0;
virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0;
virtual BOOL isInvisibleAlphaMask() const = 0;
......@@ -85,7 +85,7 @@ class LLTexLayerInterface
BOOL isMorphValid() const { return mMorphMasksValid; }
void requestUpdate();
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0;
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0;
BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
ERenderPass getRenderPass() const;
......@@ -121,10 +121,10 @@ class LLTexLayerTemplate : public LLTexLayerInterface
LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance);
LLTexLayerTemplate(const LLTexLayerTemplate &layer);
/*virtual*/ ~LLTexLayerTemplate();
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target);
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
/*virtual*/ void setHasMorph(BOOL newval);
/*virtual*/ void deleteCaches();
/*virtual*/ BOOL isInvisibleAlphaMask() const;
......@@ -152,16 +152,16 @@ class LLTexLayer : public LLTexLayerInterface
/*virtual*/ ~LLTexLayer();
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target);
/*virtual*/ void deleteCaches();
const U8* getAlphaData() const;
BOOL findNetColor(LLColor4* color) const;
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render);
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render);
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
/*virtual*/ BOOL isInvisibleAlphaMask() const;
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
......@@ -194,13 +194,13 @@ class LLTexLayerSet
const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist.
virtual void createComposite() = 0;
void destroyComposite();
void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height);
void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target);
const LLTexLayerSetInfo* getInfo() const { return mInfo; }
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
BOOL render(S32 x, S32 y, S32 width, S32 height);
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr);
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false);
BOOL isBodyRegion(const std::string& region) const;
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
......@@ -282,7 +282,7 @@ class LLTexLayerSetBuffer : public virtual LLRefCount
virtual S32 getCompositeOriginY() const = 0;
virtual S32 getCompositeWidth() const = 0;
virtual S32 getCompositeHeight() const = 0;
BOOL renderTexLayerSet();
BOOL renderTexLayerSet(LLRenderTarget* bound_target);
LLTexLayerSet* const mTexLayerSet;
};
......
......@@ -240,6 +240,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
gDepthDirty = TRUE;
gGL.color4f(1,1,1,1);
dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mWaterDis : nullptr);
dynamicTexture->preRender(); // Must be called outside of startRender()
result = FALSE;
if (dynamicTexture->render())
......@@ -250,7 +251,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
}
//gGL.flush();
LLVertexBuffer::unbind();
dynamicTexture->setBoundTarget(nullptr);
dynamicTexture->postRender(result);
}
}
......
......@@ -88,6 +88,9 @@ class LLViewerDynamicTexture : public LLViewerTexture
static BOOL updateAllInstances();
static void destroyGL() ;
static void restoreGL() ;
void setBoundTarget(LLRenderTarget* target) { mBoundTarget = target; }
protected:
void generateGLTexture();
void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE);
......@@ -97,6 +100,8 @@ class LLViewerDynamicTexture : public LLViewerTexture
LLCoordGL mOrigin;
LL_ALIGN_16(LLCamera mCamera);
LLRenderTarget* mBoundTarget;
typedef std::set<LLViewerDynamicTexture*> instance_list_t;
static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
static S32 sNumRenders;
......
......@@ -111,7 +111,7 @@ class LLViewerTexLayerSetBuffer : public LLTexLayerSetBuffer, public LLViewerDyn
// Pass these along for tex layer rendering.
virtual void preRender(BOOL clear_depth) { preRenderTexLayerSet(); }
virtual void postRender(BOOL success) { postRenderTexLayerSet(success); }
virtual BOOL render() { return renderTexLayerSet(); }
virtual BOOL render() { return renderTexLayerSet(mBoundTarget); }
//--------------------------------------------------------------------
// Updates
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment