phoenix-firestorm/indra/newview/lltexlayer.h

417 lines
14 KiB
C++

/**
* @file lltexlayer.h
* @brief A texture layer. Used for avatars.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLTEXLAYER_H
#define LL_LLTEXLAYER_H
#include <deque>
#include "lldynamictexture.h"
#include "llwearable.h"
#include "llvoavatardefines.h"
class LLVOAvatar;
class LLVOAvatarSelf;
class LLImageTGA;
class LLImageRaw;
class LLXmlTreeNode;
class LLPolyMorphTarget;
class LLTexLayerSet;
class LLTexLayerSetInfo;
class LLTexLayerInfo;
class LLTexLayerSetBuffer;
class LLTexLayerParamColor;
class LLTexLayerParamColorInfo;
class LLTexLayerParamAlpha;
class LLTexLayerParamAlphaInfo;
class LLWearable;
class LLViewerVisualParam;
typedef std::vector<LLTexLayerParamColor *> param_color_list_t;
typedef std::vector<LLTexLayerParamAlpha *> param_alpha_list_t;
typedef std::vector<LLTexLayerParamColorInfo *> param_color_info_list_t;
typedef std::vector<LLTexLayerParamAlphaInfo *> param_alpha_info_list_t;
//-----------------------------------------------------------------------------
// LLTexLayerInterface
// Interface class to generalize functionality shared by LLTexLayer and LLTexLayerTemplate.
class LLTexLayerInterface
{
public:
enum ERenderPass
{
RP_COLOR,
RP_BUMP,
RP_SHINE
};
LLTexLayerInterface(LLTexLayerSet* const layer_set);
LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
virtual ~LLTexLayerInterface() {}
const LLTexLayerInfo* getInfo() const { return mInfo; }
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) = 0;
void requestUpdate();
LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; }
virtual void deleteCaches() = 0;
void invalidateMorphMasks();
virtual void setHasMorph(BOOL newval) { mHasMorph = newval; }
BOOL hasMorph() { return mHasMorph; }
BOOL isMorphValid() { return mMorphMasksValid; }
const std::string& getName() const;
ERenderPass getRenderPass() const;
const std::string& getGlobalColor() const;
virtual BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) = 0;
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0;
BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
BOOL isVisibilityMask() const;
virtual BOOL isInvisibleAlphaMask() = 0;
LLTexLayerSet* getLayerSet() {return mTexLayerSet;}
LLViewerVisualParam* getVisualParamPtr(S32 index);
protected:
LLTexLayerSet* const mTexLayerSet;
// Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order.
param_color_list_t mParamColorList;
// mGlobalColor name stored in mInfo
// mFixedColor value stored in mInfo
param_alpha_list_t mParamAlphaList;
BOOL mMorphMasksValid;
BOOL mStaticImageInvalid;
BOOL mHasMorph;
const LLTexLayerInfo *mInfo;
};
//-----------------------------------------------------------------------------
// LLTexLayerTemplate
// Template class
// Only exists for llvoavatarself
class LLTexLayerTemplate : public LLTexLayerInterface
{
public:
LLTexLayerTemplate(LLTexLayerSet* const layer_set);
LLTexLayerTemplate(const LLTexLayerTemplate &layer);
/*virtual*/ ~LLTexLayerTemplate();
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
/*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 setHasMorph(BOOL newval);
/*virtual*/ void deleteCaches();
/*virtual*/ BOOL isInvisibleAlphaMask();
private:
U32 updateWearableCache();
LLTexLayer* getLayer(U32 i);
typedef std::vector<LLWearable*> wearable_cache_t;
wearable_cache_t mWearableCache;
};
//-----------------------------------------------------------------------------
// LLTexLayer
// A single texture layer
// Only exists for llvoavatarself
class LLTexLayer : public LLTexLayerInterface
{
public:
LLTexLayer(LLTexLayerSet* const layer_set);
LLTexLayer(const LLTexLayer &layer, LLWearable *wearable);
LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable);
/*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*/ void deleteCaches();
U8* getAlphaData();
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);
BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color);
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
/*virtual*/ BOOL isInvisibleAlphaMask();
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
LLLocalTextureObject* getLTO() { return mLocalTextureObject; }
static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
private:
LLUUID getUUID();
typedef std::map<U32, U8*> alpha_cache_t;
alpha_cache_t mAlphaCache;
LLLocalTextureObject *mLocalTextureObject;
};
// Make private
class LLTexLayerInfo
{
friend class LLTexLayer;
friend class LLTexLayerTemplate;
friend class LLTexLayerInterface;
public:
LLTexLayerInfo();
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
BOOL createVisualParams(LLVOAvatar *avatar);
BOOL isUserSettable() { return mLocalTexture != -1; }
S32 getLocalTexture() const { return mLocalTexture; }
BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
std::string getName() const { return mName; }
private:
std::string mName;
BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer,
LLTexLayer::ERenderPass mRenderPass;
std::string mGlobalColor;
LLColor4 mFixedColor;
S32 mLocalTexture;
std::string mStaticImageFileName;
BOOL mStaticImageIsMask;
BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask
BOOL mIsVisibilityMask;
typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t;
morph_name_list_t mMorphNameList;
param_color_info_list_t mParamColorInfoList;
param_alpha_info_list_t mParamAlphaInfoList;
};
//
// LLTexLayer
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
// Only exists for llvoavatarself
class LLTexLayerSet
{
friend class LLTexLayerSetBuffer;
public:
LLTexLayerSet(LLVOAvatarSelf* const avatar);
~LLTexLayerSet();
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 isBodyRegion(const std::string& region) const;
LLTexLayerSetBuffer* getComposite();
void requestUpdate();
void requestUpload();
void cancelUpload();
void updateComposite();
BOOL isLocalTextureDataAvailable() const;
BOOL isLocalTextureDataFinal() const;
void createComposite();
void destroyComposite();
void setUpdatesEnabled(BOOL b);
BOOL getUpdatesEnabled() const { return mUpdatesEnabled; }
void deleteCaches();
void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
BOOL isMorphValid();
void invalidateMorphMasks();
LLTexLayerInterface* findLayerByName(const std::string& name);
void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable);
LLVOAvatarSelf* getAvatar() const { return mAvatar; }
const std::string getBodyRegion() const;
BOOL hasComposite() const { return (mComposite.notNull()); }
LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
void setBakedTexIndex( LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
BOOL isVisible() const { return mIsVisible; }
public:
static BOOL sHasCaches;
typedef std::vector<LLTexLayerInterface *> layer_list_t;
private:
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
LLPointer<LLTexLayerSetBuffer> mComposite;
LLVOAvatarSelf* const mAvatar; // Backlink only; don't make this an LLPointer.
BOOL mUpdatesEnabled;
BOOL mIsVisible;
LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
const LLTexLayerSetInfo *mInfo;
};
// Contains shared layer set data
class LLTexLayerSetInfo
{
friend class LLTexLayerSet;
public:
LLTexLayerSetInfo();
~LLTexLayerSetInfo();
BOOL parseXml(LLXmlTreeNode* node);
void createVisualParams(LLVOAvatar *avatar);
private:
std::string mBodyRegion;
S32 mWidth;
S32 mHeight;
std::string mStaticAlphaFileName;
BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName)
typedef std::vector<LLTexLayerInfo*> layer_info_list_t;
layer_info_list_t mLayerInfoList;
};
// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
class LLTexLayerSetBuffer : public LLViewerDynamicTexture
{
public:
LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
virtual ~LLTexLayerSetBuffer();
virtual void preRender(BOOL clear_depth);
virtual void postRender(BOOL success);
virtual BOOL render();
BOOL updateImmediate();
bool isInitialized(void) const;
BOOL needsRender();
void requestUpdate();
void requestUpload();
void cancelUpload();
BOOL uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
void readBackAndUpload();
static void onTextureUploadComplete(const LLUUID& uuid,
void* userdata,
S32 result, LLExtStat ext_status);
static void dumpTotalByteCount();
virtual void restoreGLTexture();
virtual void destroyGLTexture();
private:
void pushProjection() const;
void popProjection() const;
private:
LLTexLayerSet* const mTexLayerSet;
BOOL mNeedsUpdate;
BOOL mNeedsUpload;
BOOL mUploadPending;
LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit)
static S32 sGLByteCount;
};
//
// LLTexLayerSet
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLTexLayerStaticImageList
//
class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList>
{
public:
LLTexLayerStaticImageList();
~LLTexLayerStaticImageList();
LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask);
LLImageTGA* getImageTGA(const std::string& file_name);
void deleteCachedImages();
void dumpByteCount();
private:
BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw);
private:
LLStringTable mImageNames;
typedef std::map< const char*, LLPointer<LLViewerTexture> > texture_map_t;
texture_map_t mStaticImageList;
typedef std::map< const char*, LLPointer<LLImageTGA> > image_tga_map_t;
image_tga_map_t mStaticImageListTGA;
S32 mGLBytes;
S32 mTGABytes;
};
// Used by LLTexLayerSetBuffer for a callback.
// Note to anyone merging branches - this supercedes the previous fix
// for DEV-31590 "Heap corruption and crash after outfit changes",
// here and in lltexlayer.cpp. Equally correct and a bit simpler.
class LLBakedUploadData
{
public:
LLBakedUploadData(const LLVOAvatarSelf* avatar, LLTexLayerSet* layerset, const LLUUID& id);
~LLBakedUploadData() {}
const LLUUID mID;
const LLVOAvatarSelf* mAvatar; // just backlink, don't LLPointer
LLTexLayerSet* mTexLayerSet;
const U64 mStartTime; // Used to measure time baked texture upload requires
};
#endif // LL_LLTEXLAYER_H