Commit 4cb5d10a authored by Euclid Linden's avatar Euclid Linden
Browse files

Merged in euclid-15299 (pull request #580)

SL-15299 SL-15313 BUG-230802 Revert BOM fix causing issues with avatar alpha masks.

Approved-by: Andrey Kleshchev
parents 272da688 7199ce45
......@@ -28,8 +28,6 @@
#include "llmaterial.h"
#include "../llrender/llglheaders.h"
/**
* Materials cap parameters
*/
......@@ -107,8 +105,6 @@ LLMaterial::LLMaterial()
, mSpecularLightExponent(LLMaterial::DEFAULT_SPECULAR_LIGHT_EXPONENT)
, mEnvironmentIntensity(LLMaterial::DEFAULT_ENV_INTENSITY)
, mDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
, mDiffuseFormatPrimary(GL_RGBA)
, mDiffuseBaked(false)
, mAlphaMaskCutoff(0)
{
}
......@@ -315,20 +311,6 @@ void LLMaterial::setEnvironmentIntensity(U8 intensity)
mEnvironmentIntensity = intensity;
}
U8 LLMaterial::getDiffuseAlphaModeRender() const
{
if (mDiffuseBaked
|| mDiffuseFormatPrimary == GL_RGBA
|| mDiffuseFormatPrimary == GL_ALPHA)
{
return mDiffuseAlphaMode;
}
else
{
return DIFFUSE_ALPHA_MODE_NONE;
}
}
U8 LLMaterial::getDiffuseAlphaMode() const
{
return mDiffuseAlphaMode;
......@@ -339,26 +321,6 @@ void LLMaterial::setDiffuseAlphaMode(U8 alpha_mode)
mDiffuseAlphaMode = alpha_mode;
}
U32 LLMaterial::getDiffuseFormatPrimary() const
{
return mDiffuseFormatPrimary;
}
void LLMaterial::setDiffuseFormatPrimary(U32 format_primary)
{
mDiffuseFormatPrimary = format_primary;
}
bool LLMaterial::getIsDiffuseBaked() const
{
return mDiffuseBaked;
}
void LLMaterial::setDiffuseBaked(bool baked)
{
mDiffuseBaked = baked;
}
U8 LLMaterial::getAlphaMaskCutoff() const
{
return mAlphaMaskCutoff;
......@@ -475,7 +437,7 @@ U32 LLMaterial::getShaderMask(U32 alpha_mode)
}
else
{
ret = getDiffuseAlphaModeRender();
ret = getDiffuseAlphaMode();
}
llassert(ret < SHADER_COUNT);
......
......@@ -115,17 +115,8 @@ class LLMaterial : public LLRefCount
void setSpecularLightExponent(U8 exponent);
U8 getEnvironmentIntensity() const;
void setEnvironmentIntensity(U8 intensity);
// getDiffuseAlphaModeRender takes into account if image supports alpha
// and returns value apropriate for render
// getDiffuseAlphaMode() returns value as is
U8 getDiffuseAlphaModeRender() const;
U8 getDiffuseAlphaMode() const;
void setDiffuseAlphaMode(U8 alpha_mode);
U32 getDiffuseFormatPrimary() const;
void setDiffuseFormatPrimary(U32 format_primary);
bool getIsDiffuseBaked() const;
void setDiffuseBaked(bool baked);
U8 getAlphaMaskCutoff() const;
void setAlphaMaskCutoff(U8 cutoff);
......@@ -156,8 +147,6 @@ class LLMaterial : public LLRefCount
U8 mSpecularLightExponent;
U8 mEnvironmentIntensity;
U8 mDiffuseAlphaMode;
U32 mDiffuseFormatPrimary; // value from texture, LLGLenum, is not included in fromLLSD/asLLSD
bool mDiffuseBaked; // is not included in fromLLSD/asLLSD
U8 mAlphaMaskCutoff;
};
......
......@@ -2129,7 +2129,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
if (mat)
{
switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaModeRender()))
switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode()))
{
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
{
......@@ -2267,7 +2267,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env);
if (mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
F32 cutoff = mat->getAlphaMaskCutoff()/255.f;
sVertexProgram->setMinimumAlpha(cutoff);
......
......@@ -1165,7 +1165,7 @@ bool LLFace::canRenderAsMask()
}
LLMaterial* mat = te->getMaterialParams();
if (mat && mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
{
return false;
}
......@@ -1412,7 +1412,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
else
{
if (!mat || mat->getDiffuseAlphaModeRender() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
if (!mat || mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
shiny_in_alpha = true;
}
......
......@@ -4880,78 +4880,22 @@ void LLViewerObject::refreshBakeTexture()
}
}
void LLViewerObject::updateDiffuseMatParams(const U8 te, LLMaterial* mat, LLViewerTexture *imagep, bool baked_texture)
{
// Objects getting non-alpha texture and alpha mask can result in graphical bugs, like white or red alphas.
// To resolve the issue this function provides image format to material and based on format material's
// getDiffuseAlphaModeRender() function will decide what value to provide to render
//
// Unfortunately LLMaterial has no access to diffuse image, so we have to set this data in LLViewerObject
// regardles of object being used/seen or frequency of image-updates.
mat->setDiffuseBaked(baked_texture);
if (!baked_texture)
{
if (imagep->isMissingAsset())
{
mat->setDiffuseFormatPrimary(0);
}
else if (0 == imagep->getPrimaryFormat())
{
// We don't have information about this texture, wait for it
mWaitingTextureInfo.insert(uuid_material_mmap_t::value_type(imagep->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
// Temporary assume RGBA image
mat->setDiffuseFormatPrimary(GL_RGBA);
}
else
{
mat->setDiffuseFormatPrimary(imagep->getPrimaryFormat());
}
}
}
S32 LLViewerObject::setDiffuseImageAndParams(const U8 te, LLViewerTexture *imagep)
{
LLUUID new_id = imagep->getID();
S32 retval = LLPrimitive::setTETexture(te, new_id);
LLTextureEntry* tep = getTE(te);
LLUUID old_image_id = tep->getID();
LLViewerTexture* baked_texture = getBakedTextureForMagicId(new_id);
mTEImages[te] = baked_texture ? baked_texture : imagep;
updateAvatarMeshVisibility(new_id, old_image_id);
LLMaterial* mat = tep->getMaterialParams();
if (mat)
{
// Don't update format from texture (and don't shedule one) if material has no alpha mode set,
// just assume RGBA format, format will get updated with setTEMaterialParams call if mode changes
if (mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
{
bool baked = baked_texture != NULL;
updateDiffuseMatParams(te, mat, imagep, baked);
}
else
{
mat->setDiffuseFormatPrimary(GL_RGBA);
}
}
setChanged(TEXTURE);
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
}
return retval;
}
void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
{
if (mTEImages[te] != imagep)
{
setDiffuseImageAndParams(te, imagep);
LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null;
LLPrimitive::setTETexture(te, imagep->getID());
LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID());
mTEImages[te] = baked_texture ? baked_texture : imagep;
updateAvatarMeshVisibility(imagep->getID(), old_image_id);
setChanged(TEXTURE);
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
}
}
}
......@@ -4963,7 +4907,15 @@ S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image)
if (uuid != getTE(te)->getID() ||
uuid == LLUUID::null)
{
retval = setDiffuseImageAndParams(te, image);
retval = LLPrimitive::setTETexture(te, uuid);
LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid);
mTEImages[te] = baked_texture ? baked_texture : image;
updateAvatarMeshVisibility(uuid,old_image_id);
setChanged(TEXTURE);
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
}
}
return retval;
}
......@@ -5258,29 +5210,6 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return 0;
}
if (pMaterialParams.notNull()
&& pMaterialParams->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
{
// Don't update if no alpha is set. If alpha changes, this function will run again,
// no point in sheduling additional texture callbacks (in updateDiffuseMatParams)
LLTextureEntry* tex_entry = getTE(te);
bool is_baked = tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID());
LLViewerTexture *img_diffuse = getTEImage(te);
llassert(NULL != img_diffuse);
if (NULL != img_diffuse)
{
// Will modify alpha mask provided to renderer to fit image
updateDiffuseMatParams(te, pMaterialParams.get(), img_diffuse, is_baked);
}
else
{
LLMaterial *mat = pMaterialParams.get(); // to avoid const
mat->setDiffuseFormatPrimary(0);
}
}
retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams);
LL_DEBUGS("Material") << "Changing material params for te " << (S32)te
<< ", object " << mID
......@@ -5293,84 +5222,6 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return retval;
}
bool LLViewerObject::notifyAboutCreatingTexture(LLViewerTexture *texture)
{
// Confirmation about texture creation, check wait-list
// and make changes, or return false
std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
bool refresh_materials = false;
// RGB textures without alpha channels won't work right with alpha,
// we provide format to material for material to decide when to drop alpha
for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.notNull()
&& LLRender::DIFFUSE_MAP == range_it->second.map)
{
U32 format = texture->getPrimaryFormat();
if (format != cur_material->getDiffuseFormatPrimary())
{
cur_material->setDiffuseFormatPrimary(format);
refresh_materials = true;
}
}
} //for
if (refresh_materials)
{
LLViewerObject::refreshMaterials();
}
//clear wait-list
mWaitingTextureInfo.erase(range.first, range.second);
return refresh_materials;
}
bool LLViewerObject::notifyAboutMissingAsset(LLViewerTexture *texture)
{
// When waiting information about texture it turned out to be missing.
// Confirm the state, update values accordingly
std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
if (range.first == range.second) return false;
bool refresh_materials = false;
for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.isNull())
continue;
if (range_it->second.map == LLRender::DIFFUSE_MAP)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.notNull()
&& LLRender::DIFFUSE_MAP == range_it->second.map)
{
if (0 != cur_material->getDiffuseFormatPrimary())
{
cur_material->setDiffuseFormatPrimary(0);
refresh_materials = true;
}
}
}
} //for
if (refresh_materials)
{
LLViewerObject::refreshMaterials();
}
//clear wait-list
mWaitingTextureInfo.erase(range.first, range.second);
return refresh_materials;
}
void LLViewerObject::refreshMaterials()
{
setChanged(TEXTURE);
......
......@@ -768,12 +768,7 @@ class LLViewerObject
void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy);
void deleteParticleSource();
void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id);
// Helper function to modify alpha mask provided to render according to image (ex: RGB image will drop alpha mask)
void updateDiffuseMatParams(const U8 te, LLMaterial* mat, LLViewerTexture *imagep, bool baked_texture);
// Shared part of code from setTEImage and setTETextureCore
S32 setDiffuseImageAndParams(const U8 te, LLViewerTexture *imagep);
private:
void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string
void deleteTEImages(); // correctly deletes list of images
......@@ -906,27 +901,10 @@ class LLViewerObject
LLJointRiggingInfoTab mJointRiggingInfoTab;
bool notifyAboutCreatingTexture(LLViewerTexture *texture);
bool notifyAboutMissingAsset(LLViewerTexture *texture);
private:
LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
EObjectUpdateType mLastUpdateType;
BOOL mLastUpdateCached;
struct material_info
{
LLRender::eTexIndex map;
U8 te;
material_info(LLRender::eTexIndex map_, U8 te_)
: map(map_)
, te(te_)
{}
};
typedef std::multimap<LLUUID, material_info> uuid_material_mmap_t;
uuid_material_mmap_t mWaitingTextureInfo;
};
///////////////////
......
......@@ -2295,11 +2295,243 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
return res;
}
bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)
{ //Ok, here we have confirmation about texture creation, check our wait-list
//and make changes, or return false
std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
typedef std::map<U8, LLMaterialPtr> map_te_material;
map_te_material new_material;
for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
//here we just interesting in DIFFUSE_MAP only!
if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat())
{ //ok let's check the diffuse mode
switch(cur_material->getDiffuseAlphaMode())
{
case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
{ //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
LLMaterialPtr mat = NULL;
map_te_material::iterator it = new_material.find(range_it->second.te);
if(new_material.end() == it) {
mat = new LLMaterial(cur_material->asLLSD());
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
} else {
mat = it->second;
}
mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
} break;
} //switch
} //if
} //for
//setup new materials
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
{
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
LLViewerObject::setTEMaterialParams(it->first, it->second);
}
//clear wait-list
mWaitingTextureInfo.erase(range.first, range.second);
return 0 != new_material.size();
}
bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
{ //Ok, here if we wait information about texture and it's missing
//then depending from the texture map (diffuse, normal, or specular)
//make changes in material and confirm it. If not return false.
std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
if(range.first == range.second) return false;
typedef std::map<U8, LLMaterialPtr> map_te_material;
map_te_material new_material;
for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.isNull())
continue;
switch(range_it->second.map)
{
case LLRender::DIFFUSE_MAP:
{
if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode())
{ //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
LLMaterialPtr mat = NULL;
map_te_material::iterator it = new_material.find(range_it->second.te);
if(new_material.end() == it) {
mat = new LLMaterial(cur_material->asLLSD());
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
} else {
mat = it->second;
}
mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
}
} break;
case LLRender::NORMAL_MAP:
{ //missing texture => reset material texture id
LLMaterialPtr mat = NULL;
map_te_material::iterator it = new_material.find(range_it->second.te);
if(new_material.end() == it) {
mat = new LLMaterial(cur_material->asLLSD());
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
} else {
mat = it->second;
}
mat->setNormalID(LLUUID::null);
} break;
case LLRender::SPECULAR_MAP:
{ //missing texture => reset material texture id
LLMaterialPtr mat = NULL;
map_te_material::iterator it = new_material.find(range_it->second.te);
if(new_material.end() == it) {
mat = new LLMaterial(cur_material->asLLSD());
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
} else {
mat = it->second;
}
mat->setSpecularID(LLUUID::null);
} break;
case LLRender::NUM_TEXTURE_CHANNELS:
//nothing to do, make compiler happy
break;
} //switch
} //for
//setup new materials
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
{
LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second);
LLViewerObject::setTEMaterialParams(it->first, it->second);
}
//clear wait-list
mWaitingTextureInfo.erase(range.first, range.second);
return 0 != new_material.size();
}
S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
{
S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams);
if(pMaterialParams)
{ //check all of them according to material settings
LLViewerTexture *img_diffuse = getTEImage(te);
LLViewerTexture *img_normal = getTENormalMap(te);
LLViewerTexture *img_specular = getTESpecularMap(te);
llassert(NULL != img_diffuse);
LLMaterialPtr new_material = NULL;
//diffuse
if(NULL != img_diffuse)
{ //guard
if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset())
{ //ok here we don't have information about texture, let's belief and leave material settings
//but we remember this case
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
}
else
{
bool bSetDiffuseNone = false;
if(img_diffuse->isMissingAsset())
{
bSetDiffuseNone = true;
}
else
{
switch(pMaterialParams->getDiffuseAlphaMode())
{
case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
{ //all of them modes available only for 32 bit textures
LLTextureEntry* tex_entry = getTE(te);
bool bIsBakedImageId = false;
if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID()))
{
bIsBakedImageId = true;
}
if (GL_RGBA != img_diffuse->getPrimaryFormat() && !bIsBakedImageId)
{
bSetDiffuseNone = true;
}
} break;
}
} //else
if(bSetDiffuseNone)
{ //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE
new_material = new LLMaterial(pMaterialParams->asLLSD());
new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
}
}
}
//normal
if(LLUUID::null != pMaterialParams->getNormalID())
{
if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID())
{
if(!new_material) {
new_material = new LLMaterial(pMaterialParams->asLLSD());
}