/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ /////////////////////////////////////////////////////////////////////////////// // // // plMipmap Class Header // // Derived bitmap class representing a single mipmap. // // Cyan, Inc. // // // //// Version History ////////////////////////////////////////////////////////// // // // 6.7.2001 mcn - Created. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef _plMipmap_h #define _plMipmap_h #include "plBitmap.h" #ifdef HS_DEBUGGING #define ASSERT_PIXELSIZE(bitmap, pixelsize) hsAssert((bitmap)->fPixelSize == (pixelsize), "pixelSize mismatch") #define ASSERT_XY(bitmap, x, y) hsAssert(x < (bitmap)->fWidth && y < (bitmap)->fHeight, "bad XY") #define ASSERT_UNCOMPRESSED() hsAssert(fCompressionType!=kDirectXCompression, "Can't operate on compressed map.") // Define the following konstant to enable mipmap leak checking. This is because our normal // memory manager sucks when trying to track down these problems #define MEMORY_LEAK_TRACER #else #define ASSERT_PIXELSIZE(bitmap, pixelsize) #define ASSERT_XY(bitmap, x, y) #define ASSERT_UNCOMPRESSED() #endif //// Class Definition ///////////////////////////////////////////////////////// class plBitmapCreator; class plTextGenerator; class plMipmap : public plBitmap { friend class plBitmapCreator; friend class plTextGenerator; public: //// Public Flags //// //// Public Data ///// //// Public Members //// plMipmap(); plMipmap( UInt32 width, UInt32 height, unsigned config, UInt8 numLevels = 0, UInt8 compType = kUncompressed, UInt8 format = UncompressedInfo::kRGB8888 ); plMipmap( plMipmap *bm, hsScalar sig, UInt32 createFlags, hsScalar detailDropoffStart, hsScalar detailDropoffStop, hsScalar detailMax, hsScalar detailMin ); virtual ~plMipmap(); CLASSNAME_REGISTER( plMipmap ); GETINTERFACE_ANY( plMipmap, plBitmap ); void Create( UInt32 width, UInt32 height, unsigned config, UInt8 numLevels, UInt8 compType = kUncompressed, UInt8 format = UncompressedInfo::kRGB8888 ); virtual void Reset(); // Get the total size in bytes virtual UInt32 GetTotalSize() const; virtual void Read( hsStream *s, hsResMgr *mgr ) { hsKeyedObject::Read( s, mgr ); this->Read( s ); } virtual void Write( hsStream *s, hsResMgr *mgr ) { hsKeyedObject::Write( s, mgr ); this->Write( s ); } virtual UInt8 GetNumLevels() const { return fNumLevels; } virtual UInt32 GetLevelSize( UInt8 level ); // 0 is the largest virtual void Colorize(); virtual plMipmap *Clone() const; virtual void CopyFrom( const plMipmap *source ); inline UInt32 GetWidth() const { return fWidth; } inline UInt32 GetHeight() const { return fHeight; } inline UInt32 GetRowBytes() const { return fRowBytes; } void *GetImage() const { return fImage; } void SetImagePtr( void *ptr ) { fImage = ptr; } UInt8 *GetLevelPtr( UInt8 level, UInt32 *width = nil, UInt32 *height = nil, UInt32 *rowBytes = nil ); // Sets the current level pointer for use with GetAddr* virtual void SetCurrLevel(UInt8 level); void *GetCurrLevelPtr() const { return fCurrLevelPtr; } UInt32 GetCurrWidth() const { return fCurrLevelWidth; } UInt32 GetCurrHeight() const { return fCurrLevelHeight; } UInt32 GetCurrLevelSize() const { return fLevelSizes[ fCurrLevel ]; } UInt32 GetCurrLevel() const { return fCurrLevel; } // These methods return the address of the pixel specified by x and y // They are meant to be fast, therefore they are inlined and do not check // the fPixelSize field at runtime (except when debugging) UInt8* GetAddr8(unsigned x, unsigned y) const { ASSERT_PIXELSIZE(this, 8); ASSERT_XY(this, x, y); ASSERT_UNCOMPRESSED(); return (UInt8*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + x); } UInt16* GetAddr16(unsigned x, unsigned y) const { ASSERT_PIXELSIZE(this, 16); ASSERT_XY(this, x, y); ASSERT_UNCOMPRESSED(); return (UInt16*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + (x << 1)); } UInt32* GetAddr32(unsigned x, unsigned y) const { ASSERT_PIXELSIZE(this, 32); ASSERT_XY(this, x, y); ASSERT_UNCOMPRESSED(); return (UInt32*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + (x << 2)); } void* GetAddr64(unsigned x, unsigned y) const { ASSERT_PIXELSIZE(this, 64); ASSERT_XY(this, x, y); ASSERT_UNCOMPRESSED(); return (void*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + (x << 3)); } // This sets fPixelSize, fSpace, fFlags, for you // All you need to set is // fWidth, fHeight, fRowBytes, fImage and fColorTable enum { kColor8Config = 0, kGray44Config = 1, kGray4Config = 2, kGray8Config = 8, // So we can use bit depths instead kRGB16Config = 16, kRGB32Config = 24, kARGB32Config = 32, }; void SetConfig( unsigned config ); //// Really complex creation stuff //// enum { kCreateDetailAlpha = 0x1, kCreateDetailAdd = 0x2, kCreateDetailMult = 0x4, kCreateDetailMask = kCreateDetailAlpha | kCreateDetailAdd | kCreateDetailMult, kCreateCarryAlpha = 0x8, kCreateCarryWhite = 0x10, kCreateCarryBlack = 0x20, kCreateCarryMask = kCreateCarryAlpha | kCreateCarryWhite | kCreateCarryBlack }; enum hsGPixelType { kPixelARGB4444, kPixelARGB1555, kPixelAI88, kPixelI8 }; enum hsGCopyOptions { kCopyLODMask, }; enum { kColorDataRLE = 0x1, kAlphaDataRLE = 0x2 }; void SetBitmapAsLevel(UInt8 iDst, plMipmap *bm, hsScalar sig, UInt32 createFlags, hsScalar detailDropoffStart, hsScalar detailDropoffStop, hsScalar detailMax, hsScalar detailMin); void ICreateLevelNoDetail(UInt8 iDst, const plFilterMask& mask); void IBlendLevelDetailAlpha(UInt8 iDst, const plFilterMask& mask, hsScalar detailDropoffStart, hsScalar detailDropoffStop, hsScalar detailMax, hsScalar detailMin); void IBlendLevelDetailAdd(UInt8 iDst, const plFilterMask& mask, hsScalar detailDropoffStart, hsScalar detailDropoffStop, hsScalar detailMax, hsScalar detailMin); void IBlendLevelDetailMult(UInt8 iDst, const plFilterMask& mask, hsScalar detailDropoffStart, hsScalar detailDropoffStop, hsScalar detailMax, hsScalar detailMin); void Filter(hsScalar sig); UInt32 CopyOutPixels(UInt32 destXSize, UInt32 destYSize, UInt32 dstFormat, void *destPixels, UInt32 copyOptions); void ClipToMaxSize( UInt32 maxDimension ); void RemoveMipping(); void EnsureKonstantBorder( hsBool clampU, hsBool clampV ); enum CompositeFlags { kForceOpaque = 0x0001, // Copy src pixels raw, force dest alphas to opaque kCopySrcAlpha = 0x0002, // Copy the src pixels raw, including alphas, overwrite dest kBlendSrcAlpha = 0x0004, // Blend src pixels onto dest using src alpha, dest alpha = src alpha kMaskSrcAlpha = 0x0008, // Same as copySrcAlpha, but dest is untouched when src alpha = 0 kBlendWriteAlpha= 0x0010 // Like default (0), but writes dest alpha values }; class CompositeOptions { // Helper class for specifying options to Composite() public: UInt16 fFlags; UInt8 fSrcLevelsToSkip; UInt8 fOpacity; hsScalar fRedTint, fGreenTint, fBlueTint; UInt16 fSrcClipX, fSrcClipY; // Clipping is applied AFTER levelSkip UInt16 fSrcClipWidth, fSrcClipHeight; // 0 means max width/height CompositeOptions() { fFlags = 0; fSrcLevelsToSkip = 0; fRedTint = fGreenTint = fBlueTint = 1.f; fSrcClipX = fSrcClipY = fSrcClipWidth = fSrcClipHeight = 0; fOpacity = 255;} CompositeOptions( UInt16 flags, UInt8 srcLevelsToSkip = 0, hsScalar red = 1.f, hsScalar green = 1.f, hsScalar blue = 1.f, UInt16 srcClipX = 0, UInt16 srcClipY = 0, UInt16 srcClipWidth = 0, UInt16 srcClipHeight = 0, UInt8 opacity = 255 ) { fFlags = flags; fSrcLevelsToSkip = srcLevelsToSkip; fRedTint = red; fGreenTint = green; fBlueTint = blue; fSrcClipX = srcClipX; fSrcClipY = srcClipY; fSrcClipWidth = srcClipWidth; fSrcClipHeight = srcClipHeight; fOpacity = opacity; } }; // Compositing function. Take a (smaller) mipmap and composite it onto this one at the given location. Nil options means use default virtual void Composite( plMipmap *source, UInt16 x, UInt16 y, CompositeOptions *options = nil ); // Scaling function enum ScaleFilter { kBoxFilter, kDefaultFilter = kBoxFilter }; virtual void ScaleNicely( UInt32 *destPtr, UInt16 destWidth, UInt16 destHeight, UInt16 destStride, plMipmap::ScaleFilter filter ) const; virtual hsBool ResizeNicely( UInt16 newWidth, UInt16 newHeight, plMipmap::ScaleFilter filter ); protected: //// Protected Members //// void *fImage; UInt32 fWidth, fHeight, fRowBytes, fTotalSize; UInt8 fNumLevels; UInt32 *fLevelSizes; void *fCurrLevelPtr; UInt8 fCurrLevel; UInt32 fCurrLevelWidth, fCurrLevelHeight, fCurrLevelRowBytes; void IReadRawImage( hsStream *stream ); void IWriteRawImage( hsStream *stream ); plMipmap *ISplitAlpha(); void IRecombineAlpha( plMipmap *alphaChannel ); plMipmap *IReadRLEImage( hsStream *stream ); void IWriteRLEImage( hsStream *stream, plMipmap *mipmap ); void IReadJPEGImage( hsStream *stream ); void IWriteJPEGImage( hsStream *stream ); void IBuildLevelSizes(); void IColorLevel( UInt8 level, const UInt8 *colorMask ); hsScalar IGetDetailLevelAlpha( UInt8 level, hsScalar dropStart, hsScalar dropStop, hsScalar min, hsScalar max ); void ICarryZeroAlpha(UInt8 iDst); void ICarryColor(UInt8 iDst, UInt32 col); hsBool IGrabBorderColor( hsBool grabVNotU, UInt32 *color ); void ISetCurrLevelUBorder( UInt32 color ); void ISetCurrLevelVBorder( UInt32 color ); virtual UInt32 Read( hsStream *s ); virtual UInt32 Write( hsStream *s ); friend class plCubicEnvironmap; #ifdef MEMORY_LEAK_TRACER protected: class plRecord { public: plRecord *fNext; plRecord **fBackPtr; char fKeyName[ 256 ]; void *fImage; UInt32 fWidth, fHeight, fRowBytes; UInt8 fNumLevels; UInt8 fCompressionType; union { DirectXInfo fDirectXInfo; UncompressedInfo fUncompressedInfo; }; enum Method { kViaCreate, kViaRead, kViaClipToMaxSize, kViaDetailMapConstructor, kViaCopyFrom, kViaResize } fCreationMethod; void Link( plRecord **backPtr ) { fBackPtr = backPtr; fNext = *backPtr; if( fNext != nil ) fNext->fBackPtr = &fNext; *backPtr = this; } void Unlink() { *fBackPtr = fNext; if( fNext != nil ) fNext->fBackPtr = fBackPtr; } }; static plRecord *fRecords; static UInt32 fNumMipmaps; static void IAddToMemRecord( plMipmap *mip, plRecord::Method method ); static void IRemoveFromMemRecord( UInt8 *image ); static void IReportLeaks(); #endif }; #endif // _plMipmap_h