home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / tri3 / d3dapp.c < prev    next >
C/C++ Source or Header  |  1997-07-14  |  48KB  |  1,374 lines

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: d3dapp.c
  5.  *
  6.  *  Top level D3DApp functions and internal global variables.  See
  7.  *  d3dapp.h for more information.
  8.  *
  9.  *  D3DApp is a collection of helper functions for Direct3D applications.
  10.  *  D3DApp consists of the following files:
  11.  *    d3dapp.h    Main D3DApp header to be included by application
  12.  *      d3dappi.h   Internal header
  13.  *      d3dapp.c    D3DApp functions seen by application.
  14.  *      ddcalls.c   All calls to DirectDraw objects except textures
  15.  *      d3dcalls.c  All calls to Direct3D objects except textures
  16.  *      texture.c   Texture loading and managing texture list
  17.  *      misc.c        Miscellaneous calls
  18.  */
  19.  
  20. #include "d3dappi.h"
  21.  
  22. #define INITGUID
  23.  
  24. /***************************************************************************/
  25. /*                           GLOBAL VARIABLES                              */
  26. /***************************************************************************/
  27. /*
  28.  * All DD and D3D objects which are also available to the application
  29.  * See d3dapp.h for typedef
  30.  */
  31. D3DAppInfo d3dappi;
  32. /*
  33.  * Internal record of the render state.  See d3dapp.h for typedef
  34.  */
  35. D3DAppRenderState d3dapprs; 
  36. /* 
  37.  * Callback functions for D3D device creation and destruction
  38.  */
  39. BOOL(*D3DDeviceDestroyCallback)(LPVOID);
  40. LPVOID D3DDeviceDestroyCallbackContext;
  41. BOOL(*D3DDeviceCreateCallback)(int, int, LPDIRECT3DVIEWPORT2*, LPVOID);
  42. LPVOID D3DDeviceCreateCallbackContext;
  43. /*
  44.  * The last error code and string
  45.  */
  46. HRESULT LastError;
  47. char LastErrorString[256];
  48. /*
  49.  * List of dirty rectangles on back buffer and client area
  50.  */
  51. int NumDirtyClientRects, NumDirtyBackRects, NumDirtyZRects;
  52. D3DRECT DirtyClient[D3DAPP_MAXCLEARRECTS];
  53. D3DRECT DirtyBack[D3DAPP_MAXCLEARRECTS];
  54. D3DRECT DirtyZ[D3DAPP_MAXCLEARRECTS];
  55. /*
  56.  * List of texture handles which is copied to D3DAppInfo structure when
  57.  * necessary
  58.  */
  59. D3DTEXTUREHANDLE MasterTextureHandle[D3DAPP_MAXTEXTURES];
  60.  
  61. LPDIRECTDRAWCLIPPER lpClipper; /* Clipper in windowed case */
  62. LPDIRECTDRAWPALETTE lpPalette; /* Front buffer's palette */
  63. PALETTEENTRY ppe[256];         /* Current palette entries */
  64. PALETTEENTRY Originalppe[256]; /* Windows palette entries at startup */
  65. BOOL bD3DAppInitialized;       /* Is D3DApp initialized? */
  66. BOOL bPrimaryPalettized;       /* Is the front buffer palettized? */
  67. BOOL bPaletteActivate;           /* Is the front buffer's palette valid? */
  68. BOOL bIgnoreWM_SIZE;           /* Ignore this WM_SIZE messages */
  69. SIZE szLastClient;           /* Dimensions of the last window */
  70. SIZE szBuffers;               /* Current buffer dimensions, not necessarily
  71.                   the same as the client window */
  72. int CallbackRefCount;           /* How many times DeviceCreateCallback has
  73.                   been called in a row */
  74.  
  75. /***************************************************************************/
  76. /*                               FUNCTIONS                                 */
  77. /***************************************************************************/
  78. /*
  79.  * D3DAppCreateFromHWND
  80.  */
  81. BOOL D3DAppCreateFromHWND(DWORD flags, HWND hwnd,
  82.               BOOL(*DeviceCreateCallback)(int, int,
  83.                               LPDIRECT3DVIEWPORT2*,
  84.                               LPVOID),
  85.               LPVOID lpCreateContext,
  86.               BOOL(*DeviceDestroyCallback)(LPVOID),
  87.               LPVOID lpDestroyContext,
  88.               D3DAppInfo** D3DApp)
  89. {
  90.     int driver, mode, w, h;
  91.     /* 
  92.      * Clean the global varaibles and check the flags
  93.      */
  94.     D3DAppISetDefaults();
  95.     if (flags & D3DAPP_ONLYSYSTEMMEMORY) {
  96.     d3dappi.bOnlySystemMemory = TRUE;
  97.     d3dappi.bOnlyEmulation = TRUE;
  98.     }
  99.     if (flags & D3DAPP_ONLYD3DEMULATION)
  100.     d3dappi.bOnlyEmulation = TRUE;
  101.     /* 
  102.      * Create DirectDraw, remember the Windows display mode and enumerate the
  103.      * display modes
  104.      */
  105.     ATTEMPT(D3DAppICreateDD(d3dappi.bOnlyEmulation ?
  106.                 D3DAPP_ONLYDDEMULATION : 0L));
  107.     ATTEMPT(D3DAppIRememberWindowsMode());
  108.     ATTEMPT(D3DAppIEnumDisplayModes());
  109.     /*
  110.      * Create Direct3D and enumerate the D3D drivers
  111.      */
  112.     ATTEMPT(D3DAppICreateD3D());
  113.     ATTEMPT(D3DAppIEnumDevices());
  114.     /*
  115.      * Set the device creation and destroy callback functions
  116.      */
  117.     D3DDeviceDestroyCallback = DeviceDestroyCallback;
  118.     D3DDeviceDestroyCallbackContext = lpDestroyContext;
  119.     D3DDeviceCreateCallback = DeviceCreateCallback;
  120.     D3DDeviceCreateCallbackContext = lpCreateContext;
  121.     *D3DApp = &d3dappi;
  122.     d3dappi.hwnd = hwnd;
  123.     /*
  124.      * Choose a driver and display mode.  Using the current window is 
  125.      * prefered, but a fullscreen mode may be selected.  Set the cooperative
  126.      * level and create the front and back buffers for this mode.
  127.      */
  128.     driver = D3DAPP_YOUDECIDE;
  129.     mode = D3DAPP_YOUDECIDE;
  130.     ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
  131.     D3DAppIGetClientWin(hwnd);
  132.     if (mode == D3DAPP_USEWINDOW) {
  133.     w = d3dappi.szClient.cx;
  134.     h = d3dappi.szClient.cy;
  135.     ATTEMPT(D3DAppISetCoopLevel(hwnd, FALSE));
  136.     ATTEMPT(D3DAppICreateBuffers(hwnd, w, h, D3DAPP_BOGUS, FALSE,
  137.                      d3dappi.Driver[driver].bIsHardware));
  138.     /*
  139.      * Change the currently selected mode if it's not compatible with
  140.      * this driver.  Just to make sure that CurrMode is always a mode the
  141.      * current driver can do.
  142.      */
  143.     if (!(d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth &
  144.           D3DAppIBPPToDDBD(d3dappi.Mode[d3dappi.CurrMode].bpp))){
  145.         ATTEMPT(D3DAppIPickDisplayMode(&d3dappi.CurrMode,
  146.                 d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth));
  147.     }
  148.     } else {
  149.     szLastClient = d3dappi.szClient;
  150.     w = d3dappi.Mode[mode].w;
  151.     h = d3dappi.Mode[mode].h;
  152.     d3dappi.szClient.cx = w; d3dappi.szClient.cy = h;
  153.     ATTEMPT(D3DAppISetCoopLevel(hwnd, TRUE));
  154.     ATTEMPT(D3DAppISetDisplayMode(w, h, d3dappi.Mode[mode].bpp));
  155.     d3dappi.CurrMode = mode;
  156.     ATTEMPT(D3DAppICreateBuffers(hwnd, w, h, d3dappi.Mode[mode].bpp, TRUE,
  157.                      d3dappi.Driver[driver].bIsHardware));
  158.     }
  159.     /*
  160.      * If the front buffer is palettized, initialize its palette
  161.      */
  162.     ATTEMPT(D3DAppICheckForPalettized());
  163.     /*
  164.      * Create the Z-buffer
  165.      */
  166.     ATTEMPT(D3DAppICreateZBuffer(w, h, driver));
  167.     /*
  168.      * Create the D3D device, load the textures, call the device create
  169.      * callback and set a default render state
  170.      */
  171.     ATTEMPT(D3DAppICreateDevice(driver));
  172.     ATTEMPT(D3DAppILoadAllTextures());
  173.     ATTEMPT(D3DAppIFilterDisplayModes(driver));  /* bThisDriverCanDo flags */
  174.     ATTEMPT(D3DAppICallDeviceCreateCallback(w, h));
  175.     ATTEMPT(D3DAppISetRenderState());
  176.     /* 
  177.      * Initialize dirty rectangle information
  178.      */
  179.     D3DAppIValidateDirtyRects();
  180.     /*
  181.      * Ready to render
  182.      */
  183.     bD3DAppInitialized = TRUE;
  184.     d3dappi.bRenderingIsOK = TRUE;
  185.     return TRUE;
  186.  
  187. exit_with_error:
  188.     D3DAppICallDeviceDestroyCallback();
  189.     RELEASE(d3dappi.lpD3DDevice);
  190.     RELEASE(d3dappi.lpZBuffer);
  191.     RELEASE(lpPalette);
  192.     RELEASE(lpClipper);
  193.     RELEASE(d3dappi.lpBackBuffer);
  194.     RELEASE(d3dappi.lpFrontBuffer);
  195.     if (d3dappi.bFullscreen) {
  196.     D3DAppIRestoreDispMode();
  197.     D3DAppISetCoopLevel(hwnd, FALSE);
  198.     }
  199.     RELEASE(d3dappi.lpD3D);
  200.     RELEASE(d3dappi.lpDD);
  201.     return FALSE;
  202. }   
  203.  
  204. /*
  205.  * D3DAppFullscreen
  206.  */
  207. BOOL D3DAppFullscreen(int mode)
  208. {
  209.     int w, h, bpp;
  210.     BOOL b; /* was already in a fullscreen mode? */
  211.  
  212.     d3dappi.bRenderingIsOK = FALSE;
  213.     /* 
  214.      * Make sure this is a valid request, otherwise doctor mode so it will
  215.      * work with this driver.
  216.      */
  217.     ATTEMPT(D3DAppIVerifyDriverAndMode(&d3dappi.CurrDriver, &mode));
  218.     /* 
  219.      * Release everything
  220.      */
  221.     ATTEMPT(D3DAppICallDeviceDestroyCallback());
  222.     if (d3dappi.bFullscreen) {
  223.     ATTEMPT(D3DAppIClearBuffers());
  224.     }
  225.     D3DAppIReleaseAllTextures();
  226.     RELEASE(d3dappi.lpD3DDevice);
  227.     RELEASE(d3dappi.lpZBuffer);
  228.     RELEASE(lpPalette);
  229.     RELEASE(lpClipper);
  230.     RELEASE(d3dappi.lpBackBuffer);
  231.     RELEASE(d3dappi.lpFrontBuffer);
  232.     /*
  233.      * Record information about the current status
  234.      */
  235.     b = d3dappi.bFullscreen;
  236.     w = d3dappi.Mode[mode].w;
  237.     h = d3dappi.Mode[mode].h;
  238.     bpp = d3dappi.Mode[mode].bpp;
  239.     if (!b) {
  240.     /*
  241.      * If this is not a fullscreen mode, we'll need to record the window
  242.      * size for when we return to it.
  243.      */
  244.     szLastClient = d3dappi.szClient;
  245.     }
  246.     /*
  247.      * Set the cooperative level and create front and back buffers
  248.      */
  249.     d3dappi.szClient.cx = w; d3dappi.szClient.cy = h;
  250.     ATTEMPT(D3DAppISetCoopLevel(d3dappi.hwnd, TRUE));
  251.     ATTEMPT(D3DAppISetDisplayMode(w, h, bpp));
  252.     d3dappi.CurrMode = mode;
  253.     ATTEMPT(D3DAppICreateBuffers(d3dappi.hwnd, w, h, bpp, TRUE,
  254.                  d3dappi.Driver[d3dappi.CurrDriver].bIsHardware));
  255.     /*
  256.      * If the front buffer is palettized, initialize its palette
  257.      */
  258.     ATTEMPT(D3DAppICheckForPalettized());
  259.     /*
  260.      * Create the Z-buffer
  261.      */
  262.     ATTEMPT(D3DAppICreateZBuffer(w, h, d3dappi.CurrDriver));
  263.     /*
  264.      * Create the D3D device, load the textures, call the device create
  265.      * callback and set a default render state
  266.      */
  267.     ATTEMPT(D3DAppICreateDevice(d3dappi.CurrDriver));
  268.     ATTEMPT(D3DAppILoadAllTextures());
  269.     ATTEMPT(D3DAppICallDeviceCreateCallback(w, h));
  270.     ATTEMPT(D3DAppISetRenderState());
  271.     /* 
  272.      * Set current mode and clear dirty rectangle information
  273.      */
  274.     d3dappi.CurrMode = mode;
  275.     D3DAppIValidateDirtyRects();
  276.     d3dappi.bRenderingIsOK = TRUE;
  277.     return TRUE;
  278.  
  279. exit_with_error:
  280.     D3DAppICallDeviceDestroyCallback();
  281.     RELEASE(d3dappi.lpD3DDevice);
  282.     RELEASE(d3dappi.lpZBuffer);
  283.     RELEASE(lpPalette);
  284.     RELEASE(lpClipper);
  285.     RELEASE(d3dappi.lpBackBuffer);
  286.     RELEASE(d3dappi.lpFrontBuffer);
  287.     if (!b) {
  288.     D3DAppIRestoreDispMode();
  289.     D3DAppISetCoopLevel(d3dappi.hwnd, FALSE);
  290.     }
  291.     return FALSE;
  292. }
  293.  
  294. /*
  295.  * D3DAppWindow
  296.  */
  297. BOOL
  298. D3DAppWindow(int w, int h)
  299. {
  300.     BOOL b; /* changing from a fullscreen mode? */
  301.  
  302.     if (!d3dappi.bIsPrimary) {
  303.     D3DAppISetErrorString("It is not possible to create a D3D window with a hardware DirectDraw device.  Check the bIsPrimary flag before calling D3DAppWindow.");
  304.     return FALSE;
  305.     }
  306.     b = d3dappi.bFullscreen;
  307.     /*
  308.      * If asked to set the window size, return it to the last value or use
  309.      * a default value.
  310.      */
  311.     if (w == D3DAPP_YOUDECIDE) {
  312.     w = b ? szLastClient.cx : D3DAPP_DEFAULTWINDOWDIM;
  313.     }
  314.     if (h == D3DAPP_YOUDECIDE) {
  315.     h = b ? szLastClient.cy : D3DAPP_DEFAULTWINDOWDIM;
  316.     }
  317.     /*
  318.      * Release everything
  319.      */
  320.     d3dappi.bRenderingIsOK = FALSE;
  321.     ATTEMPT(D3DAppICallDeviceDestroyCallback());
  322.     if (b) {
  323.     ATTEMPT(D3DAppIClearBuffers());
  324.     }
  325.     D3DAppIReleaseAllTextures();
  326.     RELEASE(d3dappi.lpD3DDevice);
  327.     RELEASE(d3dappi.lpZBuffer);
  328.     RELEASE(lpPalette);
  329.     RELEASE(lpClipper);
  330.     RELEASE(d3dappi.lpBackBuffer);
  331.     RELEASE(d3dappi.lpFrontBuffer);
  332.     /* 
  333.      * Restore the display mode if we were in a fullscreen mode
  334.      */
  335.     if (b) {
  336.     D3DAppIRestoreDispMode();
  337.     }
  338.     /* 
  339.      * Set the cooperative level and create front and back buffers
  340.      */
  341.     D3DAppISetCoopLevel(d3dappi.hwnd, FALSE);
  342.     D3DAppISetClientSize(d3dappi.hwnd, w, h, b);
  343.     ATTEMPT(D3DAppICreateBuffers(d3dappi.hwnd, w, h, D3DAPP_BOGUS, FALSE,
  344.                  d3dappi.Driver[d3dappi.CurrDriver].bIsHardware));
  345.     /*
  346.      * If the front buffer is palettized, initialize its palette
  347.      */
  348.     ATTEMPT(D3DAppICheckForPalettized());
  349.     /*
  350.      * Create the Z-buffer
  351.      */
  352.     ATTEMPT(D3DAppICreateZBuffer(szBuffers.cx, szBuffers.cy,
  353.                  d3dappi.CurrDriver));
  354.     /*
  355.      * Create the D3D device, load the textures, call the device create
  356.      * callback and set a default render state
  357.      */
  358.     ATTEMPT(D3DAppICreateDevice(d3dappi.CurrDriver));
  359.     ATTEMPT(D3DAppILoadAllTextures());        
  360.     ATTEMPT(D3DAppICallDeviceCreateCallback(szBuffers.cx, szBuffers.cy));
  361.     ATTEMPT(D3DAppISetRenderState());
  362.     /* 
  363.      * Clear dirty rectangle information
  364.      */
  365.     D3DAppIValidateDirtyRects();
  366.     d3dappi.bRenderingIsOK = TRUE;
  367.     return TRUE;
  368.  
  369. exit_with_error:
  370.     D3DAppICallDeviceDestroyCallback();
  371.     RELEASE(d3dappi.lpD3DDevice);
  372.     RELEASE(d3dappi.lpZBuffer);
  373.     RELEASE(lpPalette);
  374.     RELEASE(lpClipper);
  375.     RELEASE(d3dappi.lpBackBuffer);
  376.     RELEASE(d3dappi.lpFrontBuffer);
  377.     return FALSE;  
  378. }
  379.  
  380.  
  381. /*
  382.  * D3DAppChangeDriver 
  383.  */
  384. BOOL
  385. D3DAppChangeDriver(int driver, DWORD flags)
  386. {
  387.     int mode;
  388.  
  389.     /*
  390.      * Verify the compatibility of this mode with the specified driver.
  391.      * The mode may change.
  392.      */
  393.     if (d3dappi.bFullscreen)
  394.     mode = d3dappi.CurrMode;
  395.     else
  396.     mode = D3DAPP_USEWINDOW;
  397.     ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
  398.     if (driver == D3DAPP_BOGUS || mode == D3DAPP_BOGUS)
  399.     goto exit_with_error;
  400.     /*
  401.      * Update the current driver and set bThisDriverCanDo flags
  402.      */
  403.     d3dappi.CurrDriver = driver;
  404.     ATTEMPT(D3DAppIFilterDisplayModes(driver));
  405.     /*
  406.      * Either call D3DAppWindow or D3DAppFullscreen depending on mode
  407.      */
  408.     if (mode == D3DAPP_USEWINDOW) {
  409.     if (d3dappi.bFullscreen) {
  410.         /*
  411.          * We need to switch to a window.  D3DApp will either use the
  412.          * size of the last window it saw or use a default size.
  413.          */
  414.         ATTEMPT(D3DAppWindow(D3DAPP_YOUDECIDE, D3DAPP_YOUDECIDE));
  415.     } else {
  416.         /*
  417.          * We need to recreate the current window.  Don't let D3DApp
  418.          * decide on the size.
  419.          */
  420.         ATTEMPT(D3DAppWindow(d3dappi.szClient.cx, d3dappi.szClient.cy));
  421.     }
  422.     /*
  423.      * Change the currently selected mode if it's not compatible with
  424.      * this driver.  Just to make sure that CurrMode is always a mode the
  425.      * current driver can do.
  426.      */
  427.     if (!(d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth &
  428.           D3DAppIBPPToDDBD(d3dappi.Mode[d3dappi.CurrMode].bpp))){
  429.         ATTEMPT(D3DAppIPickDisplayMode(&d3dappi.CurrMode,
  430.                 d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth));
  431.     }
  432.     return TRUE;
  433.     } else {
  434.     /*
  435.      * We need to switch to fullscreen or switch fullscreen modes or stay
  436.      * in the same fullscreen mode.  In any of these cases, we call the
  437.      * same function.
  438.      */
  439.     ATTEMPT(D3DAppFullscreen(mode));
  440.     return TRUE;
  441.     }
  442.  
  443. exit_with_error:
  444.     /*
  445.      * The failed mode setting call would have released everything
  446.      */
  447.     return FALSE;
  448. }
  449.  
  450.  
  451. /*
  452.  * D3DAppWindowProc
  453.  */
  454. BOOL
  455. D3DAppWindowProc(BOOL* bStopProcessing, LRESULT* lresult, HWND hwnd,
  456.          UINT message, WPARAM wParam, LPARAM lParam)
  457. {
  458.     PAINTSTRUCT ps;
  459.     *bStopProcessing = FALSE;
  460.     if (!bD3DAppInitialized)
  461.     return TRUE;
  462.     /*
  463.      * Look for messages which effect rendering.  In some cases, we will not
  464.      * want the app to continue processing the message, so set the flag and
  465.      * provide a return value in lresult.
  466.      */
  467.     switch(message) {
  468.     case WM_SIZE:
  469.         if (!bIgnoreWM_SIZE) {
  470.         /*
  471.          * Too long to fit here, see ddcalls.c. Updates the buffers
  472.          * and re-creates the device.
  473.          */
  474.         ATTEMPT(D3DAppIHandleWM_SIZE(lresult, d3dappi.hwnd, message,
  475.                          wParam, lParam));
  476.         *bStopProcessing = TRUE;
  477.         }
  478.         break;
  479.     case WM_MOVE:
  480.         /*
  481.          * Update client window position information
  482.          */
  483.         d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
  484.         ClientToScreen(hwnd, &d3dappi.pClientOnPrimary);
  485.         break;
  486.     case WM_ACTIVATE:
  487.         /*
  488.          * Set the front buffer's palette
  489.          */
  490.         if (bPaletteActivate && bPrimaryPalettized &&
  491.         d3dappi.lpFrontBuffer) {
  492.         d3dappi.lpFrontBuffer->lpVtbl->SetPalette(d3dappi.lpFrontBuffer,
  493.                               lpPalette);
  494.         }
  495.         break;
  496.         case WM_ACTIVATEAPP:
  497.             d3dappi.bAppActive = (BOOL)wParam;
  498.             break;
  499.         case WM_SETCURSOR:
  500.         /*
  501.          * Prevent the cursor from being shown in fullscreen
  502.          */
  503.             if (d3dappi.bFullscreen && !d3dappi.bPaused) {
  504.                 SetCursor(NULL);
  505.                 *lresult = 1;
  506.         *bStopProcessing = TRUE;
  507.         return TRUE;
  508.             }
  509.             break;
  510.     case WM_MOVING:
  511.         /*
  512.          * Prevent the window from moving in fullscreen
  513.          */
  514.         if (d3dappi.bFullscreen) {
  515.         GetWindowRect(hwnd, (LPRECT)lParam);
  516.                 *lresult = 1;
  517.         *bStopProcessing = TRUE;
  518.         return TRUE;
  519.         }
  520.         break;
  521.     case WM_GETMINMAXINFO:
  522.         /*
  523.          * Ensure the window won't resize in fullscreen
  524.          */
  525.         if (d3dappi.bFullscreen) {
  526.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x= d3dappi.ThisMode.w;
  527.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y= d3dappi.ThisMode.h;
  528.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.x= d3dappi.ThisMode.w;
  529.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.y= d3dappi.ThisMode.h;
  530.                 *lresult = 0;
  531.         *bStopProcessing = TRUE;
  532.         return TRUE;
  533.         } else {
  534.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x =
  535.                             d3dappi.WindowsDisplay.w;
  536.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y =
  537.                             d3dappi.WindowsDisplay.h;
  538.                 *lresult = 0;
  539.         *bStopProcessing = TRUE;
  540.         return TRUE;
  541.         }
  542.         break;
  543.     case WM_PAINT:
  544.         /*
  545.          * Clear the rectangle and blt the backbuffer image
  546.          */
  547.         BeginPaint(hwnd, &ps);
  548.         if (d3dappi.bRenderingIsOK && !d3dappi.bFullscreen) {
  549.         D3DAppShowBackBuffer(D3DAPP_SHOWALL);
  550.         }
  551.         D3DAppIValidateDirtyRects();
  552.         EndPaint(hwnd, &ps);
  553.         *lresult = 1;
  554.         *bStopProcessing = TRUE;
  555.         return TRUE;
  556.     case WM_NCPAINT:
  557.         /*
  558.          * When in fullscreen mode, don't draw the window frame.
  559.          */
  560.         if (d3dappi.bFullscreen && !d3dappi.bPaused) {
  561.         *lresult = 0;
  562.         *bStopProcessing = TRUE;
  563.         return TRUE;
  564.         }
  565.         break;
  566.     }
  567.     return TRUE;
  568.  
  569. exit_with_error:
  570.     return FALSE;
  571. }
  572.  
  573. /*
  574.  * D3DAppAddTexture 
  575.  */
  576. BOOL
  577. D3DAppAddTexture(const char* imagefile)
  578. {
  579.     if (d3dappi.NumTextures == D3DAPP_MAXTEXTURES - 1) {
  580.     D3DAppISetErrorString("Can only load %i textures.", D3DAPP_MAXTEXTURES);
  581.     return FALSE;
  582.     }
  583.     lstrcpy(d3dappi.ImageFile[d3dappi.NumTextures], imagefile);
  584.     /*
  585.      * If this driver does texture mapping, load the texture.
  586.      * This test also tests that a device has been created.
  587.      */
  588.     if (d3dappi.ThisDriver.bDoesTextures && d3dappi.NumUsableTextures == d3dappi.NumTextures) {
  589.     BOOL bInVideo;
  590.     ATTEMPT(D3DAppILoadTextureSurf(d3dappi.NumTextures, &bInVideo));
  591.     if (!bInVideo && d3dappi.ThisDriver.bIsHardware) {
  592.         D3DAppIReleaseTexture(d3dappi.NumTextures);
  593.     } else {
  594.         ATTEMPT(D3DAppIGetTextureHandle(d3dappi.NumTextures));
  595.         ++d3dappi.NumUsableTextures;
  596.     }
  597.     }
  598.     d3dappi.NumTextures++;
  599.     return TRUE;
  600.  
  601. exit_with_error:
  602.     d3dappi.ImageFile[d3dappi.NumTextures][0] = 0;
  603.     return FALSE;
  604. }
  605.  
  606. /*
  607.  * D3DAppChangeTextureFormat
  608.  */
  609. BOOL
  610. D3DAppChangeTextureFormat(int format)
  611. {
  612.     /*
  613.      * Release all the textures, change the format and load them again
  614.      */
  615.     d3dappi.bRenderingIsOK = FALSE;
  616.     D3DAppIReleaseAllTextures();
  617.     d3dappi.CurrTextureFormat = format;
  618.     memcpy(&d3dappi.ThisTextureFormat, &d3dappi.TextureFormat[format],
  619.        sizeof(D3DAppTextureFormat));
  620.     ATTEMPT(D3DAppILoadAllTextures());
  621.     d3dappi.bRenderingIsOK = TRUE;
  622.     return TRUE;
  623.  
  624. exit_with_error:
  625.     D3DAppIReleaseAllTextures();
  626.     return FALSE;
  627. }
  628.  
  629. /*
  630.  * D3DAppDisableTextures
  631.  */
  632. BOOL
  633. D3DAppDisableTextures(BOOL flag)
  634. {
  635.     int i;
  636.     if (flag == d3dappi.bTexturesDisabled)
  637.     return TRUE;
  638.     if (flag) {
  639.     /*
  640.      * Set all the texture handles to 0
  641.      */
  642.     d3dappi.bTexturesDisabled = TRUE;
  643.     for (i = 0; i < d3dappi.NumTextures; i++)
  644.         d3dappi.TextureHandle[i] = 0;
  645.     } else {
  646.     /*
  647.      * Restore the texture handles from the master array
  648.      */
  649.     d3dappi.bTexturesDisabled = FALSE;
  650.     memcpy(d3dappi.TextureHandle, MasterTextureHandle,
  651.            sizeof(D3DTEXTUREHANDLE) * D3DAPP_MAXTEXTURES);
  652.     }
  653.     return TRUE;
  654. }
  655.  
  656. /*
  657.  * D3DAppSwapTextures
  658.  */
  659. BOOL
  660. D3DAppSwapTextures()
  661. {
  662.     int i;
  663.     char tempfile[30];
  664.     LPDIRECT3DTEXTURE2 lptempTexture;
  665.     LPDIRECTDRAWSURFACE lptempSurface;
  666.   if (d3dappi.bTexturesDisabled || d3dappi.NumTextures == 0) {
  667.     D3DAppISetErrorString("Cannot swap textures which are disable or not loaded.\n");
  668.     goto exit_with_error;
  669.     }
  670.     if (!d3dappi.ThisDriver.bDoesTextures)
  671.     return TRUE;
  672.     /*
  673.      * Swap texture 1 with 2, then 2 with 3, then 3 with 4, etc.
  674.      * Don't forget the image file names, texture objects and surfaces
  675.      */
  676.     for (i = 0; i < d3dappi.NumUsableTextures - 1; i++) {
  677.     lstrcpy(tempfile, d3dappi.ImageFile[i]);
  678.     lstrcpy(d3dappi.ImageFile[i], d3dappi.ImageFile[i+1]);
  679.     lstrcpy(d3dappi.ImageFile[i+1], tempfile);
  680.     d3dappi.lpD3DDevice->lpVtbl->SwapTextureHandles(d3dappi.lpD3DDevice,
  681.                               d3dappi.lpTexture[i],
  682.                               d3dappi.lpTexture[i+1]);
  683.     lptempTexture = d3dappi.lpTexture[i];
  684.     d3dappi.lpTexture[i] = d3dappi.lpTexture[i+1];
  685.     d3dappi.lpTexture[i+1] = lptempTexture;
  686.     lptempSurface = d3dappi.lpTextureSurf[i];
  687.     d3dappi.lpTextureSurf[i] = d3dappi.lpTextureSurf[i+1];
  688.     d3dappi.lpTextureSurf[i+1] = lptempSurface;
  689.     }
  690.     return TRUE;
  691. exit_with_error:
  692.     return FALSE;
  693. }
  694.  
  695. /*
  696.  * D3DAppSetRenderState
  697.  */
  698. BOOL
  699. D3DAppSetRenderState(D3DAppRenderState* lpState)
  700. {
  701.     /*
  702.      * If none was provided, reset the current render state.
  703.      */
  704.     if (!lpState)
  705.     lpState = &d3dapprs;
  706.     /*
  707.      * Record this render state and set it.
  708.      */
  709.     if (lpState != &d3dapprs)
  710.     memcpy(&d3dapprs, lpState, sizeof(D3DAppRenderState));
  711.     if (d3dappi.bRenderingIsOK) {
  712.     ATTEMPT(D3DAppISetRenderState());
  713.     }
  714.     return TRUE;
  715.  
  716. exit_with_error:
  717.     return FALSE;
  718. }
  719.  
  720. /*
  721.  * D3DAppGetRenderState
  722.  */
  723. BOOL
  724. D3DAppGetRenderState(D3DAppRenderState* lpState)
  725. {
  726.     memcpy(lpState, &d3dapprs, sizeof(D3DAppRenderState));
  727.     return TRUE;
  728. }
  729.  
  730. /*
  731.  * D3DAppShowBackBuffer
  732.  */
  733. BOOL
  734. D3DAppShowBackBuffer(DWORD flags)
  735. {
  736.     if (!d3dappi.bRenderingIsOK) {
  737.     D3DAppISetErrorString("Cannot call D3DAppShowBackBuffer while bRenderingIsOK is FALSE.\n");
  738.     return FALSE;
  739.     }
  740.     if (d3dappi.bPaused)
  741.     return TRUE;
  742.     if (d3dappi.bFullscreen) {  
  743.     int numtemp;
  744.     D3DRECT temp[D3DAPP_MAXCLEARRECTS];
  745.     /*
  746.      * Flip the back and front buffers
  747.      */
  748.         LastError = d3dappi.lpFrontBuffer->lpVtbl->Flip(d3dappi.lpFrontBuffer,
  749.                             d3dappi.lpBackBuffer,
  750.                             1);
  751.     if (LastError == DDERR_SURFACELOST) {
  752.         d3dappi.lpFrontBuffer->lpVtbl->Restore(d3dappi.lpFrontBuffer);
  753.         d3dappi.lpBackBuffer->lpVtbl->Restore(d3dappi.lpBackBuffer);
  754.         D3DAppIClearBuffers();
  755.     } else if (LastError != DD_OK) {
  756.             D3DAppISetErrorString("Flipping complex display surface failed.\n%s", D3DAppErrorToString(LastError));
  757.             return FALSE;
  758.         }
  759.     if (d3dappi.bBackBufferInVideo) {
  760.         /*
  761.          * This is a real flip, so the client and back buffer dirty
  762.          * rectangles also flip
  763.          */
  764.         D3DAppICopyRectList(&numtemp, temp, NumDirtyClientRects,
  765.                 DirtyClient);
  766.         D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
  767.                 NumDirtyBackRects, DirtyBack);
  768.         D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, numtemp, temp);
  769.     } else {
  770.         /*
  771.          * The flip is being emulated as a blt from a system memory back
  772.          * buffer, so the back buffer's dirty rectangles are now also the
  773.          * client's.
  774.          */
  775.         D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
  776.                 NumDirtyBackRects, DirtyBack);
  777.     }
  778.     } else {
  779.     int NumFrontRects, NumBufferRects, i;
  780.     RECT front[D3DAPP_MAXCLEARRECTS];
  781.     RECT buffer[D3DAPP_MAXCLEARRECTS];
  782.     /*
  783.      * Set the rectangle to blt from the back to front bufer
  784.      */
  785.     if (flags & D3DAPP_SHOWALL) {
  786.         /*
  787.          * Set to entire client window
  788.          */
  789.         NumBufferRects = 1;
  790.         SetRect(&buffer[0], 0, 0, d3dappi.szClient.cx,
  791.             d3dappi.szClient.cy);
  792.         SetRect(&front[0],
  793.             d3dappi.pClientOnPrimary.x, d3dappi.pClientOnPrimary.y,
  794.             d3dappi.szClient.cx + d3dappi.pClientOnPrimary.x,
  795.             d3dappi.szClient.cy + d3dappi.pClientOnPrimary.y);
  796.     } else {
  797.         /*
  798.          * Merge the back and front buffer dirty rectangle lists to get
  799.          * a list of rectangles to blt.  This will simultaneously clear
  800.          * the smallest front buffer region while blt'ing all the back
  801.          * buffer which changed.
  802.          */
  803.         D3DAppIMergeRectLists(&NumBufferRects, (LPD3DRECT)buffer,
  804.                   NumDirtyClientRects, DirtyClient,
  805.                   NumDirtyBackRects, DirtyBack);
  806.         D3DAppICopyRectList(&NumFrontRects, (LPD3DRECT)front,
  807.                 NumBufferRects, (LPD3DRECT)buffer);
  808.         for (i = 0; i < NumFrontRects; i++) {
  809.         front[i].top += d3dappi.pClientOnPrimary.y;
  810.         front[i].left += d3dappi.pClientOnPrimary.x;
  811.         front[i].bottom += d3dappi.pClientOnPrimary.y;
  812.         front[i].right += d3dappi.pClientOnPrimary.x;
  813.         }
  814.     }
  815.     /*
  816.      * Blt the list of rectangles from the back to front buffer
  817.      */
  818.     for (i = 0; i < NumBufferRects; i++) {
  819.         LastError =
  820.             d3dappi.lpFrontBuffer->lpVtbl->Blt(d3dappi.lpFrontBuffer,
  821.                                      &front[i], d3dappi.lpBackBuffer,
  822.                          &buffer[i], DDBLT_WAIT, NULL);
  823.         if (LastError == DDERR_SURFACELOST) {
  824.         d3dappi.lpFrontBuffer->lpVtbl->Restore(d3dappi.lpFrontBuffer);
  825.         d3dappi.lpBackBuffer->lpVtbl->Restore(d3dappi.lpBackBuffer);
  826.         D3DAppIClearBuffers();
  827.         } else if (LastError != DD_OK) {
  828.         D3DAppISetErrorString("Blt of back buffer to front buffer failed.\n%s", D3DAppErrorToString(LastError));
  829.         return FALSE;
  830.         }
  831.     }
  832.     /*
  833.      * The back buffer's dirty rectangles are now also the client's
  834.      */
  835.     D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
  836.                 NumDirtyBackRects, DirtyBack);
  837.     }
  838.     return TRUE;
  839. }
  840.  
  841. /*
  842.  * D3DAppRenderExtents
  843.  */
  844. BOOL
  845. D3DAppRenderExtents(DWORD dwCount, LPD3DRECT extent, DWORD flags)
  846. {
  847.     if (dwCount > D3DAPP_MAXCLEARRECTS) {
  848.     D3DAppISetErrorString("The number of clear rectangles exceeded D3DAPP_MAXCLEARRECTS.");
  849.     return FALSE;
  850.     }
  851.     if (flags & D3DAPP_CLEARALL) {
  852.     /*
  853.      * Set the back buffer dirty rectangle to the entire client area
  854.      */
  855.     D3DRECT dummy;
  856.     dummy.x1 = dummy.y1 = 0;
  857.     dummy.x2 = d3dappi.szClient.cx;
  858.     dummy.y2 = d3dappi.szClient.cy;
  859.     D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, 1, &dummy);
  860.     D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient, 1, &dummy);
  861.     D3DAppICopyRectList(&NumDirtyZRects, DirtyZ, 1, &dummy);
  862.     } else {
  863.     /*
  864.      * Set the back and Z buffer dirty rectangle list as specified
  865.      */
  866.     D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, dwCount, extent);
  867.     D3DAppICopyRectList(&NumDirtyZRects, DirtyZ, dwCount, extent);
  868.     }
  869.     return TRUE;
  870. }
  871.  
  872. /*
  873.  * D3DAppClearBackBuffer
  874.  */
  875. BOOL
  876. D3DAppClearBackBuffer(DWORD flags)
  877. {
  878.     if (!d3dappi.bRenderingIsOK) {
  879.     D3DAppISetErrorString("Cannot call D3DAppClearBackBuffer while bRenderingIsOK is FALSE.\n");
  880.     return FALSE;
  881.     }
  882.     if (flags & D3DAPP_CLEARALL) {
  883.     /*
  884.      * Clear the entire back buffer
  885.      */
  886.     int clearflags;
  887.     D3DRECT dummy;
  888.     /*
  889.      * Decided wether to clear just back buffer or also z-buffer
  890.      */
  891.     clearflags = D3DCLEAR_TARGET;
  892.     if (d3dapprs.bZBufferOn)
  893.         clearflags |= D3DCLEAR_ZBUFFER;
  894.     dummy.x1 = dummy.y1 = 0;
  895.     dummy.x2 = d3dappi.szClient.cx;
  896.     dummy.y2 = d3dappi.szClient.cy;
  897.     LastError =
  898.               d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
  899.                                1, &dummy,
  900.                                clearflags);
  901.     if (LastError != D3D_OK) {
  902.         D3DAppISetErrorString("Viewport clear failed.\n%s",
  903.                           D3DAppErrorToString(LastError));
  904.         return FALSE;
  905.     }
  906.     } else {
  907.     /*
  908.      * Clear the dirty rectangles on the back buffer
  909.      */
  910.     LastError =
  911.               d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
  912.                                                NumDirtyBackRects,
  913.                               DirtyBack, D3DCLEAR_TARGET);
  914.     if (LastError != D3D_OK) {
  915.         D3DAppISetErrorString("Viewport clear of back buffer failed.\n%s",
  916.                           D3DAppErrorToString(LastError));
  917.         return FALSE;
  918.     }
  919.     /*
  920.      * Clear the dirty rectangles on the Z buffer
  921.      */
  922.     LastError =
  923.               d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
  924.                                                NumDirtyZRects,
  925.                               DirtyZ, D3DCLEAR_ZBUFFER);
  926.     if (LastError != D3D_OK) {
  927.         D3DAppISetErrorString("Viewport clear of Z buffer failed.\n%s",
  928.                           D3DAppErrorToString(LastError));
  929.         return FALSE;
  930.     }
  931.  
  932.     }
  933.     return TRUE;
  934. }
  935.  
  936. /*
  937.  * D3DAppCheckForLostSurfaces
  938.  */
  939. #define CHECKSURF(x) if (x) {                            \
  940.             if (x->lpVtbl->IsLost(x) == DDERR_SURFACELOST) {    \
  941.                 LastError = x->lpVtbl->Restore(x);            \
  942.                 if (LastError != DD_OK) goto exit_with_error;   \
  943.                 b = TRUE;                        \
  944.             }                            \
  945.              }
  946. BOOL
  947. D3DAppCheckForLostSurfaces(void)
  948. {
  949.     int i;
  950.     BOOL b = FALSE;
  951.     /*
  952.      * Check all the surfaces D3DApp owns and restore them if lost.
  953.      */
  954.     CHECKSURF(d3dappi.lpFrontBuffer);
  955.     CHECKSURF(d3dappi.lpBackBuffer);
  956.     CHECKSURF(d3dappi.lpZBuffer);
  957.     if (b) {
  958.     /*
  959.      * If any of the surfaces were lost and restored, clear all the buffers.
  960.      * If this fails, that's fine, just move on.
  961.      */
  962.     D3DAppIClearBuffers();
  963.     }
  964.     for (i = 0; i < d3dappi.NumUsableTextures; i++) {
  965.     b = FALSE;
  966.     CHECKSURF(d3dappi.lpTextureSurf[i]);
  967.     if (b) {
  968.         ATTEMPT(D3DAppIReloadTextureSurf(i));
  969.     }
  970.     }
  971.     return TRUE;
  972.  
  973. exit_with_error:
  974.     D3DAppISetErrorString("Restoring of a lost surface failed.\n%s",
  975.                   D3DAppErrorToString(LastError));
  976.     return FALSE;
  977. }
  978.  
  979. /*
  980.  * D3DAppPause
  981.  */
  982. BOOL
  983. D3DAppPause(BOOL flag)
  984. {
  985.     static int pausecount;
  986.  
  987.     /*
  988.      * Keep a count of the number of times D3DAppPause has been called to 
  989.      * prevent pausing more than once in a row.
  990.      */
  991.     if (pausecount != 0) {
  992.     if (flag) {
  993.         ++pausecount;
  994.         return TRUE;
  995.     } else {
  996.         --pausecount;
  997.         if (pausecount != 0)
  998.         return TRUE;
  999.     } 
  1000.     }
  1001.  
  1002.     d3dappi.bPaused = flag;
  1003.     if (!flag) {
  1004.     /*
  1005.      * Returning from a pause
  1006.      */
  1007.         if (d3dappi.bFullscreen && bPrimaryPalettized && lpPalette) {
  1008.         /*
  1009.          * Set front buffer's palette back to what it was before pause
  1010.          */
  1011.             LastError = lpPalette->lpVtbl->SetEntries(lpPalette, 0, 0, 256,
  1012.                               &ppe[0]);
  1013.         if (LastError != DD_OK) {
  1014.         D3DAppISetErrorString("Setting palette entries during unpause failed.\n%s", D3DAppErrorToString(LastError));
  1015.         goto exit_with_error;
  1016.         }
  1017.         }
  1018.     /*
  1019.      * Dirty rectangle info is no longer valid
  1020.      */
  1021.     D3DAppIValidateDirtyRects();
  1022.     }
  1023.     if (flag && d3dappi.bFullscreen) {
  1024.     /*
  1025.      * Pausing in a fullscreen mode
  1026.      */
  1027.         if (bPrimaryPalettized && lpPalette) {
  1028.         /*
  1029.          * Save the front buffer's current palette and restore the
  1030.          * original Windows palette.
  1031.          */
  1032.             int i;
  1033.             LastError = lpPalette->lpVtbl->GetEntries(lpPalette, 0, 0, 256,
  1034.                               &ppe[0]);
  1035.         if (LastError != DD_OK) {
  1036.         D3DAppISetErrorString("Getting palette entries before a pause failed.\n%s", D3DAppErrorToString(LastError));
  1037.         goto exit_with_error;
  1038.         }
  1039.             for (i = 10; i < 246; i++)
  1040.                 Originalppe[i] = ppe[i];
  1041.             LastError = lpPalette->lpVtbl->SetEntries(lpPalette, 0, 0, 256,
  1042.                                &Originalppe[0]);
  1043.         if (LastError != DD_OK) {
  1044.         D3DAppISetErrorString("Returning palette entries to defaults failed.\n%s", D3DAppErrorToString(LastError));
  1045.         goto exit_with_error;
  1046.         }
  1047.         }
  1048.     /*
  1049.      * Flip to GDI surface (either front or back buffer)
  1050.      */
  1051.         if (d3dappi.lpDD) {
  1052.             LastError = d3dappi.lpDD->lpVtbl->FlipToGDISurface(d3dappi.lpDD);
  1053.         if (LastError != DD_OK) {
  1054.         D3DAppISetErrorString("Flipping to GDI surface failed.\n%s", D3DAppErrorToString(LastError));
  1055.         goto exit_with_error;
  1056.         }
  1057.     }
  1058.     /*
  1059.      * Draw the menu and frame
  1060.      */
  1061.         DrawMenuBar(d3dappi.hwnd);
  1062.         RedrawWindow(d3dappi.hwnd, NULL, NULL, RDW_FRAME);
  1063.     }
  1064.     return TRUE;
  1065. exit_with_error:
  1066.     return FALSE;
  1067. }
  1068.  
  1069. /*
  1070.  * D3DAppCreateSurface
  1071.  */
  1072. BOOL
  1073. D3DAppCreateSurface(DDSURFACEDESC *ddsd, LPDIRECTDRAWSURFACE *lplpSurf)
  1074. {
  1075.     return D3DAppICreateSurface(ddsd, lplpSurf);
  1076. }
  1077.  
  1078. /*
  1079.  * D3DAppLastError
  1080.  */
  1081. HRESULT
  1082. D3DAppLastError(void)
  1083. {
  1084.     return LastError;  
  1085. }
  1086.  
  1087. /*
  1088.  * D3DAppLastD3DAppISetErrorString
  1089.  */
  1090. char*
  1091. D3DAppLastErrorString(void)
  1092. {
  1093.     return LastErrorString;
  1094. }
  1095.  
  1096.  
  1097. /*
  1098.  * D3DAppDestroy
  1099.  */
  1100. BOOL
  1101. D3DAppDestroy(void)
  1102. {
  1103.     /*
  1104.      * Destroys all objects including Direct Draw.
  1105.      */
  1106.     d3dappi.bRenderingIsOK = FALSE;
  1107.     d3dappi.hwnd = NULL;
  1108.     ATTEMPT(D3DAppICallDeviceDestroyCallback());
  1109.     D3DAppIReleaseAllTextures();
  1110.     RELEASE(d3dappi.lpD3DDevice);
  1111.     RELEASE(d3dappi.lpZBuffer);
  1112.     RELEASE(lpPalette);
  1113.     RELEASE(lpClipper);
  1114.     RELEASE(d3dappi.lpBackBuffer);
  1115.     RELEASE(d3dappi.lpFrontBuffer);
  1116.     if (d3dappi.bFullscreen) {
  1117.     D3DAppIRestoreDispMode();
  1118.     D3DAppISetCoopLevel(d3dappi.hwnd, FALSE);
  1119.     }
  1120.     D3DAppIReleasePathList();
  1121.     RELEASE(d3dappi.lpD3D);
  1122.     RELEASE(d3dappi.lpDD);
  1123.     return TRUE;
  1124. exit_with_error:
  1125.     return FALSE;
  1126. }
  1127.  
  1128.  
  1129. /*
  1130.  * D3DAppErrorToString
  1131.  */
  1132. char*
  1133. D3DAppErrorToString(HRESULT error)
  1134. {
  1135.     switch(error) {
  1136.         case DD_OK:
  1137.             return "No error.\0";
  1138.         case DDERR_ALREADYINITIALIZED:
  1139.             return "This object is already initialized.\0";
  1140.         case DDERR_BLTFASTCANTCLIP:
  1141.             return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
  1142.         case DDERR_CANNOTATTACHSURFACE:
  1143.             return "This surface can not be attached to the requested surface.\0";
  1144.         case DDERR_CANNOTDETACHSURFACE:
  1145.             return "This surface can not be detached from the requested surface.\0";
  1146.         case DDERR_CANTCREATEDC:
  1147.             return "Windows can not create any more DCs.\0";
  1148.         case DDERR_CANTDUPLICATE:
  1149.             return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
  1150.         case DDERR_CLIPPERISUSINGHWND:
  1151.             return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
  1152.         case DDERR_COLORKEYNOTSET:
  1153.             return "No src color key specified for this operation.\0";
  1154.         case DDERR_CURRENTLYNOTAVAIL:
  1155.             return "Support is currently not available.\0";
  1156.         case DDERR_DIRECTDRAWALREADYCREATED:
  1157.             return "A DirectDraw object representing this driver has already been created for this process.\0";
  1158.         case DDERR_EXCEPTION:
  1159.             return "An exception was encountered while performing the requested operation.\0";
  1160.         case DDERR_EXCLUSIVEMODEALREADYSET:
  1161.             return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
  1162.         case DDERR_GENERIC:
  1163.             return "Generic failure.\0";
  1164.         case DDERR_HEIGHTALIGN:
  1165.             return "Height of rectangle provided is not a multiple of reqd alignment.\0";
  1166.         case DDERR_HWNDALREADYSET:
  1167.             return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
  1168.         case DDERR_HWNDSUBCLASSED:
  1169.             return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
  1170.         case DDERR_IMPLICITLYCREATED:
  1171.             return "This surface can not be restored because it is an implicitly created surface.\0";
  1172.         case DDERR_INCOMPATIBLEPRIMARY:
  1173.             return "Unable to match primary surface creation request with existing primary surface.\0";
  1174.         case DDERR_INVALIDCAPS:
  1175.             return "One or more of the caps bits passed to the callback are incorrect.\0";
  1176.         case DDERR_INVALIDCLIPLIST:
  1177.             return "DirectDraw does not support the provided cliplist.\0";
  1178.         case DDERR_INVALIDDIRECTDRAWGUID:
  1179.             return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
  1180.         case DDERR_INVALIDMODE:
  1181.             return "DirectDraw does not support the requested mode.\0";
  1182.         case DDERR_INVALIDOBJECT:
  1183.             return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
  1184.         case DDERR_INVALIDPARAMS:
  1185.             return "One or more of the parameters passed to the function are incorrect.\0";
  1186.         case DDERR_INVALIDPIXELFORMAT:
  1187.             return "The pixel format was invalid as specified.\0";
  1188.         case DDERR_INVALIDPOSITION:
  1189.             return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
  1190.         case DDERR_INVALIDRECT:
  1191.             return "Rectangle provided was invalid.\0";
  1192.         case DDERR_LOCKEDSURFACES:
  1193.             return "Operation could not be carried out because one or more surfaces are locked.\0";
  1194.         case DDERR_NO3D:
  1195.             return "There is no 3D present.\0";
  1196.         case DDERR_NOALPHAHW:
  1197.             return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
  1198.         case DDERR_NOBLTHW:
  1199.             return "No blitter hardware present.\0";
  1200.         case DDERR_NOCLIPLIST:
  1201.             return "No cliplist available.\0";
  1202.         case DDERR_NOCLIPPERATTACHED:
  1203.             return "No clipper object attached to surface object.\0";
  1204.         case DDERR_NOCOLORCONVHW:
  1205.             return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
  1206.         case DDERR_NOCOLORKEY:
  1207.             return "Surface doesn't currently have a color key\0";
  1208.         case DDERR_NOCOLORKEYHW:
  1209.             return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
  1210.         case DDERR_NOCOOPERATIVELEVELSET:
  1211.             return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
  1212.         case DDERR_NODC:
  1213.             return "No DC was ever created for this surface.\0";
  1214.         case DDERR_NODDROPSHW:
  1215.             return "No DirectDraw ROP hardware.\0";
  1216.         case DDERR_NODIRECTDRAWHW:
  1217.             return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
  1218.         case DDERR_NOEMULATION:
  1219.             return "Software emulation not available.\0";
  1220.         case DDERR_NOEXCLUSIVEMODE:
  1221.             return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
  1222.         case DDERR_NOFLIPHW:
  1223.             return "Flipping visible surfaces is not supported.\0";
  1224.         case DDERR_NOGDI:
  1225.             return "There is no GDI present.\0";
  1226.         case DDERR_NOHWND:
  1227.             return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
  1228.         case DDERR_NOMIRRORHW:
  1229.             return "Operation could not be carried out because there is no hardware present or available.\0";
  1230.         case DDERR_NOOVERLAYDEST:
  1231.             return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
  1232.         case DDERR_NOOVERLAYHW:
  1233.             return "Operation could not be carried out because there is no overlay hardware present or available.\0";
  1234.         case DDERR_NOPALETTEATTACHED:
  1235.             return "No palette object attached to this surface.\0";
  1236.         case DDERR_NOPALETTEHW:
  1237.             return "No hardware support for 16 or 256 color palettes.\0";
  1238.         case DDERR_NORASTEROPHW:
  1239.             return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
  1240.         case DDERR_NOROTATIONHW:
  1241.             return "Operation could not be carried out because there is no rotation hardware present or available.\0";
  1242.         case DDERR_NOSTRETCHHW:
  1243.             return "Operation could not be carried out because there is no hardware support for stretching.\0";
  1244.         case DDERR_NOT4BITCOLOR:
  1245.             return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
  1246.         case DDERR_NOT4BITCOLORINDEX:
  1247.             return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
  1248.         case DDERR_NOT8BITCOLOR:
  1249.             return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
  1250.         case DDERR_NOTAOVERLAYSURFACE:
  1251.             return "Returned when an overlay member is called for a non-overlay surface.\0";
  1252.         case DDERR_NOTEXTUREHW:
  1253.             return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
  1254.         case DDERR_NOTFLIPPABLE:
  1255.             return "An attempt has been made to flip a surface that is not flippable.\0";
  1256.         case DDERR_NOTFOUND:
  1257.             return "Requested item was not found.\0";
  1258.         case DDERR_NOTLOCKED:
  1259.             return "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
  1260.         case DDERR_NOTPALETTIZED:
  1261.             return "The surface being used is not a palette-based surface.\0";
  1262.         case DDERR_NOVSYNCHW:
  1263.             return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
  1264.         case DDERR_NOZBUFFERHW:
  1265.             return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
  1266.         case DDERR_NOZOVERLAYHW:
  1267.             return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
  1268.         case DDERR_OUTOFCAPS:
  1269.             return "The hardware needed for the requested operation has already been allocated.\0";
  1270.         case DDERR_OUTOFMEMORY:
  1271.             return "DirectDraw does not have enough memory to perform the operation.\0";
  1272.         case DDERR_OUTOFVIDEOMEMORY:
  1273.             return "DirectDraw does not have enough memory to perform the operation.\0";
  1274.         case DDERR_OVERLAYCANTCLIP:
  1275.             return "The hardware does not support clipped overlays.\0";
  1276.         case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
  1277.             return "Can only have ony color key active at one time for overlays.\0";
  1278.         case DDERR_OVERLAYNOTVISIBLE:
  1279.             return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
  1280.         case DDERR_PALETTEBUSY:
  1281.             return "Access to this palette is being refused because the palette is already locked by another thread.\0";
  1282.         case DDERR_PRIMARYSURFACEALREADYEXISTS:
  1283.             return "This process already has created a primary surface.\0";
  1284.         case DDERR_REGIONTOOSMALL:
  1285.             return "Region passed to Clipper::GetClipList is too small.\0";
  1286.         case DDERR_SURFACEALREADYATTACHED:
  1287.             return "This surface is already attached to the surface it is being attached to.\0";
  1288.         case DDERR_SURFACEALREADYDEPENDENT:
  1289.             return "This surface is already a dependency of the surface it is being made a dependency of.\0";
  1290.         case DDERR_SURFACEBUSY:
  1291.             return "Access to this surface is being refused because the surface is already locked by another thread.\0";
  1292.         case DDERR_SURFACEISOBSCURED:
  1293.             return "Access to surface refused because the surface is obscured.\0";
  1294.         case DDERR_SURFACELOST:
  1295.             return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
  1296.         case DDERR_SURFACENOTATTACHED:
  1297.             return "The requested surface is not attached.\0";
  1298.         case DDERR_TOOBIGHEIGHT:
  1299.             return "Height requested by DirectDraw is too large.\0";
  1300.         case DDERR_TOOBIGSIZE:
  1301.             return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
  1302.         case DDERR_TOOBIGWIDTH:
  1303.             return "Width requested by DirectDraw is too large.\0";
  1304.         case DDERR_UNSUPPORTED:
  1305.             return "Action not supported.\0";
  1306.         case DDERR_UNSUPPORTEDFORMAT:
  1307.             return "FOURCC format requested is unsupported by DirectDraw.\0";
  1308.         case DDERR_UNSUPPORTEDMASK:
  1309.             return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
  1310.         case DDERR_VERTICALBLANKINPROGRESS:
  1311.             return "Vertical blank is in progress.\0";
  1312.         case DDERR_WASSTILLDRAWING:
  1313.             return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
  1314.         case DDERR_WRONGMODE:
  1315.             return "This surface can not be restored because it was created in a different mode.\0";
  1316.         case DDERR_XALIGN:
  1317.             return "Rectangle provided was not horizontally aligned on required boundary.\0";
  1318.         case D3DERR_BADMAJORVERSION:
  1319.             return "D3DERR_BADMAJORVERSION\0";
  1320.         case D3DERR_BADMINORVERSION:
  1321.             return "D3DERR_BADMINORVERSION\0";
  1322.         case D3DERR_EXECUTE_LOCKED:
  1323.             return "D3DERR_EXECUTE_LOCKED\0";
  1324.         case D3DERR_EXECUTE_NOT_LOCKED:
  1325.             return "D3DERR_EXECUTE_NOT_LOCKED\0";
  1326.         case D3DERR_EXECUTE_CREATE_FAILED:
  1327.             return "D3DERR_EXECUTE_CREATE_FAILED\0";
  1328.         case D3DERR_EXECUTE_DESTROY_FAILED:
  1329.             return "D3DERR_EXECUTE_DESTROY_FAILED\0";
  1330.         case D3DERR_EXECUTE_LOCK_FAILED:
  1331.             return "D3DERR_EXECUTE_LOCK_FAILED\0";
  1332.         case D3DERR_EXECUTE_UNLOCK_FAILED:
  1333.             return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
  1334.         case D3DERR_EXECUTE_FAILED:
  1335.             return "D3DERR_EXECUTE_FAILED\0";
  1336.         case D3DERR_EXECUTE_CLIPPED_FAILED:
  1337.             return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
  1338.         case D3DERR_TEXTURE_NO_SUPPORT:
  1339.             return "D3DERR_TEXTURE_NO_SUPPORT\0";
  1340.         case D3DERR_TEXTURE_NOT_LOCKED:
  1341.             return "D3DERR_TEXTURE_NOT_LOCKED\0";
  1342.         case D3DERR_TEXTURE_LOCKED:
  1343.             return "D3DERR_TEXTURELOCKED\0";
  1344.         case D3DERR_TEXTURE_CREATE_FAILED:
  1345.             return "D3DERR_TEXTURE_CREATE_FAILED\0";
  1346.         case D3DERR_TEXTURE_DESTROY_FAILED:
  1347.             return "D3DERR_TEXTURE_DESTROY_FAILED\0";
  1348.         case D3DERR_TEXTURE_LOCK_FAILED:
  1349.             return "D3DERR_TEXTURE_LOCK_FAILED\0";
  1350.         case D3DERR_TEXTURE_UNLOCK_FAILED:
  1351.             return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
  1352.         case D3DERR_TEXTURE_LOAD_FAILED:
  1353.             return "D3DERR_TEXTURE_LOAD_FAILED\0";
  1354.         case D3DERR_MATRIX_CREATE_FAILED:
  1355.             return "D3DERR_MATRIX_CREATE_FAILED\0";
  1356.         case D3DERR_MATRIX_DESTROY_FAILED:
  1357.             return "D3DERR_MATRIX_DESTROY_FAILED\0";
  1358.         case D3DERR_MATRIX_SETDATA_FAILED:
  1359.             return "D3DERR_MATRIX_SETDATA_FAILED\0";
  1360.         case D3DERR_SETVIEWPORTDATA_FAILED:
  1361.             return "D3DERR_SETVIEWPORTDATA_FAILED\0";
  1362.         case D3DERR_MATERIAL_CREATE_FAILED:
  1363.             return "D3DERR_MATERIAL_CREATE_FAILED\0";
  1364.         case D3DERR_MATERIAL_DESTROY_FAILED:
  1365.             return "D3DERR_MATERIAL_DESTROY_FAILED\0";
  1366.         case D3DERR_MATERIAL_SETDATA_FAILED:
  1367.             return "D3DERR_MATERIAL_SETDATA_FAILED\0";
  1368.         case D3DERR_LIGHT_SET_FAILED:
  1369.             return "D3DERR_LIGHT_SET_FAILED\0";
  1370.         default:
  1371.             return "Unrecognized error value.\0";
  1372.     }
  1373. }
  1374.