Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/dxgsg8/dxTextureContext8.cxx

Go to the documentation of this file.
00001 // Filename: dxTextureContext8.cxx
00002 // Created by:  georges (02Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include <assert.h>
00020 #include <time.h>
00021 #include "dxTextureContext8.h"
00022 #include "config_dxgsg8.h"
00023 #include "dxGraphicsStateGuardian8.h"
00024 //#include "pnmImage.h"
00025 #include "d3dx8tex.h"
00026 
00027 //#define FORCE_16bpp_1555
00028 static const DWORD g_LowByteMask = 0x000000FF;
00029 
00030 #define PANDA_BGRA_ORDER
00031 
00032 #ifdef PANDA_BGRA_ORDER
00033 // assume Panda uses byte-order BGRA/LA to store pixels, which when read into little-endian word is ARGB/AL
00034 // these macros GET from PixelBuffer, (wont work from DDSurface)
00035 #define GET_RED_BYTE(PIXEL_DWORD)  ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask))
00036 #define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD)       & g_LowByteMask))
00037 #else
00038 // otherwise Panda uses int ABGR (big-endian RGBA order), (byte-order RGBA or RGB)
00039 #define GET_RED_BYTE(PIXEL_DWORD)  ((BYTE)(PIXEL_DWORD         & g_LowByteMask))
00040 #define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask))
00041 #endif
00042 
00043 #define GET_GREEN_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 8) & g_LowByteMask))
00044 #define GET_ALPHA_BYTE(PIXEL_DWORD) ((BYTE)(((DWORD)PIXEL_DWORD) >> 24))  // unsigned >> shifts in 0's, so dont need to mask off upper bits
00045 
00046 #ifdef DO_CUSTOM_CONVERSIONS
00047 typedef enum {
00048     None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_X555,
00049     Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24,
00050     Conv24to16_X555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444,
00051     ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_X555,ConvLum8to16_0565,ConvLum8to16_A8L8,
00052     ConvAlpha8to16_4444,ConvAlpha8to32,ConvAlpha8to8,ConvAlpha8to16_A8L8
00053 } ConversionType;
00054 
00055 #ifndef NDEBUG
00056 char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_X555",
00057     "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24","Conv24to16_X555","Conv24to16_0565",
00058     "ConvLum16to16_1555","ConvLum16to16_4444","ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32",
00059     "ConvLum8to16_X555","ConvLum8to16_0565","ConvLum8to16_A8L8",
00060     "ConvAlpha8to16_4444","ConvAlpha8to32","ConvAlpha8to8","ConvAlpha8to16_A8L8"
00061 };
00062 #endif
00063 #endif
00064 
00065 char *PandaFilterNameStrs[] = {"FT_nearest","FT_linear","FT_nearest_mipmap_nearest","FT_linear_mipmap_nearest",
00066     "FT_nearest_mipmap_linear", "FT_linear_mipmap_linear"
00067 };
00068 
00069 
00070 TypeHandle DXTextureContext8::_type_handle;
00071 
00072 #define SWAPDWORDS(X,Y)  { DWORD temp=X;  X=Y; Y=temp; }
00073 
00074 #ifdef _DEBUG
00075 /*
00076 static void DebugPrintPixFmt(DDPIXELFORMAT* pddpf) {
00077     static int iddpfnum=0;
00078     ostream *dbgout = &dxgsg_cat.debug();
00079 
00080     *dbgout << "DDPF[" << iddpfnum << "]: RGBBitCount:" << pddpf->dwRGBBitCount
00081     << " Flags:"  << (void *)pddpf->dwFlags ;
00082 
00083     if(pddpf->dwFlags & DDPF_RGB) {
00084         *dbgout << " RGBmask:" << (void *) (pddpf->dwRBitMask | pddpf->dwGBitMask | pddpf->dwBBitMask);
00085         *dbgout << " Rmask:" << (void *) (pddpf->dwRBitMask);
00086     }
00087 
00088     if(pddpf->dwFlags & DDPF_ALPHAPIXELS) {
00089         *dbgout << " Amask:" << (void *) pddpf->dwRGBAlphaBitMask;
00090     }
00091 
00092     if(pddpf->dwFlags & DDPF_LUMINANCE) {
00093         *dbgout << " Lummask:" << (void *) pddpf->dwLuminanceBitMask;
00094     }
00095 
00096     *dbgout << endl;
00097 
00098     iddpfnum++;
00099 }
00100 */
00101 void PrintLastError(char *msgbuf) {
00102     DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
00103 
00104     if(msgbuf==NULL) {
00105         LPVOID lpMsgBuf;
00106         dwFlags|=FORMAT_MESSAGE_ALLOCATE_BUFFER;
00107         FormatMessage( dwFlags,
00108                        NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00109                        (LPTSTR) &lpMsgBuf,0,NULL );
00110         MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
00111         LocalFree(lpMsgBuf);
00112     } else {
00113         FormatMessage( dwFlags,
00114                        NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00115                        (LPTSTR) msgbuf,500,NULL );
00116     }
00117 }
00118 
00119 #endif
00120 
00121 
00122 /* for reference
00123 enum Format {
00124   F_color_index,
00125   F_stencil_index,
00126   F_depth_component,
00127   F_red,
00128   F_green,
00129   F_blue,
00130   F_alpha,
00131   F_rgb,     // any suitable RGB mode, whatever the hardware prefers
00132   F_rgb5,    // specifically, 5 bits per R,G,B channel
00133   F_rgb8,    // 8 bits per R,G,B channel
00134   F_rgb12,   // 12 bits per R,G,B channel
00135   F_rgb332,  // 3 bits per R & G, 2 bits for B
00136   F_rgba,    // any suitable RGBA mode, whatever the hardware prefers
00137   F_rgbm,    // as above, but only requires 1 bit for alpha (i.e. mask)
00138   F_rgba4,   // 4 bits per R,G,B,A channel
00139   F_rgba5,   // 5 bits per R,G,B channel, 1 bit alpha
00140   F_rgba8,   // 8 bits per R,G,B,A channel
00141   F_rgba12,  // 12 bits per R,G,B,A channel
00142   F_luminance,
00143   F_luminance_alpha
00144 };
00145 
00146   enum Type {
00147     T_unsigned_byte,   // 1 byte per channel
00148     T_unsigned_short,  // 2 byte per channel
00149     T_unsigned_byte_332,  // RGB in 1 byte
00150     T_float,             // 1 channel stored as float
00151   };
00152 */
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: DXTextureContext8::get_bits_per_pixel
00156 //       Access: Protected
00157 //  Description: Maps from the PixelBuffer's Format symbols
00158 //               to bpp.  returns # of alpha bits
00159 //               Note: PixelBuffer's format indicates REQUESTED final format,
00160 //                     not the stored format, which is indicated by pixelbuffer type
00161 ////////////////////////////////////////////////////////////////////
00162 
00163 unsigned int DXTextureContext8::
00164 get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) {
00165     *alphbits = 0;      // assume no alpha bits
00166     switch(format) {
00167         case PixelBuffer::F_alpha:
00168             *alphbits = 8;
00169         case PixelBuffer::F_color_index:
00170         case PixelBuffer::F_red:
00171         case PixelBuffer::F_green:
00172         case PixelBuffer::F_blue:
00173         case PixelBuffer::F_rgb332:
00174             return 8;
00175         case PixelBuffer::F_luminance_alphamask:
00176             *alphbits = 1;
00177             return 16;
00178         case PixelBuffer::F_luminance_alpha:
00179             *alphbits = 8;
00180             return 16;
00181         case PixelBuffer::F_luminance:
00182             return 8;
00183         case PixelBuffer::F_rgba4:
00184             *alphbits = 4;
00185             return 16;
00186         case PixelBuffer::F_rgba5:
00187             *alphbits = 1;
00188             return 16;
00189         case PixelBuffer::F_depth_component:
00190         case PixelBuffer::F_rgb5:
00191             return 16;
00192         case PixelBuffer::F_rgb8:
00193         case PixelBuffer::F_rgb:
00194             return 24;
00195         case PixelBuffer::F_rgba8:
00196         case PixelBuffer::F_rgba:
00197         case PixelBuffer::F_rgbm:
00198             if(format==PixelBuffer::F_rgbm)   // does this make any sense?
00199              *alphbits = 1;
00200             else *alphbits = 8;
00201             return 32;
00202         case PixelBuffer::F_rgb12:
00203             return 36;
00204         case PixelBuffer::F_rgba12:
00205             *alphbits = 12;
00206             return 48;
00207     }
00208     return 8;
00209 }
00210 
00211 /*   // This is superseded by D3DXLoadSurfaceFromMemory(), but keep this stuff around in case its needed
00212 
00213 #ifdef DO_CUSTOM_CONVERSIONS
00214 HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWSURFACE7 pDDSurf) {
00215     HRESULT hr;
00216     DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
00217 
00218     if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) {
00219         dxgsg_cat.error() << "ConvertPixBuftoDDSurf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n";
00220         exit(1);
00221     }
00222 
00223     if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd,  DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) {
00224         dxgsg_cat.error() << "CreateTexture failed: _surface->Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n";
00225         return hr;
00226     }
00227 
00228     //pbuf contains raw ARGB in PixelBuffer byteorder
00229 
00230     DWORD lPitch = ddsd.lPitch;
00231     BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface;
00232     DWORD dwOrigWidth=ddsd.dwWidth,dwOrigHeight=ddsd.dwHeight;
00233 
00234     switch(ConvNeeded) {
00235         case Conv32to32:
00236         case Conv32to32_NoAlpha: {
00237 
00238 #ifdef PANDA_BGRA_ORDER
00239                 if(ConvNeeded==Conv32to32) {
00240                     memcpy(pDDSurfBytes,(BYTE*) pbuf,dwOrigWidth*dwOrigHeight*sizeof(DWORD));
00241                 } else {
00242                     DWORD *pSrcWord = (DWORD *) pbuf;
00243                     DWORD *pDstWord;
00244 
00245                     // need to set all pixels alpha to 0xFF
00246                     for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00247                         pDstWord = (DWORD*)pDDSurfBytes;
00248                         for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00249                             *pDstWord = *pSrcWord | 0xFF000000;
00250                         }
00251                     }
00252                 }
00253 #else
00254                 DWORD *pDstWord,*pSrcWord = (DWORD *) pbuf;
00255                 DWORD dwAlphaMaskOn = (ConvNeeded==Conv32to32_NoAlpha) ? 0xFF000000 : 0x0;
00256 
00257                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00258                     pDstWord = (DWORD*)pDDSurfBytes;
00259                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00260                         DWORD dwPixel = *pSrcWord;
00261 
00262                         // pixel buffer is in ABGR format(it stores big-endian RGBA)
00263                         // need to change byte order to ARGB
00264 
00265                         BYTE r,b;
00266                         // just swap r & b
00267                         b = GET_BLUE_BYTE(dwPixel);
00268                         r = GET_RED_BYTE(dwPixel);
00269                         *pDstWord = ((dwPixel & 0xff00ff00) | (r<<16) | b) | dwAlphaMaskOn;
00270                     }
00271                 }
00272 #endif
00273                 break;
00274             }
00275 
00276         case Conv32to16_1555:
00277         case Conv32to16_X555: {
00278                 DWORD *pSrcWord = (DWORD *) pbuf;
00279                 WORD *pDstWord;
00280 
00281                 unsigned short dwAlphaMaskOn = (ConvNeeded==Conv32to16_X555) ? 0x8000 : 0x0;
00282 
00283                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00);
00284 
00285                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00286                     pDstWord = (WORD*)pDDSurfBytes;
00287 
00288                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00289                         BYTE r,g,b;
00290                         DWORD dwPixel = *pSrcWord;
00291                         unsigned short abit;
00292 
00293                         // just look at most-signf-bit for alpha.  (alternately, could
00294                         // convert any non-zero alpha to full transparent)
00295 
00296                         abit = ((dwPixel>>16) & 0x00008000) | dwAlphaMaskOn;  // just copy high bit
00297                         g = GET_GREEN_BYTE(dwPixel) >> 3;
00298                         b = GET_BLUE_BYTE(dwPixel) >> 3;
00299                         r = GET_RED_BYTE(dwPixel) >> 3;
00300 
00301                         // truncates 8 bit values to 5 bit (or 1 for alpha)
00302 
00303                         *pDstWord = (abit | (r << 10)| (g << 5) | b);
00304                     }
00305                 }
00306                 break;
00307             }
00308 
00309         case Conv32to16_0565: {   // could merge this w/above case, but whatever
00310                 DWORD *pSrcWord = (DWORD *) pbuf;
00311                 WORD *pDstWord;
00312 
00313                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800);
00314                 // for some reason, bits are 'in-order' when converting to 16bit
00315 
00316                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00317                     pDstWord = (WORD*)pDDSurfBytes;
00318 
00319                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00320                         BYTE r,g,b;
00321                         DWORD dwPixel = *pSrcWord;
00322 
00323                         g = GET_GREEN_BYTE(dwPixel) >> 2;
00324                         b = GET_BLUE_BYTE(dwPixel) >> 3;
00325                         r = GET_RED_BYTE(dwPixel) >> 3;
00326                         *pDstWord = ((r << 11)| (g << 5) | b);
00327                     }
00328                 }
00329                 break;
00330             }
00331 
00332         case Conv32to16_4444: {
00333                 DWORD *pSrcWord = (DWORD *) pbuf;
00334                 WORD *pDstWord;
00335 
00336                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000);  // assumes ARGB
00337                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0x0f00);  // assumes ARGB
00338 
00339                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00340                     pDstWord = (WORD*)pDDSurfBytes;
00341 
00342                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00343                         BYTE r,g,b,a;
00344                         DWORD dwPixel = *pSrcWord;
00345 
00346                         a = GET_ALPHA_BYTE(dwPixel)  >> 4;
00347                         g = GET_GREEN_BYTE(dwPixel)  >> 4;
00348                         b = GET_BLUE_BYTE(dwPixel)   >> 4;
00349                         r = GET_RED_BYTE(dwPixel)    >> 4;
00350 
00351                         *pDstWord = (a << 12) | (r << 8)| (g << 4) | b;
00352                     }
00353                 }
00354                 break;
00355             }
00356 
00357         case Conv32to24: {
00358 
00359                 DWORD *pSrcWord = (DWORD *) pbuf;
00360                 BYTE *pDstWord;
00361 
00362                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00363                     pDstWord = (BYTE*)pDDSurfBytes;
00364 
00365                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord+=3) {
00366                         BYTE r,g,b;
00367                         DWORD dwPixel = *pSrcWord;
00368 
00369                         r = GET_RED_BYTE(dwPixel);
00370                         g = GET_GREEN_BYTE(dwPixel);
00371                         b = GET_BLUE_BYTE(dwPixel);
00372 
00373                         *pDstWord     = r;
00374                         *(pDstWord+1) = g;
00375                         *(pDstWord+2) = b;
00376                     }
00377                 }
00378                 break;
00379             }
00380 
00381 
00382         case Conv24to24: {
00383             #ifdef PANDA_BGRA_ORDER
00384                 memcpy(pDDSurfBytes,(BYTE*)pbuf,dwOrigHeight*dwOrigWidth*3);
00385             #else
00386                 BYTE *pSrcWord = (BYTE *) pbuf;
00387                 BYTE *pDstWord;
00388 
00389                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00390                     pDstWord = (BYTE*)pDDSurfBytes;
00391 
00392                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord+=3) {
00393                         BYTE r,g,b;
00394 
00395                         b = *pSrcWord;
00396                         g = *(pSrcWord+1);
00397                         r = *(pSrcWord+2);
00398 
00399                         *pDstWord     = r;
00400                         *(pDstWord+1) = g;
00401                         *(pDstWord+2) = b;
00402                     }
00403                 }
00404              #endif
00405                 break;
00406             }
00407 
00408         case Conv24to16_X555: {
00409                 BYTE *pSrcWord = (BYTE *) pbuf;
00410                 WORD *pDstWord;
00411 
00412                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00);
00413              // for some reason, bits are 'in-order' when converting to 16bit
00414 
00415                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00416                     pDstWord = (WORD*)pDDSurfBytes;
00417 
00418                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord++) {
00419                         BYTE r,g,b;
00420 
00421                     #ifdef PANDA_BGRA_ORDER
00422                         b = *pSrcWord       >> 3;
00423                         r = *(pSrcWord+2)   >> 3;
00424                     #else
00425                         r = *pSrcWord       >> 3;
00426                         b = *(pSrcWord+2)   >> 3;
00427                     #endif
00428                         g = *(pSrcWord+1)   >> 3;
00429 
00430                         *pDstWord = 0x8000 | (r << 10)| (g << 5) | b;
00431                     }
00432                 }
00433                 break;
00434             }
00435 
00436         case Conv24to16_0565: {
00437                 BYTE *pSrcWord = (BYTE *) pbuf;
00438                 WORD *pDstWord;
00439 
00440                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800);
00441 
00442                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00443                     pDstWord = (WORD*)pDDSurfBytes;
00444 
00445                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord++) {
00446                         BYTE r,g,b;
00447 
00448                     #ifdef PANDA_BGRA_ORDER
00449                         b = *pSrcWord       >> 3;
00450                         g = *(pSrcWord+1)   >> 2;
00451                         r = *(pSrcWord+2)   >> 3;
00452                     #else
00453                         r = *pSrcWord       >> 3;
00454                         g = *(pSrcWord+1)   >> 2;
00455                         b = *(pSrcWord+2)   >> 3;
00456                     #endif
00457                      // code truncates 8 bit values to 5 bit
00458                      *pDstWord = (r << 11)| (g << 5) | b;
00459                     }
00460                 }
00461                 break;
00462             }
00463 
00464         case Conv24to32: {
00465                 BYTE *pSrcWord = (BYTE *) pbuf;
00466                 DWORD *pDstWord;
00467 
00468                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00469                     pDstWord = (DWORD *)pDDSurfBytes;
00470 
00471                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord++) {
00472                         BYTE r,g,b;
00473                         // pixel buffer is in ABGR format(it stores big-endian RGBA)
00474                         // need to change byte order to ARGB
00475 
00476                     #ifdef PANDA_BGRA_ORDER
00477                         b = *pSrcWord;
00478                         r = *(pSrcWord+2);
00479                     #else
00480                         r = *pSrcWord;
00481                         b = *(pSrcWord+2);
00482                     #endif
00483                         g = *(pSrcWord+1);
00484 
00485                         *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b;
00486                     }
00487                 }
00488                 break;
00489             }
00490 
00491         case ConvLum16to32: {
00492                 WORD *pSrcWord = (WORD *) pbuf;
00493                 DWORD *pDstWord;
00494 
00495                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00496                     pDstWord = (DWORD *)pDDSurfBytes;
00497 
00498                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00499                         // pixel buffer is in ABGR format(it stores big-endian RGBA)
00500                         // need to change byte order to ARGB
00501                         DWORD dwPixel=*pSrcWord;
00502                         BYTE lum,a;
00503 
00504                         a = dwPixel >> 8;
00505                         lum = dwPixel & 0xFF;
00506                         *pDstWord = (a<<24) | lum | (lum << 8) | (lum << 16);
00507                     }
00508                 }
00509                 break;
00510             }
00511 
00512         case ConvLum16to16_4444: {
00513                 WORD *pSrcWord = (WORD *) pbuf;
00514                 WORD *pDstWord;
00515 
00516                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000);  // assumes ARGB
00517 
00518                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00519                     pDstWord = (WORD*)pDDSurfBytes;
00520 
00521                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00522                         DWORD dwPixel=*pSrcWord;
00523                         BYTE lum,a;
00524                         dwPixel = *pSrcWord;
00525 
00526                         a =   (BYTE)(dwPixel>>8)           >> 4;
00527                         lum = (BYTE)(dwPixel & 0x000000ff) >> 4;
00528 
00529                         *pDstWord = (a << 12) | lum | (lum << 4)| (lum << 8);
00530                     }
00531                 }
00532                 break;
00533             }
00534 
00535         case ConvLum16to16_1555: {
00536                 WORD *pSrcWord = (WORD *) pbuf;
00537                 WORD *pDstWord;
00538 
00539                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0x8000);  // assumes ARGB
00540 
00541                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00542                     pDstWord = (WORD*)pDDSurfBytes;
00543 
00544                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00545                         WORD dwPixel=*pSrcWord;
00546                         BYTE lum;
00547 
00548                         lum = (BYTE)(dwPixel & 0x00FF) >> 3;
00549 
00550                         *pDstWord = (dwPixel & 0x8000) | lum | (lum << 5) | (lum << 10);
00551                     }
00552                 }
00553                 break;
00554             }
00555 
00556         case ConvLum16to16: {
00557                 // All bytes are in same order?
00558                 CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2);
00559                 break;
00560             }
00561 
00562         case ConvLum8to16_0565:
00563         case ConvLum8to16_X555: {
00564                 BYTE *pSrcWord = (BYTE *) pbuf;
00565                 WORD *pDstWord;
00566                 DWORD FarShift,OrVal,MiddleRoundShift;
00567 
00568                 if(ConvNeeded==ConvLum8to16_X555) {
00569                     FarShift=10;  OrVal=0x8000;  // turn on alpha bit, just in case
00570                     MiddleRoundShift = 3;
00571                     assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00);
00572                 } else {
00573                     FarShift=11;  OrVal=0x0;
00574                     MiddleRoundShift = 2;
00575                     assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800);
00576                 }
00577 
00578                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00579                     pDstWord = (WORD*)pDDSurfBytes;
00580 
00581                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00582                         DWORD dwPixel=*pSrcWord,GrnVal;
00583                         BYTE r;
00584 
00585                         r = (BYTE) dwPixel >> 3;
00586                         GrnVal = (BYTE) dwPixel >> MiddleRoundShift;
00587 
00588                         // code truncates 8 bit values to 5 bit  (set alpha=1 for opaque)
00589 
00590                         *pDstWord = ((r << FarShift)| (GrnVal << 5) | r) | OrVal;
00591                     }
00592                 }
00593                 break;
00594             }
00595 
00596         case ConvLum8to8: {
00597                 CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight);
00598                 break;
00599             }
00600 
00601         case ConvLum8to32: {
00602 
00603           // this is kind of a waste of space, but we trade it for lum resolution
00604                 BYTE *pSrcWord = (BYTE *) pbuf;
00605                 DWORD *pDstWord;
00606 
00607                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00608                     pDstWord = (DWORD *)pDDSurfBytes;
00609 
00610                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00611                         DWORD dwPixel=*pSrcWord;
00612 
00613                         *pDstWord = 0xFF000000 | dwPixel | (dwPixel << 8) | (dwPixel<<16);
00614                     }
00615                 }
00616                 break;
00617             }
00618 
00619         case ConvLum8to24: {
00620                 // this is kind of a waste of space, but we trade it for lum resolution
00621                 BYTE *pSrcWord = (BYTE *) pbuf;
00622                 BYTE *pDstWord;
00623 
00624                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00625                     pDstWord = (BYTE *)pDDSurfBytes;
00626 
00627                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00628                         DWORD dwPixel=*pSrcWord;
00629 
00630                         *pDstWord++ = dwPixel;
00631                         *pDstWord++ = dwPixel;
00632                         *pDstWord   = dwPixel;
00633                     }
00634                 }
00635                 break;
00636             }
00637 
00638        case ConvLum8to16_A8L8: {
00639                 // wastes space, since alpha is just fully opaque, but Lum-only may not be avail
00640                 BYTE *pSrcWord = (BYTE *) pbuf;
00641                 WORD *pDstWord;
00642 
00643                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00644                     pDstWord = (DWORD *)pDDSurfBytes;
00645 
00646                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00647                         *pDstWord = 0xFF00 | *pSrcWord;   // add fully-opaque alpha
00648                     }
00649                 }
00650                 break;
00651         }
00652 
00653         case ConvAlpha8to16_A8L8: {
00654             // need to investigate why alpha-only A8 surfaces dont work on voodoo's
00655                 BYTE *pSrcWord = (BYTE *) pbuf;
00656                 WORD *pDstWord;
00657 
00658                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00659                     pDstWord = (DWORD *)pDDSurfBytes;
00660 
00661                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00662                         *pDstWord = (*pSrcWord << 8) | 0x00FF;   // add full white
00663                     }
00664                 }
00665                 break;
00666         }
00667 
00668         case ConvAlpha8to32: {
00669               //  huge waste of space, but this may be only fmt where we get 8bits alpha resolution
00670                 BYTE *pSrcWord = (BYTE *) pbuf;
00671                 DWORD *pDstWord;
00672 
00673                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00674                     pDstWord = (DWORD *)pDDSurfBytes;
00675 
00676                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00677                         // OR alpha with full white
00678                         *pDstWord = (*pSrcWord << 24) | 0x00FFFFFF;
00679                     }
00680                 }
00681                 break;
00682             }
00683 
00684         case ConvAlpha8to16_4444: {
00685                 BYTE *pSrcWord = (BYTE *) pbuf;
00686                 WORD *pDstWord;
00687 
00688                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000);  // assumes ARGB order
00689 
00690                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00691                     pDstWord = (WORD*)pDDSurfBytes;
00692 
00693                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00694                         WORD a = (BYTE)(*pSrcWord>>4);
00695                         *pDstWord = (a << 12) | 0x0FFF; // OR alpha with full white
00696                     }
00697                 }
00698                 break;
00699             }
00700 
00701         default:
00702             dxgsg_cat.error() << "CreateTexture failed! unhandled texture conversion type: "<< ConvNeeded <<" \n";
00703             pDDSurf->Unlock(NULL);
00704             return E_INVALIDARG;
00705     }
00706 
00707     pDDSurf->Unlock(NULL);
00708 
00709     return S_OK;
00710 }
00711 #endif
00712 */
00713 
00714 // still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer
00715 HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf) {
00716 // copies SrcRect in pD3DSurf to upper left of pixbuf
00717     HRESULT hr;
00718     DWORD dwNumComponents=pixbuf->get_num_components();
00719 
00720     assert(pixbuf->get_component_width()==sizeof(BYTE));   // cant handle anything else now
00721     assert(pixbuf->get_image_type()==PixelBuffer::T_unsigned_byte);   // cant handle anything else now
00722     assert((dwNumComponents==3) || (dwNumComponents==4));  // cant handle anything else now
00723     assert(IS_VALID_PTR(pD3DSurf8));
00724 
00725     BYTE *pbuf=pixbuf->_image.p();
00726 
00727     if(IsBadWritePtr(pD3DSurf8,sizeof(DWORD))) {
00728         dxgsg8_cat.error() << "ConvertDDSurftoPixBuf failed: bad pD3DSurf ptr value (" << ((void*)pD3DSurf8) << ")\n";
00729         exit(1);
00730     }
00731 
00732     DWORD dwXWindowOffset,dwYWindowOffset;
00733     DWORD dwCopyWidth,dwCopyHeight;
00734 
00735     D3DLOCKED_RECT LockedRect;
00736     D3DSURFACE_DESC SurfDesc;
00737 
00738     hr = pD3DSurf8->GetDesc(&SurfDesc);
00739 
00740     dwXWindowOffset=SrcRect.left,dwYWindowOffset=SrcRect.top;
00741     dwCopyWidth=RECT_XSIZE(SrcRect);
00742     dwCopyHeight=RECT_YSIZE(SrcRect);
00743 
00744     //make sure there's enough space in the pixbuf, its size must match (especially xsize)
00745    // or scanlines will be too long
00746 
00747     if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) {
00748         dxgsg8_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size too small to hold display surface!\n";
00749         assert(0);
00750         return E_FAIL;
00751     }
00752 
00753     hr = pD3DSurf8->LockRect(&LockedRect,(CONST RECT*)NULL,(D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE /* | D3DLOCK_NOSYSLOCK */));
00754     if(FAILED(hr)) {
00755         dxgsg8_cat.error() << "ConvertDDSurftoPixBuf LockRect() failed!" << D3DERRORSTRING(hr);
00756         return hr;
00757     }
00758 
00759     // ones not listed not handled yet
00760     assert((SurfDesc.Format==D3DFMT_A8R8G8B8)||(SurfDesc.Format==D3DFMT_X8R8G8B8)||(SurfDesc.Format==D3DFMT_R8G8B8)||
00761            (SurfDesc.Format==D3DFMT_R5G6B5)||(SurfDesc.Format==D3DFMT_X1R5G5B5)||(SurfDesc.Format==D3DFMT_A1R5G5B5)||
00762            (SurfDesc.Format==D3DFMT_A4R4G4B4));
00763 
00764     //pbuf contains raw ARGB in PixelBuffer byteorder
00765 
00766     DWORD BytePitch = LockedRect.Pitch;
00767     BYTE* pSurfBytes = (BYTE*)LockedRect.pBits;
00768 
00769     // writes out last line in DDSurf first in PixelBuf, so Y line order precedes inversely
00770 
00771     if(dxgsg8_cat.is_debug()) {
00772         dxgsg8_cat.debug() << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to "
00773                           <<  dwNumComponents << "-channel panda PixelBuffer\n";
00774     }
00775 
00776     DWORD *pDstWord = (DWORD *) pbuf;
00777     BYTE *pDstByte = (BYTE *) pbuf;
00778 
00779     switch(SurfDesc.Format) {
00780         case D3DFMT_A8R8G8B8:
00781         case D3DFMT_X8R8G8B8: {
00782             if(dwNumComponents==4) {
00783                     DWORD *pSrcWord;
00784                    #ifdef PANDA_BGRA_ORDER
00785                     BYTE *pDstLine = (BYTE*)pDstWord;
00786                    #endif
00787 
00788                         pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1);
00789                         for(DWORD y=0; y<dwCopyHeight; y++,pSurfBytes-=BytePitch) {
00790                             pSrcWord = ((DWORD*)pSurfBytes)+dwXWindowOffset;
00791                             #ifdef PANDA_BGRA_ORDER
00792                                 memcpy(pDstLine,pSrcWord,BytePitch);
00793                                 pDstLine+=BytePitch;
00794                             #else
00795                                 for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++,pDstWord++) {
00796                                       DWORD dwPixel = *pSrcWord;
00797                                       BYTE r,b;
00798 
00799                                       // DDsurf is in ARGB
00800                                       r=  (BYTE) ((dwPixel >> 16) & g_LowByteMask);
00801                                       b = (BYTE)  (dwPixel & g_LowByteMask);
00802 
00803                                       // want to write out ABGR
00804                                       *pDstWord = (dwPixel & 0xFF00FF00) | (b<<16) | r;
00805                                 }
00806                             #endif
00807                         }
00808             } else {
00809                 // 24bpp pixbuf case (numComponents==3)
00810                 DWORD *pSrcWord;
00811                 pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1);
00812                 for(DWORD y=0; y<dwCopyHeight; y++,pSurfBytes-=BytePitch) {
00813                     pSrcWord = ((DWORD*)pSurfBytes)+dwXWindowOffset;
00814 
00815                     for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++) {
00816                         BYTE r,g,b;
00817                         DWORD dwPixel = *pSrcWord;
00818 
00819                         r = (BYTE)((dwPixel>>16) & g_LowByteMask);
00820                         g = (BYTE)((dwPixel>> 8) & g_LowByteMask);
00821                         b = (BYTE)((dwPixel    ) & g_LowByteMask);
00822 
00823                         #ifdef PANDA_BGRA_ORDER
00824                             *pDstByte++ = b;
00825                             *pDstByte++ = g;
00826                             *pDstByte++ = r;
00827                         #else
00828                             *pDstByte++ = r;
00829                             *pDstByte++ = g;
00830                             *pDstByte++ = b;
00831                         #endif
00832                     }
00833                 }
00834             }
00835             break;
00836         }
00837 
00838         case D3DFMT_R8G8B8: {
00839                 BYTE *pSrcByte;
00840                 pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1);
00841 
00842                 if(dwNumComponents==4) {
00843                     for(DWORD y=0; y<dwCopyHeight; y++,pSurfBytes-=BytePitch) {
00844                         pSrcByte = pSurfBytes+dwXWindowOffset*3*sizeof(BYTE);
00845                         for(DWORD x=0; x<dwCopyWidth; x++,pDstWord++) {
00846                             DWORD r,g,b;
00847 
00848                             b = *pSrcByte++;
00849                             g = *pSrcByte++;
00850                             r = *pSrcByte++;
00851 
00852                             #ifdef PANDA_BGRA_ORDER
00853                                *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b;
00854                             #else
00855                                *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r;
00856                             #endif
00857                         }
00858                     }
00859                 } else {
00860                     // 24bpp pixbuf case (numComponents==3)
00861                     for(DWORD y=0; y<dwCopyHeight; y++,pSurfBytes-=BytePitch) {
00862                         pSrcByte = pSurfBytes+dwXWindowOffset*3*sizeof(BYTE);
00863                      #ifdef PANDA_BGRA_ORDER
00864                         memcpy(pDstByte,pSrcByte,BytePitch);
00865                         pDstByte+=BytePitch;
00866                      #else
00867                         for(DWORD x=0; x<dwCopyWidth; x++) {
00868                             BYTE r,g,b;
00869 
00870                             // pixel buffer is in ABGR format(it stores big-endian RGBA)
00871                             // need to change byte order from ARGB
00872 
00873                             b = *pSrcByte++;
00874                             g = *pSrcByte++;
00875                             r = *pSrcByte++;
00876 
00877                             *pDstByte++ = r;
00878                             *pDstByte++ = g;
00879                             *pDstByte++ = b;
00880                         }
00881                       #endif
00882                     }
00883                 }
00884                 break;
00885         }
00886 
00887         case D3DFMT_R5G6B5:
00888         case D3DFMT_X1R5G5B5:
00889         case D3DFMT_A1R5G5B5:
00890         case D3DFMT_A4R4G4B4: {
00891                 WORD  *pSrcWord;
00892                 // handle 0555,1555,0565,4444 in same loop
00893 
00894                 BYTE redshift,greenshift,blueshift;
00895                 DWORD redmask,greenmask,bluemask;
00896 
00897                 if(SurfDesc.Format==D3DFMT_R5G6B5) {
00898                     redshift=(11-3);
00899                     redmask=0xF800;
00900                     greenmask=0x07E0;
00901                     greenshift=(5-2);
00902                     bluemask=0x001F;
00903                     blueshift=3;
00904                 } else if(SurfDesc.Format==D3DFMT_A4R4G4B4) {
00905                     redmask=0x0F00;
00906                     redshift=4;
00907                     greenmask=0x00F0;
00908                     greenshift=0;
00909                     bluemask=0x000F;
00910                     blueshift=4;
00911                 } else {  // 1555 or x555
00912                     redmask=0x7C00;
00913                     redshift=(10-3);
00914                     greenmask=0x03E0;
00915                     greenshift=(5-3);
00916                     bluemask=0x001F;
00917                     blueshift=3;
00918                 }
00919 
00920                 pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1);
00921                 if(dwNumComponents==4) {
00922                     // Note: these 16bpp loops ignore input alpha completely (alpha is set to fully opaque in pixbuf!)
00923                     //       if we need to capture alpha, probably need to make separate loops for diff 16bpp fmts
00924                     //       for best speed
00925 
00926                     for(DWORD y=0; y<dwCopyHeight; y++,pSurfBytes-=BytePitch) {
00927                         pSrcWord = ((WORD*)pSurfBytes)+dwXWindowOffset;
00928                         for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++,pDstWord++) {
00929                             WORD dwPixel = *pSrcWord;
00930                             BYTE r,g,b;
00931 
00932                             b = (dwPixel & bluemask) << blueshift;
00933                             g = (dwPixel & greenmask) >> greenshift;
00934                             r = (dwPixel & redmask) >> redshift;
00935 
00936                             // alpha is just set to 0xFF
00937 
00938                             #ifdef PANDA_BGRA_ORDER
00939                               *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b;
00940                             #else
00941                               *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r;
00942                             #endif
00943                         }
00944                     }
00945                 } else {
00946                     // 24bpp pixbuf case (numComponents==3)
00947                     for(DWORD y=0; y<dwCopyHeight; y++,pSurfBytes-=BytePitch) {
00948                         pSrcWord = ((WORD*)pSurfBytes)+dwXWindowOffset;
00949                         for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++) {
00950                             WORD dwPixel = *pSrcWord;
00951                             BYTE r,g,b;
00952 
00953                             b = (dwPixel & bluemask) << blueshift;
00954                             g = (dwPixel & greenmask) >> greenshift;
00955                             r = (dwPixel & redmask) >> redshift;
00956 
00957                             #ifdef PANDA_BGRA_ORDER
00958                                 *pDstByte++ = b;
00959                                 *pDstByte++ = g;
00960                                 *pDstByte++ = r;
00961                             #else
00962                                 *pDstByte++ = r;
00963                                 *pDstByte++ = g;
00964                                 *pDstByte++ = b;
00965                             #endif
00966                         }
00967                     }
00968                 }
00969                 break;
00970         }
00971 
00972         default:
00973             dxgsg8_cat.error() << "ConvertD3DSurftoPixBuf: unsupported D3DFORMAT!\n";
00974     }
00975 
00976     pD3DSurf8->UnlockRect();
00977     return S_OK;
00978 }
00979 
00980 //-----------------------------------------------------------------------------
00981 // Name: CreateTexture()
00982 // Desc: Use panda texture's pixelbuffer to create a texture for the specified device.
00983 //       This code gets the attributes of the texture from the bitmap, creates the
00984 //       texture, and then copies the bitmap into the texture.
00985 //-----------------------------------------------------------------------------
00986 IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
00987     HRESULT hr;
00988     int cNumAlphaBits;     //  number of alpha bits in texture pixfmt
00989     D3DFORMAT TargetPixFmt=D3DFMT_UNKNOWN;
00990     bool bNeedLuminance = false;
00991 
00992     assert(IS_VALID_PTR(_texture));
00993 
00994     PixelBuffer *pbuf = _texture->_pbuffer;
00995     // bpp indicates requested fmt, not pixbuf fmt
00996     DWORD target_bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits);
00997     PixelBuffer::Type pixbuf_type = pbuf->get_image_type();
00998     DWORD cNumColorChannels = pbuf->get_num_components();
00999 
01000     assert(pbuf->get_component_width()==sizeof(BYTE));   // cant handle anything else now
01001     assert(pixbuf_type==PixelBuffer::T_unsigned_byte);   // cant handle anything else now
01002 
01003     //PRINT_REFCNT(dxgsg8,scrn.pD3D8);
01004 
01005     if((pixbuf_type!=PixelBuffer::T_unsigned_byte) || (pbuf->get_component_width()!=1)) {
01006         dxgsg8_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n";
01007         return NULL;
01008     }
01009 
01010     DWORD dwOrigWidth  = (DWORD)pbuf->get_xsize();
01011     DWORD dwOrigHeight = (DWORD)pbuf->get_ysize();
01012 
01013     if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)||
01014        (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) ||
01015        (pbuf->get_format() == PixelBuffer::F_luminance)) {
01016         bNeedLuminance = true;
01017     }
01018 
01019     if(cNumAlphaBits>0) {
01020         if(cNumColorChannels==3) {
01021             dxgsg8_cat.error() << "ERROR: texture " << _tex->get_name() << " has no inherent alpha channel, but alpha format is requested (that would be wasteful)!\n";
01022             exit(1);
01023         }
01024     }
01025 
01026     _PixBufD3DFmt=D3DFMT_UNKNOWN;
01027 
01028 #ifndef DO_CUSTOM_CONVERSIONS
01029     // figure out what 'D3DFMT' the PixelBuffer is in, so D3DXLoadSurfFromMem knows how to perform copy
01030 
01031     switch(cNumColorChannels) {
01032         case 1:
01033             if(cNumAlphaBits>0)
01034                 _PixBufD3DFmt=D3DFMT_A8;
01035             else if(bNeedLuminance)
01036                    _PixBufD3DFmt=D3DFMT_L8;
01037             break;
01038         case 2:
01039             assert(bNeedLuminance && (cNumAlphaBits>0));
01040             _PixBufD3DFmt=D3DFMT_A8L8;
01041             break;
01042         case 3:
01043             _PixBufD3DFmt=D3DFMT_R8G8B8;
01044             break;
01045         case 4:
01046             _PixBufD3DFmt=D3DFMT_A8R8G8B8;
01047             break;
01048     }
01049 
01050     // make sure we handled all the possible cases
01051     assert(_PixBufD3DFmt!=D3DFMT_UNKNOWN);
01052 #endif
01053 
01054     DWORD TargetWidth=dwOrigWidth;
01055     DWORD TargetHeight=dwOrigHeight;
01056 
01057     if(!ISPOW2(dwOrigWidth) || !ISPOW2(dwOrigHeight)) {
01058         dxgsg8_cat.error() << "ERROR: texture dimensions are not a power of 2 for " << _tex->get_name() << "! Please rescale them so it doesnt have to be done at runtime.\n";
01059         #ifndef NDEBUG
01060           exit(1);  // want to catch badtexsize errors
01061         #else
01062           goto error_exit;
01063         #endif
01064     }
01065 
01066     bool bShrinkOriginal;
01067     bShrinkOriginal=false;
01068 
01069     if((dwOrigWidth>scrn.d3dcaps.MaxTextureWidth)||(dwOrigHeight>scrn.d3dcaps.MaxTextureHeight)) {
01070         #ifdef _DEBUG
01071            dxgsg8_cat.error() << "WARNING: " <<_tex->get_name() << ": Image size exceeds max texture dimensions of (" << scrn.d3dcaps.MaxTextureWidth << "," << scrn.d3dcaps.MaxTextureHeight << ") !!\n"
01072            << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," <<dwOrigHeight << ") => ("<<  scrn.d3dcaps.MaxTextureWidth << "," << scrn.d3dcaps.MaxTextureHeight << ") !\n";
01073         #endif
01074 
01075         if(dwOrigWidth>scrn.d3dcaps.MaxTextureWidth)
01076             TargetWidth=scrn.d3dcaps.MaxTextureWidth;
01077         if(dwOrigHeight>scrn.d3dcaps.MaxTextureHeight)
01078             TargetHeight=scrn.d3dcaps.MaxTextureHeight;
01079         bShrinkOriginal=true;
01080     }
01081 
01082     // checks for SQUARE reqmt (nvidia riva128 needs this)
01083     if((TargetWidth != TargetHeight) && (scrn.d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)) {
01084         // assume pow2 textures.   sum exponents, divide by 2 rounding down to get sq size
01085         int i,width_exp,height_exp;
01086         for(i=TargetWidth,width_exp=0;i>1;width_exp++,i>>=1);
01087         for(i=TargetHeight,height_exp=0;i>1;height_exp++,i>>=1);
01088         TargetHeight = TargetWidth = 1<<((width_exp+height_exp)>>1);
01089         bShrinkOriginal=true;
01090 
01091 #ifdef _DEBUG
01092         dxgsg8_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," <<dwOrigHeight << ") => ("<< TargetWidth<<"," << TargetHeight << ") to meet HW square texture reqmt\n";
01093 #endif
01094     }
01095 /*
01096     // we now use D3DXLoadSurfFromMem to do resizing as well as fmt conversion
01097     if(bShrinkOriginal) {
01098         // need 2 add checks for errors
01099         PNMImage pnmi_src;
01100         PNMImage *pnmi = new PNMImage(TargetWidth, TargetHeight, cNumColorChannels);
01101         pbuf->store(pnmi_src);
01102         pnmi->quick_filter_from(pnmi_src,0,0);
01103 
01104         pbuf->load(*pnmi);  // violates device independence of pixbufs
01105 
01106         dwOrigWidth  = (DWORD)pbuf->get_xsize();
01107         dwOrigHeight = (DWORD)pbuf->get_ysize();
01108         delete pnmi;
01109     }
01110 */
01111 
01112     char *szErrorMsg;
01113 
01114     szErrorMsg = "CreateTexture failed: couldn't find compatible device Texture Pixel Format for input texture";
01115 
01116     if(dxgsg8_cat.is_spam())
01117         dxgsg8_cat.spam() << "CreateTexture handling target bitdepth: " << target_bpp << " alphabits: " << cNumAlphaBits << endl;
01118 
01119     // I could possibly replace some of this logic with D3DXCheckTextureRequirements(), but
01120     // it wouldnt handle all my specialized low-memory cases perfectly
01121 
01122 #ifdef DO_CUSTOM_CONVERSIONS
01123     ConversionType ConvNeeded;
01124 
01125 #define CONVTYPE_STMT ConvNeeded=CONV
01126 #else
01127 #define CONVTYPE_STMT
01128 #endif
01129 
01130 #define CHECK_FOR_FMT(FMT,CONV)  \
01131                     if(scrn.SupportedTexFmtsMask & FMT##_FLAG) {   \
01132                         CONVTYPE_STMT;                             \
01133                         TargetPixFmt=D3DFMT_##FMT;                 \
01134                         goto found_matching_format; }
01135 
01136     // handle each target bitdepth separately.  might be less confusing to reorg by cNumColorChannels (input type, rather
01137     // than desired 1st target)
01138     switch(target_bpp) {
01139 
01140     // IMPORTANT NOTE:
01141     // target_bpp is REQUESTED bpp, not what exists in the pixbuf array (the pixbuf array contains cNumColorChannels*8bits)
01142 
01143         case 32:
01144             if(!((cNumColorChannels==3) || (cNumColorChannels==4)))
01145                 break; //bail
01146 
01147             if(!dx_force_16bpptextures) {
01148                 if(cNumColorChannels==4) {
01149                     CHECK_FOR_FMT(A8R8G8B8,Conv32to32);
01150                 } else {
01151                     CHECK_FOR_FMT(A8R8G8B8,Conv24to32);
01152                 }
01153             }
01154 
01155             if(cNumAlphaBits>0) {
01156                 assert(cNumColorChannels==4);
01157 
01158             // no 32-bit fmt, look for 16 bit w/alpha  (1-15)
01159 
01160             // 32 bit RGBA was requested, but only 16 bit alpha fmts are avail
01161             // by default, convert to 4-4-4-4 which has 4-bit alpha for blurry edges
01162             // if we know tex only needs 1 bit alpha (i.e. for a mask), use 1555 instead
01163 
01164 //                ConversionType ConvTo1=Conv32to16_4444,ConvTo2=Conv32to16_1555;
01165 //                DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000;
01166             // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion
01167             // this should be true on most cards.
01168 
01169 #ifndef FORCE_16bpp_1555
01170                 if(cNumAlphaBits==1)
01171 #endif
01172                 {
01173                     CHECK_FOR_FMT(A1R5G5B5,Conv32to16_1555);
01174                 }
01175 
01176                 // normally prefer 4444 due to better alpha channel resolution
01177                 CHECK_FOR_FMT(A4R4G4B4,Conv32to16_4444);
01178                 CHECK_FOR_FMT(A1R5G5B5,Conv32to16_1555);
01179 
01180                 // at this point, bail.  dont worry about converting to non-alpha formats yet,
01181                 // I think this will be a very rare case
01182                 szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!";
01183             } else {
01184                 // convert 3 or 4 channel to closest 16bpp color fmt
01185 
01186                 if(cNumColorChannels==3) {
01187                     CHECK_FOR_FMT(R5G6B5,Conv24to16_4444);
01188                     CHECK_FOR_FMT(X1R5G5B5,Conv24to16_X555);
01189                 } else {
01190                     CHECK_FOR_FMT(R5G6B5,Conv32to16_4444);
01191                     CHECK_FOR_FMT(X1R5G5B5,Conv32to16_X555);
01192                 }
01193             }
01194             break;
01195 
01196         case 24:
01197             assert(cNumColorChannels==3);
01198 
01199             if(!dx_force_16bpptextures) {
01200                 CHECK_FOR_FMT(R8G8B8,Conv24to24);
01201 
01202                 // no 24-bit fmt.  look for 32 bit fmt  (note: this is memory-hogging choice
01203                 // instead I could look for memory-conserving 16-bit fmt).
01204 
01205                 CHECK_FOR_FMT(X8R8G8B8,Conv24to32);
01206             }
01207 
01208              // no 24-bit or 32 fmt.  look for 16 bit fmt (higher res 565 1st)
01209             CHECK_FOR_FMT(R5G6B5,Conv24to16_0565);
01210             CHECK_FOR_FMT(X1R5G5B5,Conv24to16_X555);
01211             break;
01212 
01213         case 16:
01214             if(bNeedLuminance) {
01215                 assert(cNumAlphaBits>0);
01216                 assert(cNumColorChannels==2);
01217 
01218                 CHECK_FOR_FMT(A8L8,ConvLum16to16);
01219 
01220                 if(!dx_force_16bpptextures) {
01221                     CHECK_FOR_FMT(A8R8G8B8,ConvLum16to32);
01222                 }
01223 
01224               #ifndef FORCE_16bpp_1555
01225                 if(cNumAlphaBits==1)
01226               #endif
01227                 {
01228                     CHECK_FOR_FMT(A1R5G5B5,ConvLum16to16_1555);
01229                 }
01230 
01231                 // normally prefer 4444 due to better alpha channel resolution
01232                 CHECK_FOR_FMT(A4R4G4B4,ConvLum16to16_4444);
01233                 CHECK_FOR_FMT(A1R5G5B5,ConvLum16to16_1555);
01234             } else {
01235                assert((cNumColorChannels==3)||(cNumColorChannels==4));
01236           // look for compatible 16bit fmts, if none then give up
01237           // (dont worry about other bitdepths for 16 bit)
01238                 switch(cNumAlphaBits) {
01239                     case 0:
01240                       if(cNumColorChannels==3) {
01241                           CHECK_FOR_FMT(R5G6B5,Conv24to16_0565);
01242                           CHECK_FOR_FMT(X1R5G5B5,Conv24to16_X555);
01243                       } else {
01244                           assert(cNumColorChannels==4);
01245                         // it could be 4 if user asks us to throw away the alpha channel
01246                           CHECK_FOR_FMT(R5G6B5,Conv32to16_0565);
01247                           CHECK_FOR_FMT(X1R5G5B5,Conv32to16_X555);
01248                       }
01249                       break;
01250                     case 1:
01251                       // app specifically requests 1-5-5-5 F_rgba5 case, where you explicitly want 1-5-5-5 fmt, as opposed
01252                       // to F_rgbm, which could use 32bpp ARGB.  fail if this particular fmt not avail.
01253                       assert(cNumColorChannels==4);
01254                       CHECK_FOR_FMT(X1R5G5B5,Conv32to16_X555);
01255                       break;
01256                     case 4:
01257                       // app specifically requests 4-4-4-4 F_rgba4 case, as opposed to F_rgba, which could use 32bpp ARGB
01258                       assert(cNumColorChannels==4);
01259                       CHECK_FOR_FMT(A4R4G4B4,Conv32to16_4444);
01260                       break;
01261                     default: assert(0);  // problem in get_bits_per_pixel()?
01262                 }
01263             }
01264         case 8:
01265             if(bNeedLuminance) {
01266                 // dont bother handling those other 8bit lum fmts like 4-4, since 16 8-8 is usually supported too
01267                 assert(cNumColorChannels==1);
01268 
01269                 // look for native lum fmt first
01270                 CHECK_FOR_FMT(L8,ConvLum8to8);
01271                 CHECK_FOR_FMT(L8,ConvLum8to16_A8L8);
01272 
01273                 if(!dx_force_16bpptextures) {
01274                     CHECK_FOR_FMT(R8G8B8,ConvLum8to24);
01275                     CHECK_FOR_FMT(X8R8G8B8,ConvLum8to32);
01276                 }
01277 
01278                 CHECK_FOR_FMT(R5G6B5,ConvLum8to16_0565);
01279                 CHECK_FOR_FMT(X1R5G5B5,ConvLum8to16_X555);
01280 
01281             } else if(cNumAlphaBits==8) {
01282                 // look for 16bpp A8L8, else 32-bit ARGB, else 16-4444.
01283 
01284                 // skip 8bit alpha only (D3DFMT_A8), because I think only voodoo supports it
01285                 // and the voodoo support isn't the kind of blending model we need somehow
01286                 // (is it that voodoo assumes color is white?  isnt that what we do in ConvAlpha8to32 anyway?)
01287 
01288                 CHECK_FOR_FMT(A8L8,ConvAlpha8to16_A8L8);
01289 
01290                 if(!dx_force_16bpptextures) {
01291                     CHECK_FOR_FMT(A8R8G8B8,ConvAlpha8to32);
01292                 }
01293 
01294                 CHECK_FOR_FMT(A4R4G4B4,ConvAlpha8to16_4444);
01295             }
01296             break;
01297 
01298         default:
01299             szErrorMsg = "CreateTexture failed: unhandled pixel bitdepth in DX loader";
01300     }
01301 
01302     // if we've gotten here, haven't found a match
01303     dxgsg8_cat.error() << szErrorMsg << ": " << _tex->get_name() << endl
01304                       << "NumColorChannels: " <<cNumColorChannels << "; NumAlphaBits: " << cNumAlphaBits
01305                       << "; targetbpp: " <<target_bpp << "; SupportedTexFmtsMask: 0x" << (void*)scrn.SupportedTexFmtsMask
01306                       << "; NeedLuminance: " << bNeedLuminance << endl;
01307     goto error_exit;
01308 
01309     ///////////////////////////////////////////////////////////
01310 
01311  found_matching_format:
01312     // validate magfilter setting
01313     // degrade filtering if no HW support
01314 
01315     Texture::FilterType ft;
01316 
01317     ft =_tex->get_magfilter();
01318     if((ft!=Texture::FT_linear) && ft!=Texture::FT_nearest) {
01319     // mipmap settings make no sense for magfilter
01320         if(ft==Texture::FT_nearest_mipmap_nearest)
01321             ft=Texture::FT_nearest;
01322         else ft=Texture::FT_linear;
01323     }
01324 
01325     if((ft==Texture::FT_linear) && !(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR))
01326         ft=Texture::FT_nearest;
01327     _tex->set_magfilter(ft);
01328 
01329     // figure out if we are mipmapping this texture
01330     ft =_tex->get_minfilter();
01331     _bHasMipMaps=FALSE;
01332 
01333     if(!dx_ignore_mipmaps) {  // set if no HW mipmap capable
01334         switch(ft) {
01335             case Texture::FT_nearest_mipmap_nearest:
01336             case Texture::FT_linear_mipmap_nearest:
01337             case Texture::FT_nearest_mipmap_linear:  // pick nearest in each, interpolate linearly b/w them
01338             case Texture::FT_linear_mipmap_linear:
01339                 _bHasMipMaps=TRUE;
01340         }
01341 
01342         if(dx_mipmap_everything) {  // debug toggle, ok to leave in since its just a creation cost
01343            _bHasMipMaps=TRUE;
01344            if(dxgsg8_cat.is_spam()) {
01345                if(ft != Texture::FT_linear_mipmap_linear)
01346                    dxgsg8_cat.spam() << "Forcing trilinear mipmapping on DX texture [" << _tex->get_name() << "]\n";
01347            }
01348            ft = Texture::FT_linear_mipmap_linear;
01349            _tex->set_minfilter(ft);
01350         }
01351     } else if((ft==Texture::FT_nearest_mipmap_nearest) ||   // cvt to no-mipmap filter types
01352               (ft==Texture::FT_nearest_mipmap_linear)) {
01353         ft=Texture::FT_nearest;
01354     } else if((ft==Texture::FT_linear_mipmap_nearest) ||
01355               (ft==Texture::FT_linear_mipmap_linear)) {
01356         ft=Texture::FT_linear;
01357     }
01358 
01359     assert((scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT)!=0);
01360 
01361 #define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR)
01362 
01363     // do any other filter type degradations necessary
01364     switch(ft) {
01365         case Texture::FT_linear_mipmap_linear:
01366             if((scrn.d3dcaps.TextureFilterCaps & TRILINEAR_MIPMAP_TEXFILTERCAPS)!=TRILINEAR_MIPMAP_TEXFILTERCAPS) {
01367                if(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)
01368                    ft=Texture::FT_linear_mipmap_nearest;
01369                 else ft=Texture::FT_nearest_mipmap_nearest;  // if you cant do linear in a level, you probably cant do linear b/w levels, so just do nearest-all
01370             }
01371             break;
01372         case Texture::FT_nearest_mipmap_linear:
01373             // if we dont have bilinear, do nearest_nearest
01374             if(!((scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT) &&
01375                  (scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)))
01376                 ft=Texture::FT_nearest_mipmap_nearest;
01377             break;
01378         case Texture::FT_linear_mipmap_nearest:
01379             // if we dont have mip linear, do nearest_nearest
01380             if(!(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR))
01381                 ft=Texture::FT_nearest_mipmap_nearest;
01382             break;
01383         case Texture::FT_linear:
01384             if(!(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR))
01385                 ft=Texture::FT_nearest;
01386             break;
01387     }
01388 
01389     _tex->set_minfilter(ft);
01390 
01391     uint aniso_degree;
01392 
01393     aniso_degree=1;
01394     if(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
01395         aniso_degree=_tex->get_anisotropic_degree();
01396         if((aniso_degree>scrn.d3dcaps.MaxAnisotropy) || dx_force_anisotropic_filtering)
01397             aniso_degree=scrn.d3dcaps.MaxAnisotropy;
01398     }
01399     _tex->set_anisotropic_degree(aniso_degree);
01400 
01401 #ifdef _DEBUG
01402     dxgsg8_cat.spam() << "CreateTexture: setting aniso degree for "<< _tex->get_name() << " to: " << aniso_degree << endl;
01403 #endif
01404 
01405     UINT cMipLevelCount;
01406 
01407     if(_bHasMipMaps) {
01408         cMipLevelCount=0;  // tell CreateTex to alloc space for all mip levels down to 1x1
01409 
01410         if(dxgsg8_cat.is_debug())
01411             dxgsg8_cat.debug() << "CreateTexture: generating mipmaps for "<< _tex->get_name() << endl;
01412     } else cMipLevelCount=1;
01413 
01414     if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0,
01415                                                    TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) {
01416         dxgsg8_cat.error() << "D3D CreateTexture failed!" << D3DERRORSTRING(hr);
01417         goto error_exit;
01418     }
01419 
01420 #ifdef DO_CUSTOM_CONVERSIONS
01421     _PixBufConversionType=ConvNeeded;
01422 #endif
01423 
01424 #ifdef _DEBUG
01425 #ifdef DO_CUSTOM_CONVERSIONS
01426     dxgsg8_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting " << ConvNameStrs[ConvNeeded] << " \n";
01427 #else
01428     dxgsg8_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting panda equivalent of " << D3DFormatStr(_PixBufD3DFmt) << " => " << D3DFormatStr(TargetPixFmt) << endl;
01429 #endif
01430 #endif
01431 
01432     // Note: user may want to create an empty "texture" that will be written to by rendering and copy operations.
01433     //       this will never have a backing store of main memory in panda fmt, and on disk in a file.
01434     //       so for this case, you dont want to call FillDDSurf.
01435     //       need a better way for user to indicate this usage than lack of ram_image, because it conflicts
01436     //       with the multi-open case mentioned below
01437 
01438     if(_texture->has_ram_image()) {
01439         hr = FillDDSurfTexturePixels();
01440         if(FAILED(hr)) {
01441             goto error_exit;
01442         }
01443     }
01444 
01445     // PRINT_REFCNT(dxgsg8,scrn.pD3D8);
01446 
01447     // Return the newly created texture
01448     return _pD3DTexture8;
01449 
01450   error_exit:
01451 
01452     RELEASE(_pD3DTexture8,dxgsg8,"texture",RELEASE_ONCE);
01453     return NULL;
01454 }
01455 
01456 HRESULT DXTextureContext8::
01457 FillDDSurfTexturePixels(void) {
01458     HRESULT hr=E_FAIL;
01459     assert(IS_VALID_PTR(_texture));
01460 
01461     // It is a mistake to insist that has_ram_image() be true before
01462     // we try to load the texture.  This function only indicates
01463     // whether the texture image is already present in main ram or
01464     // not; it has nothing to do with whether get_ram_image() will
01465     // fail.  When there is only one GSG in the world, has_ram_image()
01466     // will generally be true whenever the texture has not been loaded
01467     // before, but when there are multiple GSG's (for instance, if we
01468     // close and reopen the main window), then has_ram_image() is
01469     // largely irrelevant to the GSG.
01470     /*
01471     if(!_texture->has_ram_image()) {
01472       dxgsg8_cat.warning() << "CreateTexture: tried to fill surface that has no ram image!\n";
01473       return S_OK;
01474     }
01475     */
01476 
01477     PixelBuffer *pbuf = _texture->get_ram_image();
01478     if (pbuf == (PixelBuffer *)NULL) {
01479       dxgsg8_cat.fatal() << "CreateTexture: get_ram_image() failed\n";
01480       // The texture doesn't have an image to load.
01481       return E_FAIL;
01482     }
01483 
01484     assert(IS_VALID_PTR(_pD3DTexture8));
01485 
01486     DWORD OrigWidth  = (DWORD) pbuf->get_xsize();
01487     DWORD OrigHeight = (DWORD) pbuf->get_ysize();
01488     DWORD cNumColorChannels = pbuf->get_num_components();
01489     D3DFORMAT SrcFormat=_PixBufD3DFmt;
01490     BYTE *pPixels=(BYTE*)pbuf->_image.p();
01491 
01492     assert(IS_VALID_PTR(pPixels));
01493 
01494     IDirect3DSurface8 *pMipLevel0;
01495     hr=_pD3DTexture8->GetSurfaceLevel(0,&pMipLevel0);
01496     if(FAILED(hr)) {
01497        dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
01498        return E_FAIL;
01499     }
01500 
01501     RECT SrcSize;
01502     SrcSize.left = SrcSize.top = 0;
01503     SrcSize.right = OrigWidth;
01504     SrcSize.bottom = OrigHeight;
01505 
01506     UINT SrcPixBufRowByteLength=OrigWidth*cNumColorChannels;
01507 
01508     DWORD Lev0Filter,MipFilterFlags;
01509     bool bUsingTempPixBuf=false;
01510 
01511     // need filtering if size changes, (also if bitdepth reduced (need dithering)??)
01512     Lev0Filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER;  //dithering looks ugly on i810 for 4444 textures
01513 
01514     // D3DXLoadSurfaceFromMemory will load black luminance and we want full white,
01515     // so convert to explicit luminance-alpha format
01516     if(_PixBufD3DFmt==D3DFMT_A8) {
01517         // alloc buffer for explicit D3DFMT_A8L8
01518         USHORT *pTempPixBuf=new USHORT[OrigWidth*OrigHeight];
01519         if(!IS_VALID_PTR(pTempPixBuf)) {
01520             dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
01521             goto exit_FillDDSurf;
01522         }
01523         bUsingTempPixBuf=true;
01524 
01525         USHORT *pOutPix=pTempPixBuf;
01526         BYTE *pSrcPix=pPixels;
01527         for(UINT y=0;y<OrigHeight;y++)
01528           for(UINT x=0;x<OrigWidth;x++,pSrcPix++,pOutPix++)
01529               *pOutPix = ((*pSrcPix) << 8 ) | 0xFF;  // add full white, which is our interpretation of alpha-only (similar to default adding full opaque alpha 0xFF to RGB-only textures)
01530 
01531         SrcFormat=D3DFMT_A8L8;
01532         SrcPixBufRowByteLength=OrigWidth*sizeof(USHORT);
01533         pPixels=(BYTE*)pTempPixBuf;
01534     }
01535 
01536     // filtering may be done here if texture if targetsize!=origsize
01537     hr=D3DXLoadSurfaceFromMemory(pMipLevel0,(PALETTEENTRY*)NULL,(RECT*)NULL,(LPCVOID)pPixels,SrcFormat,
01538                                  SrcPixBufRowByteLength,(PALETTEENTRY*)NULL,&SrcSize,Lev0Filter,(D3DCOLOR)0x0);
01539     if(FAILED(hr)) {
01540        dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
01541        goto exit_FillDDSurf;
01542     }
01543 
01544     if(_bHasMipMaps) {
01545         if(!dx_use_triangle_mipgen_filter)
01546           MipFilterFlags = D3DX_FILTER_BOX;
01547          else MipFilterFlags = D3DX_FILTER_TRIANGLE;
01548 
01549     //    MipFilterFlags|= D3DX_FILTER_DITHER;
01550 
01551         hr=D3DXFilterTexture(_pD3DTexture8,(PALETTEENTRY*)NULL,0,MipFilterFlags);
01552         if(FAILED(hr)) {
01553             dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXFilterTex failed" << D3DERRORSTRING(hr);
01554             goto exit_FillDDSurf;
01555         }
01556     }
01557 
01558  exit_FillDDSurf:
01559     if(bUsingTempPixBuf) {
01560       SAFE_DELETE_ARRAY(pPixels);
01561     }
01562     RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE);
01563     return hr;
01564 }
01565 
01566 //-----------------------------------------------------------------------------
01567 // Name: DeleteTexture()
01568 // Desc: Release the surface used to store the texture
01569 //-----------------------------------------------------------------------------
01570 void DXTextureContext8::
01571 DeleteTexture( ) {
01572     if(_pD3DTexture8==NULL) {
01573         // dont bother printing the msg below, since we already released it.
01574         return;
01575     }
01576 
01577     if(dxgsg8_cat.is_spam()) {
01578         dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
01579     }
01580 
01581     RELEASE(_pD3DTexture8,dxgsg8,"texture",RELEASE_ONCE);
01582 /*
01583 #ifdef DEBUG_RELEASES
01584     if(_surface) {
01585         LPDIRECTDRAW7 pDD;
01586         _surface->GetDDInterface( (VOID**)&pDD );
01587         pDD->Release();
01588 
01589         PRINTREFCNT(pDD,"before DeleteTex, IDDraw7");
01590         RELEASE(_surface,dxgsg8,"texture",false);
01591         PRINTREFCNT(pDD,"after DeleteTex, IDDraw7");
01592     }
01593 #else
01594 
01595     RELEASE(_pD3DSurf8,dxgsg8,"texture",false);
01596  #endif
01597 */
01598 }
01599 
01600 
01601 ////////////////////////////////////////////////////////////////////
01602 //     Function: DXTextureContext8::Constructor
01603 //       Access: Public
01604 //  Description:
01605 ////////////////////////////////////////////////////////////////////
01606 DXTextureContext8::
01607 DXTextureContext8(Texture *tex) :
01608 TextureContext(tex) {
01609 
01610     if(dxgsg8_cat.is_spam()) {
01611        dxgsg8_cat.spam() << "Creating DX texture [" << tex->get_name() << "], minfilter(" << PandaFilterNameStrs[tex->get_minfilter()] << "), magfilter("<<PandaFilterNameStrs[tex->get_magfilter()] << "), anisodeg(" << tex->get_anisotropic_degree() << ")\n";
01612     }
01613 
01614     _pD3DTexture8 = NULL;
01615     _bHasMipMaps = FALSE;
01616     _tex = tex;
01617 }
01618 
01619 DXTextureContext8::
01620 ~DXTextureContext8() {
01621     if(dxgsg8_cat.is_spam()) {
01622         dxgsg8_cat.spam() << "Deleting DX8 TexContext for " << _tex->get_name() << "\n";
01623     }
01624     DeleteTexture();
01625     TextureContext::~TextureContext();
01626     _tex = NULL;
01627 }
01628 

Generated on Fri May 2 00:37:18 2003 for Panda by doxygen1.3