home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / MISC / D3DCALLS.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  16KB  |  402 lines

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: d3dcalls.c
  5.  *
  6.  *  Calls to Direct3D objects needed for rendering.  Part of D3DApp.
  7.  *
  8.  *  D3DApp is a collection of helper functions for Direct3D applications.
  9.  *  D3DApp consists of the following files:
  10.  *      d3dapp.h    Main D3DApp header to be included by application
  11.  *      d3dappi.h   Internal header
  12.  *      d3dapp.c    D3DApp functions seen by application.
  13.  *      ddcalls.c   All calls to DirectDraw objects except textures
  14.  *      d3dcalls.c  All calls to Direct3D objects except textures
  15.  *      texture.c   Texture loading and managing texture list
  16.  *      misc.c      Miscellaneous calls
  17.  */
  18.  
  19. #define INITGUID
  20. #include "d3dappi.h"
  21.  
  22. /***************************************************************************/
  23. /*                            Creation of D3D                              */
  24. /***************************************************************************/
  25. BOOL
  26. D3DAppICreateD3D(void)
  27. {
  28.     LastError = d3dappi.lpDD->lpVtbl->QueryInterface(d3dappi.lpDD,
  29.                                     &IID_IDirect3D, (LPVOID*)&d3dappi.lpD3D);
  30.     if (LastError != DD_OK) {
  31.         D3DAppISetErrorString("Creation of IDirect3D failed.\n%s",
  32.                               D3DAppErrorToString(LastError));
  33.         goto exit_with_error;
  34.     }
  35.     return TRUE;
  36. exit_with_error:
  37.     return FALSE;
  38. }
  39.  
  40. /***************************************************************************/
  41. /*                           D3D Device Enumeration                        */
  42. /***************************************************************************/
  43. /*
  44.  * enumDeviceFunc
  45.  * Device enumeration callback.  Record information about the D3D device
  46.  * reported by D3D.
  47.  */
  48. static HRESULT
  49. WINAPI enumDeviceFunc(LPGUID lpGuid, LPSTR lpDeviceDescription,
  50.                       LPSTR lpDeviceName, LPD3DDEVICEDESC lpHWDesc,
  51.                       LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext)
  52. {
  53.     lpContext = lpContext;
  54.     /*
  55.      * Don't accept any hardware D3D devices if emulation only option is set
  56.      */
  57.     if (lpHWDesc->dcmColorModel && d3dappi.bOnlyEmulation)
  58.         return D3DENUMRET_OK;
  59.     /*
  60.      * Record the D3D driver's inforamation
  61.      */
  62.     memcpy(&d3dappi.Driver[d3dappi.NumDrivers].Guid, lpGuid, sizeof(GUID));
  63.     lstrcpy(d3dappi.Driver[d3dappi.NumDrivers].About, lpDeviceDescription);
  64.     lstrcpy(d3dappi.Driver[d3dappi.NumDrivers].Name, lpDeviceName);
  65.     /*
  66.      * Is this a hardware device or software emulation?  Checking the color
  67.      * model for a valid model works.
  68.      */
  69.     if (lpHWDesc->dcmColorModel) {
  70.         d3dappi.Driver[d3dappi.NumDrivers].bIsHardware = TRUE;
  71.         memcpy(&d3dappi.Driver[d3dappi.NumDrivers].Desc, lpHWDesc,
  72.                sizeof(D3DDEVICEDESC));
  73.     } else {
  74.         d3dappi.Driver[d3dappi.NumDrivers].bIsHardware = FALSE;
  75.         memcpy(&d3dappi.Driver[d3dappi.NumDrivers].Desc, lpHELDesc,
  76.                sizeof(D3DDEVICEDESC));
  77.     }
  78.     /*
  79.      * Does this driver do texture mapping?
  80.      */
  81.     d3dappi.Driver[d3dappi.NumDrivers].bDoesTextures =
  82.         (d3dappi.Driver[d3dappi.NumDrivers].Desc.dpcTriCaps.dwTextureCaps &
  83.          D3DPTEXTURECAPS_PERSPECTIVE) ? TRUE : FALSE;
  84.     /*
  85.      * Can this driver use a z-buffer?
  86.      */
  87.     d3dappi.Driver[d3dappi.NumDrivers].bDoesZBuffer =
  88.         d3dappi.Driver[d3dappi.NumDrivers].Desc.dwDeviceZBufferBitDepth
  89.                 ? TRUE : FALSE;
  90.     /*
  91.      * Can this driver render to the Windows display depth
  92.      */
  93.     d3dappi.Driver[d3dappi.NumDrivers].bCanDoWindow =
  94.         (d3dappi.Driver[d3dappi.NumDrivers].Desc.dwDeviceRenderBitDepth &
  95.          D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp)) ? TRUE : FALSE;
  96.     if (!d3dappi.bIsPrimary)
  97.         d3dappi.Driver[d3dappi.NumDrivers].bCanDoWindow = FALSE;
  98.  
  99.     d3dappi.NumDrivers++;
  100.     if (d3dappi.NumDrivers == D3DAPP_MAXD3DDRIVERS)
  101.         return (D3DENUMRET_CANCEL);
  102.     return (D3DENUMRET_OK);
  103. }
  104.  
  105. /*
  106.  * D3DAppIEnumDevices
  107.  * Get the available drivers from Direct3D by enumeration.
  108.  */
  109. BOOL
  110. D3DAppIEnumDevices(void)
  111. {
  112.     d3dappi.NumDrivers = 0;
  113.     LastError = d3dappi.lpD3D->lpVtbl->EnumDevices(d3dappi.lpD3D,
  114.                                                    enumDeviceFunc, NULL);
  115.     if (LastError != DD_OK) {
  116.         D3DAppISetErrorString("Enumeration of drivers failed.\n%s",
  117.                               D3DAppErrorToString(LastError));
  118.         return FALSE;
  119.     }
  120.     d3dappi.CurrDriver = 0;
  121.     return TRUE;
  122. }
  123.  
  124. /***************************************************************************/
  125. /*                    Enumeration of texure format                         */
  126. /***************************************************************************/
  127. /*
  128.  * EnumTextureFormatsCallback
  129.  * Record information about each texture format the current D3D driver can
  130.  * support. Choose one as the default format (paletted formats are prefered)
  131.  * and return it through lpContext.
  132.  */
  133. static HRESULT
  134. CALLBACK EnumTextureFormatsCallback(LPDDSURFACEDESC lpDDSD, LPVOID lpContext)
  135. {
  136.     unsigned long m;
  137.     int r, g, b;
  138.     int *lpStartFormat = (int *)lpContext;
  139.     /*
  140.      * Record the DDSURFACEDESC of this texture format
  141.      */
  142.     memset(&d3dappi.TextureFormat[d3dappi.NumTextureFormats], 0,
  143.            sizeof(D3DAppTextureFormat));
  144.     memcpy(&d3dappi.TextureFormat[d3dappi.NumTextureFormats].ddsd, lpDDSD,
  145.            sizeof(DDSURFACEDESC));
  146.     /*
  147.      * Is this format palettized?  How many bits?  Otherwise, how many RGB
  148.      * bits?
  149.      */
  150.     if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
  151.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].bPalettized = TRUE;
  152.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].IndexBPP = 8;
  153.     } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
  154.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].bPalettized = TRUE;
  155.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].IndexBPP = 4;
  156.     } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) {
  157.                 /*
  158.                  * The sample apps don't currently understand
  159.                  * the alpha bit - just filter this format
  160.                  * away for now.
  161.                  */
  162.  
  163.                 return DDENUMRET_OK;
  164.     } else
  165.     {
  166.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].bPalettized = FALSE;
  167.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].IndexBPP = 0;
  168.         for (r = 0, m = lpDDSD->ddpfPixelFormat.dwRBitMask; !(m & 1);
  169.                                                                r++, m >>= 1);
  170.         for (r = 0; m & 1; r++, m >>= 1);
  171.         for (g = 0, m = lpDDSD->ddpfPixelFormat.dwGBitMask; !(m & 1);
  172.                                                                g++, m >>= 1);
  173.         for (g = 0; m & 1; g++, m >>= 1);
  174.         for (b = 0, m = lpDDSD->ddpfPixelFormat.dwBBitMask; !(m & 1);
  175.                                                                b++, m >>= 1);
  176.         for (b = 0; m & 1; b++, m >>= 1);
  177.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].RedBPP = r;
  178.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].GreenBPP = g;
  179.         d3dappi.TextureFormat[d3dappi.NumTextureFormats].BlueBPP = b;
  180.     }
  181.     /*
  182.      * If lpStarFormat is -1, this is the first format.  Select it.
  183.      */
  184.     if (*lpStartFormat == -1)
  185.         *lpStartFormat = d3dappi.NumTextureFormats;
  186.     /* 
  187.      * If this format is paletted, select it.
  188.      */
  189.     if (d3dappi.TextureFormat[d3dappi.NumTextureFormats].bPalettized) {
  190.         *lpStartFormat = d3dappi.NumTextureFormats;
  191.     }
  192.     d3dappi.NumTextureFormats++;
  193.     return DDENUMRET_OK;
  194. }
  195.  
  196. /*
  197.  * D3DAppIEnumTextureFormats
  198.  * Get a list of available texture map formats from the Direct3D driver by
  199.  * enumeration.  Choose a default format (paletted is prefered).
  200.  */
  201. BOOL
  202. D3DAppIEnumTextureFormats(void)
  203. {
  204.     int StartFormat;
  205.     /*
  206.      * Set the default format to -1 to let the callback know it's being 
  207.      * called for the first time.
  208.      */
  209.     StartFormat = -1;
  210.     d3dappi.NumTextureFormats = 0;
  211.     LastError =
  212.          d3dappi.lpD3DDevice->lpVtbl->EnumTextureFormats(d3dappi.lpD3DDevice,
  213.                                                   EnumTextureFormatsCallback,
  214.                                                   (LPVOID)&StartFormat);
  215.     if (LastError != DD_OK) {
  216.         D3DAppISetErrorString("Enumeration of texture formats failed.\n%s",
  217.                               D3DAppErrorToString(LastError));
  218.         return FALSE;
  219.     }
  220.     memcpy(&d3dappi.ThisTextureFormat, &d3dappi.TextureFormat[StartFormat],
  221.            sizeof(D3DAppTextureFormat));
  222.     d3dappi.CurrTextureFormat = StartFormat;
  223.     return TRUE;
  224. }
  225.  
  226. /***************************************************************************/
  227. /*                               Device creation                           */
  228. /***************************************************************************/
  229. /*
  230.  * D3DAppICreateDevice
  231.  * Create the D3D device and enumerate the texture formats
  232.  */
  233. BOOL
  234. D3DAppICreateDevice(int driver)
  235. {
  236.  
  237.     RELEASE(d3dappi.lpD3DDevice);
  238.  
  239.     if (d3dappi.Driver[driver].bIsHardware && !d3dappi.bBackBufferInVideo) {
  240.         D3DAppISetErrorString("Could not fit the rendering surfaces in video memory for this hardware device.\n");
  241.         goto exit_with_error;
  242.     }
  243.  
  244.     d3dappi.CurrDriver = driver;
  245.     memcpy(&d3dappi.ThisDriver, &d3dappi.Driver[driver], sizeof(D3DAppD3DDriver));
  246.     LastError =
  247.            d3dappi.lpBackBuffer->lpVtbl->QueryInterface(d3dappi.lpBackBuffer,
  248.                                                 &d3dappi.Driver[driver].Guid,
  249.                                               (LPVOID*)&d3dappi.lpD3DDevice);
  250.     if (LastError != DD_OK) {
  251.         D3DAppISetErrorString("Create D3D device failed.\n%s",
  252.                               D3DAppErrorToString(LastError));
  253.         goto exit_with_error;
  254.     }
  255.     d3dappi.CurrDriver = driver;
  256.     d3dappi.NumTextureFormats = 0;
  257.     if (d3dappi.Driver[driver].bDoesTextures) {
  258.         if (!D3DAppIEnumTextureFormats())
  259.             goto exit_with_error;
  260.     }
  261.  
  262.     return TRUE;
  263. exit_with_error:
  264.     RELEASE(d3dappi.lpD3DDevice);
  265.     return FALSE;
  266. }
  267.  
  268. /***************************************************************************/
  269. /*                      Setting the render state                           */
  270. /***************************************************************************/
  271. /*
  272.  * D3DAppISetRenderState
  273.  * Create and execute an execute buffer which will set the render state and
  274.  * light state for the current viewport.
  275.  */
  276. BOOL
  277. D3DAppISetRenderState()
  278. {
  279.     D3DEXECUTEBUFFERDESC debDesc;
  280.     D3DEXECUTEDATA d3dExData;
  281.     LPDIRECT3DEXECUTEBUFFER lpD3DExCmdBuf = NULL;
  282.     LPVOID lpBuffer, lpInsStart;
  283.     size_t size;
  284.  
  285.     /*
  286.      * If there is no D3D Viewport, we must return true because it is not
  287.      * required.
  288.      */
  289.     if (!d3dappi.lpD3DViewport)
  290.         return TRUE;
  291.     /*
  292.      * Create an execute buffer of the required size
  293.      */
  294.     size = 0;
  295.     size += sizeof(D3DINSTRUCTION) * 3;
  296.     size += sizeof(D3DSTATE) * 17;
  297.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  298.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  299.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  300.     debDesc.dwBufferSize = size;
  301.     LastError =
  302.         d3dappi.lpD3DDevice->lpVtbl->CreateExecuteBuffer(d3dappi.lpD3DDevice,
  303.                                              &debDesc, &lpD3DExCmdBuf, NULL);
  304.     if (LastError != D3D_OK) {
  305.         D3DAppISetErrorString("CreateExecuteBuffer failed in SetRenderState.\n%s",
  306.                               D3DAppErrorToString(LastError));
  307.         goto exit_with_error;
  308.     }
  309.     /*
  310.      * Lock the execute buffer so it can be filled
  311.      */
  312.     LastError = lpD3DExCmdBuf->lpVtbl->Lock(lpD3DExCmdBuf, &debDesc);
  313.     if (LastError != D3D_OK) {
  314.         D3DAppISetErrorString("Lock failed on execute buffer in SetRenderState.\n%s",
  315.                               D3DAppErrorToString(LastError));
  316.         goto exit_with_error;
  317.     }
  318.     memset(debDesc.lpData, 0, size);
  319.  
  320.     lpInsStart = debDesc.lpData;
  321.     lpBuffer = lpInsStart;
  322.     /*
  323.      * Set render state
  324.      */
  325.     OP_STATE_RENDER(14, lpBuffer);
  326.       STATE_DATA(D3DRENDERSTATE_SHADEMODE, d3dapprs.ShadeMode, lpBuffer);
  327.       STATE_DATA(D3DRENDERSTATE_TEXTUREPERSPECTIVE, d3dapprs.bPerspCorrect,
  328.                  lpBuffer);
  329.       STATE_DATA(D3DRENDERSTATE_ZENABLE, d3dapprs.bZBufferOn &&
  330.                                   d3dappi.ThisDriver.bDoesZBuffer, lpBuffer);
  331.       STATE_DATA(D3DRENDERSTATE_ZWRITEENABLE, d3dapprs.bZBufferOn, lpBuffer);
  332.       STATE_DATA(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL, lpBuffer);
  333.       STATE_DATA(D3DRENDERSTATE_TEXTUREMAG, d3dapprs.TextureFilter,lpBuffer);
  334.       STATE_DATA(D3DRENDERSTATE_TEXTUREMIN, d3dapprs.TextureFilter,lpBuffer);
  335.       STATE_DATA(D3DRENDERSTATE_TEXTUREMAPBLEND, d3dapprs.TextureBlend,
  336.                  lpBuffer);
  337.       STATE_DATA(D3DRENDERSTATE_FILLMODE, d3dapprs.FillMode, lpBuffer);
  338.       STATE_DATA(D3DRENDERSTATE_DITHERENABLE, d3dapprs.bDithering, lpBuffer);
  339.       STATE_DATA(D3DRENDERSTATE_SPECULARENABLE, d3dapprs.bSpecular,lpBuffer);
  340.       STATE_DATA(D3DRENDERSTATE_ANTIALIAS, d3dapprs.bAntialiasing, lpBuffer);
  341.       STATE_DATA(D3DRENDERSTATE_FOGENABLE, d3dapprs.bFogEnabled, lpBuffer);
  342.       STATE_DATA(D3DRENDERSTATE_FOGCOLOR, d3dapprs.FogColor, lpBuffer);
  343.     /*
  344.      * Set light state
  345.      */
  346.     OP_STATE_LIGHT(3, lpBuffer);
  347.       STATE_DATA(D3DLIGHTSTATE_FOGMODE, d3dapprs.bFogEnabled ?
  348.                  d3dapprs.FogMode : D3DFOG_NONE, lpBuffer);
  349.       STATE_DATA(D3DLIGHTSTATE_FOGSTART, *(unsigned long*)&d3dapprs.FogStart,
  350.                  lpBuffer);
  351.       STATE_DATA(D3DLIGHTSTATE_FOGEND, *(unsigned long*)&d3dapprs.FogEnd,
  352.                  lpBuffer);
  353.     OP_EXIT(lpBuffer);
  354.  
  355.     LastError = lpD3DExCmdBuf->lpVtbl->Unlock(lpD3DExCmdBuf);
  356.     if (LastError != D3D_OK) {
  357.         D3DAppISetErrorString("Unlock failed on execute buffer in SetRenderState.\n%s",
  358.                               D3DAppErrorToString(LastError));
  359.         goto exit_with_error;
  360.     }
  361.     /*
  362.      * Set the execute data and exectue the buffer
  363.      */
  364.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  365.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  366.     d3dExData.dwInstructionOffset = (ULONG) 0;
  367.     d3dExData.dwInstructionLength = (ULONG) ((char*)lpBuffer -
  368.                                                           (char*)lpInsStart);
  369.     lpD3DExCmdBuf->lpVtbl->SetExecuteData(lpD3DExCmdBuf, &d3dExData);
  370.     LastError = d3dappi.lpD3DDevice->lpVtbl->BeginScene(d3dappi.lpD3DDevice);
  371.     if (LastError != D3D_OK) {
  372.         D3DAppISetErrorString("BeginScene failed in SetRenderState.\n%s",
  373.                               D3DAppErrorToString(LastError));
  374.         goto exit_with_error;
  375.     }
  376.     LastError = d3dappi.lpD3DDevice->lpVtbl->Execute(d3dappi.lpD3DDevice,
  377.                                                      lpD3DExCmdBuf,
  378.                                                      d3dappi.lpD3DViewport,
  379.                                                      D3DEXECUTE_UNCLIPPED);
  380.     if (LastError != D3D_OK) {
  381.         D3DAppISetErrorString("Execute failed in SetRenderState.\n%s",
  382.                               D3DAppErrorToString(LastError));
  383.         goto exit_with_error;
  384.     }
  385.     LastError = d3dappi.lpD3DDevice->lpVtbl->EndScene(d3dappi.lpD3DDevice);
  386.     if (LastError != D3D_OK) {
  387.         D3DAppISetErrorString("EndScene failed in SetRenderState.\n%s",
  388.                               D3DAppErrorToString(LastError));
  389.         goto exit_with_error;
  390.     }
  391.     /*
  392.      * We are done with the execute buffer, so release it.
  393.      */
  394.     lpD3DExCmdBuf->lpVtbl->Release(lpD3DExCmdBuf);
  395.     return TRUE;
  396.  
  397. exit_with_error:
  398.     RELEASE(lpD3DExCmdBuf);
  399.     return FALSE;
  400. }
  401.  
  402.