1 #ifndef _INCLUDED_AWTEXLD_HPP_ 2 #define _INCLUDED_AWTEXLD_HPP_ 3 4 #include "awtexld.h" 5 #include "media.hpp" 6 #include "db.h" 7 #ifndef DB_COMMA 8 #define DB_COMMA , 9 #endif 10 11 namespace AwTl { 12 13 #define CANT_HAPPEN db_msgf1(("AwCreateTexture(): (Line %u) CAN'T HAPPEN!",__LINE__)); 14 15 /*********************************/ 16 /* Pixel format global structure */ 17 /*********************************/ 18 19 struct PixelFormat 20 { PixelFormatAwTl::PixelFormat21 PixelFormat() : validB(false){} 22 23 bool palettizedB : 1; 24 bool alphaB : 1; 25 bool validB : 1; 26 bool texB : 1; 27 28 unsigned bitsPerPixel; 29 unsigned redLeftShift; 30 unsigned redRightShift; 31 unsigned greenLeftShift; 32 unsigned greenRightShift; 33 unsigned blueLeftShift; 34 unsigned blueRightShift; 35 36 unsigned dwRGBAlphaBitMask; 37 // DDPIXELFORMAT ddpf; 38 }; 39 40 // DO SOMTHING ABOUT THIS 41 extern PixelFormat pixelFormat; 42 extern PixelFormat pfSurfaceFormat; 43 44 class CreateTextureParms; 45 46 /********************/ 47 /* Colour structure */ 48 /********************/ 49 50 struct Colour 51 { 52 BYTE r,g,b; 53 54 class ConvNonTransp 55 { 56 public: DoConv(Colour const * _colP,Colour const * =NULL db_code1 (DB_COMMA unsigned=0))57 static inline unsigned DoConv (Colour const * _colP, Colour const * = NULL db_code1(DB_COMMA unsigned = 0)) 58 { 59 return 60 static_cast<unsigned>(_colP->r)>>pixelFormat.redRightShift<<pixelFormat.redLeftShift 61 |static_cast<unsigned>(_colP->g)>>pixelFormat.greenRightShift<<pixelFormat.greenLeftShift 62 |static_cast<unsigned>(_colP->b)>>pixelFormat.blueRightShift<<pixelFormat.blueLeftShift 63 |pixelFormat.dwRGBAlphaBitMask; 64 } DoConv(BYTE const * _colP,Colour const * _paletteP db_code1 (DB_COMMA unsigned _paletteSize))65 static inline unsigned DoConv(BYTE const * _colP, Colour const * _paletteP db_code1(DB_COMMA unsigned _paletteSize)) 66 { 67 db_assert1(_paletteP); 68 db_onlyassert1(*_colP < _paletteSize); 69 return DoConv(&_paletteP[*_colP]); 70 } 71 }; 72 73 class ConvTransp 74 { 75 private: MakeNonTranspCol(Colour const * _colP)76 static inline unsigned MakeNonTranspCol(Colour const * _colP) 77 { 78 unsigned rv = ConvNonTransp::DoConv(_colP); 79 if (rv) return rv; 80 // make one of r,g or b in the output == 1, choose the one which is closest to the input 81 unsigned rdiff = (1<<pixelFormat.redRightShift) - _colP->r; 82 unsigned bdiff = (1<<pixelFormat.blueRightShift) - _colP->b; 83 unsigned gdiff = (1<<pixelFormat.greenRightShift) - _colP->g; 84 if (bdiff<=rdiff && bdiff<=gdiff) 85 return 1<<pixelFormat.blueLeftShift; 86 else if (rdiff<=gdiff) 87 return 1<<pixelFormat.redLeftShift; 88 else 89 return 1<<pixelFormat.greenLeftShift; 90 } 91 public: DoConv(Colour const * _colP,Colour const * =NULL db_code1 (DB_COMMA unsigned=0))92 static inline unsigned DoConv (Colour const * _colP, Colour const * = NULL db_code1(DB_COMMA unsigned = 0)) 93 { 94 if (!_colP->b && !_colP->r && !_colP->g) 95 //return pixelFormat.alphaB ? pixelFormat.ddsd.ddpfPixelFormat.dwRBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwGBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwBBitMask : 0; 96 return 0; 97 else 98 return MakeNonTranspCol(_colP); 99 } DoConv(BYTE const * _colP,Colour const * _paletteP db_code1 (DB_COMMA unsigned _paletteSize))100 static inline unsigned DoConv(BYTE const * _colP, Colour const * _paletteP db_code1(DB_COMMA unsigned _paletteSize)) 101 { 102 db_assert1(_paletteP); 103 db_onlyassert1(*_colP < _paletteSize); 104 if (!*_colP) 105 //return pixelFormat.alphaB ? pixelFormat.ddsd.ddpfPixelFormat.dwRBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwGBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwBBitMask : 0; 106 return 0; 107 else 108 return MakeNonTranspCol(&_paletteP[*_colP]); 109 } 110 }; 111 112 class ConvNull 113 { 114 public: 115 static inline unsigned DoConv (BYTE const * _colP, Colour const * db_code1(DB_COMMA unsigned = 0)) 116 { 117 db_assert1(pixelFormat.palettizedB); 118 return *_colP; 119 } 120 }; 121 }; 122 123 /*****************/ 124 /* Pointer union */ 125 /*****************/ 126 127 union SurfUnion 128 { 129 D3DTexture * textureP; 130 DDSurface * surfaceP; 131 void * voidP; SurfUnion()132 SurfUnion(){} SurfUnion(void * p)133 SurfUnion(void * p) : voidP(p){} 134 }; 135 136 union PtrUnion 137 { 138 void * voidP; 139 char * charP; 140 signed char * scharP; 141 unsigned char * ucharP; 142 BYTE * byteP; 143 short * shortP; 144 unsigned short * ushortP; 145 WORD * wordP; 146 signed * intP; 147 unsigned * uintP; 148 DWORD * dwordP; 149 long * longP; 150 unsigned long * ulongP; 151 Colour * colourP; 152 PtrUnion()153 inline PtrUnion(){} PtrUnion(void * _voidP)154 inline PtrUnion(void * _voidP):voidP(_voidP){} operator void*() const155 inline operator void * () const { return voidP; } 156 }; 157 158 union PtrUnionConst 159 { 160 void const * voidP; 161 char const * charP; 162 signed char const * scharP; 163 unsigned char const * ucharP; 164 BYTE const * byteP; 165 short const * shortP; 166 unsigned short const * ushortP; 167 WORD const * wordP; 168 signed const * intP; 169 unsigned const * uintP; 170 DWORD const * dwordP; 171 long const * longP; 172 unsigned long const * ulongP; 173 Colour const * colourP; 174 PtrUnionConst()175 inline PtrUnionConst(){} PtrUnionConst(void const * _voidP)176 inline PtrUnionConst(void const * _voidP):voidP(_voidP){} PtrUnionConst(PtrUnion _uP)177 inline PtrUnionConst(PtrUnion _uP):voidP(_uP.voidP){} operator void const*() const178 inline operator void const * () const { return voidP; } 179 }; 180 181 /***************************************/ 182 /* Generic copying to surface function */ 183 /***************************************/ 184 185 template<class CONVERT, class SRCTYPE> 186 class GenericConvertRow 187 { 188 public: 189 static void Do (PtrUnion _dstRowP, unsigned _dstWidth, SRCTYPE const * _srcRowP, unsigned _srcWidth, Colour const * _paletteP = NULL db_code1(DB_COMMA unsigned _paletteSize = 0)); 190 }; 191 192 template<class CONVERT, class SRCTYPE> Do(PtrUnion _dstRowP,unsigned _dstWidth,SRCTYPE const * _srcRowP,unsigned _srcWidth,Colour const * _paletteP db_code1 (DB_COMMA unsigned _paletteSize))193 void GenericConvertRow<CONVERT, SRCTYPE>::Do (PtrUnion _dstRowP, unsigned _dstWidth, SRCTYPE const * _srcRowP, unsigned _srcWidth, Colour const * _paletteP db_code1(DB_COMMA unsigned _paletteSize)) 194 { 195 switch (pixelFormat.bitsPerPixel) 196 { 197 default: 198 CANT_HAPPEN 199 case 16: 200 { 201 db_assert1(!pixelFormat.palettizedB); 202 for (unsigned colcount = _srcWidth; colcount; --colcount) 203 { 204 *_dstRowP.wordP++ = static_cast<WORD>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize))); 205 } 206 if (_srcWidth<_dstWidth) 207 *_dstRowP.wordP = static_cast<WORD>(CONVERT::DoConv(_srcRowP-1,_paletteP db_code1(DB_COMMA _paletteSize))); 208 break; 209 } 210 case 24: 211 { 212 db_assert1(!pixelFormat.palettizedB); 213 union { DWORD dw; BYTE b[3]; } u; 214 for (unsigned colcount = _srcWidth; colcount; --colcount) 215 { 216 u.dw = static_cast<DWORD>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize))); 217 *_dstRowP.byteP++ = u.b[0]; 218 *_dstRowP.byteP++ = u.b[1]; 219 *_dstRowP.byteP++ = u.b[2]; 220 } 221 if (_srcWidth<_dstWidth) 222 { 223 *_dstRowP.byteP++ = u.b[0]; 224 *_dstRowP.byteP++ = u.b[1]; 225 *_dstRowP.byteP = u.b[2]; 226 } 227 break; 228 } 229 case 32: 230 { 231 db_assert1(!pixelFormat.palettizedB); 232 for (unsigned colcount = _srcWidth; colcount; --colcount) 233 { 234 *_dstRowP.dwordP++ = static_cast<DWORD>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize))); 235 } 236 if (_srcWidth<_dstWidth) 237 *_dstRowP.dwordP = static_cast<DWORD>(CONVERT::DoConv(_srcRowP-1,_paletteP db_code1(DB_COMMA _paletteSize))); 238 break; 239 } 240 case 8: 241 { 242 for (unsigned colcount = _srcWidth; colcount; --colcount) 243 { 244 *_dstRowP.byteP++ = static_cast<BYTE>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize))); 245 } 246 if (_srcWidth<_dstWidth) 247 *_dstRowP.byteP = static_cast<BYTE>(CONVERT::DoConv(_srcRowP-1,_paletteP db_code1(DB_COMMA _paletteSize))); 248 break; 249 } 250 case 1: 251 case 2: 252 db_assert1(pixelFormat.palettizedB); 253 case 4: 254 { 255 unsigned shift=0; 256 unsigned val=0; 257 --_dstRowP.byteP; // decrement here because we increment before the first write 258 for (unsigned colcount = _srcWidth; colcount; --colcount) 259 { 260 val = CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize)); 261 if (!shift) 262 *++_dstRowP.byteP = static_cast<BYTE>(val); 263 else 264 *_dstRowP.byteP |= static_cast<BYTE>(val<<shift); 265 shift += pixelFormat.bitsPerPixel; 266 shift &= 7; 267 } 268 if (_srcWidth<_dstWidth) 269 { 270 if (!shift) 271 *++_dstRowP.byteP = static_cast<BYTE>(val); 272 else 273 *_dstRowP.byteP |= static_cast<BYTE>(val<<shift); 274 } 275 break; 276 } 277 } 278 } 279 280 // reference counting support 281 class RefCntObj 282 { 283 public: AddRef()284 unsigned AddRef() { return ++m_nRefCnt; } Release()285 unsigned Release() { if (0==(--m_nRefCnt)) { delete this; return 0;} else return m_nRefCnt; } 286 protected: ~RefCntObj()287 virtual ~RefCntObj(){ 288 #ifndef NDEBUG 289 DbForget(this); 290 #endif 291 } RefCntObj()292 RefCntObj() : m_nRefCnt(1){ 293 #ifndef NDEBUG 294 DbRemember(this); 295 #endif 296 } RefCntObj(RefCntObj const &)297 RefCntObj(RefCntObj const &) : m_nRefCnt(1){ 298 #ifndef NDEBUG 299 DbRemember(this); 300 #endif 301 } operator =(RefCntObj const &)302 RefCntObj & operator = (RefCntObj const &){ return *this;} 303 private: 304 unsigned m_nRefCnt; 305 306 #ifndef NDEBUG 307 friend void DbRemember(RefCntObj * pObj); 308 friend void DbForget(RefCntObj * pObj); 309 friend class AllocList; 310 #endif 311 }; 312 313 SurfUnion LoadFromParams(CreateTextureParms *); 314 315 } // namespace AwTl 316 317 struct AwBackupTexture : public AwTl::RefCntObj 318 { 319 public: 320 AwTl::SurfUnion Restore(AwTl::CreateTextureParms const & rParams); 321 protected: 322 AwTl::SurfUnion CreateTexture(AwTl::CreateTextureParms const & rParams); 323 324 void ChoosePixelFormat(AwTl::CreateTextureParms const & rParams); 325 ~AwBackupTextureAwBackupTexture326 virtual ~AwBackupTexture(){} 327 328 // return the number of unique colours in the image or zero if this cannot be determined 329 virtual unsigned GetNumColours() = 0; 330 331 // return the smallest palette size that is available for the image 332 virtual unsigned GetMinPaletteSize() = 0; 333 334 // return true if the image has a single transparent colour 335 virtual bool HasTransparentMask(bool bDefault); 336 337 // called when a backup texture is about to be used for restoring, but after the above two functions have been called 338 virtual void OnBeginRestoring(unsigned nMaxPaletteSize); 339 340 virtual AwTl::Colour * GetPalette() = 0; 341 342 virtual bool AreRowsReversed(); 343 344 virtual AwTl::PtrUnion GetRowPtr(unsigned nRow) = 0; 345 346 virtual void LoadNextRow(AwTl::PtrUnion pRow) = 0; 347 348 virtual void ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize)); 349 350 virtual DWORD GetTransparentColour(); 351 352 virtual void OnFinishRestoring(bool bSuccess); 353 354 // metrics 355 unsigned m_nWidth; 356 unsigned m_nHeight; 357 unsigned m_nPaletteSize; // 0 inicates no palette 358 359 unsigned m_fFlags; 360 361 private: 362 bool m_bTranspMask; 363 364 friend AwTl::SurfUnion AwTl::LoadFromParams(AwTl::CreateTextureParms *); 365 }; 366 367 namespace AwTl { 368 369 class TypicalBackupTexture : public ::AwBackupTexture 370 { 371 public: TypicalBackupTexture(AwBackupTexture const & rBase,PtrUnion * ppPixMap,Colour * pPalette)372 TypicalBackupTexture(AwBackupTexture const & rBase, PtrUnion * ppPixMap, Colour * pPalette) 373 : AwBackupTexture(rBase) 374 , m_ppPixMap(ppPixMap) 375 , m_pPalette(pPalette) 376 {} 377 ~TypicalBackupTexture()378 virtual ~TypicalBackupTexture() 379 { 380 if (m_pPalette) 381 { 382 delete[] m_pPalette; 383 if (m_ppPixMap) 384 { 385 delete[] m_ppPixMap->byteP; 386 delete[] m_ppPixMap; 387 } 388 } 389 else 390 { 391 if (m_ppPixMap) 392 { 393 delete[] m_ppPixMap->colourP; 394 delete[] m_ppPixMap; 395 } 396 } 397 } 398 399 virtual Colour * GetPalette(); 400 401 virtual PtrUnion GetRowPtr(unsigned nRow); 402 403 virtual void LoadNextRow(PtrUnion pRow); 404 405 // note: the palette size member must be set in 406 // LoadHeaderInfo() for these functions to work correctly 407 virtual unsigned GetNumColours(); 408 409 virtual unsigned GetMinPaletteSize(); 410 411 private: 412 PtrUnion * m_ppPixMap; 413 Colour * m_pPalette; 414 }; 415 416 class TexFileLoader : public AwBackupTexture 417 { 418 public: 419 SurfUnion Load(MediaMedium * pMedium, CreateTextureParms const & rParams); 420 421 protected: 422 // standard constructor 423 // & destructor 424 425 // Interface Functions. Each overridden version should set awTlLastErr 426 // when an error occurs 427 428 // Called to set the width and height members; the palette size member can also be safely set at this point. 429 // Neither the width height or palette size members need actually be set until AllocateBuffers returns 430 virtual void LoadHeaderInfo(MediaMedium * pMedium) = 0; 431 432 // should ensure that the palette size is set 433 virtual void AllocateBuffers(bool bWantBackup, unsigned nMaxPaletteSize) = 0; 434 435 virtual void OnFinishLoading(bool bSuccess); 436 437 virtual AwBackupTexture * CreateBackupTexture() = 0; 438 }; 439 440 class TypicalTexFileLoader : public TexFileLoader 441 { 442 protected: TypicalTexFileLoader()443 TypicalTexFileLoader() : m_pPalette(NULL), m_ppPixMap(NULL), m_pRowBuf(NULL) {} 444 445 virtual ~TypicalTexFileLoader(); 446 447 virtual unsigned GetNumColours(); 448 449 virtual unsigned GetMinPaletteSize(); 450 451 virtual void AllocateBuffers(bool bWantBackup, unsigned nMaxPaletteSize); 452 453 virtual PtrUnion GetRowPtr(unsigned nRow); 454 455 virtual AwBackupTexture * CreateBackupTexture(); 456 457 Colour * m_pPalette; 458 private: 459 PtrUnion * m_ppPixMap; 460 461 PtrUnion m_pRowBuf; 462 }; 463 464 extern void RegisterLoader(char const * pszMagic, AwTl::TexFileLoader * (* pfnCreate) () ); 465 466 } // namespace AwTl 467 468 #define AWTEXLD_IMPLEMENT_DYNCREATE(pszMagic, tokenClassName) _AWTEXLD_IMPLEMENT_DYNCREATE_LINE_EX(pszMagic,tokenClassName,__LINE__) 469 #define _AWTEXLD_IMPLEMENT_DYNCREATE_LINE_EX(pszMagic, tokenClassName, nLine) _AWTEXLD_IMPLEMENT_DYNCREATE_LINE(pszMagic,tokenClassName,nLine) 470 471 #define _AWTEXLD_IMPLEMENT_DYNCREATE_LINE(pszMagic,tokenClassName,nLine) \ 472 AwTl::TexFileLoader * AwTlCreateClassObject ##_## tokenClassName ##_## nLine () { \ 473 return new tokenClassName; \ 474 } \ 475 class AwTlRegisterLoaderClass ##_## tokenClassName ##_## nLine { \ 476 public: AwTlRegisterLoaderClass ##_## tokenClassName ##_## nLine () { \ 477 AwTl::RegisterLoader(pszMagic, AwTlCreateClassObject ##_## tokenClassName ##_## nLine); \ 478 } \ 479 } rlc ## tokenClassName ##_## nLine; 480 481 #endif // ! _INCLUDED_AWTEXLD_HPP_ 482