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 / d3dmain.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  41KB  |  1,274 lines

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: d3dmain.cpp
  5.  *
  6.  *  Each of the Direct3D samples must be linked with this file.  It contains
  7.  *  the code which allows them to run in the Windows environment.
  8.  *
  9.  *  A window is created using d3dmain.res which allows the user to select the
  10.  *  Direct3D driver to use and change the render options.  The D3DApp
  11.  *  collection of functions is used to initialize DirectDraw, Direct3D and
  12.  *  keep surfaces and D3D devices available for rendering.
  13.  *
  14.  *  Frame rate and a screen mode information buffer is Blt'ed to the screen
  15.  *  by functions in stats.cpp.
  16.  *
  17.  *  Each sample is executed through the functions: InitScene, InitView,
  18.  *  RenderScene, ReleaseView, ReleaseScene and OverrideDefaults, as described
  19.  *  in d3ddemo.h.  Samples can also read mouse and keyboard input via
  20.  *  SetMouseCallback and SetKeyboardCallback.
  21.  */
  22.  
  23. #include "d3dmain.h"
  24.  
  25. /*
  26.  * GLOBAL VARIABLES
  27.  */
  28. D3DAppInfo* d3dapp;        /* Pointer to read only collection of DD and D3D
  29.                    objects maintained by D3DApp */
  30. d3dmainglobals myglobs;        /* collection of global variables */
  31.  
  32. BOOL(*MouseHandler)(UINT, WPARAM, LPARAM);    /* sample's function which traps
  33.                          mouse input */
  34. BOOL(*KeyboardHandler)(UINT, WPARAM, LPARAM); /* sample's functions which traps
  35.                                                  keyboard input */
  36.  
  37. /*
  38.  *  INTERNAL FUNCTION PROTOTYPES
  39.  */
  40. static BOOL AppInit(HINSTANCE hInstance, LPSTR lpCmdLine);
  41. static BOOL CreateD3DApp(LPSTR lpCmdLine);
  42. static BOOL BeforeDeviceDestroyed(LPVOID lpContext);
  43. static BOOL AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT2* lpViewport,
  44.                    LPVOID lpContext);
  45. void CleanUpAndPostQuit(void);
  46. static void InitGlobals(void);
  47. static BOOL AppPause(BOOL f);
  48. void ReportD3DAppError(void);
  49. static BOOL RenderLoop(void);
  50. static BOOL RestoreSurfaces();
  51. long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  52.                LPARAM lParam );
  53.  
  54. /****************************************************************************/
  55. /*                            WinMain                                       */
  56. /****************************************************************************/
  57. /*
  58.  * Initializes the application then enters a message loop which calls sample's
  59.  * RenderScene until a quit message is received.
  60.  */
  61. int PASCAL
  62. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  63.     int nCmdShow)
  64. {
  65.     int failcount = 0; /* number of times RenderLoop has failed */
  66.     MSG    msg;
  67.     HACCEL hAccelApp;
  68.  
  69.     hPrevInstance;
  70.     /*
  71.      * Create the window and initialize all objects needed to begin rendering
  72.      */
  73.     if(!AppInit(hInstance, lpCmdLine))
  74.         return FALSE;
  75.     hAccelApp = LoadAccelerators(hInstance, "AppAccel");    
  76.  
  77.     while (!myglobs.bQuit) {
  78.     /* 
  79.      * Monitor the message queue until there are no pressing
  80.      * messages
  81.      */
  82.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  83.             if (msg.message == WM_QUIT) {
  84.         CleanUpAndPostQuit();
  85.                 break;
  86.         }
  87.             if (!myglobs.hWndMain || !TranslateAccelerator(myglobs.hWndMain,
  88.                                hAccelApp, &msg)) {
  89.                 TranslateMessage(&msg); 
  90.                 DispatchMessage(&msg);
  91.             }
  92.     /* 
  93.      * If the app is not minimized, not about to quit, not paused, either the
  94.      * active fullscreen app or in a window and D3D has been initialized,
  95.      * we can render
  96.      */
  97.         } else if (d3dapp->bRenderingIsOK && !d3dapp->bMinimized 
  98.            && !d3dapp->bPaused && !myglobs.bQuit
  99.            && (d3dapp->bAppActive || !d3dapp->bFullscreen)) {
  100.         /*
  101.          * If were are not in single step mode or if we are and the
  102.          * bDrawAFrame flag is set, render one frame
  103.          */
  104.             if (!(myglobs.bSingleStepMode && !myglobs.bDrawAFrame)) {
  105.         /* 
  106.          * Attempt to render a frame, if it fails, take a note.  If
  107.          * rendering fails more than twice, abort execution.
  108.          */
  109.         if (!RenderLoop()) {
  110.             ++failcount;
  111.             if (failcount == 3) {
  112.             Msg("Rendering has failed too many times.  Aborting execution.\n");
  113.             CleanUpAndPostQuit();
  114.             break;
  115.             }
  116.         }
  117.         }
  118.         /*
  119.          * Reset the bDrawAFrame flag if we are in single step mode
  120.          */
  121.             if (myglobs.bSingleStepMode)
  122.                 myglobs.bDrawAFrame = FALSE;
  123.         } else {
  124.             WaitMessage();
  125.     }
  126.     }
  127.  
  128.     DestroyWindow(myglobs.hWndMain);
  129.     return msg.wParam;
  130. }
  131.  
  132. /****************************************************************************/
  133. /*             D3DApp Initialization and callback functions                 */
  134. /****************************************************************************/
  135. /*
  136.  * AppInit
  137.  * Creates the window and initializes all objects necessary to begin rendering
  138.  */
  139. static BOOL
  140. AppInit(HINSTANCE hInstance, LPSTR lpCmdLine)
  141. {
  142.     WNDCLASS wc;
  143.  
  144.     /*
  145.      * Initialize the global variables
  146.      */
  147.     InitGlobals();
  148.     myglobs.hInstApp = hInstance;
  149.     /*
  150.      * Register the window class
  151.      */
  152.     wc.style = CS_HREDRAW | CS_VREDRAW;
  153.     wc.lpfnWndProc = WindowProc;
  154.     wc.cbClsExtra = 0;
  155.     wc.cbWndExtra = 0;
  156.     wc.hInstance = hInstance;
  157.     wc.hIcon = LoadIcon( hInstance, "AppIcon");
  158.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  159.     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  160.     wc.lpszMenuName = "AppMenu";
  161.     wc.lpszClassName = "Example";
  162.     if (!RegisterClass(&wc))
  163.         return FALSE;
  164.     /*
  165.      * Create a window with some default settings that may change
  166.      */
  167.     myglobs.hWndMain = CreateWindowEx(
  168.          WS_EX_APPWINDOW,
  169.      "Example",
  170.      "D3D Example",
  171.      WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
  172.      WS_THICKFRAME | WS_MINIMIZEBOX,
  173.          CW_USEDEFAULT, CW_USEDEFAULT,
  174.      START_WIN_SIZE, START_WIN_SIZE,
  175.          NULL,                    /* parent window */
  176.      NULL,                    /* menu handle */
  177.      hInstance,                /* program handle */
  178.      NULL);                    /* create parms */    
  179.     if (!myglobs.hWndMain){
  180.         Msg("CreateWindowEx failed");
  181.         return FALSE;
  182.     }
  183.     /*
  184.      * Display the window
  185.      */
  186.     ShowWindow(myglobs.hWndMain, SW_SHOWNORMAL);
  187.     UpdateWindow(myglobs.hWndMain);
  188.     /* 
  189.      * Have the example initialize it components which remain constant
  190.      * throughout execution
  191.      */
  192.     if (!InitScene())
  193.         return FALSE;
  194.     /*
  195.      * Call D3DApp to initialize all DD and D3D objects necessary to render.
  196.      * D3DApp will call the device creation callback which will initialize the
  197.      * viewport and the sample's execute buffers.
  198.      */
  199.     if (!CreateD3DApp(lpCmdLine))
  200.     return FALSE;
  201.  
  202.     return TRUE;
  203. }
  204.  
  205. /*
  206.  * CreateD3DApp
  207.  * Create all DirectDraw and Direct3D objects necessary to begin rendering.
  208.  * Add the list of D3D drivers to the file menu.
  209.  */
  210. static BOOL
  211. CreateD3DApp(LPSTR lpCmdLine)
  212. {
  213.     HMENU hmenu;
  214.     int i;
  215.     LPSTR option;
  216.     BOOL bOnlySystemMemory, bOnlyEmulation;
  217.     DWORD flags;
  218.     Defaults defaults;
  219.  
  220.     /*
  221.      * Give D3DApp a list of textures to keep track of.
  222.      */
  223.     D3DAppAddTexture("checker.ppm");
  224.     D3DAppAddTexture("tex2.ppm");
  225.     D3DAppAddTexture("tex7.ppm");
  226.     D3DAppAddTexture("win95.ppm");
  227.     /*
  228.      * Parse the command line in seach of one of the following options:
  229.      *     systemmemory  All surfaces should be created in system memory.
  230.      *                   Hardware DD and D3D devices are disabled, but
  231.      *                   debugging during the Win16 lock becomes possible.
  232.      *     emulation     Do not use hardware DD or D3D devices.
  233.      */
  234.     bOnlySystemMemory = FALSE;
  235.     bOnlyEmulation = FALSE;
  236.     option = strtok(lpCmdLine, " -");
  237.     while(option != NULL )   {
  238.         if (!lstrcmp(option, "systemmemory")) {
  239.             bOnlySystemMemory = TRUE;
  240.         } else if (!lstrcmp(option, "emulation")) {
  241.         bOnlyEmulation = TRUE;
  242.     } else {
  243.             Msg("Invalid command line options given.\nLegal options: -systemmemory, -emulation\n");
  244.             return FALSE;
  245.         }
  246.         option = strtok(NULL, " -");
  247.     }
  248.     /*
  249.      * Set the flags to pass to the D3DApp creation based on command line
  250.      */
  251.     flags = ((bOnlySystemMemory) ? D3DAPP_ONLYSYSTEMMEMORY : 0) | 
  252.         ((bOnlyEmulation) ? (D3DAPP_ONLYD3DEMULATION |
  253.                  D3DAPP_ONLYDDEMULATION) : 0);
  254.     /*
  255.      * Create all the DirectDraw and D3D objects neccesary to render.  The
  256.      * AfterDeviceCreated callback function is called by D3DApp to create the
  257.      * viewport and the example's execute buffers.
  258.      */
  259.     if (!D3DAppCreateFromHWND(flags, myglobs.hWndMain, AfterDeviceCreated,
  260.                   NULL, BeforeDeviceDestroyed, NULL, &d3dapp)) {
  261.     ReportD3DAppError();
  262.     return FALSE;
  263.     }
  264.     /*
  265.      * Add the the list of display modes D3DApp found to the mode menu
  266.      */
  267.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 4);
  268.     for (i = 0; i < d3dapp->NumModes; i++) {
  269.         char ach[80];
  270.         wsprintf(ach,"%dx%dx%d", d3dapp->Mode[i].w, d3dapp->Mode[i].h,
  271.          d3dapp->Mode[i].bpp);
  272.         AppendMenu(hmenu, MF_STRING, MENU_FIRST_MODE+i, ach);
  273.     }
  274.     /*
  275.      * Add the list of D3D drivers D3DApp foudn to the file menu
  276.      */
  277.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 0);
  278.     for (i = 0; i < d3dapp->NumDrivers; i++) {
  279.         InsertMenu(hmenu, 6 + i, MF_BYPOSITION | MF_STRING,
  280.            MENU_FIRST_DRIVER + i, d3dapp->Driver[i].Name);
  281.     }
  282.     /*
  283.      * Allow the sample to override the default render state and other
  284.      * settings
  285.      */
  286.     if (!D3DAppGetRenderState(&defaults.rs)) {
  287.     ReportD3DAppError();
  288.     return FALSE;
  289.     }
  290.     lstrcpy(defaults.Name, "D3D Example");
  291.     defaults.bTexturesDisabled = FALSE;
  292.     defaults.bResizingDisabled = myglobs.bResizingDisabled;
  293.     defaults.bClearsOn = myglobs.bClearsOn;
  294.     OverrideDefaults(&defaults);
  295.     myglobs.bClearsOn = defaults.bClearsOn;
  296.     myglobs.bResizingDisabled = defaults.bResizingDisabled;
  297.     /*
  298.      * Apply any changes to the render state
  299.      */
  300.     memcpy(&myglobs.rstate, &defaults.rs, sizeof(D3DAppRenderState));
  301.     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  302.     ReportD3DAppError();
  303.     return FALSE;
  304.     }
  305.     /*
  306.      * If I should begin with textures off, disable them and re-create
  307.      * the view.
  308.      */
  309.     if (defaults.bTexturesDisabled) {
  310.     if (!D3DAppDisableTextures(defaults.bTexturesDisabled)) {
  311.         ReportD3DAppError();
  312.         return FALSE;
  313.     }
  314.     /*
  315.      * Release all objects (ie execute buffers) created by InitView
  316.      */
  317.     ReleaseView(d3dapp->lpD3DViewport);
  318.     /*
  319.      * Create the sample's execute buffers via InitView
  320.      */
  321.     if (!InitView(d3dapp->lpDD, d3dapp->lpD3D, d3dapp->lpD3DDevice,
  322.               d3dapp->lpD3DViewport, d3dapp->NumUsableTextures,
  323.               d3dapp->TextureHandle)) {
  324.         Msg("InitView failed.\n");
  325.         CleanUpAndPostQuit();
  326.         return FALSE;
  327.     }
  328.     }
  329.  
  330.     SetWindowText(myglobs.hWndMain, defaults.Name);
  331.  
  332.     return TRUE;
  333. }
  334.  
  335. /*
  336.  * AfterDeviceCreated
  337.  * D3DApp will call this function immediately after the D3D device has been
  338.  * created (or re-created).  D3DApp expects the D3D viewport to be created and
  339.  * returned.  The sample's execute buffers are also created (or re-created)
  340.  * here.
  341.  */
  342. static BOOL
  343. AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT2* lplpViewport, LPVOID lpContext)
  344. {
  345.     HMENU hmenu;
  346.     int i;
  347.     char ach[20];
  348.     LPDIRECT3DVIEWPORT2 lpD3DViewport;
  349.     HRESULT rval;
  350.  
  351.     /*
  352.      * Create the D3D viewport object
  353.      */
  354.     rval = d3dapp->lpD3D->CreateViewport(&lpD3DViewport, NULL);
  355.     if (rval != D3D_OK) {
  356.         Msg("Create D3D viewport failed.\n%s", D3DAppErrorToString(rval));
  357.     CleanUpAndPostQuit();
  358.     return FALSE;
  359.     }
  360.     /*
  361.      * Add the viewport to the D3D device
  362.      */
  363.     rval = d3dapp->lpD3DDevice->AddViewport(lpD3DViewport);
  364.     if (rval != D3D_OK) {
  365.         Msg("Add D3D viewport failed.\n%s", D3DAppErrorToString(rval));
  366.     CleanUpAndPostQuit();
  367.     return FALSE;
  368.     }
  369.     /*
  370.      * Setup the viewport for a reasonable viewing area
  371.      */
  372.     D3DVIEWPORT2 viewData;
  373.     memset(&viewData, 0, sizeof(D3DVIEWPORT2));
  374.     viewData.dwSize = sizeof(D3DVIEWPORT2);
  375.     viewData.dwX = viewData.dwY = 0;
  376.     viewData.dwWidth = w;
  377.     viewData.dwHeight = h;
  378.     viewData.dvClipX = -1.0f;
  379.     viewData.dvClipWidth = 2.0f;
  380.     viewData.dvClipHeight = h * 2.0f / w;
  381.     viewData.dvClipY = viewData.dvClipHeight / 2.0f;
  382.     viewData.dvMinZ = 0.0f;
  383.     viewData.dvMaxZ = 1.0f;
  384.     rval = lpD3DViewport->SetViewport2(&viewData);
  385.     if (rval != D3D_OK) {
  386.         Msg("SetViewport failed.\n%s", D3DAppErrorToString(rval));
  387.     CleanUpAndPostQuit();
  388.     return FALSE;
  389.     }
  390.     /*
  391.      * Return the viewport to D3DApp so it can use it
  392.      */
  393.     *lplpViewport = lpD3DViewport;
  394.     /*
  395.      * Create the sample's execute buffers via InitView
  396.      */
  397.     if (!InitView(d3dapp->lpDD, d3dapp->lpD3D, d3dapp->lpD3DDevice,
  398.           lpD3DViewport, d3dapp->NumUsableTextures,
  399.           d3dapp->TextureHandle)) {
  400.     Msg("InitView failed.\n");
  401.     CleanUpAndPostQuit();
  402.     return FALSE;
  403.     }
  404.     /*
  405.      * Add the list of texture formats found by D3DApp to the texture menu
  406.      */
  407.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 3);
  408.     for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  409.     if (d3dapp->TextureFormat[i].bPalettized) {
  410.         wsprintf(ach, "%d-bit Palettized",
  411.              d3dapp->TextureFormat[i].IndexBPP);
  412.     } else {
  413.         wsprintf(ach, "%d%d%d RGB", d3dapp->TextureFormat[i].RedBPP,
  414.              d3dapp->TextureFormat[i].GreenBPP,
  415.              d3dapp->TextureFormat[i].BlueBPP);
  416.     }
  417.         AppendMenu(hmenu, MF_STRING, MENU_FIRST_FORMAT + i, ach);
  418.     }
  419.     /*
  420.      * Create and initialize the surfaces containing the frame rate and
  421.      * window information
  422.      */
  423.     if (!InitFontAndTextBuffers()) {
  424.         Msg("InitFontAndTextBuffers failed.\n");
  425.         CleanUpAndPostQuit();
  426.         return FALSE;
  427.     }
  428.  
  429.     return TRUE;
  430. }
  431.  
  432. /*
  433.  * BeforeDeviceDestroyed
  434.  * D3DApp will call this function before the current D3D device is destroyed
  435.  * to give the app the opportunity to destroy objects it has created with the
  436.  * DD or D3D objects.
  437.  */
  438. static BOOL
  439. BeforeDeviceDestroyed(LPVOID lpContext)
  440. {
  441.     HMENU hmenu;
  442.     int i;
  443.     /*
  444.      * Release the font object and buffers containing stats
  445.      */
  446.     ReleaseFontAndTextBuffers();
  447.     /*
  448.      * Release all objects (ie execute buffers) created by InitView
  449.      */
  450.     ReleaseView(d3dapp->lpD3DViewport);
  451.     /*
  452.      * Since we created the viewport it is our responsibility to release
  453.      * it.  Use D3DApp's pointer to it since we didn't save one.
  454.      */
  455.     d3dapp->lpD3DViewport->Release();
  456.     /*
  457.      * Delete the list of texture formats from the texture menu because
  458.      * they are likely to change
  459.      */
  460.     if (myglobs.hWndMain) {
  461.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 3);
  462.     if (hmenu) {
  463.         for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  464.         DeleteMenu(hmenu, MENU_FIRST_FORMAT + i, MF_BYCOMMAND);
  465.         }
  466.     }
  467.     }
  468.     return TRUE;
  469. }
  470.  
  471. /****************************************************************************/
  472. /*                            Rendering loop                                */
  473. /****************************************************************************/
  474. /*
  475.  * RenderLoop
  476.  * Render the next frame and update the window
  477.  */
  478. static BOOL
  479. RenderLoop()
  480. {
  481.     D3DRECT extents[D3DAPP_MAXCLEARRECTS];
  482.     int count;
  483.     /*
  484.      * If all the DD and D3D objects have been initialized we can render
  485.      */
  486.     if (d3dapp->bRenderingIsOK) {
  487.     /*
  488.      * Restore any lost surfaces
  489.      */
  490.         if (!RestoreSurfaces()) {
  491.         /*
  492.          * Restoring surfaces sometimes fails because the surfaces cannot
  493.          * yet be restored.  If this is the case, the error will show up
  494.          * somewhere else and we should return success here to prevent
  495.          * unnecessary error's being reported.
  496.          */
  497.         return TRUE;
  498.     }
  499.     /*
  500.      * Calculate the frame rate
  501.      */
  502.         if (!CalculateFrameRate())
  503.         return FALSE;
  504.  
  505.         /*
  506.          * Clear the back buffer and Z buffer if enabled.  If bResized is set,
  507.      * clear the entire window.
  508.          */
  509.     if (myglobs.bClearsOn) {
  510.         if (!D3DAppClearBackBuffer(myglobs.bResized ?
  511.                        D3DAPP_CLEARALL : NULL)) {
  512.         ReportD3DAppError();
  513.         return FALSE;
  514.         }
  515.     }
  516.     /*
  517.      * Call the sample's RenderScene to render this frame
  518.      */
  519.     {
  520.         // init the extent to something wrong
  521.         extents[0].x1 = 2048;
  522.         extents[0].x2 = 0;
  523.         extents[0].y1 = 2048;
  524.         extents[0].y2 = 0;
  525.         if (!RenderScene(d3dapp->lpD3DDevice, d3dapp->lpD3DViewport,
  526.                  &extents[0])) {
  527.         Msg("RenderScene failed.\n");
  528.         return FALSE;
  529.         }
  530.         count = 1;
  531.     }
  532.     /*
  533.      * Blt the frame rate and window stat text to the back buffer
  534.      */
  535.         if (!DisplayFrameRate(&count, &extents[1]))
  536.             return FALSE;
  537.     /*
  538.      * Give D3DApp the extents so it can keep track of dirty sections of
  539.      * the back and front buffers.  Look to see if the extent from RenderScene
  540.      * changed any.  If not, skip it's dirty rect.
  541.      */
  542.  
  543.     if (extents[0].x1 == 2048.0) {    // nothing changed
  544.         if (!D3DAppRenderExtents(count-1, &extents[1], myglobs.bResized ?
  545.                      D3DAPP_CLEARALL : NULL)) {
  546.             ReportD3DAppError();
  547.             return FALSE;
  548.         }
  549.     } else {
  550.         // correct for not quite right extent behavior in some drivers
  551.         if (extents[0].x1 != 0)
  552.             extents[0].x1 -= 1;
  553.         if (extents[0].y1 != 0)
  554.             extents[0].y1 -= 1;
  555.         if (!D3DAppRenderExtents(count, extents, myglobs.bResized ?
  556.                      D3DAPP_CLEARALL : NULL)) {
  557.             ReportD3DAppError();
  558.             return FALSE;
  559.         }
  560.     }
  561.     /*
  562.      * Blt or flip the back buffer to the front buffer.  Don't report an
  563.      * error if this fails.
  564.      */
  565.     D3DAppShowBackBuffer(myglobs.bResized ? D3DAPP_SHOWALL : NULL);
  566.  
  567.     /*
  568.      * Reset the resize flag
  569.      */
  570.         myglobs.bResized = FALSE;
  571.     }
  572.     return TRUE;
  573. }
  574.  
  575. /*
  576.  * AppPause
  577.  * Pause and unpause the application
  578.  */
  579. static BOOL
  580. AppPause(BOOL f)
  581. {
  582.     /*
  583.      * Flip to the GDI surface and halt rendering
  584.      */
  585.     if (!D3DAppPause(f))
  586.     return FALSE;
  587.     /*
  588.      * When returning from a pause, reset the frame rate count
  589.      */
  590.     if (!f) {
  591.         ResetFrameRate();
  592.     }
  593.     return TRUE;
  594. }
  595.  
  596. /*
  597.  * RestoreSurfaces
  598.  * Restores any lost surfaces.  Returns TRUE if all surfaces are not lost and
  599.  * FALSE if one or more surfaces is lost and can not be restored at the
  600.  * moment.
  601.  */
  602. static BOOL
  603. RestoreSurfaces()
  604. {
  605.     HRESULT d3drval;
  606.  
  607.     /*
  608.      * Have D3DApp check all the surfaces it's in charge of
  609.      */
  610.     if (!D3DAppCheckForLostSurfaces()) {
  611.             return FALSE;
  612.     }
  613.     /*
  614.      * Check frame rate and info surfaces and re-write them if they
  615.      * were lost.
  616.      */
  617.     if (myglobs.lpFrameRateBuffer->IsLost() == DDERR_SURFACELOST) {
  618.         d3drval = myglobs.lpFrameRateBuffer->Restore();
  619.         if (d3drval != DD_OK) {
  620.             return FALSE;
  621.         }
  622.     if (!WriteFrameRateBuffer(0.0f, 0))
  623.         return FALSE;
  624.     }
  625.     if (myglobs.lpInfoBuffer->IsLost() == DDERR_SURFACELOST) {
  626.         d3drval = myglobs.lpInfoBuffer->Restore();
  627.         if (d3drval != DD_OK) {
  628.             return FALSE;
  629.         }
  630.     if (!WriteInfoBuffer())
  631.         return FALSE;
  632.     }
  633.     return TRUE;
  634. }
  635.  
  636.  
  637. /*************************************************************************
  638.   Windows message handlers
  639.  *************************************************************************/
  640. /*
  641.  * AppAbout
  642.  * About box message handler
  643.  */
  644. BOOL
  645. FAR PASCAL AppAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  646. {
  647.   switch (msg)
  648.   {
  649.     case WM_COMMAND:
  650.       if (LOWORD(wParam) == IDOK)
  651.         EndDialog(hwnd, TRUE);
  652.       break;
  653.  
  654.     case WM_INITDIALOG:
  655.       return TRUE;
  656.   }
  657.   return FALSE;
  658. }
  659.  
  660. /*
  661.  * WindowProc
  662.  * Main window message handler.
  663.  */
  664. long
  665. FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  666.                LPARAM lParam )
  667. {
  668.     int i;
  669.     BOOL bStop;
  670.     LRESULT lresult;
  671.  
  672.     /*
  673.      * Give D3DApp an opportunity to process any messages it MUST see in order
  674.      * to perform it's function.
  675.      */
  676.     if (!D3DAppWindowProc(&bStop, &lresult, hWnd, message, wParam, lParam)) {
  677.     ReportD3DAppError();
  678.     CleanUpAndPostQuit();
  679.     return 0;
  680.     }
  681.  
  682.     /*
  683.      * Prevent resizing through this message
  684.      */
  685.     if (message == WM_GETMINMAXINFO && myglobs.bResizingDisabled && !d3dapp->bFullscreen && !d3dapp->bMinimized) {
  686.     RECT rc;
  687.     GetWindowRect(hWnd, &rc);
  688.     ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = START_WIN_SIZE;
  689.     ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = START_WIN_SIZE;
  690.     ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = START_WIN_SIZE;
  691.     ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = START_WIN_SIZE;
  692.         return 0;
  693.     }
  694.  
  695.     /* 
  696.      * If bStop is set by D3DApp, the app should not process the message but
  697.      * return lresult.
  698.      */
  699.     if (bStop)
  700.     return lresult;
  701.  
  702.     switch( message ) {
  703.         case WM_MOUSEMOVE:
  704.         case WM_LBUTTONDOWN:
  705.         case WM_LBUTTONUP:
  706.         case WM_RBUTTONDOWN:
  707.         case WM_RBUTTONUP:
  708.         case WM_MBUTTONDOWN:
  709.         case WM_MBUTTONUP:
  710.         /*
  711.          * Call the sample's MouseHandler if available
  712.          */
  713.             if (!MouseHandler)
  714.                 break;
  715.             if ((MouseHandler)(message, wParam, lParam))
  716.                 return 1;
  717.             break;
  718.         case WM_KEYDOWN:
  719.         /*
  720.          * Call the sample's keyboard handler if available
  721.          */
  722.             if (!KeyboardHandler)
  723.                 break;
  724.             if ((KeyboardHandler)(message, wParam, lParam))
  725.                 return 1;
  726.             break;
  727.     /*
  728.      * Pause and unpause the app when entering/leaving the menu
  729.      */
  730.         case WM_ENTERMENULOOP:
  731.             AppPause(TRUE);
  732.             break;
  733.         case WM_EXITMENULOOP:
  734.             AppPause(FALSE);
  735.             break;
  736.         case WM_DESTROY:
  737.             myglobs.hWndMain = NULL;
  738.             CleanUpAndPostQuit();
  739.             break;
  740.         case WM_INITMENUPOPUP:
  741.         /*
  742.              * Check and enable the appropriate menu items
  743.          */
  744.         if (d3dapp->ThisDriver.bDoesZBuffer) {
  745.         EnableMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_ENABLED);
  746.         CheckMenuItem((HMENU)wParam, MENU_ZBUFFER, myglobs.rstate.bZBufferOn ? MF_CHECKED : MF_UNCHECKED);
  747.         } else {
  748.         EnableMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_GRAYED);
  749.         CheckMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_UNCHECKED);
  750.         }
  751.             CheckMenuItem((HMENU)wParam, MENU_STEP, (myglobs.bSingleStepMode) ? MF_CHECKED : MF_UNCHECKED);
  752.             EnableMenuItem((HMENU)wParam, MENU_GO, (myglobs.bSingleStepMode) ? MF_ENABLED : MF_GRAYED);
  753.             CheckMenuItem((HMENU)wParam, MENU_FLAT, (myglobs.rstate.ShadeMode == D3DSHADE_FLAT) ? MF_CHECKED : MF_UNCHECKED);
  754.             CheckMenuItem((HMENU)wParam, MENU_GOURAUD, (myglobs.rstate.ShadeMode == D3DSHADE_GOURAUD) ? MF_CHECKED : MF_UNCHECKED);
  755.             CheckMenuItem((HMENU)wParam, MENU_PHONG, (myglobs.rstate.ShadeMode == D3DSHADE_PHONG) ? MF_CHECKED : MF_UNCHECKED);
  756.         EnableMenuItem((HMENU)wParam, MENU_PHONG, MF_GRAYED);
  757.             CheckMenuItem((HMENU)wParam, MENU_CLEARS, myglobs.bClearsOn ? MF_CHECKED : MF_UNCHECKED);
  758.             CheckMenuItem((HMENU)wParam, MENU_POINT, (myglobs.rstate.FillMode == D3DFILL_POINT) ? MF_CHECKED : MF_UNCHECKED);
  759.             CheckMenuItem((HMENU)wParam, MENU_WIREFRAME, (myglobs.rstate.FillMode == D3DFILL_WIREFRAME) ? MF_CHECKED : MF_UNCHECKED);
  760.             CheckMenuItem((HMENU)wParam, MENU_SOLID, (myglobs.rstate.FillMode == D3DFILL_SOLID) ? MF_CHECKED : MF_UNCHECKED);
  761.             CheckMenuItem((HMENU)wParam, MENU_DITHERING, myglobs.rstate.bDithering ? MF_CHECKED : MF_UNCHECKED);
  762.             CheckMenuItem((HMENU)wParam, MENU_SPECULAR, myglobs.rstate.bSpecular ? MF_CHECKED : MF_UNCHECKED);
  763.             EnableMenuItem((HMENU)wParam, MENU_SPECULAR, MF_ENABLED);
  764.             CheckMenuItem((HMENU)wParam, MENU_FOG, myglobs.rstate.bFogEnabled ? MF_CHECKED : MF_UNCHECKED);
  765.             CheckMenuItem((HMENU)wParam, MENU_ANTIALIAS, myglobs.rstate.bAntialiasing ? MF_CHECKED : MF_UNCHECKED);
  766.         if (d3dapp->ThisDriver.bDoesTextures) {
  767.         CheckMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, (!d3dapp->bTexturesDisabled) ? MF_CHECKED : MF_UNCHECKED);
  768.         EnableMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, MF_ENABLED);
  769.         EnableMenuItem((HMENU)wParam, MENU_TEXTURE_SWAP, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  770.         CheckMenuItem((HMENU)wParam, MENU_PERSPCORRECT, myglobs.rstate.bPerspCorrect ? MF_CHECKED : MF_UNCHECKED);
  771.         EnableMenuItem((HMENU)wParam, MENU_PERSPCORRECT, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  772.         CheckMenuItem((HMENU)wParam, MENU_POINT_FILTER, (myglobs.rstate.TextureFilter == D3DFILTER_NEAREST) ? MF_CHECKED : MF_UNCHECKED);
  773.         EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  774.         CheckMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (myglobs.rstate.TextureFilter == D3DFILTER_LINEAR) ? MF_CHECKED : MF_UNCHECKED);
  775.         EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  776.         for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  777.             CheckMenuItem((HMENU)wParam, MENU_FIRST_FORMAT + i, (i == d3dapp->CurrTextureFormat) ? MF_CHECKED : MF_UNCHECKED);
  778.             EnableMenuItem((HMENU)wParam, MENU_FIRST_FORMAT + i, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  779.         }
  780.         } else {
  781.         EnableMenuItem((HMENU)wParam, MENU_TEXTURE_SWAP, MF_GRAYED);
  782.         EnableMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, MF_GRAYED);
  783.         EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, MF_GRAYED);
  784.         EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, MF_GRAYED);
  785.         EnableMenuItem((HMENU)wParam, MENU_PERSPCORRECT, MF_GRAYED);
  786.         }
  787.         if (d3dapp->bIsPrimary) {
  788.         CheckMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen ? MF_CHECKED : MF_UNCHECKED);
  789.         EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen && !d3dapp->ThisDriver.bCanDoWindow ? MF_GRAYED : MF_ENABLED);
  790.         EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  791.         EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  792.         } else {
  793.         EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, MF_GRAYED);
  794.         EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, MF_GRAYED);
  795.         EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, MF_GRAYED);
  796.         }
  797.         for (i = 0; i < d3dapp->NumModes; i++) {
  798.         CheckMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (i == d3dapp->CurrMode) ? MF_CHECKED : MF_UNCHECKED);
  799.         EnableMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (d3dapp->Mode[i].bThisDriverCanDo) ? MF_ENABLED : MF_GRAYED);
  800.         }
  801.             for (i = 0; i < d3dapp->NumDrivers; i++) {
  802.                 CheckMenuItem((HMENU)wParam, MENU_FIRST_DRIVER + i, (i == d3dapp->CurrDriver) ? MF_CHECKED : MF_UNCHECKED);
  803.             }
  804.             break;
  805.     case WM_GETMINMAXINFO:
  806.         /*
  807.          * Some samples don't like being resized, such as those which use
  808.          * screen coordinates (TLVERTEXs).
  809.          */
  810.         if (myglobs.bResizingDisabled) {
  811.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = START_WIN_SIZE;
  812.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = START_WIN_SIZE;
  813.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = START_WIN_SIZE;
  814.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = START_WIN_SIZE;
  815.         return 0;
  816.         }
  817.         break;
  818.         case WM_COMMAND:
  819.             switch(LOWORD(wParam)) {
  820.                 case MENU_ABOUT:
  821.                     AppPause(TRUE);
  822.                     DialogBox(myglobs.hInstApp, "AppAbout", myglobs.hWndMain, (DLGPROC)AppAbout);
  823.                     AppPause(FALSE);
  824.                     break;
  825.                 case MENU_EXIT:
  826.                 CleanUpAndPostQuit();
  827.                 break;
  828.                 case MENU_STEP:
  829.             /*
  830.              * Begin single step more or draw a frame if in single
  831.              * step mode
  832.              */
  833.                     if (!myglobs.bSingleStepMode) {
  834.                         myglobs.bSingleStepMode = TRUE;
  835.                         myglobs.bDrawAFrame = TRUE;
  836.                     } else if (!myglobs.bDrawAFrame) {
  837.                         myglobs.bDrawAFrame = TRUE;
  838.                     }
  839.                     break;
  840.                 case MENU_GO:
  841.             /*
  842.              * Exit single step mode
  843.              */
  844.                     if (myglobs.bSingleStepMode) {
  845.                         myglobs.bSingleStepMode = FALSE;
  846.                         ResetFrameRate();
  847.                     }
  848.                     break;
  849.                 case MENU_STATS:
  850.             /*
  851.              * Toggle output of frame rate and window info
  852.              */
  853.                     if ((myglobs.bShowFrameRate) && (myglobs.bShowInfo)) {
  854.                         myglobs.bShowFrameRate = FALSE;
  855.                         myglobs.bShowInfo = FALSE;
  856.                         break;
  857.                     }
  858.                     if ((!myglobs.bShowFrameRate) && (!myglobs.bShowInfo)) {
  859.                         myglobs.bShowFrameRate = TRUE;
  860.                         break;
  861.                     }
  862.                     myglobs.bShowInfo = TRUE;
  863.                     break;
  864.             case MENU_FULLSCREEN:
  865.             if (d3dapp->bFullscreen) {
  866.             /*
  867.              * Return to a windowed mode.  Let D3DApp decide which
  868.              * D3D driver to use in case this one cannot render to
  869.              * the Windows display depth
  870.              */
  871.             if (!D3DAppWindow(D3DAPP_YOUDECIDE, D3DAPP_YOUDECIDE)) {
  872.                 ReportD3DAppError();
  873.                 CleanUpAndPostQuit();
  874.                 break;
  875.             }
  876.             } else {
  877.             /*
  878.              * Enter the current fullscreen mode.  D3DApp may
  879.              * resort to another mode if this driver cannot do
  880.              * the currently selected mode.
  881.              */
  882.             if (!D3DAppFullscreen(d3dapp->CurrMode)) {
  883.                 ReportD3DAppError();
  884.                 CleanUpAndPostQuit();
  885.                 break;
  886.             }
  887.             }
  888.                     break;
  889.         /*
  890.          * Texture filter method selection
  891.          */
  892.                 case MENU_POINT_FILTER:
  893.                     if (myglobs.rstate.TextureFilter == D3DFILTER_NEAREST)
  894.                         break;
  895.                     myglobs.rstate.TextureFilter = D3DFILTER_NEAREST;
  896.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  897.             ReportD3DAppError();
  898.             break;
  899.             }
  900.             break;
  901.                 case MENU_LINEAR_FILTER:
  902.                     if (myglobs.rstate.TextureFilter == D3DFILTER_LINEAR)
  903.                         break;
  904.                     myglobs.rstate.TextureFilter = D3DFILTER_LINEAR;
  905.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  906.             ReportD3DAppError();
  907.             break;
  908.             }
  909.             break;
  910.         /* 
  911.          * Shading selection
  912.          */
  913.                 case MENU_FLAT:
  914.                     if (myglobs.rstate.ShadeMode == D3DSHADE_FLAT)
  915.                         break;
  916.                     myglobs.rstate.ShadeMode = D3DSHADE_FLAT;
  917.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  918.             ReportD3DAppError();
  919.             break;
  920.             }
  921.             break;
  922.                 case MENU_GOURAUD:
  923.                     if (myglobs.rstate.ShadeMode == D3DSHADE_GOURAUD)
  924.                         break;
  925.                     myglobs.rstate.ShadeMode = D3DSHADE_GOURAUD;
  926.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  927.             ReportD3DAppError();
  928.             break;
  929.             }
  930.                     break;
  931.                 case MENU_PHONG:
  932.                     if (myglobs.rstate.ShadeMode == D3DSHADE_PHONG)
  933.                         break;
  934.                     myglobs.rstate.ShadeMode = D3DSHADE_PHONG;
  935.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  936.             ReportD3DAppError();
  937.             break;
  938.             }
  939.                     break;
  940.         /*
  941.          * Fill mode selection
  942.          */
  943.                 case MENU_POINT:
  944.                     if (myglobs.rstate.FillMode == D3DFILL_POINT)
  945.                         break;
  946.                     myglobs.rstate.FillMode = D3DFILL_POINT;
  947.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  948.             ReportD3DAppError();
  949.             break;
  950.             }
  951.                     break;
  952.                 case MENU_WIREFRAME:
  953.                     if (myglobs.rstate.FillMode == D3DFILL_WIREFRAME)
  954.                         break;
  955.                     myglobs.rstate.FillMode = D3DFILL_WIREFRAME;
  956.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  957.             ReportD3DAppError();
  958.             break;
  959.             }
  960.                     break;
  961.                 case MENU_SOLID:
  962.                     if (myglobs.rstate.FillMode == D3DFILL_SOLID)
  963.                         break;
  964.                     myglobs.rstate.FillMode = D3DFILL_SOLID;
  965.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  966.             ReportD3DAppError();
  967.             break;
  968.             }
  969.                     break;
  970.                 case MENU_PERSPCORRECT:
  971.             /*
  972.              * Toggle perspective correction
  973.              */
  974.                     myglobs.rstate.bPerspCorrect =
  975.             !myglobs.rstate.bPerspCorrect;
  976.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  977.             ReportD3DAppError();
  978.             break;
  979.             }
  980.                     break;
  981.                 case MENU_CLEARS:
  982.             /*
  983.              * Toggle the clearing the the back buffer and Z-buffer
  984.              * and set the resized flag to clear the entire window
  985.              */
  986.                     myglobs.bClearsOn = !myglobs.bClearsOn;
  987.                     if (myglobs.bClearsOn)
  988.                         myglobs.bResized = TRUE;
  989.                     break;
  990.                 case MENU_ZBUFFER:
  991.             /*
  992.              * Toggle the use of a Z-buffer
  993.              */
  994.                     myglobs.rstate.bZBufferOn = !myglobs.rstate.bZBufferOn;
  995.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  996.             ReportD3DAppError();
  997.             break;
  998.             }
  999.             break;
  1000.                 case MENU_DITHERING:
  1001.             /*
  1002.              * Toggle dithering
  1003.              */
  1004.                     myglobs.rstate.bDithering = !myglobs.rstate.bDithering;
  1005.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1006.             ReportD3DAppError();
  1007.             break;
  1008.             }
  1009.             break;
  1010.                 case MENU_SPECULAR:
  1011.             /*
  1012.              * Toggle specular highlights
  1013.              */
  1014.                     myglobs.rstate.bSpecular = !myglobs.rstate.bSpecular;
  1015.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1016.             ReportD3DAppError();
  1017.             break;
  1018.             }
  1019.             break;
  1020.                 case MENU_FOG:
  1021.             /*
  1022.              * Toggle fog
  1023.              */
  1024.                     myglobs.rstate.bFogEnabled = !myglobs.rstate.bFogEnabled;
  1025.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1026.             ReportD3DAppError();
  1027.             break;
  1028.             }
  1029.             break;
  1030.                 case MENU_ANTIALIAS:
  1031.             /*
  1032.              * Toggle anti-aliasing
  1033.              */
  1034.                     myglobs.rstate.bAntialiasing =
  1035.             !myglobs.rstate.bAntialiasing;
  1036.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1037.             ReportD3DAppError();
  1038.             break;
  1039.             }
  1040.             break;
  1041.                 case MENU_TEXTURE_TOGGLE:
  1042.             /*
  1043.              * Release the sample's execute buffers, toggle the
  1044.              * texture disabled state and recreate them.
  1045.              */
  1046.             ReleaseView(d3dapp->lpD3DViewport);
  1047.             D3DAppDisableTextures(!d3dapp->bTexturesDisabled);
  1048.             {
  1049.             if (!InitView(d3dapp->lpDD, d3dapp->lpD3D,
  1050.                       d3dapp->lpD3DDevice,
  1051.                       d3dapp->lpD3DViewport,
  1052.                       d3dapp->NumUsableTextures,
  1053.                       d3dapp->TextureHandle)) {
  1054.                 Msg("InitView failed.\n");
  1055.                 CleanUpAndPostQuit();
  1056.                 break;
  1057.             }
  1058.             }
  1059.             myglobs.bResized = TRUE;
  1060.             break;
  1061.         case MENU_TEXTURE_SWAP:
  1062.             /*
  1063.              * Swap textures using the load command
  1064.              */
  1065.             if (!D3DAppSwapTextures()) {
  1066.             ReportD3DAppError();
  1067.             break;
  1068.             }
  1069.             /*
  1070.              * Just in case we have a texture background
  1071.              */
  1072.             myglobs.bResized = TRUE;
  1073.             break;
  1074.         case MENU_NEXT_MODE:
  1075.             /*
  1076.              * Enter the next usable fullscreen mode
  1077.              */
  1078.             i = d3dapp->CurrMode;
  1079.             do {
  1080.             ++i;
  1081.             if (i >= d3dapp->NumModes)
  1082.                 i = 0;
  1083.             if (!d3dapp->Mode[i].bThisDriverCanDo)
  1084.                 continue;
  1085.             else {
  1086.                 if (!D3DAppFullscreen(i)) {
  1087.                 ReportD3DAppError();
  1088.                 CleanUpAndPostQuit();
  1089.                 }
  1090.                 break;
  1091.             }
  1092.             } while(i != d3dapp->CurrMode);
  1093.             break;
  1094.         case MENU_PREVIOUS_MODE:
  1095.             /*
  1096.              * Enter the previous usable fullscreen mode
  1097.              */
  1098.             i = d3dapp->CurrMode;
  1099.             do {
  1100.             --i;
  1101.             if (i < 0)
  1102.                 i = d3dapp->NumModes - 1;
  1103.             if (!d3dapp->Mode[i].bThisDriverCanDo)
  1104.                 continue;
  1105.             else {
  1106.                 if (!D3DAppFullscreen(i)) {
  1107.                 ReportD3DAppError();
  1108.                 CleanUpAndPostQuit();
  1109.                 }
  1110.                 break;
  1111.             }
  1112.             } while(i != d3dapp->CurrMode);
  1113.                     break;
  1114.             }
  1115.             if (   LOWORD(wParam) >= MENU_FIRST_FORMAT
  1116.         && LOWORD(wParam) < MENU_FIRST_FORMAT +
  1117.             D3DAPP_MAXTEXTUREFORMATS
  1118.         && d3dapp->CurrTextureFormat !=
  1119.             LOWORD(wParam) - MENU_FIRST_FORMAT) {
  1120.         /*
  1121.          * Release the sample's execute buffers, change the texture
  1122.          * format and recreate the view.
  1123.          */
  1124.         ReleaseView(d3dapp->lpD3DViewport);
  1125.         if (!D3DAppChangeTextureFormat(LOWORD(wParam) -
  1126.                              MENU_FIRST_FORMAT)) {
  1127.             ReportD3DAppError();
  1128.             CleanUpAndPostQuit();
  1129.         }
  1130.         {
  1131.             if (!InitView(d3dapp->lpDD, d3dapp->lpD3D,
  1132.                   d3dapp->lpD3DDevice, d3dapp->lpD3DViewport,
  1133.                   d3dapp->NumUsableTextures,
  1134.                   d3dapp->TextureHandle)) {
  1135.             Msg("InitView failed.\n");
  1136.             CleanUpAndPostQuit();
  1137.             break;
  1138.             }
  1139.         }
  1140.                 ResetFrameRate();
  1141.             }
  1142.             if (   LOWORD(wParam) >= MENU_FIRST_DRIVER
  1143.         && LOWORD(wParam) < MENU_FIRST_DRIVER + D3DAPP_MAXD3DDRIVERS
  1144.         && d3dapp->CurrDriver != LOWORD(wParam) - MENU_FIRST_DRIVER) {
  1145.         /*
  1146.          * Change the D3D driver
  1147.          */
  1148.         if (!D3DAppChangeDriver(LOWORD(wParam) - MENU_FIRST_DRIVER,
  1149.                     NULL)) {
  1150.             ReportD3DAppError();
  1151.             CleanUpAndPostQuit();
  1152.         }
  1153.             }
  1154.             if (   LOWORD(wParam) >= MENU_FIRST_MODE
  1155.         && LOWORD(wParam) < MENU_FIRST_MODE+100) {
  1156.         /*
  1157.          * Switch to the selected fullscreen mode
  1158.          */
  1159.         if (!D3DAppFullscreen(LOWORD(wParam) - MENU_FIRST_MODE)) {
  1160.             ReportD3DAppError();
  1161.             CleanUpAndPostQuit();
  1162.         }
  1163.             }
  1164.         /*
  1165.          * Whenever we receive a command in single step mode, draw a frame
  1166.          */
  1167.         if (myglobs.bSingleStepMode)
  1168.         myglobs.bDrawAFrame = TRUE;
  1169.             return 0L;
  1170.     }
  1171.     return DefWindowProc(hWnd, message, wParam, lParam);
  1172. }
  1173.  
  1174.  
  1175. /****************************************************************************/
  1176. /*                 Setting up callbacks for examples                        */
  1177. /****************************************************************************/
  1178.  /*
  1179.   * SetMouseCallback
  1180.   * Called in an example to set a callback function for all WM messages
  1181.   * dealing with the mouse.  The handler should return whether or not
  1182.   * it handled the message.
  1183.   */
  1184. BOOL
  1185. SetMouseCallback(BOOL(*Handler)(UINT, WPARAM, LPARAM))
  1186. {
  1187.     MouseHandler = Handler;
  1188.     return TRUE;
  1189. }
  1190.  
  1191. /*
  1192.  * SetKeyboardCallback
  1193.  * Called in an example to set a callback function for all WM messages
  1194.  * dealing with the keyboard. The handler should return whether or not it
  1195.  * handled the message.
  1196.  */
  1197. BOOL
  1198. SetKeyboardCallback(BOOL(*Handler)(UINT, WPARAM, LPARAM)) {
  1199.     
  1200.     KeyboardHandler = Handler;
  1201.     return TRUE;
  1202. }
  1203.  
  1204. /****************************************************************************/
  1205. /*          Initialization, error reporting and release functions.          */
  1206. /****************************************************************************/
  1207. /*
  1208.  * InitGlobals
  1209.  * Called once at program initialization to initialize global variables.
  1210.  */
  1211. static void
  1212. InitGlobals(void)
  1213. {
  1214.     d3dapp = NULL;
  1215.     memset(&myglobs.rstate, 0, sizeof(myglobs.rstate));
  1216.     memset(&myglobs, 0, sizeof(myglobs));
  1217.     myglobs.bClearsOn = TRUE;
  1218.     myglobs.bShowFrameRate = TRUE;
  1219.     myglobs.bShowInfo = TRUE;
  1220.     MouseHandler = NULL;
  1221.     KeyboardHandler = NULL;
  1222. }
  1223.  
  1224. /*
  1225.  * CleanUpAndPostQuit
  1226.  * Release all D3D objects, post a quit message and set the bQuit flag
  1227.  */
  1228. void
  1229. CleanUpAndPostQuit(void)
  1230. {
  1231.     if (myglobs.bQuit)
  1232.     return;
  1233.     if (!D3DAppDestroy())
  1234.     ReportD3DAppError();
  1235.     ReleaseScene();
  1236.     myglobs.bQuit = TRUE;
  1237.     PostQuitMessage( 0 );
  1238. }
  1239.  
  1240. /*
  1241.  * ReportD3DAppError
  1242.  * Reports an error during a d3d app call.
  1243.  */
  1244. void
  1245. ReportD3DAppError(void)
  1246. {
  1247.     Msg("%s", D3DAppLastErrorString());
  1248. }
  1249.  
  1250. /* Msg
  1251.  * Message output for error notification.
  1252.  */
  1253. void __cdecl
  1254. Msg( LPSTR fmt, ... )
  1255. {
  1256.     char buff[256];
  1257.     va_list va;
  1258.  
  1259.     va_start( va, fmt );
  1260.     wvsprintf( buff, fmt, va );
  1261.     va_end( va );
  1262.     lstrcat(buff, "\r\n");
  1263.     AppPause(TRUE);
  1264.     if (d3dapp && d3dapp->bFullscreen)
  1265.     SetWindowPos(myglobs.hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
  1266.              SWP_NOSIZE | SWP_NOMOVE);
  1267.     MessageBox( myglobs.hWndMain, buff, "D3D Example Message", MB_OK );
  1268.     if (d3dapp && d3dapp->bFullscreen)
  1269.     SetWindowPos(myglobs.hWndMain, HWND_TOPMOST, 0, 0, 0, 0,
  1270.              SWP_NOSIZE | SWP_NOMOVE);
  1271.     AppPause(FALSE);
  1272. }
  1273.  
  1274.