You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
389 lines
13 KiB
389 lines
13 KiB
/*==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 <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
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 |
|
|
|
kDestPremultiplied = 0x0020, // Dest has color premultiplied by alpha |
|
// (src always assumed nonpremultiplied for now) |
|
}; |
|
|
|
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
|
|
|