D3DTEX.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:12k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /**************************************************************************
  2.  D3DTexture class
  3.  **************************************************************************/
  4. #define D3D_OVERLOADS
  5. #include <windows.h>
  6. #include <windowsx.h>
  7. #include <ddraw.h>
  8. #include <d3d.h>
  9. #include "d3dtex.h"
  10. /**************************************************************************
  11.  DEBUG junk
  12.  **************************************************************************/
  13. #if defined(DEBUG) || defined(_DEBUG)
  14. static void DPF(char *fmt, ...)
  15. {
  16.     char ach[128];
  17.     va_list va;
  18.     va_start( va, fmt );
  19.     wvsprintf( ach, fmt, va );
  20.     va_end( va );
  21.     OutputDebugString("TEXTURE: ");
  22.     OutputDebugString(ach);
  23.     OutputDebugString("rn");
  24. }
  25. #else
  26. #define DPF if (0) 
  27. #endif
  28. /**************************************************************************
  29.  ChooseTextureFormat
  30.  **************************************************************************/
  31. typedef struct {
  32.     DWORD           bpp;        // we want a texture format of this bpp
  33.     DDPIXELFORMAT   ddpf;       // place the format here
  34. }   FindTextureData;
  35. HRESULT CALLBACK FindTextureCallback(DDSURFACEDESC *DeviceFmt, LPVOID lParam)
  36. {
  37.     FindTextureData * FindData = (FindTextureData *)lParam;
  38.     DDPIXELFORMAT ddpf = DeviceFmt->ddpfPixelFormat;
  39.     DPF("FindTexture: %d %s%s%s %08X %08X %08X %08X", 
  40. ddpf.dwRGBBitCount, 
  41.         (ddpf.dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS)) ? "ALPHA " : "", 
  42.         (ddpf.dwFlags & (DDPF_RGB)) ? "RGB " : "", 
  43.         (ddpf.dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4)) ? "PAL " : "", 
  44. ddpf.dwRBitMask,
  45. ddpf.dwGBitMask,
  46. ddpf.dwBBitMask,
  47. ddpf.dwRGBAlphaBitMask);
  48.     //
  49.     // we use GetDC/BitBlt to init textures so we only
  50.     // want to use formats that GetDC will support.
  51.     //
  52.     if (ddpf.dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS))
  53.         return DDENUMRET_OK;
  54.     if (ddpf.dwRGBBitCount <= 8 &&
  55.         !(ddpf.dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4)))
  56.         return DDENUMRET_OK;
  57.     if (ddpf.dwRGBBitCount > 8 && !(ddpf.dwFlags & DDPF_RGB))
  58.         return DDENUMRET_OK;
  59.     //
  60.     // BUGBUG GetDC does not work for 1 or 4bpp YET!
  61.     //
  62.     if (ddpf.dwRGBBitCount < 8)
  63.         return DDENUMRET_OK;
  64.     //
  65.     // keep the texture format that is nearest to the bitmap we have
  66.     //
  67.     if (FindData->ddpf.dwRGBBitCount == 0 ||
  68.        (ddpf.dwRGBBitCount >= FindData->bpp &&
  69.        (UINT)(ddpf.dwRGBBitCount - FindData->bpp) < (UINT)(FindData->ddpf.dwRGBBitCount - FindData->bpp)))
  70.     {
  71.         FindData->ddpf = ddpf;
  72.     }
  73.     return DDENUMRET_OK;
  74. }
  75. void ChooseTextureFormat(IDirect3DDevice2 *Device, DWORD bpp, DDPIXELFORMAT *pddpf)
  76. {
  77.     FindTextureData FindData;
  78.     ZeroMemory(&FindData, sizeof(FindData));
  79.     FindData.bpp = bpp;
  80.     Device->EnumTextureFormats(FindTextureCallback, (LPVOID)&FindData);
  81.     *pddpf = FindData.ddpf;
  82.     DPF("ChooseTexture: %d %s%s%s %08X %08X %08X %08X", 
  83. pddpf->dwRGBBitCount, 
  84.         (pddpf->dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS)) ? "ALPHA " : "", 
  85.         (pddpf->dwFlags & (DDPF_RGB)) ? "RGB " : "", 
  86.         (pddpf->dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4)) ? "PAL " : "", 
  87. pddpf->dwRBitMask,
  88. pddpf->dwGBitMask,
  89. pddpf->dwBBitMask,
  90. pddpf->dwRGBAlphaBitMask);
  91. }
  92. /**************************************************************************
  93.  PaletteFromBitmap
  94.  **************************************************************************/
  95. static IDirectDrawPalette * PaletteFromBitmap(IDirectDraw *DirectDraw, HBITMAP Bitmap)
  96. {
  97.     IDirectDrawPalette *    Palette = NULL;
  98.     HDC                     BitmapDC;
  99.     DWORD                   adw[256];
  100.     int                     colors, i;
  101.     //
  102.     // get the color table from the DIBSection
  103.     //
  104.     BitmapDC = CreateCompatibleDC(NULL);
  105.     SelectObject(BitmapDC, Bitmap);
  106.     colors = GetDIBColorTable(BitmapDC, 0, 256, (RGBQUAD *)adw);
  107.     DeleteDC(BitmapDC);
  108.     if (colors != 0)
  109.     {
  110.         //
  111.         // convert BGR to RGB (stupid IBM!)
  112.         //
  113.         for (i=0; i<colors; i++)
  114.             adw[i] = RGB(GetBValue(adw[i]),GetGValue(adw[i]),GetRValue(adw[i]));
  115.         //
  116.         // create a DirectDraw palette for the texture.
  117.         //
  118.         DirectDraw->CreatePalette(colors <= 16 ? DDPCAPS_4BIT : DDPCAPS_8BIT,
  119.             (PALETTEENTRY *)adw, &Palette, NULL);
  120.     }
  121.     return Palette;
  122. }
  123. /**************************************************************************
  124.  GetDD
  125.  get the IDirectDraw from a IDirect3DDevice, we need the DD
  126.  to create surfaces.
  127.  this function does not do a AddRef on the DirectDraw object
  128.  (ie you dont need to Release)
  129.  NOTE if your app has this around as a global you can use
  130.  the global instead of this code.
  131.  **************************************************************************/
  132. static IDirectDraw * GetDD(IDirect3DDevice2 *Device)
  133. {
  134.     IDirectDraw *       DirectDraw;
  135.     IDirectDrawSurface *Target;
  136.     IDirectDrawSurface2*Target2;
  137.     //
  138.     // get the render target (we need it to get the IDirectDraw)
  139.     //
  140.     if (Device==NULL || Device->GetRenderTarget(&Target) != DD_OK)
  141.         return NULL;
  142.     //
  143.     // get the DirectDraw object, but first we need a IDirectDrawSurface2
  144.     //
  145.     if (Target->QueryInterface(IID_IDirectDrawSurface2, (void**)&Target2) != DD_OK)
  146.         return NULL;
  147.     Target->Release();
  148.     Target2->GetDDInterface((void**)&DirectDraw);
  149.     Target2->Release();
  150.     DirectDraw->Release();  // dont up ref count
  151.     return DirectDraw;
  152. }
  153. /**************************************************************************
  154.  D3DTexture::Load
  155.  load a bitmap from the resource, or bmp file and create a
  156.  D3D texture map
  157.  **************************************************************************/
  158. BOOL D3DTexture::Load(IDirect3DDevice2 *Device, char *BitmapName)
  159. {
  160.     BITMAP              bm;
  161.     DDSURFACEDESC       ddsd;
  162.     HBITMAP             Bitmap;
  163.     IDirectDraw *       DirectDraw;
  164.     DPF("D3DTexture::Load(%s)", BitmapName);
  165.     //
  166.     // we need a IDirectDraw so we can create a surface.
  167.     //
  168.     if ((DirectDraw = GetDD(Device)) == NULL)
  169.         return FALSE;
  170.     //
  171.     // load the bitmap from a resource or file.
  172.     //
  173.     Bitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), BitmapName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
  174.     if (Bitmap == NULL)
  175.         Bitmap = (HBITMAP)LoadImage(NULL, BitmapName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  176.     if (Bitmap == NULL)
  177.         return FALSE;
  178.     // free any existing texture.
  179.     Release();
  180.     GetObject(Bitmap, sizeof(bm), &bm);      // get size of bitmap
  181.     //
  182.     // find the best texture format to use.
  183.     //
  184.     ZeroMemory(&ddsd, sizeof(ddsd));
  185.     ddsd.dwSize = sizeof(ddsd);
  186.     ChooseTextureFormat(Device, bm.bmBitsPixel, &ddsd.ddpfPixelFormat);
  187.     ddsd.dwFlags |= DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
  188.     ddsd.dwWidth = bm.bmWidth;
  189.     ddsd.dwHeight = bm.bmHeight;
  190.     //
  191.     // create a video memory texture
  192.     //
  193.     // if we are dealing with a HAL create in video memory, else
  194.     // create in system memory.
  195.     //
  196.     D3DDEVICEDESC hal, hel;
  197.     ZeroMemory(&hal, sizeof(hal));
  198.     hal.dwSize = sizeof(hal);
  199.     ZeroMemory(&hel, sizeof(hel));
  200.     hel.dwSize = sizeof(hel);
  201.     Device->GetCaps(&hal, &hel);
  202.     // BUGBUG should we check for texture caps?
  203.     if (hal.dcmColorModel)
  204.         ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD;
  205.     else
  206.         ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY| DDSCAPS_TEXTURE;
  207.     if (DirectDraw->CreateSurface(&ddsd, &DeviceSurface, NULL) != DD_OK)
  208.         goto error;
  209.     //
  210.     // create a system memory surface for the texture.
  211.     //
  212.     // we use this system memory surface for the ::Load call
  213.     // and this surface does not get lost.
  214.     //
  215.     if (hal.dcmColorModel)
  216.     {
  217.         ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
  218.         if (DirectDraw->CreateSurface(&ddsd, &MemorySurface, NULL) != DD_OK)
  219.             goto error;
  220.     }
  221.     else
  222.     {
  223.         //
  224.         // when dealing with a SW rasterizer we dont need to make two
  225.         // surfaces.
  226.         //
  227.         MemorySurface = DeviceSurface;
  228.         DeviceSurface->AddRef();
  229.     }
  230.     //
  231.     // create a palette for the texture
  232.     //
  233.     if (ddsd.ddpfPixelFormat.dwRGBBitCount <= 8)
  234.     {
  235.         Palette = PaletteFromBitmap(DirectDraw, Bitmap);
  236.         //
  237.         // now we have a palette, attach the palette to the Surface
  238.         // and the texture
  239.         //
  240.         MemorySurface->SetPalette(Palette);
  241.         DeviceSurface->SetPalette(Palette);
  242.     }
  243.     //
  244.     // copy the bitmap to our surface
  245.     //
  246.     if (!Copy(Bitmap))
  247.         goto error;
  248.     //
  249.     // get the texture handle
  250.     //
  251.     IDirect3DTexture2 * Texture;
  252.     DeviceSurface->QueryInterface(IID_IDirect3DTexture2, (void**)&Texture);
  253.     Texture->GetHandle(Device, &Handle);
  254.     Texture->Release();
  255.     //
  256.     // we are done, delete the bitmap (we made a copy) and return.
  257.     //
  258.     DeleteObject(Bitmap);
  259.     return TRUE;
  260. error:
  261.     if (Bitmap)
  262.         DeleteObject(Bitmap);
  263.     Release();
  264.     return FALSE;
  265. }
  266. /**************************************************************************
  267.  D3DTexture::Copy
  268.  init the system memory surface from a GDI Bitmap
  269.  **************************************************************************/
  270. BOOL D3DTexture::Copy(HBITMAP Bitmap)
  271. {
  272.     BITMAP  bm;
  273.     HDC     BitmapDC;
  274.     HDC     SurfaceDC;
  275.     BOOL    result = FALSE;
  276.     DPF("D3DTexture::Copy");
  277.     GetObject(Bitmap, sizeof(bm), &bm);    // get size of bitmap
  278.     BitmapDC = CreateCompatibleDC(NULL);
  279.     SelectObject(BitmapDC, Bitmap);
  280.     if (MemorySurface->GetDC(&SurfaceDC) == DD_OK)
  281.     {
  282.         BitBlt(SurfaceDC, 0, 0, bm.bmWidth, bm.bmHeight, BitmapDC, 0, 0, SRCCOPY);
  283.         MemorySurface->ReleaseDC(SurfaceDC);
  284.         result = Restore();
  285.     }
  286.     DeleteDC(BitmapDC);
  287.     return result;
  288. }
  289. /**************************************************************************
  290.  D3DTexture::Restore
  291.  restore the texture image
  292.  **************************************************************************/
  293. BOOL D3DTexture::Restore()
  294. {
  295.     HRESULT             err;
  296.     IDirect3DTexture2  *MemoryTexture;
  297.     IDirect3DTexture2  *DeviceTexture;
  298.     DPF("D3DTexture::Restore");
  299.     if (DeviceSurface == NULL || MemorySurface == NULL)
  300.         return FALSE;
  301.     //
  302.     // we dont need to do this step for system memory surfaces.
  303.     //
  304.     if (DeviceSurface == MemorySurface)
  305.         return TRUE;
  306.     //
  307.     // restore the video memory texture.
  308.     //
  309.     if (DeviceSurface->Restore() != DD_OK)
  310.         return FALSE;
  311.     //
  312.     // call IDirect3DTexture::Load() to copy the texture to the device.
  313.     //
  314.     DeviceSurface->QueryInterface(IID_IDirect3DTexture2, (void**)&DeviceTexture);
  315.     MemorySurface->QueryInterface(IID_IDirect3DTexture2, (void**)&MemoryTexture);
  316.     err = DeviceTexture->Load(MemoryTexture);
  317.     DeviceTexture->Release();
  318.     MemoryTexture->Release();
  319.     return err == DD_OK;
  320. }
  321. /**************************************************************************
  322.  D3DTexture::Release
  323.  free the texture, free all objects associated with this texture
  324.  NOTE we cant do this in the destructor because DirectDraw
  325.  will clean up all the surfaces when the main direct draw object
  326.  is destroyed, before a static destructor will be called.
  327.  **************************************************************************/
  328. void D3DTexture::Release()
  329. {
  330.     DPF("D3DTexture::Release");
  331.     if (MemorySurface)
  332.        MemorySurface->Release();
  333.     MemorySurface = 0;
  334.     if (DeviceSurface)
  335.        DeviceSurface->Release();
  336.     DeviceSurface = 0;
  337.     if (Palette)
  338.        Palette->Release();
  339.     Palette = 0;
  340.     Handle = 0;
  341. }