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