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

panda/src/dxgsg7/dxTextureContext7.cxx

Go to the documentation of this file.
00001 // Filename: dxTextureContext7.cxx
00002 // Created by:  drose (07Oct99)
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 "dxTextureContext7.h"
00022 #include "config_dxgsg7.h"
00023 #include "dxGraphicsStateGuardian7.h"
00024 #include "pnmImage.h"
00025 
00026 static const DWORD g_LowByteMask = 0x000000FF;
00027 
00028 //#define FORCE_16bpp_1555
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 typedef enum {
00047     None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_X555,
00048     Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24,
00049     Conv24to16_X555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444,
00050     ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_X555,ConvLum8to16_0565,
00051     ConvAlpha8to16_4444,ConvAlpha8to32,ConvAlpha8to8
00052 } ConversionType;
00053 
00054 #ifndef NDEBUG
00055 char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_X555",
00056     "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24",
00057     "Conv24to16_X555","Conv24to16_0565","ConvLum16to16_1555","ConvLum16to16_4444",
00058     "ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32",
00059     "ConvLum8to16_X555","ConvLum8to16_0565","ConvAlpha8to16_4444","ConvAlpha8to32","ConvAlpha8to8"
00060 };
00061 #endif
00062 
00063 char *PandaFilterNameStrs[] = {"FT_nearest","FT_linear","FT_nearest_mipmap_nearest","FT_linear_mipmap_nearest",
00064     "FT_nearest_mipmap_linear", "FT_linear_mipmap_linear"
00065 };
00066 
00067 TypeHandle DXTextureContext7::_type_handle;
00068 
00069 #define SWAPDWORDS(X,Y)  { DWORD temp=X;  X=Y; Y=temp; }
00070 
00071 #ifdef _DEBUG
00072 static void DebugPrintPixFmt(DDPIXELFORMAT* pddpf) {
00073     static int iddpfnum=0;
00074     ostream *dbgout = &dxgsg7_cat.debug();
00075 
00076     *dbgout << "DDPF[" << iddpfnum << "]: RGBBitCount:" << pddpf->dwRGBBitCount
00077     << " Flags:"  << (void *)pddpf->dwFlags ;
00078 
00079     if(pddpf->dwFlags & DDPF_RGB) {
00080         *dbgout << " RGBmask:" << (void *) (pddpf->dwRBitMask | pddpf->dwGBitMask | pddpf->dwBBitMask);
00081         *dbgout << " Rmask:" << (void *) (pddpf->dwRBitMask);
00082     }
00083 
00084     if(pddpf->dwFlags & DDPF_ALPHAPIXELS) {
00085         *dbgout << " Amask:" << (void *) pddpf->dwRGBAlphaBitMask;
00086     }
00087 
00088     if(pddpf->dwFlags & DDPF_LUMINANCE) {
00089         *dbgout << " Lummask:" << (void *) pddpf->dwLuminanceBitMask;
00090     }
00091 
00092     *dbgout << endl;
00093 
00094     iddpfnum++;
00095 }
00096 
00097 void PrintLastError(char *msgbuf) {
00098     DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
00099 
00100     if(msgbuf==NULL) {
00101         LPVOID lpMsgBuf;
00102         dwFlags|=FORMAT_MESSAGE_ALLOCATE_BUFFER;
00103         FormatMessage( dwFlags,
00104                        NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00105                        (LPTSTR) &lpMsgBuf,0,NULL );
00106         MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
00107         LocalFree(lpMsgBuf);
00108     } else {
00109         FormatMessage( dwFlags,
00110                        NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00111                        (LPTSTR) msgbuf,500,NULL );
00112     }
00113 }
00114 
00115 #endif
00116 
00117 
00118 /* for reference
00119 enum Format {
00120   F_color_index,
00121   F_stencil_index,
00122   F_depth_component,
00123   F_red,
00124   F_green,
00125   F_blue,
00126   F_alpha,
00127   F_rgb,     // any suitable RGB mode, whatever the hardware prefers
00128   F_rgb5,    // specifically, 5 bits per R,G,B channel
00129   F_rgb8,    // 8 bits per R,G,B channel
00130   F_rgb12,   // 12 bits per R,G,B channel
00131   F_rgb332,  // 3 bits per R & G, 2 bits for B
00132   F_rgba,    // any suitable RGBA mode, whatever the hardware prefers
00133   F_rgbm,    // as above, but only requires 1 bit for alpha (i.e. mask)
00134   F_rgba4,   // 4 bits per R,G,B,A channel
00135   F_rgba5,   // 5 bits per R,G,B channel, 1 bit alpha
00136   F_rgba8,   // 8 bits per R,G,B,A channel
00137   F_rgba12,  // 12 bits per R,G,B,A channel
00138   F_luminance,
00139   F_luminance_alpha
00140 };
00141 
00142   enum Type {
00143     T_unsigned_byte,   // 1 byte per channel
00144     T_unsigned_short,  // 2 byte per channel
00145     T_unsigned_byte_332,  // RGB in 1 byte
00146     T_float,             // 1 channel stored as float
00147   };
00148 */
00149 
00150 ////////////////////////////////////////////////////////////////////
00151 //     Function: DXTextureContext7::get_bits_per_pixel
00152 //       Access: Protected
00153 //  Description: Maps from the PixelBuffer's Format symbols
00154 //               to bpp.  returns # of alpha bits
00155 //               Note: PixelBuffer's format indicates REQUESTED final format,
00156 //                     not the stored format, which is indicated by pixelbuffer type
00157 ////////////////////////////////////////////////////////////////////
00158 
00159 unsigned int DXTextureContext7::
00160 get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) {
00161     *alphbits = 0;      // assume no alpha bits
00162     switch(format) {
00163         case PixelBuffer::F_alpha:
00164             *alphbits = 8;
00165             return 8;
00166         case PixelBuffer::F_color_index:
00167         case PixelBuffer::F_red:
00168         case PixelBuffer::F_green:
00169         case PixelBuffer::F_blue:
00170         case PixelBuffer::F_rgb332:
00171         case PixelBuffer::F_luminance_alphamask:
00172             *alphbits = 1;
00173             return 16;
00174         case PixelBuffer::F_luminance_alpha:
00175             *alphbits = 8;
00176             return 16;
00177         case PixelBuffer::F_luminance:
00178             return 8;
00179         case PixelBuffer::F_rgba4:
00180             *alphbits = 4;
00181             return 16;
00182         case PixelBuffer::F_rgba5:
00183             *alphbits = 1;
00184             return 16;
00185         case PixelBuffer::F_depth_component:
00186         case PixelBuffer::F_rgb5:
00187             return 16;
00188         case PixelBuffer::F_rgb8:
00189         case PixelBuffer::F_rgb:
00190             return 24;
00191         case PixelBuffer::F_rgba8:
00192         case PixelBuffer::F_rgba:
00193             *alphbits = 8;
00194             return 32;
00195         case PixelBuffer::F_rgbm:
00196             *alphbits = 1;
00197             return 32;
00198         case PixelBuffer::F_rgb12:
00199             return 36;
00200         case PixelBuffer::F_rgba12:
00201             *alphbits = 12;
00202             return 48;
00203     }
00204     return 8;
00205 }
00206 
00207 HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWSURFACE7 pDDSurf) {
00208     HRESULT hr;
00209     DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
00210 
00211     if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) {
00212         dxgsg7_cat.error() << "ConvertPixBuftoDDSurf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n";
00213         exit(1);
00214     }
00215 
00216     if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd,  DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) {
00217         dxgsg7_cat.error() << "CreateTexture failed: _surface->Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n";
00218         return hr;
00219     }
00220 
00221     //pbuf contains raw ARGB in PixelBuffer byteorder
00222 
00223     DWORD lPitch = ddsd.lPitch;
00224     BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface;
00225     DWORD dwOrigWidth=ddsd.dwWidth,dwOrigHeight=ddsd.dwHeight;
00226 
00227     switch(ConvNeeded) {
00228         case Conv32to32:
00229         case Conv32to32_NoAlpha: {
00230 
00231 #ifdef PANDA_BGRA_ORDER
00232                 if(ConvNeeded==Conv32to32) {
00233                     memcpy(pDDSurfBytes,(BYTE*) pbuf,dwOrigWidth*dwOrigHeight*sizeof(DWORD));
00234                 } else {
00235                     DWORD *pSrcWord = (DWORD *) pbuf;
00236                     DWORD *pDstWord;
00237 
00238                     // need to set all pixels alpha to 0xFF
00239                     for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00240                         pDstWord = (DWORD*)pDDSurfBytes;
00241                         for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00242                             *pDstWord = *pSrcWord | 0xFF000000;
00243                         }
00244                     }
00245                 }
00246 #else
00247                 DWORD *pDstWord,*pSrcWord = (DWORD *) pbuf;
00248                 DWORD dwAlphaMaskOn = (ConvNeeded==Conv32to32_NoAlpha) ? 0xFF000000 : 0x0;
00249 
00250                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00251                     pDstWord = (DWORD*)pDDSurfBytes;
00252                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00253                         DWORD dwPixel = *pSrcWord;
00254 
00255                         // pixel buffer is in ABGR format(it stores big-endian RGBA)
00256                         // need to change byte order to ARGB
00257 
00258                         BYTE r,b;
00259                         // just swap r & b
00260                         b = GET_BLUE_BYTE(dwPixel);
00261                         r = GET_RED_BYTE(dwPixel);
00262                         *pDstWord = ((dwPixel & 0xff00ff00) | (r<<16) | b) | dwAlphaMaskOn;
00263                     }
00264                 }
00265 #endif
00266                 break;
00267             }
00268 
00269         case Conv32to16_1555:
00270         case Conv32to16_X555: {
00271                 DWORD *pSrcWord = (DWORD *) pbuf;
00272                 WORD *pDstWord;
00273 
00274                 unsigned short dwAlphaMaskOn = (ConvNeeded==Conv32to16_X555) ? 0x8000 : 0x0;
00275 
00276                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00);
00277 
00278                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00279                     pDstWord = (WORD*)pDDSurfBytes;
00280 
00281                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00282                         BYTE r,g,b;
00283                         DWORD dwPixel = *pSrcWord;
00284                         unsigned short abit;
00285 
00286                         // just look at most-signf-bit for alpha.  (alternately, could
00287                         // convert any non-zero alpha to full transparent)
00288 
00289                         abit = ((dwPixel>>16) & 0x00008000) | dwAlphaMaskOn;  // just copy high bit
00290                         g = GET_GREEN_BYTE(dwPixel) >> 3;
00291                         b = GET_BLUE_BYTE(dwPixel) >> 3;
00292                         r = GET_RED_BYTE(dwPixel) >> 3;
00293 
00294                         // truncates 8 bit values to 5 bit (or 1 for alpha)
00295 
00296                         *pDstWord = (abit | (r << 10)| (g << 5) | b);
00297                     }
00298                 }
00299                 break;
00300             }
00301 
00302         case Conv32to16_0565: {   // could merge this w/above case, but whatever
00303                 DWORD *pSrcWord = (DWORD *) pbuf;
00304                 WORD *pDstWord;
00305 
00306                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800);
00307                 // for some reason, bits are 'in-order' when converting to 16bit
00308 
00309                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00310                     pDstWord = (WORD*)pDDSurfBytes;
00311 
00312                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00313                         BYTE r,g,b;
00314                         DWORD dwPixel = *pSrcWord;
00315 
00316                         g = GET_GREEN_BYTE(dwPixel) >> 2;
00317                         b = GET_BLUE_BYTE(dwPixel) >> 3;
00318                         r = GET_RED_BYTE(dwPixel) >> 3;
00319                         *pDstWord = ((r << 11)| (g << 5) | b);
00320                     }
00321                 }
00322                 break;
00323             }
00324 
00325         case Conv32to16_4444: {
00326                 DWORD *pSrcWord = (DWORD *) pbuf;
00327                 WORD *pDstWord;
00328 
00329                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000);  // assumes ARGB
00330                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0x0f00);  // assumes ARGB
00331 
00332                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00333                     pDstWord = (WORD*)pDDSurfBytes;
00334 
00335                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00336                         BYTE r,g,b,a;
00337                         DWORD dwPixel = *pSrcWord;
00338 
00339                         a = GET_ALPHA_BYTE(dwPixel)  >> 4;
00340                         g = GET_GREEN_BYTE(dwPixel)  >> 4;
00341                         b = GET_BLUE_BYTE(dwPixel)   >> 4;
00342                         r = GET_RED_BYTE(dwPixel)    >> 4;
00343 
00344                         *pDstWord = (a << 12) | (r << 8)| (g << 4) | b;
00345                     }
00346                 }
00347                 break;
00348             }
00349 
00350         case Conv32to24: {
00351 
00352                 DWORD *pSrcWord = (DWORD *) pbuf;
00353                 BYTE *pDstWord;
00354 
00355                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00356                     pDstWord = (BYTE*)pDDSurfBytes;
00357 
00358                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord+=3) {
00359                         BYTE r,g,b;
00360                         DWORD dwPixel = *pSrcWord;
00361 
00362                         r = GET_RED_BYTE(dwPixel);
00363                         g = GET_GREEN_BYTE(dwPixel);
00364                         b = GET_BLUE_BYTE(dwPixel);
00365 
00366                         *pDstWord     = r;
00367                         *(pDstWord+1) = g;
00368                         *(pDstWord+2) = b;
00369                     }
00370                 }
00371                 break;
00372             }
00373 
00374 
00375         case Conv24to24: {
00376             #ifdef PANDA_BGRA_ORDER
00377                 memcpy(pDDSurfBytes,(BYTE*)pbuf,dwOrigHeight*dwOrigWidth*3);
00378             #else
00379                 BYTE *pSrcWord = (BYTE *) pbuf;
00380                 BYTE *pDstWord;
00381             
00382                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00383                     pDstWord = (BYTE*)pDDSurfBytes;
00384 
00385                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord+=3) {
00386                         BYTE r,g,b;
00387 
00388                         b = *pSrcWord;
00389                         g = *(pSrcWord+1);
00390                         r = *(pSrcWord+2);
00391 
00392                         *pDstWord     = r;
00393                         *(pDstWord+1) = g;
00394                         *(pDstWord+2) = b;
00395                     }
00396                 }
00397              #endif
00398                 break;
00399             }
00400 
00401         case Conv24to16_X555: {
00402                 BYTE *pSrcWord = (BYTE *) pbuf;
00403                 WORD *pDstWord;
00404 
00405                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00);
00406              // for some reason, bits are 'in-order' when converting to 16bit
00407 
00408                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00409                     pDstWord = (WORD*)pDDSurfBytes;
00410 
00411                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord++) {
00412                         BYTE r,g,b;
00413 
00414                     #ifdef PANDA_BGRA_ORDER
00415                         b = *pSrcWord       >> 3;
00416                         r = *(pSrcWord+2)   >> 3;
00417                     #else
00418                         r = *pSrcWord       >> 3;
00419                         b = *(pSrcWord+2)   >> 3;                   
00420                     #endif
00421                         g = *(pSrcWord+1)   >> 3;
00422 
00423                         *pDstWord = 0x8000 | (r << 10)| (g << 5) | b;
00424                     }
00425                 }
00426                 break;
00427             }
00428 
00429         case Conv24to16_0565: {
00430                 BYTE *pSrcWord = (BYTE *) pbuf;
00431                 WORD *pDstWord;
00432 
00433                 assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800);
00434 
00435                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00436                     pDstWord = (WORD*)pDDSurfBytes;
00437 
00438                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord++) {
00439                         BYTE r,g,b;
00440 
00441                     #ifdef PANDA_BGRA_ORDER
00442                         b = *pSrcWord       >> 3;
00443                         g = *(pSrcWord+1)   >> 2;
00444                         r = *(pSrcWord+2)   >> 3;
00445                     #else
00446                         r = *pSrcWord       >> 3;
00447                         g = *(pSrcWord+1)   >> 2;
00448                         b = *(pSrcWord+2)   >> 3;
00449                     #endif
00450                      // code truncates 8 bit values to 5 bit
00451                      *pDstWord = (r << 11)| (g << 5) | b;                   
00452                     }
00453                 }
00454                 break;
00455             }
00456 
00457         case Conv24to32: {
00458                 BYTE *pSrcWord = (BYTE *) pbuf;
00459                 DWORD *pDstWord;
00460 
00461                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00462                     pDstWord = (DWORD *)pDDSurfBytes;
00463 
00464                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord+=3,pDstWord++) {
00465                         BYTE r,g,b;
00466                         // pixel buffer is in ABGR format(it stores big-endian RGBA)
00467                         // need to change byte order to ARGB
00468 
00469                     #ifdef PANDA_BGRA_ORDER
00470                         b = *pSrcWord;
00471                         r = *(pSrcWord+2);
00472                     #else
00473                         r = *pSrcWord;
00474                         b = *(pSrcWord+2);
00475                     #endif
00476                         g = *(pSrcWord+1);
00477 
00478                         *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b;
00479                     }
00480                 }
00481                 break;
00482             }
00483 
00484         case ConvLum16to32: {
00485                 WORD *pSrcWord = (WORD *) pbuf;
00486                 DWORD *pDstWord;
00487 
00488                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00489                     pDstWord = (DWORD *)pDDSurfBytes;
00490 
00491                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00492                         // pixel buffer stores LA bytes, which in a little-endian word is AL
00493 
00494                         DWORD dwPixel=*pSrcWord;
00495                         BYTE lum,a;
00496 
00497                         a = dwPixel >> 8;
00498                         lum = dwPixel & 0xFF;
00499                         *pDstWord = (a<<24) | lum | (lum << 8) | (lum << 16);
00500                     }
00501                 }
00502                 break;
00503             }
00504 
00505         case ConvLum16to16_4444: {
00506                 WORD *pSrcWord = (WORD *) pbuf;
00507                 WORD *pDstWord;
00508 
00509                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000);  // assumes ARGB
00510 
00511                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00512                     pDstWord = (WORD*)pDDSurfBytes;
00513 
00514                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00515                         DWORD dwPixel=*pSrcWord;
00516                         BYTE lum,a;
00517                         dwPixel = *pSrcWord;
00518 
00519                         a =   (BYTE)(dwPixel>>8)           >> 4;
00520                         lum = (BYTE)(dwPixel & 0x000000ff) >> 4;
00521 
00522                         *pDstWord = (a << 12) | lum | (lum << 4)| (lum << 8);
00523                     }
00524                 }
00525                 break;
00526             }
00527 
00528         case ConvLum16to16_1555: {
00529                 WORD *pSrcWord = (WORD *) pbuf;
00530                 WORD *pDstWord;
00531 
00532                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0x8000);  // assumes ARGB
00533 
00534                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00535                     pDstWord = (WORD*)pDDSurfBytes;
00536 
00537                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00538                         WORD dwPixel=*pSrcWord;
00539                         BYTE lum;
00540 
00541                         lum = (BYTE)(dwPixel & 0x00FF) >> 3;
00542 
00543                         *pDstWord = (dwPixel & 0x8000) | lum | (lum << 5) | (lum << 10);
00544                     }
00545                 }
00546                 break;
00547             }
00548 
00549         case ConvLum16to16: {
00550                 // All bytes are in same order?
00551                 CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2);
00552                 break;
00553             }
00554 
00555         case ConvLum8to16_0565:
00556         case ConvLum8to16_X555: {
00557                 BYTE *pSrcWord = (BYTE *) pbuf;
00558                 WORD *pDstWord;
00559                 DWORD FarShift,OrVal,MiddleRoundShift;
00560 
00561                 if(ConvNeeded==ConvLum8to16_X555) {
00562                     FarShift=10;  OrVal=0x8000;  // turn on alpha bit, just in case
00563                     MiddleRoundShift = 3;
00564                     assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00);
00565                 } else {
00566                     FarShift=11;  OrVal=0x0;
00567                     MiddleRoundShift = 2;
00568                     assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800);
00569                 }
00570 
00571                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes+=ddsd.lPitch) {
00572                     pDstWord = (WORD*)pDDSurfBytes;
00573 
00574                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00575                         DWORD dwPixel=*pSrcWord,GrnVal;
00576                         BYTE r;
00577 
00578                         r = (BYTE) dwPixel >> 3;
00579                         GrnVal = (BYTE) dwPixel >> MiddleRoundShift;
00580 
00581                         // code truncates 8 bit values to 5 bit  (set alpha=1 for opaque)
00582 
00583                         *pDstWord = ((r << FarShift)| (GrnVal << 5) | r) | OrVal;
00584                     }
00585                 }
00586                 break;
00587             }
00588 
00589         case ConvLum8to8: {
00590                 CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight);
00591                 break;
00592             }
00593 
00594         case ConvLum8to32: {
00595 
00596           // this is kind of a waste of space, but we trade it for lum resolution
00597                 BYTE *pSrcWord = (BYTE *) pbuf;
00598                 DWORD *pDstWord;
00599 
00600                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00601                     pDstWord = (DWORD *)pDDSurfBytes;
00602 
00603                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00604                         DWORD dwPixel=*pSrcWord;
00605 
00606                         *pDstWord = 0xFF000000 | dwPixel | (dwPixel << 8) | (dwPixel<<16);
00607                     }
00608                 }
00609                 break;
00610             }
00611 
00612         case ConvLum8to24: {
00613                 // this is kind of a waste of space, but we trade it for lum resolution
00614                 BYTE *pSrcWord = (BYTE *) pbuf;
00615                 BYTE *pDstWord;
00616 
00617                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00618                     pDstWord = (BYTE *)pDDSurfBytes;
00619 
00620                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00621                         DWORD dwPixel=*pSrcWord;
00622 
00623                         *pDstWord++ = dwPixel;
00624                         *pDstWord++ = dwPixel;
00625                         *pDstWord   = dwPixel;
00626                     }
00627                 }
00628                 break;
00629             }
00630 
00631         case ConvAlpha8to32: {
00632               //  huge waste of space, but this may be only fmt where we get 8bits alpha resolution
00633                 BYTE *pSrcWord = (BYTE *) pbuf;
00634                 DWORD *pDstWord;
00635 
00636                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00637                     pDstWord = (DWORD *)pDDSurfBytes;
00638 
00639                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00640                         // OR alpha with full white
00641                         *pDstWord = (*pSrcWord << 24) | 0x00FFFFFF;
00642                     }
00643                 }
00644                 break;
00645             }
00646 
00647         case ConvAlpha8to16_4444: {
00648                 BYTE *pSrcWord = (BYTE *) pbuf;
00649                 WORD *pDstWord;
00650 
00651                 assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000);  // assumes ARGB order
00652 
00653                 for(DWORD y=0; y<dwOrigHeight; y++,pDDSurfBytes += ddsd.lPitch) {
00654                     pDstWord = (WORD*)pDDSurfBytes;
00655 
00656                     for(DWORD x=0; x<dwOrigWidth; x++,pSrcWord++,pDstWord++) {
00657                         WORD a = (BYTE)(*pSrcWord>>4);
00658                         *pDstWord = (a << 12) | 0x0FFF; // OR alpha with full white
00659                     }
00660                 }
00661                 break;
00662             }
00663 
00664         default:
00665             dxgsg7_cat.error() << "CreateTexture failed! unhandled texture conversion type: "<< ConvNeeded <<" \n";
00666             pDDSurf->Unlock(NULL);
00667             return E_INVALIDARG;
00668     }
00669 
00670     pDDSurf->Unlock(NULL);
00671 
00672     return S_OK;
00673 }
00674 
00675 HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) {
00676 
00677     HRESULT hr;
00678     DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
00679 
00680     DWORD dwNumComponents=pixbuf->get_num_components();
00681 
00682     assert(pixbuf->get_component_width()==sizeof(BYTE));   // cant handle anything else now
00683     assert(pixbuf->get_image_type()==PixelBuffer::T_unsigned_byte);   // cant handle anything else now
00684     assert((dwNumComponents==3) || (dwNumComponents==4));  // cant handle anything else now
00685 
00686     BYTE *pbuf=pixbuf->_image.p();
00687 
00688     if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) {
00689         dxgsg7_cat.error() << "ConvertDDSurftoPixBuf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n";
00690         exit(1);
00691     }
00692 
00693     if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd,  DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) {
00694         dxgsg7_cat.error() << "ConvertDDSurftoPixBuf Lock() failed! hr = " << ConvD3DErrorToString(hr) << "\n";
00695         return hr;
00696     }
00697 
00698     DWORD dwXWindowOffset=0,dwYWindowOffset=0;
00699     DWORD dwCopyWidth=ddsd.dwWidth,dwCopyHeight=ddsd.dwHeight;
00700 
00701    // get window offset so we know where to start grabbing pixels.  note for
00702    // fullscreen primary no clipper will be attached, that 'error' should be ignored
00703     LPDIRECTDRAWCLIPPER pDDClipper;
00704     hr = pDDSurf->GetClipper(&pDDClipper);
00705 
00706 #ifdef _DEBUG
00707     if(FAILED(hr) && !((hr == DDERR_NOCLIPPERATTACHED) && dx_full_screen)) {
00708         dxgsg7_cat.error() << "ConvertDDSurftoPixBuf GetClipper failed! hr = " << ConvD3DErrorToString(hr) << "\n";
00709         return hr;
00710     }
00711 #endif
00712 
00713     if(hr==S_OK) {
00714         HWND hWin;
00715 
00716         if(FAILED(hr = pDDClipper->GetHWnd(&hWin))) {
00717             dxgsg7_cat.error() << "ConvertDDSurftoPixBuf GetHwnd failed! hr = " << ConvD3DErrorToString(hr) << "\n";
00718             return hr;
00719         }
00720 
00721         RECT view_rect;
00722         GetClientRect( hWin, &view_rect );
00723         ClientToScreen( hWin, (POINT*)&view_rect.left );
00724         ClientToScreen( hWin, (POINT*)&view_rect.right );
00725 
00726         dwXWindowOffset=view_rect.left;
00727         dwYWindowOffset=view_rect.top;
00728         dwCopyWidth=view_rect.right-view_rect.left;
00729         dwCopyHeight=view_rect.bottom-view_rect.top;
00730 
00731         pDDClipper->Release();  // dec ref cnt
00732     }
00733 
00734     //make sure there's enough space in the pixbuf, its size must match (especially xsize)
00735    // or scanlines will be too long
00736 
00737     if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) {
00738         pDDSurf->Unlock(NULL);
00739         assert(0);
00740         dxgsg7_cat.error() << "ConvertDDSurftoPixBuf, PixBuf incorrect size to hold display surface!\n";
00741         return E_FAIL;
00742     }
00743 
00744     // others not handled yet
00745     assert((ddsd.ddpfPixelFormat.dwRGBBitCount==32)||(ddsd.ddpfPixelFormat.dwRGBBitCount==16)||(ddsd.ddpfPixelFormat.dwRGBBitCount==24));
00746 
00747     //pbuf contains raw ARGB in PixelBuffer byteorder
00748 
00749     DWORD lPitch = ddsd.lPitch;
00750     BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface;
00751 
00752     // writes out last line in DDSurf first in PixelBuf, so Y line order precedes inversely
00753 
00754     if(dxgsg7_cat.is_debug())
00755         dxgsg7_cat.debug() << "ConvertDDSurftoPixBuf converting " << ddsd.ddpfPixelFormat.dwRGBBitCount << "bpp DDSurf to " 
00756                           <<  dwNumComponents << "-channel panda PixelBuffer\n";
00757 
00758 
00759     if(dwNumComponents==4) {
00760         DWORD *pDstWord = (DWORD *) pbuf;
00761         switch(ddsd.ddpfPixelFormat.dwRGBBitCount) {
00762 
00763             case 32: {
00764                     DWORD *pSrcWord;
00765                    #ifdef PANDA_BGRA_ORDER 
00766                     BYTE *pDstLine = (BYTE*)pDstWord;
00767                    #endif
00768 
00769                     pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1);
00770                     for(DWORD y=0; y<dwCopyHeight; y++,pDDSurfBytes-=ddsd.lPitch) {
00771                         pSrcWord = ((DWORD*)pDDSurfBytes)+dwXWindowOffset;
00772                         #ifdef PANDA_BGRA_ORDER 
00773                             memcpy(pDstLine,pSrcWord,ddsd.lPitch);
00774                             pDstLine+=ddsd.lPitch;
00775                         #else
00776                             for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++,pDstWord++) {
00777                                   DWORD dwPixel = *pSrcWord;
00778                                   BYTE r,b;
00779                                 
00780                                   // DDsurf is in ARGB
00781                                   r=  (BYTE) ((dwPixel >> 16) & g_LowByteMask);
00782                                   b = (BYTE)  (dwPixel & g_LowByteMask);
00783 
00784                                   // want to write out ABGR
00785                                   *pDstWord = (dwPixel & 0xFF00FF00) | (b<<16) | r;
00786                             }
00787                         #endif
00788                     }
00789                     break;
00790                 }
00791 
00792             case 24: {
00793                     BYTE *pSrcByte;
00794 
00795                     pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1);
00796                     for(DWORD y=0; y<dwCopyHeight; y++,pDDSurfBytes-=ddsd.lPitch) {
00797                         pSrcByte = pDDSurfBytes+dwXWindowOffset*3*sizeof(BYTE);
00798                         for(DWORD x=0; x<dwCopyWidth; x++,pDstWord++) {
00799                             DWORD r,g,b;
00800 
00801                             b = *pSrcByte++;
00802                             g = *pSrcByte++;
00803                             r = *pSrcByte++;
00804 
00805                             #ifdef PANDA_BGRA_ORDER                             
00806                                *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b;
00807                             #else
00808                                *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r;                           
00809                             #endif
00810                         }
00811                     }
00812                     break;
00813                 }
00814 
00815             case 16: {
00816                     assert((ddsd.ddpfPixelFormat.dwRBitMask==0xF800)  ||  // 565
00817                            (ddsd.ddpfPixelFormat.dwRBitMask==0x0F00)  ||  // 4444
00818                            (ddsd.ddpfPixelFormat.dwRBitMask==0x7C00));    // 555 or 1555
00819 
00820                     WORD  *pSrcWord;
00821                     // handle 0555,1555,0565 in same loop
00822                     BYTE redshift,greenshift,blueshift;
00823                     DWORD redmask,greenmask,bluemask;
00824 
00825                     if(ddsd.ddpfPixelFormat.dwRBitMask==0xF800) {
00826                         redshift=(11-3);
00827                         redmask=0xF800;
00828                         greenmask=0x07E0;
00829                         greenshift=(5-2);
00830                         bluemask=0x001F;
00831                         blueshift=3;
00832                     } else if(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00) {
00833                         redmask=0x7C00;
00834                         redshift=(10-3);
00835                         greenmask=0x03E0;
00836                         greenshift=(5-3);
00837                         bluemask=0x001F;
00838                         blueshift=3;
00839                     } else {
00840                         assert(ddsd.ddpfPixelFormat.dwRBitMask==0x0F00);
00841                         redmask=0x0F00;
00842                         redshift=4;
00843                         greenmask=0x00F0;
00844                         greenshift=0;
00845                         bluemask=0x000F;
00846                         blueshift=4;
00847                     }
00848 
00849                     pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1);
00850                     for(DWORD y=0; y<dwCopyHeight; y++,pDDSurfBytes-=ddsd.lPitch) {
00851                         pSrcWord = ((WORD*)pDDSurfBytes)+dwXWindowOffset;
00852                         for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++,pDstWord++) {
00853                             WORD dwPixel = *pSrcWord;
00854                             BYTE r,g,b;
00855 
00856                             b = (dwPixel & bluemask) << blueshift;
00857                             g = (dwPixel & greenmask) >> greenshift;
00858                             r = (dwPixel & redmask) >> redshift;
00859 
00860                             #ifdef PANDA_BGRA_ORDER
00861                               *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b;
00862                             #else
00863                               *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r;   
00864                             #endif
00865                         }
00866                     }
00867                 }
00868                 break;
00869         }
00870     } else {  // convert to 24bpp pixbuf
00871         BYTE *pDstByte = (BYTE *) pbuf;
00872         switch(ddsd.ddpfPixelFormat.dwRGBBitCount) {
00873 
00874             case 32: {
00875                     DWORD *pSrcWord;
00876 
00877                     pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1);
00878                     for(DWORD y=0; y<dwCopyHeight; y++,pDDSurfBytes-=ddsd.lPitch) {
00879                         pSrcWord = ((DWORD*)pDDSurfBytes)+dwXWindowOffset;
00880 
00881                         for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++) {
00882                             BYTE r,g,b;
00883                             DWORD dwPixel = *pSrcWord;
00884 
00885                             r = (BYTE)((dwPixel>>16) & g_LowByteMask);
00886                             g = (BYTE)((dwPixel>> 8) & g_LowByteMask);
00887                             b = (BYTE)((dwPixel    ) & g_LowByteMask);
00888 
00889                             #ifdef PANDA_BGRA_ORDER
00890                                 *pDstByte++ = b;
00891                                 *pDstByte++ = g;
00892                                 *pDstByte++ = r;                            
00893                             #else
00894                                 *pDstByte++ = r;
00895                                 *pDstByte++ = g;
00896                                 *pDstByte++ = b;
00897                             #endif
00898                         }
00899                     }
00900                     break;
00901                 }
00902 
00903             case 24: {
00904                         BYTE *pSrcByte;
00905 
00906                         pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1);
00907                         for(DWORD y=0; y<dwCopyHeight; y++,pDDSurfBytes-=ddsd.lPitch) {
00908                             pSrcByte = pDDSurfBytes+dwXWindowOffset*3*sizeof(BYTE);
00909                          #ifdef PANDA_BGRA_ORDER 
00910                             memcpy(pDstByte,pSrcByte,ddsd.lPitch);
00911                             pDstByte+=ddsd.lPitch;
00912                          #else
00913                             for(DWORD x=0; x<dwCopyWidth; x++) {
00914                                 BYTE r,g,b;
00915 
00916                                 // pixel buffer is in ABGR format(it stores big-endian RGBA)
00917                                 // need to change byte order from ARGB
00918 
00919                                 b = *pSrcByte++;
00920                                 g = *pSrcByte++;
00921                                 r = *pSrcByte++;
00922 
00923                                 *pDstByte++ = r;
00924                                 *pDstByte++ = g;
00925                                 *pDstByte++ = b;
00926                             }
00927                           #endif
00928                         }
00929                         break;
00930                     }
00931 
00932             case 16: {  // handle 555,1555,565,4444 cases  (not 8-8 yet)
00933 
00934                     assert((ddsd.ddpfPixelFormat.dwRBitMask==0xF800)  ||  // 565
00935                            (ddsd.ddpfPixelFormat.dwRBitMask==0x0F00)  ||  // 4444
00936                            (ddsd.ddpfPixelFormat.dwRBitMask==0x7C00));    // 555 or 1555
00937 
00938                     WORD  *pSrcWord;
00939                         // handle 0555,1555,0565 in same loop
00940                     BYTE redshift,greenshift,blueshift;
00941                     DWORD redmask,greenmask,bluemask;
00942 
00943                     if(ddsd.ddpfPixelFormat.dwRBitMask==0xF800) {
00944                         redshift=(11-3);
00945                         redmask=0xF800;
00946                         greenmask=0x07E0;
00947                         greenshift=(5-2);
00948                         bluemask=0x001F;
00949                         blueshift=3;
00950                     } else if(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00) {
00951                         redmask=0x7C00;
00952                         redshift=(10-3);
00953                         greenmask=0x03E0;
00954                         greenshift=(5-3);
00955                         bluemask=0x001F;
00956                         blueshift=3;
00957                     } else {
00958                         assert(ddsd.ddpfPixelFormat.dwRBitMask==0x0F00);
00959                         redmask=0x0F00;
00960                         redshift=4;
00961                         greenmask=0x00F0;
00962                         greenshift=0;
00963                         bluemask=0x000F;
00964                         blueshift=4;
00965                     }
00966 
00967                     pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1);
00968                     for(DWORD y=0; y<dwCopyHeight; y++,pDDSurfBytes-=ddsd.lPitch) {
00969                         pSrcWord = ((WORD*)pDDSurfBytes)+dwXWindowOffset;
00970                         for(DWORD x=0; x<dwCopyWidth; x++,pSrcWord++) {
00971                             WORD dwPixel = *pSrcWord;
00972                             BYTE r,g,b;
00973 
00974                             b = (dwPixel & bluemask) << blueshift;
00975                             g = (dwPixel & greenmask) >> greenshift;
00976                             r = (dwPixel & redmask) >> redshift;
00977 
00978                             #ifdef PANDA_BGRA_ORDER
00979                                 *pDstByte++ = b;
00980                                 *pDstByte++ = g;
00981                                 *pDstByte++ = r;
00982                             #else
00983                                 *pDstByte++ = r;
00984                                 *pDstByte++ = g;
00985                                 *pDstByte++ = b;                            
00986                             #endif
00987                         }
00988                     }
00989                 }
00990                 break;
00991         }
00992     }
00993 
00994 
00995     pDDSurf->Unlock(NULL);
00996 
00997     return S_OK;
00998 }
00999 
01000 //-----------------------------------------------------------------------------
01001 // Name: CreateTextureFromBitmap()
01002 // Desc: Use a bitmap to create a texture for the specified device. This code
01003 //       gets the attributes of the texture from the bitmap, creates the
01004 //       texture, and then copies the bitmap into the texture.
01005 //-----------------------------------------------------------------------------
01006 LPDIRECTDRAWSURFACE7 DXTextureContext7::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevice, 
01007 #ifdef USE_TEXFMTVEC
01008                                         DDPixelFormatVec &TexFmts,LPD3DDEVICEDESC7 pD3DDevDesc)
01009 #else
01010                                         int cNumTexPixFmts, DDPIXELFORMAT *pTexFmts,LPD3DDEVICEDESC7 pD3DDevDesc)
01011 #endif
01012    {
01013     HRESULT hr;
01014     int i,cNumAlphaBits;     //  number of alpha bits in texture pixfmt
01015     DDPIXELFORMAT *pDesiredPixFmt;
01016     LPDIRECTDRAWSURFACE7 pddsRender;
01017     LPDIRECTDRAW7        pDD = NULL;
01018     ConversionType ConvNeeded;
01019 
01020     assert(_texture!=NULL);
01021 
01022     PixelBuffer *pbuf = _texture->_pbuffer;
01023 
01024 #ifdef USE_TEXFMTVEC
01025     int cNumTexPixFmts=TexturePixelFormats.size();
01026 #endif
01027     DDPIXELFORMAT *pTexPixFmts = new DDPIXELFORMAT[cNumTexPixFmts];
01028 
01029     // make local copy of array so I can muck with it during searches for this texture fmt
01030     // (such as marking pixfmts that no search will be interested in)
01031     // probably should do this faster way
01032 
01033 #ifdef USE_TEXFMTVEC
01034     memcpy(pTexPixFmts,&TexturePixelFormats[0],cNumTexPixFmts*sizeof(DDPIXELFORMAT));
01035 #else
01036     memcpy(pTexPixFmts,pTexFmts,cNumTexPixFmts*sizeof(DDPIXELFORMAT));
01037 #endif
01038 
01039     // bpp indicates requested fmt, not pixbuf fmt
01040     DWORD bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits);
01041     PixelBuffer::Type pixbuf_type = pbuf->get_image_type();
01042     DWORD cNumColorChannels = pbuf->get_num_components();
01043 
01044     assert(pbuf->get_component_width()==sizeof(BYTE));   // cant handle anything else now
01045     assert(pixbuf_type==PixelBuffer::T_unsigned_byte);   // cant handle anything else now
01046 
01047     if((pixbuf_type != PixelBuffer::T_unsigned_byte) || (pbuf->get_component_width()!=1)) {
01048         dxgsg7_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n";
01049         return NULL;
01050     }
01051 
01052     DWORD dwOrigWidth  = (DWORD)pbuf->get_xsize();
01053     DWORD dwOrigHeight = (DWORD)pbuf->get_ysize();
01054 
01055     // Use the device caps so we can check if the device has any constraints
01056     // when using textures. 
01057 
01058     assert((pD3DDevDesc->dwMaxTextureWidth>0) && (pD3DDevDesc->dwMaxTextureHeight>0));
01059 
01060     // Setup the new surface desc for the texture. Note how we are using the
01061     // texture manage attribute, so Direct3D does alot of dirty work for us
01062     DDSURFACEDESC2 ddsd;
01063     ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
01064     ddsd.dwSize          = sizeof(DDSURFACEDESC2);
01065     ddsd.dwFlags         =  DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH
01066                             | DDSD_PIXELFORMAT ;
01067 
01068     ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01069 
01070     // setup ddpf to match against avail fmts
01071 
01072     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
01073 
01074     if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)||
01075        (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) ||
01076        (pbuf->get_format() == PixelBuffer::F_luminance)) {
01077         ddsd.ddpfPixelFormat.dwFlags = DDPF_LUMINANCE;
01078     }
01079 
01080     ddsd.ddpfPixelFormat.dwRGBBitCount = bpp;
01081 
01082     if(cNumAlphaBits) {
01083         if(bpp == 8 && cNumAlphaBits == 8) { // handle special case:  Alpha only buffer
01084             ddsd.dwFlags |= DDPF_ALPHA;
01085             ddsd.dwAlphaBitDepth = 8;
01086             ddsd.ddpfPixelFormat.dwAlphaBitDepth = 8;
01087             ddsd.ddpfPixelFormat.dwFlags = DDPF_ALPHA;
01088             ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff;
01089         } else {
01090             ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
01091             if(cNumAlphaBits == 8)
01092                 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
01093             else if(cNumAlphaBits == 4)
01094                 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xf000;
01095         }
01096     }
01097 
01098     ddsd.dwWidth         = dwOrigWidth;
01099     ddsd.dwHeight        = dwOrigHeight;
01100 
01101     if(!ISPOW2(ddsd.dwWidth) || !ISPOW2(ddsd.dwHeight)) {
01102         dxgsg7_cat.error() << "ERROR: texture dimensions are not a power of 2 for " << _tex->get_name() << "!!!!! \n";
01103         #ifdef _DEBUG
01104           exit(1);  // want to catch badtexsize errors
01105         #else
01106           goto error_exit;
01107         #endif
01108     }
01109 
01110     bool bShrinkOriginal;
01111     bShrinkOriginal=false;
01112 
01113     if((dwOrigWidth>pD3DDevDesc->dwMaxTextureWidth)||(dwOrigHeight>pD3DDevDesc->dwMaxTextureHeight)) {
01114         #ifdef _DEBUG
01115            dxgsg7_cat.error() << "WARNING: " <<_tex->get_name() << ": Image size exceeds max texture dimensions of (" << pD3DDevDesc->dwMaxTextureWidth << "," << pD3DDevDesc->dwMaxTextureHeight << ") !!\n"
01116            << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," <<dwOrigHeight << ") => ("<<  pD3DDevDesc->dwMaxTextureWidth << "," << pD3DDevDesc->dwMaxTextureHeight << ") !\n";
01117         #endif
01118 
01119         if(dwOrigWidth>pD3DDevDesc->dwMaxTextureWidth)
01120             ddsd.dwWidth=pD3DDevDesc->dwMaxTextureWidth;
01121         if(dwOrigHeight>pD3DDevDesc->dwMaxTextureHeight)
01122             ddsd.dwHeight=pD3DDevDesc->dwMaxTextureHeight;
01123         bShrinkOriginal=true;
01124     }
01125 
01126     // checks for SQUARE reqmt (nvidia riva128 needs this)
01127     if((ddsd.dwWidth != ddsd.dwHeight) && (pD3DDevDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )) {
01128 
01129         // assume pow2 textures.   sum exponents, divide by 2 rounding down to get sq size
01130         int i,width_exp,height_exp;
01131         for(i=ddsd.dwWidth,width_exp=0;i>1;width_exp++,i>>=1);
01132         for(i=ddsd.dwHeight,height_exp=0;i>1;height_exp++,i>>=1);
01133         ddsd.dwHeight = ddsd.dwWidth = 1<<((width_exp+height_exp)>>1);
01134         bShrinkOriginal=true;
01135 
01136 #ifdef _DEBUG
01137         dxgsg7_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," <<dwOrigHeight << ") => ("<< ddsd.dwWidth<<"," << ddsd.dwHeight << ") to meet HW square texture reqmt\n";
01138 #endif
01139     }
01140 
01141     if(bShrinkOriginal) {
01142         // need 2 add checks for errors
01143         PNMImage pnmi_src;
01144         PNMImage *pnmi = new PNMImage(ddsd.dwWidth, ddsd.dwHeight, cNumColorChannels);
01145         pbuf->store(pnmi_src);
01146         pnmi->quick_filter_from(pnmi_src,0,0);
01147 
01148         pbuf->load(*pnmi);  // violates device independence of pixbufs
01149 
01150         dwOrigWidth  = (DWORD)pbuf->get_xsize();
01151         dwOrigHeight = (DWORD)pbuf->get_ysize();
01152         delete pnmi;
01153     }
01154 
01155 #if 0
01156 //#ifdef _DEBUG
01157 // easier to use dxcapsviewer instead of this
01158     { static BOOL bPrinted=FALSE;
01159         if(!bPrinted) {
01160             dxgsg7_cat.debug() << "Gfx card supported TexFmts:\n";
01161             for(i=0;i<cNumTexPixFmts;i++) {
01162                 DebugPrintPixFmt(&pTexPixFmts[i]);
01163             }
01164             bPrinted=TRUE;
01165         }
01166     }
01167 #endif
01168 
01169     // first search for an exact match
01170     pDesiredPixFmt = &ddsd.ddpfPixelFormat;
01171 
01172     LPDDPIXELFORMAT pCurPixFmt;
01173     char *szErrorMsg;
01174 
01175     szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT!\n";
01176 
01177     if(dxgsg7_cat.is_spam())
01178         dxgsg7_cat.spam() << "CreateTexture handling bitdepth: " << bpp << " alphabits: " << cNumAlphaBits << "\n";
01179 
01180     // Mark formats I dont want to deal with
01181     for(i=0,pCurPixFmt=pTexPixFmts;i<cNumTexPixFmts;i++,pCurPixFmt++) {
01182         if(( pCurPixFmt->dwFlags & (DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )  ||
01183            ( pCurPixFmt->dwFourCC != 0 ) ||
01184            ((cNumAlphaBits==0) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS))) {
01185 
01186             // Make sure to skip any FourCC formats, bump formats
01187             // they are not handled by this code yet
01188 
01189             // note: I'm screening out alpha if no alpha requested, so
01190             // search fails if 32-rgba avail, but not 32-bit rgb
01191             // I could recode for that case too, hopefully this case will not pop up
01192 
01193             pCurPixFmt->dwRGBBitCount+=1;  // incr so it wont be an exact match anymore
01194         }
01195     }
01196 
01197     // handle each bitdepth separately
01198 
01199     switch(bpp) {  // bpp is REQUESTED bpp, not what exists in the pixbuf array
01200 
01201         case 32:
01202 
01203 #ifdef _DEBUG
01204             if(!dx_force_16bpptextures)
01205 #endif
01206                 for(i=0,pCurPixFmt=pTexPixFmts;i<cNumTexPixFmts;i++,pCurPixFmt++) {
01207                     if((pCurPixFmt->dwRGBBitCount==32) &&
01208                        (((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)!=0)==(cNumAlphaBits!=0))) {
01209                   // we should have a match
01210                         assert(pCurPixFmt->dwRGBAlphaBitMask==0xFF000000);
01211                         ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32);
01212                         goto found_matching_format;
01213                         break;
01214                     }
01215                 }
01216 
01217             if(cNumAlphaBits>0) {
01218             // no 32-bit fmt, look for 16 bit w/alpha  (1-15)
01219 
01220             // 32 bit RGBA was requested, but only 16 bit alpha fmts are avail
01221             // by default, convert to 4-4-4-4 which has 4-bit alpha for blurry edges
01222             // if we know tex only needs 1 bit alpha (i.e. for a mask), use 1555 instead
01223 
01224                 ConversionType ConvTo1=Conv32to16_4444,ConvTo2=Conv32to16_1555;
01225                 DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000;
01226             // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion
01227             // this should be true on most cards.
01228 
01229 #ifndef FORCE_16bpp_1555
01230                 if(cNumAlphaBits==1)
01231 #endif
01232                 {
01233                     ConvTo1=Conv32to16_1555;
01234                     dwAlphaMask1=0x8000;
01235                 }
01236 
01237                 for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01238                     if((pCurPixFmt->dwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)
01239                        && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) {
01240                         ConvNeeded=ConvTo1;
01241                         goto found_matching_format;
01242                     }
01243                 }
01244 
01245 #ifdef FORCE_16bpp_1555
01246                 break;
01247 #endif
01248 
01249                 for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01250                     if((pCurPixFmt->dwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)
01251                        && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) {
01252                         ConvNeeded=ConvTo2;
01253                         goto found_matching_format;
01254                     }
01255                 }
01256 
01257             // at this point, bail.  dont worry about converting to non-alpha formats yet,
01258             // I think this will be a very rare case
01259                 szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!\n";
01260             }
01261 
01262             break;
01263 
01264         case 24:
01265 
01266             assert(cNumAlphaBits==0);  // dont know how to handle non-zero alpha for 24bit total
01267 
01268             if(!dx_force_16bpptextures)
01269                 for(i=0,pCurPixFmt=pTexPixFmts;i<cNumTexPixFmts;i++,pCurPixFmt++) {
01270                     if((pCurPixFmt->dwFlags & DDPF_RGB)&&(pCurPixFmt->dwRGBBitCount==24)) {
01271                         ConvNeeded=((cNumColorChannels==3) ? Conv24to24 : Conv32to24);
01272                         goto found_matching_format;
01273                     }
01274                 }
01275 
01276             if(!dx_force_16bpptextures) {
01277                 // no 24-bit fmt.  look for 32 bit fmt  (note: this is memory-hogging choice
01278                 // instead I could look for memory-conserving 16-bit fmt).
01279                 // check mask to ensure ARGB, not RGBA (which I am not handling here)
01280                 for(i=0,pCurPixFmt=pTexPixFmts;i<cNumTexPixFmts;i++,pCurPixFmt++) {
01281                     if((pCurPixFmt->dwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB)
01282                        && ((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0xFFFFFF)
01283                       ) {
01284                     // I'm allowing alpha formats here.  will set alpha to opaque
01285                         ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32_NoAlpha);
01286                         goto found_matching_format;
01287                     }
01288                 }
01289             }
01290 
01291           // no 24-bit or 32 fmt.  look for 16 bit fmt
01292             for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01293               // assume RGBMASK is x7fff to simplify 32->16 conversion, should be true on most cards.
01294                 if((pCurPixFmt->dwFlags & DDPF_RGB) && (pCurPixFmt->dwRGBBitCount==16)
01295                    && !(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) {  // no alpha fmts
01296                         // if numchan==4,this means user has requested we throw away the input alpha channel
01297                     if(pCurPixFmt->dwGBitMask==0x7E0) {
01298                             // assumes GBitMask is the biggest one, if we have 16 bit 3-channel
01299                         ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565);
01300                     } else {
01301                         assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF);
01302                         ConvNeeded=((cNumColorChannels==3) ? Conv24to16_X555 : Conv32to16_X555);
01303                     }
01304                     goto found_matching_format;
01305                 }
01306             }
01307 
01308           // at this point, bail.
01309             break;
01310 
01311         case 16:
01312 
01313             if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) {
01314            // look for native lum fmt
01315                 if(!dx_force_16bpptextures) {
01316                     for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01317                         if((pCurPixFmt->dwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) &&
01318                            (pCurPixFmt->dwFlags & DDPF_LUMINANCE)) {
01319                             ConvNeeded=ConvLum16to16;
01320                             goto found_matching_format;
01321                         }
01322                     }
01323 
01324            // else look for 32bpp ARGB
01325                     for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01326                         if((pCurPixFmt->dwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) &&
01327                            (pCurPixFmt->dwFlags & DDPF_RGB)) {
01328                             ConvNeeded=ConvLum16to32;
01329                             goto found_matching_format;
01330                         }
01331                     }
01332                 }
01333 
01334            // find compatible 16bpp fmt
01335                 ConversionType ConvTo1=ConvLum16to16_4444,ConvTo2=ConvLum16to16_1555;
01336                 DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000;
01337             // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion
01338             // this should be true on most cards.
01339 
01340 #ifndef FORCE_16bpp_1555
01341                 if(cNumAlphaBits==1)
01342 #endif
01343                 {
01344                     ConvTo1=ConvLum16to16_1555;
01345                     dwAlphaMask1=0x8000;
01346                 }
01347 
01348                 for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01349                     if((pCurPixFmt->dwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)
01350                        && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) {
01351                         ConvNeeded=ConvTo1;
01352                         goto found_matching_format;
01353                     }
01354                 }
01355 
01356 #ifdef FORCE_16bpp_1555
01357                 break;
01358 #endif
01359 
01360                 for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01361                     if((pCurPixFmt->dwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)
01362                        && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) {
01363                         ConvNeeded=ConvTo2;
01364                         goto found_matching_format;
01365                     }
01366                 }
01367 
01368             } else
01369 
01370           // look for compatible 16bit fmts, if none then give up
01371           // (dont worry about other bitdepths for 16 bit)
01372 
01373                 for(i=0,pCurPixFmt=pTexPixFmts;i<cNumTexPixFmts;i++,pCurPixFmt++) {
01374 
01375                     if((pCurPixFmt->dwRGBBitCount==16)&&(pCurPixFmt->dwFlags & DDPF_RGB)) {
01376                         switch(cNumAlphaBits) {
01377                             case 0:
01378                                 if(!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) {
01379                             // if numchan==4,this means user has requested we throw away the input alpha channel
01380                                     if(pCurPixFmt->dwGBitMask==0x7E0) {
01381                                 // assumes GBitMask is the biggest one, if we have 16 bit 3-channel
01382                                         ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565);
01383                                     } else {
01384                                         assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF);
01385                                         ConvNeeded=((cNumColorChannels==3) ? Conv24to16_X555 : Conv32to16_X555);
01386                                     }
01387                                     goto found_matching_format;
01388                                 }
01389                                 break;
01390                             case 1:
01391                                 if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&&
01392                                    (pCurPixFmt->dwRGBAlphaBitMask==0x8000)) {
01393                                     ConvNeeded=Conv32to16_1555;
01394                                     goto found_matching_format;
01395                                 }
01396                                 break;
01397                             case 4:
01398                                 if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&&
01399                                    (pCurPixFmt->dwRGBAlphaBitMask==0xF000)) {
01400                                     ConvNeeded=Conv32to16_4444;
01401                                     goto found_matching_format;
01402                                 }
01403                                 break;
01404                         }
01405                     }
01406                 }
01407 
01408             break;
01409 
01410         case 8:
01411             if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) {
01412               // look for native lum fmt
01413 
01414                 assert(cNumAlphaBits==0);  // dont handle those other 8bit lum fmts like 4-4, since 16 8-8 is usually supported too
01415                 if(!dx_force_16bpptextures)
01416                 {
01417                     for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01418                         if((pCurPixFmt->dwRGBBitCount==8) && (pCurPixFmt->dwFlags & DDPF_LUMINANCE) &&
01419                            (pCurPixFmt->dwLuminanceBitMask==0xFF)) {
01420                             ConvNeeded=ConvLum8to8;
01421                             goto found_matching_format;
01422                         }
01423                     }
01424 
01425               // else look for 24bpp RGB
01426                     for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01427                         if((pCurPixFmt->dwRGBBitCount==24) && (pCurPixFmt->dwFlags & DDPF_RGB)) {
01428                             ConvNeeded=ConvLum8to24;
01429                             goto found_matching_format;
01430                         }
01431                     }
01432 
01433               // else look for 32bpp RGB
01434                     for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01435                         if((pCurPixFmt->dwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB)) {
01436                             ConvNeeded=ConvLum8to32;
01437                             goto found_matching_format;
01438                         }
01439                     }
01440                 }
01441 
01442                 // find compatible 16bpp fmt, just look for any 565, then 0555
01443                 DWORD dwMasks[2] = {0xF800, 0x7C00};
01444                 ConversionType ConvType[2] = {ConvLum8to16_0565,ConvLum8to16_X555};
01445 
01446                 for(DWORD modenum=0;modenum<2;modenum++)
01447                     for(i=0,pCurPixFmt=&pTexPixFmts[0];i<cNumTexPixFmts;i++,pCurPixFmt++) {
01448                         if((pCurPixFmt->dwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_RGB)
01449                            && (!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS))
01450                            && (pCurPixFmt->dwRBitMask==dwMasks[modenum])) {
01451                             ConvNeeded=ConvType[modenum];
01452                             goto found_matching_format;
01453                         }
01454                     }
01455             } else if(ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHA) {
01456                 // look for 32-bit ARGB, else 16-4444.
01457                 // skip 8bit alpha only, because I think only voodoo supports it
01458                 // and the voodoo support isn't the kind of blending model we need 
01459                 // w/color assumed to be white (but need to verify this)
01460                 for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01461                         if((pCurPixFmt->dwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB) &&
01462                            (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) {
01463                             ConvNeeded=ConvAlpha8to32;
01464                             goto found_matching_format;
01465                         }
01466                 }
01467 
01468                 for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i<cNumTexPixFmts;i++,pCurPixFmt--) {
01469                         if((pCurPixFmt->dwRGBBitCount==16) 
01470                            && (pCurPixFmt->dwFlags & DDPF_RGB)
01471                            && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)
01472                            && (pCurPixFmt->dwRGBAlphaBitMask==0xF000)) {
01473                             ConvNeeded=ConvAlpha8to16_4444;
01474                             goto found_matching_format;
01475                         }
01476                 }
01477             }
01478             break;
01479 
01480         default:
01481             szErrorMsg = "CreateTexture failed: unhandled pixel bitdepth in DX loader";
01482     }
01483 
01484     // if we've gotten here, haven't found a match
01485 
01486     dxgsg7_cat.error() << szErrorMsg << ";  requested tex bitdepth: " << bpp << "\n";
01487     goto error_exit;
01488 
01489     ///////////////////////////////////////////////////////////
01490 
01491     found_matching_format:
01492 
01493     ddsd.ddpfPixelFormat = *pCurPixFmt;
01494 
01495     // Get the device's render target, so we can then use the render target to
01496     // get a ptr to a DDraw object. We need the DirectDraw interface for
01497     // creating surfaces.
01498 
01499     pd3dDevice->GetRenderTarget( &pddsRender );
01500     pddsRender->GetDDInterface( (VOID**)&pDD );
01501     pddsRender->Release();
01502 
01503     ddsd.ddsCaps.dwCaps  = DDSCAPS_TEXTURE;
01504 
01505     if(pD3DDevDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) {
01506         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE  // Turn on texture management
01507                                | DDSCAPS2_HINTSTATIC;  // BUGBUG:  is this ok for ALL textures?
01508     } else {
01509         ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
01510     }
01511 
01512     // validate magfilter setting
01513     // degrade filtering if no HW support
01514 
01515     Texture::FilterType ft;
01516 
01517     ft =_tex->get_magfilter();
01518     if((ft!=Texture::FT_linear) && ft!=Texture::FT_nearest) {
01519         if(ft==Texture::FT_nearest_mipmap_nearest)
01520             ft=Texture::FT_nearest;
01521         else ft=Texture::FT_linear;
01522     }
01523 
01524     if((ft==Texture::FT_linear) && !(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR))
01525         ft=Texture::FT_nearest;
01526     _tex->set_magfilter(ft);
01527 
01528     // figure out if we are mipmapping this texture
01529     ft =_tex->get_minfilter();
01530     _bHasMipMaps=FALSE;
01531 
01532     if(!dx_ignore_mipmaps) {  // set if no HW mipmap capable
01533         switch(ft) {
01534             case Texture::FT_nearest_mipmap_nearest:
01535             case Texture::FT_linear_mipmap_nearest:
01536             case Texture::FT_nearest_mipmap_linear:  // pick nearest in each, interpolate linearly b/w them
01537             case Texture::FT_linear_mipmap_linear:
01538                 _bHasMipMaps=TRUE;
01539         }
01540 
01541         if(dx_mipmap_everything) {  // debug toggle, ok to leave in since its just a creation cost
01542            _bHasMipMaps=TRUE;
01543            if(ft != Texture::FT_linear_mipmap_linear) {
01544                dxgsg7_cat.spam() << "Forcing mipmap filtering on DX texture [" << _tex->get_name() << "]\n";
01545            }
01546            ft = Texture::FT_linear_mipmap_linear;
01547            _tex->set_minfilter(ft);
01548         }
01549     } else if((ft==Texture::FT_nearest_mipmap_nearest) ||   // cvt to no-mipmap filter types
01550               (ft==Texture::FT_nearest_mipmap_linear)) {
01551         ft=Texture::FT_nearest;
01552     } else if((ft==Texture::FT_linear_mipmap_nearest) ||
01553               (ft==Texture::FT_linear_mipmap_linear)) {
01554         ft=Texture::FT_linear;
01555     }
01556 
01557     assert((pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_NEAREST)!=0);
01558 
01559     switch(ft) {
01560         case Texture::FT_nearest_mipmap_linear:
01561             if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPNEAREST))
01562                 ft=Texture::FT_nearest_mipmap_nearest;
01563             break;
01564         case Texture::FT_linear_mipmap_nearest:
01565             if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR))
01566                 ft=Texture::FT_nearest_mipmap_nearest;
01567             break;
01568         case Texture::FT_linear_mipmap_linear:
01569             if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR)) {
01570                 if(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR)
01571                     ft=Texture::FT_linear_mipmap_nearest;
01572                 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
01573             }
01574             break;
01575         case Texture::FT_linear:
01576             if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR))
01577                 ft=Texture::FT_nearest;
01578             break;
01579     }
01580 
01581     _tex->set_minfilter(ft);
01582 
01583     uint aniso_degree;
01584 
01585     aniso_degree=1;
01586     if(pD3DDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
01587         aniso_degree=_tex->get_anisotropic_degree();
01588         if((aniso_degree>pD3DDevDesc->dwMaxAnisotropy)
01589 #ifdef _DEBUG
01590            || dx_force_anisotropic_filtering
01591 #endif
01592           )
01593             aniso_degree=pD3DDevDesc->dwMaxAnisotropy;
01594     }
01595     _tex->set_anisotropic_degree(aniso_degree);
01596 #ifdef _DEBUG
01597     dxgsg7_cat.spam() << "CreateTexture: setting aniso degree for "<< _tex->get_name() << " to: " << aniso_degree << endl;
01598 #endif
01599 
01600     if(_bHasMipMaps) {
01601        // We dont specify mipmapcount, so CreateSurface will auto-create surfs
01602        // for all mipmaps down to 1x1 (if driver supports deep-mipmaps, otherwise Nx1)
01603         ddsd.ddsCaps.dwCaps |= (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX);
01604         dxgsg7_cat.debug() << "CreateTexture: generating mipmaps for "<< _tex->get_name() << endl;
01605     }
01606 
01607     if(pD3DDevDesc->dwDevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) {
01608         // must assign a texture to a specific stage
01609         // for now I'm just going to use stage 0 for all
01610         ddsd.dwTextureStage=0;
01611         ddsd.dwFlags |= DDSD_TEXTURESTAGE;
01612     }
01613 
01614     PRINTVIDMEM(pDD,&ddsd.ddsCaps,"texture surf (includes AGP mem)");
01615 
01616     // Create a new surface for the texture
01617     if(FAILED( hr = pDD->CreateSurface( &ddsd, &_surface, NULL ) )) {
01618         dxgsg7_cat.error() << "CreateTexture failed: pDD->CreateSurface() failed!  hr = " << ConvD3DErrorToString(hr) << "\n";
01619         goto error_exit;
01620     }
01621 
01622 
01623 #ifdef _DEBUG
01624     dxgsg7_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converted " << ConvNameStrs[ConvNeeded] << " \n";
01625 #endif
01626 
01627     _PixBufConversionType=ConvNeeded;
01628 
01629     hr = FillDDSurfTexturePixels();
01630     if(FAILED(hr)) {
01631         goto error_exit;
01632     }
01633 
01634     // Done with DDraw
01635     pDD->Release();
01636 
01637     delete [] pTexPixFmts;
01638 
01639     // Return the newly created texture
01640     return _surface;
01641 
01642   error_exit:
01643 
01644     if(pDD!=NULL)
01645         pDD->Release();
01646     if(_surface!=NULL) {
01647         _surface->Release();
01648         _surface = NULL;
01649     }
01650 
01651     delete [] pTexPixFmts;
01652     return NULL;
01653 }
01654 
01655 HRESULT DXTextureContext7::
01656 FillDDSurfTexturePixels(void) {
01657     
01658     PixelBuffer *pbuf = _texture->get_ram_image();
01659     if (pbuf == (PixelBuffer *)NULL) {
01660       dxgsg7_cat.fatal() << "CreateTexture: get_ram_image() failed\n";
01661       // The texture doesn't have an image to load.
01662       return E_FAIL;
01663     }
01664 
01665     HRESULT hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pbuf->_image.p(),_surface);
01666     if(FAILED(hr)) {
01667         return hr;
01668     }
01669 
01670     DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
01671 
01672     _surface->GetSurfaceDesc(&ddsd);
01673 
01674     if(_bHasMipMaps) {
01675         DWORD i,oldcurxsize,oldcurysize,curxsize,curysize,cMipMapCount=ddsd.dwMipMapCount;
01676         assert(ddsd.dwMipMapCount<20);
01677 
01678         DWORD cNumColorChannels = pbuf->get_num_components();
01679 
01680         curxsize=ddsd.dwWidth; curysize=ddsd.dwHeight;
01681 
01682         assert(pbuf->get_image_type()==PixelBuffer::T_unsigned_byte);    // cant handle anything else now
01683 
01684         // all mipmap sublevels require 1/3 of total original space. alloc 1/2 for safety
01685         BYTE *pMipMapPixBufSpace = new BYTE[((curxsize*curysize*cNumColorChannels)/2)+1024];
01686 
01687         LPDIRECTDRAWSURFACE7 pCurDDSurf=_surface;
01688         pCurDDSurf->AddRef();  // so final release doesnt release the surface
01689 
01690         BYTE *pDstWord = pMipMapPixBufSpace;
01691         BYTE *pLastMipLevelStart  = (BYTE *) pbuf->_image.p();
01692 //    clock_t  start1,finish1;
01693 //    start1=clock();
01694         for(i=1;i<ddsd.dwMipMapCount;i++) {
01695             oldcurxsize=curxsize; oldcurysize=curysize;
01696             curysize = max(curysize>>1,1);
01697             curxsize = max(curxsize>>1,1);
01698 
01699             assert(!((oldcurxsize==1)&&(oldcurysize==1)));
01700 
01701             BYTE *pSrcWord;
01702             BYTE *pSrcLineStart=pLastMipLevelStart;
01703 
01704             // inc img start to DWORD boundary
01705             while(((DWORD)pDstWord) & 0x11)
01706                 pDstWord++;
01707 
01708             pLastMipLevelStart = pDstWord;
01709 
01710             DWORD x,y,cPixelSize=cNumColorChannels;
01711             DWORD src_row_bytelength=oldcurxsize*cPixelSize;
01712             DWORD two_src_row_bytelength=2*src_row_bytelength;
01713 
01714         #define GENMIPMAP_DO_INTEGER_DIV    // should be a little faster, but no rounding up
01715         #ifdef GENMIPMAP_DO_INTEGER_DIV
01716             DWORD DivShift=2;
01717             if((oldcurxsize==1)||(oldcurysize==1))
01718                 DivShift = 1;
01719         #else
01720             float numpixels_per_filter=4.0f;
01721             if((oldcurxsize==1)||(oldcurysize==1))
01722                 numpixels_per_filter=2.0f;                
01723         #endif
01724 
01725             DWORD x_srcptr_inc = ((oldcurxsize==1)? cPixelSize: (2*cPixelSize));
01726 
01727             // box-filter shrink down, avg 4 pixels at a time
01728             for(y=0; y<curysize; y++,pSrcLineStart+=two_src_row_bytelength) {
01729                 pSrcWord=pSrcLineStart;
01730                 for(x=0; x<curxsize; x++,pSrcWord+=x_srcptr_inc,pDstWord+=cPixelSize) {
01731                   // fetches, stores byte at a time.
01732                   // inefficient, but works for all channel sizes
01733 
01734                     for(DWORD c=0;c<cPixelSize;c++) {
01735                         DWORD colr;
01736                         colr =  *(pSrcWord+c);
01737                         if(oldcurxsize>1)  // handle 1x[X], [X]x1 cases
01738                             colr += *(pSrcWord+cPixelSize+c);
01739                         if(oldcurysize>1) {
01740                             colr += *(pSrcWord+src_row_bytelength+c);
01741                             if(oldcurxsize>1)
01742                                 colr += *(pSrcWord+src_row_bytelength+cPixelSize+c);
01743                         }
01744                         #ifdef GENMIPMAP_DO_INTEGER_DIV
01745                            colr >>= DivShift;
01746                         #else
01747                            colr = (DWORD) ((((float)colr)/numpixels_per_filter)+0.5f);
01748                         #endif
01749 
01750                         *(pDstWord+c)=(BYTE)colr;
01751                     }
01752                 }
01753             }
01754 
01755             // now copy pixbuf to final DD surf
01756 
01757             DDSCAPS2 ddsCaps;
01758             LPDIRECTDRAWSURFACE7 pMipLevel_DDSurf;
01759             ZeroMemory(&ddsCaps,sizeof(DDSCAPS2));
01760             ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
01761             ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
01762 
01763             hr = pCurDDSurf->GetAttachedSurface(&ddsCaps, &pMipLevel_DDSurf);
01764             if(FAILED(hr)) {
01765                 dxgsg7_cat.error() << "CreateTexture failed creating mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n";
01766                 delete [] pMipMapPixBufSpace;
01767                 pCurDDSurf->Release();
01768                 return hr;
01769             }
01770 
01771             hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pLastMipLevelStart,pMipLevel_DDSurf);
01772             if(FAILED(hr)) {
01773                 delete [] pMipMapPixBufSpace;
01774                 pCurDDSurf->Release();
01775                 return hr;
01776             }
01777 
01778             pCurDDSurf->Release();
01779             pCurDDSurf=pMipLevel_DDSurf;
01780         }
01781 
01782         //   finish1=clock();
01783         //   double elapsed_time  = (double)(finish1 - start1) / CLOCKS_PER_SEC;
01784         //   cerr <<  "mipmap gen takes " << elapsed_time << " secs for this texture\n";
01785 
01786         delete [] pMipMapPixBufSpace;
01787         pCurDDSurf->Release();
01788 
01789 #ifdef _DEBUG
01790         if(dx_debug_view_mipmaps) {
01791 #if 0
01792             if(!(ddcaps.dwCaps & DDCAPS_BLTSTRETCH)) {
01793                 dxgsg7_cat.error() << "CreateTexture failed debug-viewing mipmaps, BLT stretching not supported!  ( we need to do SW stretch) \n";
01794                 return hr;
01795             }
01796 #endif
01797 
01798             // display mipmaps on primary surf
01799             HDC hTexDC;
01800             LPDIRECTDRAWSURFACE7 pTextureCurrent,pTexturePrev = _surface;
01801             int cury,curx;
01802             HDC hScreenDC;
01803             RECT scrnrect;
01804             hScreenDC=GetDC(NULL);
01805 
01806             scrnrect.left=scrnrect.top=0;
01807             scrnrect.bottom=GetDeviceCaps(hScreenDC,VERTRES);
01808             scrnrect.right=GetDeviceCaps(hScreenDC,HORZRES);
01809             char msg[500];
01810 
01811             pTexturePrev->AddRef();
01812 
01813             for(i = 0,curx=scrnrect.left,cury=scrnrect.top; i < ddsd.dwMipMapCount; i++) {
01814 
01815                 DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_cur);
01816                 pTexturePrev->GetSurfaceDesc(&ddsd_cur);
01817 
01818                 hr = pTexturePrev->GetDC(&hTexDC);
01819                 if(FAILED(hr)) {
01820                     dxgsg7_cat.error() << "GetDC failed hr = " << ConvD3DErrorToString(hr) << "\n";
01821                     break;
01822                 }
01823 
01824                 BOOL res;
01825                         // res = BitBlt(_dxgsg7->_hdc,0,0,ddsd.dwWidth,ddsd.dwHeight, TexDC,0,0,SRCCOPY);
01826                         // loader inverts y, so use StretchBlt to re-invert it
01827                         // res = StretchBlt(_dxgsg7->hdc,0,ddsd_cur.dwHeight+cury,ddsd_cur.dwWidth,-ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,SRCCOPY);
01828 #if 0
01829                 if(cNumAlphaBits>0) {
01830                     BLENDFUNCTION  bf;
01831                     bf.BlendOp = AC_SRC_OVER;  bf.BlendFlags=0;
01832                     bf.SourceConstantAlpha=255; bf.AlphaFormat=AC_SRC_ALPHA;
01833                     res = AlphaBlend(hScreenDC,curx,cury,ddsd_cur.dwWidth,ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,bf);
01834                     if(!res) {
01835                         PrintLastError(msg);
01836                         dxgsg7_cat.error() << "AlphaBlend BLT failed: "<<msg<<"\n";
01837                     }
01838 
01839                 } else
01840 #endif
01841                 {
01842                     res = StretchBlt(hScreenDC,curx,ddsd_cur.dwHeight+cury,ddsd_cur.dwWidth,-((int)ddsd_cur.dwHeight), hTexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,SRCCOPY);
01843                     if(!res) {
01844                         PrintLastError(msg);
01845                         dxgsg7_cat.error() << "StretchBLT failed: "<<msg<<"\n";
01846 
01847                     }
01848                 }
01849         //                SetBkMode(hScreenDC, TRANSPARENT);
01850                 sprintf(msg,"%d",i);
01851                 TextOut(hScreenDC,curx+(ddsd_cur.dwWidth)/2,5+cury+ddsd_cur.dwHeight,msg,strlen(msg));
01852 
01853                 curx+=max(20,ddsd_cur.dwWidth+10);
01854 
01855                 if(curx>scrnrect.right) {
01856                     curx=0;  cury+=(scrnrect.bottom-scrnrect.top)/2;
01857                 }
01858 
01859                 hr = pTexturePrev->ReleaseDC(hTexDC);
01860 
01861                 if(FAILED(hr)) {
01862                     dxgsg7_cat.error() << "tex ReleaseDC failed for mip "<<i<<" hr = " << ConvD3DErrorToString(hr) << "\n";
01863                     break;
01864                 }
01865 
01866                 if(i==ddsd.dwMipMapCount-1) {
01867                     pTexturePrev->Release();
01868                     continue;
01869                 }
01870 
01871                 DDSCAPS2 ddsCaps;
01872                 ZeroMemory(&ddsCaps,sizeof(DDSCAPS2));
01873                 ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
01874                 ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
01875                 hr = pTexturePrev->GetAttachedSurface(&ddsCaps, &pTextureCurrent);
01876                 if(FAILED(hr)) {
01877                     dxgsg7_cat.error() << " failed displaying mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n";
01878                 }
01879                         // done with the previous texture
01880                 pTexturePrev->Release();
01881                 pTexturePrev = pTextureCurrent;
01882             }
01883 
01884             ReleaseDC(0,hScreenDC);
01885 
01886             HANDLE hArr[1];
01887             MSG winmsg;
01888             hArr[0]=GetStdHandle(STD_INPUT_HANDLE);
01889             GetMessage(&winmsg,NULL,0,0);
01890 
01891             int val=MsgWaitForMultipleObjects(1,hArr,TRUE,INFINITE,QS_KEY);
01892             if(val==-1) {
01893                 PrintLastError(msg);
01894                 dxgsg7_cat.error() << " MsgWaitForMultipleObjects returns " << val << "  " <<msg << endl;
01895             } else {
01896                 dxgsg7_cat.error() << " MsgWaitForMultipleObjects returns " << val << endl;
01897             }
01898         }
01899 #endif
01900     }
01901     return S_OK;
01902 }
01903 
01904 
01905 
01906 //-----------------------------------------------------------------------------
01907 // Name: DeleteTexture()
01908 // Desc: Release the surface used to store the texture
01909 //-----------------------------------------------------------------------------
01910 void DXTextureContext7::
01911 DeleteTexture( ) {
01912     if(dxgsg7_cat.is_spam()) {
01913         dxgsg7_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
01914     }
01915 
01916     ULONG refcnt;
01917 
01918 #ifdef DEBUG_RELEASES
01919     if(_surface) {
01920         LPDIRECTDRAW7 pDD;
01921         _surface->GetDDInterface( (VOID**)&pDD );
01922         pDD->Release();
01923 
01924         PRINTREFCNT(pDD,"before DeleteTex, IDDraw7");
01925         RELEASE(_surface,dxgsg7,"texture",false);
01926         PRINTREFCNT(pDD,"after DeleteTex, IDDraw7");
01927     }
01928 #else
01929     RELEASE(_surface,dxgsg7,"texture",false);
01930 #endif
01931 }
01932 
01933 
01934 ////////////////////////////////////////////////////////////////////
01935 //     Function: DXTextureContext7::Constructor
01936 //       Access: Public
01937 //  Description:
01938 ////////////////////////////////////////////////////////////////////
01939 DXTextureContext7::
01940 DXTextureContext7(Texture *tex) :
01941 TextureContext(tex) {
01942 //#ifdef NDEBUG
01943     if(dxgsg7_cat.is_spam()) {
01944        dxgsg7_cat.spam() << "Creating DX texture [" << tex->get_name() << "], minfilter(" << PandaFilterNameStrs[tex->get_minfilter()] << "), magfilter("<<PandaFilterNameStrs[tex->get_magfilter()] << "), anisodeg(" << tex->get_anisotropic_degree() << ")\n";
01945     }
01946 //#endif
01947     _surface = NULL;
01948     _bHasMipMaps = FALSE;
01949     _tex = tex;
01950 }
01951 
01952 DXTextureContext7::
01953 ~DXTextureContext7() {
01954     DeleteTexture();
01955     TextureContext::~TextureContext();
01956     _tex = NULL;
01957 }
01958 

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