home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / VMRXcl / d3dtextr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  28.8 KB  |  837 lines

  1. //-----------------------------------------------------------------------------
  2. // File: D3DTextr.cpp
  3. //
  4. // Desc: Functions to manage textures, including creating (loading from a
  5. //       file), restoring lost surfaces, invalidating, and destroying.
  6. //
  7. //       Note: the implementation of these functions maintains an internal list
  8. //       of loaded textures. After creation, individual textures are referenced
  9. //       via their ASCII names.
  10. //
  11. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved
  12. //-----------------------------------------------------------------------------
  13. #include "project.h"
  14. #include <tchar.h>
  15. #include "D3DTextr.h"
  16. #include "D3DUtil.h"
  17. #include <stdio.h>
  18.  
  19.  
  20. #ifndef _T
  21. #define _T TEXT
  22. #endif
  23.  
  24. //-----------------------------------------------------------------------------
  25. // Macros, function prototypes and static variable
  26. //-----------------------------------------------------------------------------
  27. static TCHAR  g_strTexturePath[512] = _T(""); // Path for files
  28.  
  29. // Local list of textures
  30. static TextureContainer* g_ptcTextureList = NULL;
  31.  
  32.  
  33. //-----------------------------------------------------------------------------
  34. // Name: CD3DTextureManager
  35. // Desc: Class used to automatically construct and destruct the static
  36. //       texture engine class.
  37. //-----------------------------------------------------------------------------
  38. class CD3DTextureManager
  39. {
  40. public:
  41.     CD3DTextureManager() {}
  42.     ~CD3DTextureManager() { if( g_ptcTextureList ) delete g_ptcTextureList; }
  43. };
  44.  
  45. // Global instance
  46. CD3DTextureManager g_StaticTextureEngine;
  47.  
  48.  
  49. //-----------------------------------------------------------------------------
  50. // Name: struct TEXTURESEARCHINFO
  51. // Desc: Structure used to search for texture formats
  52. //-----------------------------------------------------------------------------
  53. struct TEXTURESEARCHINFO
  54. {
  55.     DWORD dwDesiredBPP;   // Input for texture format search
  56.     BOOL  bUseAlpha;
  57.     BOOL  bUsePalette;
  58.     BOOL  bFoundGoodFormat;
  59.  
  60.     DDPIXELFORMAT* pddpf; // Output of texture format search
  61. };
  62.  
  63.  
  64. //-----------------------------------------------------------------------------
  65. // Name: TextureSearchCallback()
  66. // Desc: Enumeration callback routine to find a best-matching texture format.
  67. //       The param data is the DDPIXELFORMAT of the best-so-far matching
  68. //       texture. Note: the desired BPP is passed in the dwSize field, and the
  69. //       default BPP is passed in the dwFlags field.
  70. //-----------------------------------------------------------------------------
  71. static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf,
  72.                                                VOID* param )
  73. {
  74.     if( NULL==pddpf || NULL==param )
  75.         return DDENUMRET_OK;
  76.  
  77.     TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param;
  78.  
  79.     // Skip any unusual modes
  80.     if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )
  81.         return DDENUMRET_OK;
  82.  
  83.     // Check for palettized formats
  84.     if( ptsi->bUsePalette )
  85.     {
  86.         if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) )
  87.             return DDENUMRET_OK;
  88.  
  89.         // Accept the first 8-bit palettized format we get
  90.         memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
  91.         ptsi->bFoundGoodFormat = TRUE;
  92.         return DDENUMRET_CANCEL;
  93.     }
  94.  
  95.     // Else, skip any paletized formats (all modes under 16bpp)
  96.     if( pddpf->dwRGBBitCount < 16 )
  97.         return DDENUMRET_OK;
  98.  
  99.     // Skip any FourCC formats
  100.     if( pddpf->dwFourCC != 0 )
  101.         return DDENUMRET_OK;
  102.  
  103.     // Skip any ARGB 4444 formats (which are best used for pre-authored
  104.     // content designed speciafically for an ARGB 4444 format).
  105.     if( pddpf->dwRGBAlphaBitMask == 0x0000f000 )
  106.         return DDENUMRET_OK;
  107.  
  108.     // Make sure current alpha format agrees with requested format type
  109.     if( (ptsi->bUseAlpha==TRUE) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) )
  110.         return DDENUMRET_OK;
  111.     if( (ptsi->bUseAlpha==FALSE) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) )
  112.         return DDENUMRET_OK;
  113.  
  114.     // Check if we found a good match
  115.     if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP )
  116.     {
  117.         memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
  118.         ptsi->bFoundGoodFormat = TRUE;
  119.         return DDENUMRET_CANCEL;
  120.     }
  121.  
  122.     return DDENUMRET_OK;
  123. }
  124.  
  125.  
  126. //-----------------------------------------------------------------------------
  127. // Name: FindTexture()
  128. // Desc: Searches the internal list of textures for a texture specified by
  129. //       its name. Returns the structure associated with that texture.
  130. //-----------------------------------------------------------------------------
  131. static TextureContainer* FindTexture( TCHAR* strTextureName )
  132. {
  133.     TextureContainer* ptcTexture = g_ptcTextureList;
  134.  
  135.     while( ptcTexture )
  136.     {
  137.         if( !lstrcmpi( strTextureName, ptcTexture->m_strName ) )
  138.             return ptcTexture;
  139.         ptcTexture = ptcTexture->m_pNext;
  140.     }
  141.  
  142.     return NULL;
  143. }
  144.  
  145.  
  146. //-----------------------------------------------------------------------------
  147. // Name: TextureContainer()
  148. // Desc: Constructor for a texture object
  149. //-----------------------------------------------------------------------------
  150. TextureContainer::TextureContainer( TCHAR* strName, DWORD dwStage,
  151.                                     DWORD dwFlags, UINT uintRes /*= NULL */ )
  152. {
  153.     lstrcpy( m_strName, strName );
  154.     m_dwWidth     = 0;
  155.     m_dwHeight    = 0;
  156.     m_dwStage     = dwStage;
  157.     m_dwBPP       = 0;
  158.     m_dwFlags     = dwFlags;
  159.     m_bHasAlpha   = 0;
  160.     m_nRes        = uintRes;
  161.  
  162.     m_pddsSurface = NULL;
  163.     m_hbmBitmap   = NULL;
  164.     m_pRGBAData   = NULL;
  165.  
  166.     // Add the texture to the head of the global texture list
  167.     m_pNext = g_ptcTextureList;
  168.     g_ptcTextureList = this;
  169.  
  170. }
  171.  
  172.  
  173. //-----------------------------------------------------------------------------
  174. // Name: ~TextureContainer()
  175. // Desc: Destructs the contents of the texture container
  176. //-----------------------------------------------------------------------------
  177. TextureContainer::~TextureContainer()
  178. {
  179.     SAFE_RELEASE( m_pddsSurface );
  180.     SAFE_DELETE(  m_pRGBAData );
  181.     DeleteObject( m_hbmBitmap );
  182.  
  183.     // Remove the texture container from the global list
  184.     if( g_ptcTextureList == this )
  185.         g_ptcTextureList = m_pNext;
  186.     else
  187.     {
  188.         for( TextureContainer* ptc=g_ptcTextureList; ptc; ptc=ptc->m_pNext )
  189.             if( ptc->m_pNext == this )
  190.                 ptc->m_pNext = m_pNext;
  191.     }
  192. }
  193.  
  194.  
  195. //-----------------------------------------------------------------------------
  196. // Name: LoadImageData()
  197. // Desc: Loads the texture map's image data
  198. //-----------------------------------------------------------------------------
  199. HRESULT TextureContainer::LoadImageData()
  200. {
  201.     TCHAR* strExtension;
  202.     TCHAR  strPathname[256];
  203.     HFILE  file;
  204.  
  205.     char   szAnsiName[256];
  206.  
  207.     // Check the executable's resource. If it's there, we're done!
  208.     if( m_nRes )
  209.     {
  210.         m_hbmBitmap = (HBITMAP)LoadImage(g_hInst, MAKEINTRESOURCE(m_nRes),
  211.                                          IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
  212.         if( m_hbmBitmap )
  213.         {
  214.             return S_OK;
  215.         }
  216.     }
  217.     m_hbmBitmap = (HBITMAP)LoadImage(g_hInst, m_strName,
  218.                                          IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
  219.     if( m_hbmBitmap )
  220.         return S_OK;
  221.  
  222.     // First check if the file exists in the global texture path
  223.     lstrcpy( strPathname, g_strTexturePath );
  224.     lstrcat( strPathname, m_strName );
  225.  
  226.     wsprintfA(szAnsiName, "%ls", strPathname);
  227.  
  228.     if( NULL == ( file = _lopen(szAnsiName, OF_READ) ) )
  229.     {
  230.         // Then check if the file exists in the DirectX SDK media path
  231.         lstrcpy( strPathname, D3DUtil_GetDXSDKMediaPath() );
  232.         lstrcat( strPathname, m_strName );
  233.  
  234.         wsprintfA(szAnsiName, "%ls", strPathname);
  235.         if( NULL == ( file = _lopen(szAnsiName, OF_READ) ) )
  236.             return DDERR_NOTFOUND;
  237.     }
  238.     _lclose( file );
  239.  
  240.     // Get the filename extension
  241.     if( NULL == ( strExtension = _tcsrchr( m_strName, _T('.') ) ) )
  242.         return DDERR_UNSUPPORTED;
  243.  
  244.     // Load bitmap files
  245.     if( !lstrcmpi( strExtension, _T(".bmp") ) )
  246.         return LoadBitmapFile( strPathname );
  247.  
  248.     // Can add code here to check for other file formats before failing
  249.     return DDERR_UNSUPPORTED;
  250. }
  251.  
  252.  
  253. //-----------------------------------------------------------------------------
  254. // Name: LoadBitmapFile()
  255. // Desc: Loads data from a .bmp file, and stores it in a bitmap structure.
  256. //-----------------------------------------------------------------------------
  257. HRESULT TextureContainer::LoadBitmapFile( TCHAR* strPathname )
  258. {
  259.     // Try to load the bitmap as a file
  260.     m_hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, IMAGE_BITMAP, 0, 0,
  261.                                       LR_LOADFROMFILE|LR_CREATEDIBSECTION );
  262.     if( m_hbmBitmap )
  263.         return S_OK;
  264.  
  265.     return DDERR_NOTFOUND;
  266. }
  267.  
  268.  
  269. //-----------------------------------------------------------------------------
  270. // Name: Restore()
  271. // Desc: Rebuilds the texture surface using the new device.
  272. //-----------------------------------------------------------------------------
  273. HRESULT TextureContainer::Restore( LPDIRECT3DDEVICE7 pd3dDevice )
  274. {
  275.     // Release any previously created objects
  276.     SAFE_RELEASE( m_pddsSurface );
  277.  
  278.     // Check params
  279.     if( NULL == pd3dDevice )
  280.         return DDERR_INVALIDPARAMS;
  281.  
  282.     // Get the device caps
  283.     D3DDEVICEDESC7 ddDesc;
  284.     if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) )
  285.         return E_FAIL;
  286.  
  287.     // Setup the new surface desc
  288.     DDSURFACEDESC2 ddsd;
  289.     D3DUtil_InitSurfaceDesc( ddsd );
  290.     ddsd.dwFlags         = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|
  291.                            DDSD_PIXELFORMAT /* |DDSD_TEXTURESTAGE */;
  292.     ddsd.ddsCaps.dwCaps  = DDSCAPS_TEXTURE;
  293.     ddsd.dwTextureStage  = m_dwStage;
  294.     ddsd.dwWidth         = m_dwWidth;
  295.     ddsd.dwHeight        = m_dwHeight;
  296.  
  297.     // Turn on texture management for hardware devices
  298.     ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  299.  
  300.     // Adjust width and height to be powers of 2, if the device requires it
  301.     if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
  302.     {
  303.         for( ddsd.dwWidth=1;  m_dwWidth>ddsd.dwWidth;   ddsd.dwWidth<<=1 );
  304.         for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 );
  305.     }
  306.  
  307.     // Limit max texture sizes, if the driver can't handle large textures
  308.     DWORD dwMaxWidth  = ddDesc.dwMaxTextureWidth;
  309.     DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight;
  310.     ddsd.dwWidth  = min( ddsd.dwWidth,  ( dwMaxWidth  ? dwMaxWidth  : 256 ) );
  311.     ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) );
  312.  
  313.     // Make the texture square, if the driver requires it
  314.     if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
  315.     {
  316.         if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth;
  317.         else                               ddsd.dwWidth  = ddsd.dwHeight;
  318.     }
  319.  
  320.     // Setup the structure to be used for texture enumration.
  321.     TEXTURESEARCHINFO tsi;
  322.     tsi.bFoundGoodFormat = FALSE;
  323.     tsi.pddpf            = &ddsd.ddpfPixelFormat;
  324.     tsi.dwDesiredBPP     = m_dwBPP;
  325.     tsi.bUsePalette      = ( m_dwBPP <= 8 );
  326.     tsi.bUseAlpha        = m_bHasAlpha;
  327.     if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL )
  328.         tsi.dwDesiredBPP = 16;
  329.     else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
  330.         tsi.dwDesiredBPP = 32;
  331.  
  332.     if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
  333.     {
  334.         if( tsi.bUsePalette )
  335.         {
  336.             if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
  337.             {
  338.                 tsi.bUseAlpha   = TRUE;
  339.                 tsi.bUsePalette = TRUE;
  340.             }
  341.             else
  342.             {
  343.                 tsi.bUseAlpha   = TRUE;
  344.                 tsi.bUsePalette = FALSE;
  345.             }
  346.         }
  347.     }
  348.  
  349.     OutputDebugString("Restore: calling EnumTextureFormats\n");
  350.  
  351.     // Enumerate the texture formats, and find the closest device-supported
  352.     // texture pixel format
  353.     pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
  354.  
  355.     // If we couldn't find a format, let's try a default format
  356.     if( FALSE == tsi.bFoundGoodFormat )
  357.     {
  358.         tsi.bUsePalette  = FALSE;
  359.         tsi.dwDesiredBPP = 16;
  360.         pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
  361.  
  362.         // If we still fail, we cannot create this texture
  363.         if( FALSE == tsi.bFoundGoodFormat )
  364.             return E_FAIL;
  365.     }
  366.  
  367.     // Get the DirectDraw interface for creating surfaces
  368.     LPDIRECTDRAW7        pDD;
  369.     LPDIRECTDRAWSURFACE7 pddsRender;
  370.     OutputDebugString("Restore: calling GetRenderTarget\n");
  371.  
  372.     pd3dDevice->GetRenderTarget( &pddsRender );
  373.     pddsRender->GetDDInterface( (VOID**)&pDD );
  374.     pddsRender->Release();
  375.  
  376.     // Create a new surface for the texture
  377.     OutputDebugString("Restore: calling CreateSurface\n");
  378.  
  379.     HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL );
  380.  
  381.     // Done with DDraw
  382.     pDD->Release();
  383.  
  384.     if( FAILED(hr) )
  385.         return hr;
  386.  
  387.     // For bitmap-based textures, copy the bitmap image.
  388.     OutputDebugString("Restore: calling CopyBitmapToSurface\n");
  389.     if( m_hbmBitmap )
  390.         return CopyBitmapToSurface();
  391.  
  392.     if( m_pRGBAData )
  393.         return CopyRGBADataToSurface();
  394.  
  395.     // At this point, code can be added to handle other file formats (such as
  396.     // .dds files, .jpg files, etc.).
  397.     return S_OK;
  398. }
  399.  
  400.  
  401. //-----------------------------------------------------------------------------
  402. // Name: CopyBitmapToSurface()
  403. // Desc: Copies the image of a bitmap into a surface
  404. //-----------------------------------------------------------------------------
  405. HRESULT TextureContainer::CopyBitmapToSurface()
  406. {
  407.     // Get a DDraw object to create a temporary surface
  408.     LPDIRECTDRAW7 pDD;
  409.     m_pddsSurface->GetDDInterface( (VOID**)&pDD );
  410.  
  411.     // Get the bitmap structure (to extract width, height, and bpp)
  412.     BITMAP bm;
  413.     GetObject( m_hbmBitmap, sizeof(BITMAP), &bm );
  414.  
  415.     // Setup the new surface desc
  416.     DDSURFACEDESC2 ddsd;
  417.     ddsd.dwSize = sizeof(ddsd);
  418.     m_pddsSurface->GetSurfaceDesc( &ddsd );
  419.     ddsd.dwFlags          = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
  420.                             DDSD_TEXTURESTAGE;
  421.     ddsd.ddsCaps.dwCaps   = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
  422.     ddsd.ddsCaps.dwCaps2  = 0L;
  423.     ddsd.dwWidth          = bm.bmWidth;
  424.     ddsd.dwHeight         = bm.bmHeight;
  425.  
  426.     // Create a new surface for the texture
  427.     LPDIRECTDRAWSURFACE7 pddsTempSurface;
  428.     HRESULT hr;
  429.     if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
  430.     {
  431.         pDD->Release();
  432.         return hr;
  433.     }
  434.  
  435.     // Get a DC for the bitmap
  436.     HDC hdcBitmap = CreateCompatibleDC( NULL );
  437.     if( NULL == hdcBitmap )
  438.     {
  439.         pddsTempSurface->Release();
  440.         pDD->Release();
  441.         return hr;
  442.     }
  443.     SelectObject( hdcBitmap, m_hbmBitmap );
  444.  
  445.     // Handle palettized textures. Need to attach a palette
  446.     if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 )
  447.     {
  448.         LPDIRECTDRAWPALETTE  pPalette;
  449.         DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256;
  450.         DWORD pe[256];
  451.         UINT  wNumColors     = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe );
  452.  
  453.         // Create the color table
  454.         for( WORD i=0; i<wNumColors; i++ )
  455.         {
  456.             pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) );
  457.  
  458.             // Handle textures with transparent pixels
  459.             if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
  460.             {
  461.                 // Set alpha for opaque pixels
  462.                 if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK )
  463.                 {
  464.                     if( pe[i] != 0x00000000 )
  465.                         pe[i] |= 0xff000000;
  466.                 }
  467.                 else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
  468.                 {
  469.                     if( pe[i] != 0x00ffffff )
  470.                         pe[i] |= 0xff000000;
  471.                 }
  472.             }
  473.         }
  474.         // Add DDPCAPS_ALPHA flag for textures with transparent pixels
  475.         if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
  476.             dwPaletteFlags |= DDPCAPS_ALPHA;
  477.  
  478.         // Create & attach a palette
  479.         pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL );
  480.         pddsTempSurface->SetPalette( pPalette );
  481.         m_pddsSurface->SetPalette( pPalette );
  482.         SAFE_RELEASE( pPalette );
  483.     }
  484.  
  485.     // Copy the bitmap image to the surface.
  486.     HDC hdcSurface;
  487.     if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) )
  488.     {
  489.         BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0,
  490.                 SRCCOPY );
  491.         pddsTempSurface->ReleaseDC( hdcSurface );
  492.     }
  493.     DeleteDC( hdcBitmap );
  494.  
  495.     // Copy the temp surface to the real texture surface
  496.     m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
  497.  
  498.     // Done with the temp surface
  499.     pddsTempSurface->Release();
  500.  
  501.     // For textures with real alpha (not palettized), set transparent bits
  502.     if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask )
  503.     {
  504.         if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
  505.         {
  506.             // Lock the texture surface
  507.             DDSURFACEDESC2 ddsd;
  508.             ddsd.dwSize = sizeof(ddsd);
  509.             while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) ==
  510.                    DDERR_WASSTILLDRAWING );
  511.  
  512.             DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
  513.             DWORD dwRGBMask   = ( ddsd.ddpfPixelFormat.dwRBitMask |
  514.                                   ddsd.ddpfPixelFormat.dwGBitMask |
  515.                                   ddsd.ddpfPixelFormat.dwBBitMask );
  516.             DWORD dwColorkey  = 0x00000000; // Colorkey on black
  517.             if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
  518.                 dwColorkey = dwRGBMask;     // Colorkey on white
  519.  
  520.             // Add an opaque alpha value to each non-colorkeyed pixel
  521.             for( DWORD y=0; y<ddsd.dwHeight; y++ )
  522.             {
  523.                 WORD*  p16 =  (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
  524.                 DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
  525.  
  526.                 for( DWORD x=0; x<ddsd.dwWidth; x++ )
  527.                 {
  528.                     if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
  529.                     {
  530.                         if( ( *p16 &= dwRGBMask ) != dwColorkey )
  531.                             *p16 |= dwAlphaMask;
  532.                         p16++;
  533.                     }
  534.                     if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
  535.                     {
  536.                         if( ( *p32 &= dwRGBMask ) != dwColorkey )
  537.                             *p32 |= dwAlphaMask;
  538.                         p32++;
  539.                     }
  540.                 }
  541.             }
  542.             m_pddsSurface->Unlock( NULL );
  543.         }
  544.     }
  545.  
  546.     pDD->Release();
  547.  
  548.     return S_OK;;
  549. }
  550.  
  551.  
  552. //-----------------------------------------------------------------------------
  553. // Name: CopyRGBADataToSurface()
  554. // Desc: Invalidates the current texture objects and rebuilds new ones
  555. //       using the new device.
  556. //-----------------------------------------------------------------------------
  557. HRESULT TextureContainer::CopyRGBADataToSurface()
  558. {
  559.     // Get a DDraw object to create a temporary surface
  560.     LPDIRECTDRAW7 pDD;
  561.     m_pddsSurface->GetDDInterface( (VOID**)&pDD );
  562.  
  563.     // Setup the new surface desc
  564.     DDSURFACEDESC2 ddsd;
  565.     ddsd.dwSize = sizeof(ddsd);
  566.     m_pddsSurface->GetSurfaceDesc( &ddsd );
  567.     ddsd.dwFlags         = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
  568.                            DDSD_TEXTURESTAGE;
  569.     ddsd.ddsCaps.dwCaps  = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
  570.     ddsd.ddsCaps.dwCaps2 = 0L;
  571.     ddsd.dwWidth         = m_dwWidth;
  572.     ddsd.dwHeight        = m_dwHeight;
  573.  
  574.     // Create a new surface for the texture
  575.     LPDIRECTDRAWSURFACE7 pddsTempSurface;
  576.     HRESULT hr;
  577.     if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
  578.     {
  579.         pDD->Release();
  580.         return NULL;
  581.     }
  582.  
  583.     while( pddsTempSurface->Lock( NULL, &ddsd, 0, 0 ) == DDERR_WASSTILLDRAWING );
  584.     DWORD lPitch = ddsd.lPitch;
  585.     BYTE* pBytes = (BYTE*)ddsd.lpSurface;
  586.  
  587.     DWORD dwRMask = ddsd.ddpfPixelFormat.dwRBitMask;
  588.     DWORD dwGMask = ddsd.ddpfPixelFormat.dwGBitMask;
  589.     DWORD dwBMask = ddsd.ddpfPixelFormat.dwBBitMask;
  590.     DWORD dwAMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
  591.  
  592.     DWORD dwRShiftL = 8, dwRShiftR = 0;
  593.     DWORD dwGShiftL = 8, dwGShiftR = 0;
  594.     DWORD dwBShiftL = 8, dwBShiftR = 0;
  595.     DWORD dwAShiftL = 8, dwAShiftR = 0;
  596.  
  597.     DWORD dwMask;
  598.     for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
  599.     for( ; dwMask; dwMask>>=1 ) dwRShiftL--;
  600.  
  601.     for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
  602.     for( ; dwMask; dwMask>>=1 ) dwGShiftL--;
  603.  
  604.     for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
  605.     for( ; dwMask; dwMask>>=1 ) dwBShiftL--;
  606.  
  607.     for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
  608.     for( ; dwMask; dwMask>>=1 ) dwAShiftL--;
  609.  
  610.     for( DWORD y=0; y<ddsd.dwHeight; y++ )
  611.     {
  612.         DWORD* pDstData32 = (DWORD*)pBytes;
  613.         WORD*  pDstData16 = (WORD*)pBytes;
  614.  
  615.         for( DWORD x=0; x<ddsd.dwWidth; x++ )
  616.         {
  617.             DWORD dwPixel = m_pRGBAData[y*ddsd.dwWidth+x];
  618.  
  619.             BYTE r = (BYTE)((dwPixel>>24)&0x000000ff);
  620.             BYTE g = (BYTE)((dwPixel>>16)&0x000000ff);
  621.             BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff);
  622.             BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff);
  623.  
  624.             DWORD dr = ((r>>(dwRShiftL))<<dwRShiftR)&dwRMask;
  625.             DWORD dg = ((g>>(dwGShiftL))<<dwGShiftR)&dwGMask;
  626.             DWORD db = ((b>>(dwBShiftL))<<dwBShiftR)&dwBMask;
  627.             DWORD da = ((a>>(dwAShiftL))<<dwAShiftR)&dwAMask;
  628.  
  629.             if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
  630.                 pDstData32[x] = (DWORD)(dr+dg+db+da);
  631.             else
  632.                 pDstData16[x] = (WORD)(dr+dg+db+da);
  633.         }
  634.  
  635.         pBytes += ddsd.lPitch;
  636.     }
  637.  
  638.     pddsTempSurface->Unlock(0);
  639.  
  640.     // Copy the temp surface to the real texture surface
  641.     m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
  642.  
  643.     // Done with the temp objects
  644.     pddsTempSurface->Release();
  645.     pDD->Release();
  646.  
  647.     return S_OK;
  648. }
  649.  
  650.  
  651. //-----------------------------------------------------------------------------
  652. // Name: D3DTextr_SetTexturePath()
  653. // Desc: Enumeration callback routine to find a best-matching texture format.
  654. //-----------------------------------------------------------------------------
  655. VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath )
  656. {
  657.     if( NULL == strTexturePath )
  658.         strTexturePath = _T("");
  659.     lstrcpy( g_strTexturePath, strTexturePath );
  660. }
  661.  
  662.  
  663. //-----------------------------------------------------------------------------
  664. // Name: D3DTextr_CreateTextureFromFile()
  665. // Desc: Is passed a filename and creates a local Bitmap from that file.
  666. //       The texture can not be used until it is restored, however.
  667. //-----------------------------------------------------------------------------
  668. HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage,
  669.                                         DWORD dwFlags )
  670. {
  671.     // Check parameters
  672.     if( NULL == strName )
  673.         return E_INVALIDARG;
  674.  
  675.     // Check first to see if the texture is already loaded
  676.     if( NULL != FindTexture( strName ) )
  677.         return S_OK;
  678.  
  679.     // Allocate and add the texture to the linked list of textures;
  680.     TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
  681.                                                          dwFlags );
  682.     if( NULL == ptcTexture )
  683.         return E_OUTOFMEMORY;
  684.  
  685.     // Create a bitmap and load the texture file into it,
  686.     if( FAILED( ptcTexture->LoadImageData() ) )
  687.     {
  688.         delete ptcTexture;
  689.         return E_FAIL;
  690.     }
  691.  
  692.     // Save the image's dimensions
  693.     if( ptcTexture->m_hbmBitmap )
  694.     {
  695.         BITMAP bm;
  696.         GetObject( ptcTexture->m_hbmBitmap, sizeof(BITMAP), &bm );
  697.         ptcTexture->m_dwWidth  = (DWORD)bm.bmWidth;
  698.         ptcTexture->m_dwHeight = (DWORD)bm.bmHeight;
  699.         ptcTexture->m_dwBPP    = (DWORD)bm.bmBitsPixel;
  700.     }
  701.  
  702.     return S_OK;
  703. }
  704.  
  705.  
  706. //-----------------------------------------------------------------------------
  707. // Name: D3DTextr_CreateEmptyTexture()
  708. // Desc: Creates an empty texture.
  709. //-----------------------------------------------------------------------------
  710. HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
  711.                                      DWORD dwHeight, DWORD dwStage,
  712.                                      DWORD dwFlags )
  713. {
  714.     // Check parameters
  715.     if( NULL == strName )
  716.         return E_INVALIDARG;
  717.  
  718.     // Check first to see if the texture is already loaded
  719.     if( NULL != FindTexture( strName ) )
  720.         return E_FAIL;
  721.  
  722.     // Allocate and add the texture to the linked list of textures;
  723.     TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
  724.                                                          dwFlags );
  725.     if( NULL == ptcTexture )
  726.         return E_OUTOFMEMORY;
  727.  
  728.     // Save dimensions
  729.     ptcTexture->m_dwWidth  = dwWidth;
  730.     ptcTexture->m_dwHeight = dwHeight;
  731.     ptcTexture->m_dwBPP    = 16;
  732.     if( ptcTexture->m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
  733.         ptcTexture->m_dwBPP = 32;
  734.  
  735.     // Save alpha usage flag
  736.     if( dwFlags & D3DTEXTR_CREATEWITHALPHA )
  737.         ptcTexture->m_bHasAlpha = TRUE;
  738.  
  739.     return S_OK;
  740. }
  741.  
  742.  
  743. //-----------------------------------------------------------------------------
  744. // Name: D3DTextr_Restore()
  745. // Desc: Invalidates the current texture objects and rebuilds new ones
  746. //       using the new device.
  747. //-----------------------------------------------------------------------------
  748. HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice )
  749. {
  750.     TextureContainer* ptcTexture = FindTexture( strName );
  751.     if( NULL == ptcTexture )
  752.         return DDERR_NOTFOUND;
  753.  
  754.     // Restore the texture (this recreates the new surface for this device).
  755.     return ptcTexture->Restore( pd3dDevice );
  756. }
  757.  
  758.  
  759. //-----------------------------------------------------------------------------
  760. // Name: D3DTextr_RestoreAllTextures()
  761. // Desc: This function is called when a mode is changed. It updates all
  762. //       texture objects to be valid with the new device.
  763. //-----------------------------------------------------------------------------
  764. HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice )
  765. {
  766.     TextureContainer* ptcTexture = g_ptcTextureList;
  767.  
  768.     while( ptcTexture )
  769.     {
  770.         D3DTextr_Restore( ptcTexture->m_strName, pd3dDevice );
  771.         ptcTexture = ptcTexture->m_pNext;
  772.     }
  773.  
  774.     return S_OK;
  775. }
  776.  
  777.  
  778. //-----------------------------------------------------------------------------
  779. // Name: D3DTextr_Invalidate()
  780. // Desc: Used to bump a texture out of (video) memory, this function
  781. //       actually destroys the d3dtexture and ddsurface of the texture
  782. //-----------------------------------------------------------------------------
  783. HRESULT D3DTextr_Invalidate( TCHAR* strName )
  784. {
  785.     TextureContainer* ptcTexture = FindTexture( strName );
  786.     if( NULL == ptcTexture )
  787.         return DDERR_NOTFOUND;
  788.  
  789.     SAFE_RELEASE( ptcTexture->m_pddsSurface );
  790.  
  791.     return S_OK;
  792. }
  793.  
  794.  
  795. //-----------------------------------------------------------------------------
  796. // Name: D3DTextr_InvalidateAllTextures()
  797. // Desc: This function is called when a mode is changed. It invalidates
  798. //       all texture objects so their device can be safely released.
  799. //-----------------------------------------------------------------------------
  800. HRESULT D3DTextr_InvalidateAllTextures()
  801. {
  802.     TextureContainer* ptcTexture = g_ptcTextureList;
  803.  
  804.     while( ptcTexture )
  805.     {
  806.         SAFE_RELEASE( ptcTexture->m_pddsSurface );
  807.         ptcTexture = ptcTexture->m_pNext;
  808.     }
  809.  
  810.     return S_OK;
  811. }
  812.  
  813.  
  814. //-----------------------------------------------------------------------------
  815. // Name: D3DTextr_DestroyTexture()
  816. // Desc: Frees the resources for the specified texture container
  817. //-----------------------------------------------------------------------------
  818. HRESULT D3DTextr_DestroyTexture( TCHAR* strName )
  819. {
  820.     TextureContainer* ptcTexture = FindTexture( strName );
  821.  
  822.     SAFE_DELETE( ptcTexture );
  823.  
  824.     return S_OK;
  825. }
  826.  
  827. //-----------------------------------------------------------------------------
  828. // Name: D3DTextr_GetSurface()
  829. // Desc: Returns a pointer to a d3dSurface from the name of the texture
  830. //-----------------------------------------------------------------------------
  831. LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName )
  832. {
  833.     TextureContainer* ptcTexture = FindTexture( strName );
  834.  
  835.     return ptcTexture ? ptcTexture->m_pddsSurface : NULL;
  836. }
  837.