home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / MISC / D3DMAIN.CPP < prev    next >
C/C++ Source or Header  |  1996-08-28  |  47KB  |  1,247 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, LPDIRECT3DVIEWPORT* 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, LPDIRECT3DVIEWPORT* lplpViewport, LPVOID lpContext)
  344. {
  345.     HMENU hmenu;
  346.     int i;
  347.     char ach[20];
  348.     LPDIRECT3DVIEWPORT 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.     D3DVIEWPORT viewData;
  373.     memset(&viewData, 0, sizeof(D3DVIEWPORT));
  374.     viewData.dwSize = sizeof(D3DVIEWPORT);
  375.     viewData.dwX = viewData.dwY = 0;
  376.     viewData.dwWidth = w;
  377.     viewData.dwHeight = h;
  378.     viewData.dvScaleX = viewData.dwWidth / (float)2.0;
  379.     viewData.dvScaleY = viewData.dwHeight / (float)2.0;
  380.     viewData.dvMaxX = (float)D3DDivide(D3DVAL(viewData.dwWidth),
  381.                                        D3DVAL(2 * viewData.dvScaleX));
  382.     viewData.dvMaxY = (float)D3DDivide(D3DVAL(viewData.dwHeight),
  383.                                        D3DVAL(2 * viewData.dvScaleY));
  384.     rval = lpD3DViewport->SetViewport(&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.     InitFontAndTextBuffers();
  424.  
  425.     return TRUE;
  426. }
  427.  
  428. /*
  429.  * BeforeDeviceDestroyed
  430.  * D3DApp will call this function before the current D3D device is destroyed
  431.  * to give the app the opportunity to destroy objects it has created with the
  432.  * DD or D3D objects.
  433.  */
  434. static BOOL
  435. BeforeDeviceDestroyed(LPVOID lpContext)
  436. {
  437.     HMENU hmenu;
  438.     int i;
  439.     /*
  440.      * Release the font object and buffers containing stats
  441.      */
  442.     ReleaseFontAndTextBuffers();
  443.     /*
  444.      * Release all objects (ie execute buffers) created by InitView
  445.      */
  446.     ReleaseView(d3dapp->lpD3DViewport);
  447.     /*
  448.      * Since we created the viewport it is our responsibility to release
  449.      * it.  Use D3DApp's pointer to it since we didn't save one.
  450.      */
  451.     d3dapp->lpD3DViewport->Release();
  452.     /*
  453.      * Delete the list of texture formats from the texture menu because
  454.      * they are likely to change
  455.      */
  456.     if (myglobs.hWndMain) {
  457.         hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 3);
  458.         if (hmenu) {
  459.             for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  460.                 DeleteMenu(hmenu, MENU_FIRST_FORMAT + i, MF_BYCOMMAND);
  461.             }
  462.         }
  463.     }
  464.     return TRUE;
  465. }
  466.  
  467. /****************************************************************************/
  468. /*                            Rendering loop                                */
  469. /****************************************************************************/
  470. /*
  471.  * RenderLoop
  472.  * Render the next frame and update the window
  473.  */
  474. static BOOL
  475. RenderLoop()
  476. {
  477.     D3DRECT extents[D3DAPP_MAXCLEARRECTS];
  478.     int count;
  479.     /*
  480.      * If all the DD and D3D objects have been initialized we can render
  481.      */
  482.     if (d3dapp->bRenderingIsOK) {
  483.         /*
  484.          * Restore any lost surfaces
  485.          */
  486.         if (!RestoreSurfaces()) {
  487.             /*
  488.              * Restoring surfaces sometimes fails because the surfaces cannot
  489.              * yet be restored.  If this is the case, the error will show up
  490.              * somewhere else and we should return success here to prevent
  491.              * unnecessary error's being reported.
  492.              */
  493.             return TRUE;
  494.         }
  495.         /*
  496.          * Calculate the frame rate
  497.          */
  498.         if (!CalculateFrameRate())
  499.             return FALSE;
  500.  
  501.         /*
  502.          * Clear the back buffer and Z buffer if enabled.  If bResized is set,
  503.          * clear the entire window.
  504.          */
  505.         if (myglobs.bClearsOn) {
  506.             if (!D3DAppClearBackBuffer(myglobs.bResized ?
  507.                                        D3DAPP_CLEARALL : NULL)) {
  508.                 ReportD3DAppError();
  509.                 return FALSE;
  510.             }
  511.         }
  512.         /*
  513.          * Call the sample's RenderScene to render this frame
  514.          */
  515.         {
  516.             if (!RenderScene(d3dapp->lpD3DDevice, d3dapp->lpD3DViewport,
  517.                              &extents[0])) {
  518.                 Msg("RenderScene failed.\n");
  519.                 return FALSE;
  520.             }
  521.             count = 1;
  522.         }
  523.         /*
  524.          * Blt the frame rate and window stat text to the back buffer
  525.          */
  526.         if (!DisplayFrameRate(&count, &extents[1]))
  527.             return FALSE;
  528.         /*
  529.          * Give D3DApp the extents so it can keep track of dirty sections of
  530.          * the back and front buffers
  531.          */
  532.         if (!D3DAppRenderExtents(count, extents, myglobs.bResized ?
  533.                                  D3DAPP_CLEARALL : NULL)) {
  534.             ReportD3DAppError();
  535.             return FALSE;
  536.         }
  537.         /*
  538.          * Blt or flip the back buffer to the front buffer.  Don't report an
  539.          * error if this fails.
  540.          */
  541.         D3DAppShowBackBuffer(myglobs.bResized ? D3DAPP_SHOWALL : NULL);
  542.  
  543.         /*
  544.          * Reset the resize flag
  545.          */
  546.         myglobs.bResized = FALSE;
  547.     }
  548.     return TRUE;
  549. }
  550.  
  551. /*
  552.  * AppPause
  553.  * Pause and unpause the application
  554.  */
  555. static BOOL
  556. AppPause(BOOL f)
  557. {
  558.     /*
  559.      * Flip to the GDI surface and halt rendering
  560.      */
  561.     if (!D3DAppPause(f))
  562.         return FALSE;
  563.     /*
  564.      * When returning from a pause, reset the frame rate count
  565.      */
  566.     if (!f) {
  567.         ResetFrameRate();
  568.     }
  569.     return TRUE;
  570. }
  571.  
  572. /*
  573.  * RestoreSurfaces
  574.  * Restores any lost surfaces.  Returns TRUE if all surfaces are not lost and
  575.  * FALSE if one or more surfaces is lost and can not be restored at the
  576.  * moment.
  577.  */
  578. static BOOL
  579. RestoreSurfaces()
  580. {
  581.     HRESULT d3drval;
  582.  
  583.     /*
  584.      * Have D3DApp check all the surfaces it's in charge of
  585.      */
  586.     if (!D3DAppCheckForLostSurfaces()) {
  587.             return FALSE;
  588.     }
  589.     /*
  590.      * Check frame rate and info surfaces and re-write them if they
  591.      * were lost.
  592.      */
  593.     if (myglobs.lpFrameRateBuffer->IsLost() == DDERR_SURFACELOST) {
  594.         d3drval = myglobs.lpFrameRateBuffer->Restore();
  595.         if (d3drval != DD_OK) {
  596.             return FALSE;
  597.         }
  598.         if (!WriteFrameRateBuffer(0.0f, 0))
  599.             return FALSE;
  600.     }
  601.     if (myglobs.lpInfoBuffer->IsLost() == DDERR_SURFACELOST) {
  602.         d3drval = myglobs.lpInfoBuffer->Restore();
  603.         if (d3drval != DD_OK) {
  604.             return FALSE;
  605.         }
  606.         if (!WriteInfoBuffer())
  607.             return FALSE;
  608.     }
  609.     return TRUE;
  610. }
  611.  
  612.  
  613. /*************************************************************************
  614.   Windows message handlers
  615.  *************************************************************************/
  616. /*
  617.  * AppAbout
  618.  * About box message handler
  619.  */
  620. BOOL
  621. FAR PASCAL AppAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  622. {
  623.   switch (msg)
  624.   {
  625.     case WM_COMMAND:
  626.       if (LOWORD(wParam) == IDOK)
  627.         EndDialog(hwnd, TRUE);
  628.       break;
  629.  
  630.     case WM_INITDIALOG:
  631.       return TRUE;
  632.   }
  633.   return FALSE;
  634. }
  635.  
  636. /*
  637.  * WindowProc
  638.  * Main window message handler.
  639.  */
  640. long
  641. FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  642.                            LPARAM lParam )
  643. {
  644.     int i;
  645.     BOOL bStop;
  646.     LRESULT lresult;
  647.  
  648.     /*
  649.      * Give D3DApp an opportunity to process any messages it MUST see in order
  650.      * to perform it's function.
  651.      */
  652.     if (!D3DAppWindowProc(&bStop, &lresult, hWnd, message, wParam, lParam)) {
  653.         ReportD3DAppError();
  654.         CleanUpAndPostQuit();
  655.         return 0;
  656.     }
  657.  
  658.     /*
  659.      * Prevent resizing through this message
  660.      */
  661.     if (message == WM_GETMINMAXINFO && myglobs.bResizingDisabled && !d3dapp->bFullscreen && !d3dapp->bMinimized) {
  662.         RECT rc;
  663.         GetWindowRect(hWnd, &rc);
  664.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = START_WIN_SIZE;
  665.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = START_WIN_SIZE;
  666.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = START_WIN_SIZE;
  667.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = START_WIN_SIZE;
  668.         return 0;
  669.     }
  670.  
  671.     /* 
  672.      * If bStop is set by D3DApp, the app should not process the message but
  673.      * return lresult.
  674.      */
  675.     if (bStop)
  676.         return lresult;
  677.  
  678.     switch( message ) {
  679.         case WM_MOUSEMOVE:
  680.         case WM_LBUTTONDOWN:
  681.         case WM_LBUTTONUP:
  682.         case WM_RBUTTONDOWN:
  683.         case WM_RBUTTONUP:
  684.         case WM_MBUTTONDOWN:
  685.         case WM_MBUTTONUP:
  686.             /*
  687.              * Call the sample's MouseHandler if available
  688.              */
  689.             if (!MouseHandler)
  690.                 break;
  691.             if ((MouseHandler)(message, wParam, lParam))
  692.                 return 1;
  693.             break;
  694.         case WM_KEYDOWN:
  695.             /*
  696.              * Call the sample's keyboard handler if available
  697.              */
  698.             if (!KeyboardHandler)
  699.                 break;
  700.             if ((KeyboardHandler)(message, wParam, lParam))
  701.                 return 1;
  702.             break;
  703.         /*
  704.          * Pause and unpause the app when entering/leaving the menu
  705.          */
  706.         case WM_ENTERMENULOOP:
  707.             AppPause(TRUE);
  708.             break;
  709.         case WM_EXITMENULOOP:
  710.             AppPause(FALSE);
  711.             break;
  712.         case WM_DESTROY:
  713.             myglobs.hWndMain = NULL;
  714.             CleanUpAndPostQuit();
  715.             break;
  716.         case WM_INITMENUPOPUP:
  717.             /*
  718.              * Check and enable the appropriate menu items
  719.              */
  720.             if (d3dapp->ThisDriver.bDoesZBuffer) {
  721.                 EnableMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_ENABLED);
  722.                 CheckMenuItem((HMENU)wParam, MENU_ZBUFFER, myglobs.rstate.bZBufferOn ? MF_CHECKED : MF_UNCHECKED);
  723.             } else {
  724.                 EnableMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_GRAYED);
  725.                 CheckMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_UNCHECKED);
  726.             }
  727.             CheckMenuItem((HMENU)wParam, MENU_STEP, (myglobs.bSingleStepMode) ? MF_CHECKED : MF_UNCHECKED);
  728.             EnableMenuItem((HMENU)wParam, MENU_GO, (myglobs.bSingleStepMode) ? MF_ENABLED : MF_GRAYED);
  729.             CheckMenuItem((HMENU)wParam, MENU_FLAT, (myglobs.rstate.ShadeMode == D3DSHADE_FLAT) ? MF_CHECKED : MF_UNCHECKED);
  730.             CheckMenuItem((HMENU)wParam, MENU_GOURAUD, (myglobs.rstate.ShadeMode == D3DSHADE_GOURAUD) ? MF_CHECKED : MF_UNCHECKED);
  731.             CheckMenuItem((HMENU)wParam, MENU_PHONG, (myglobs.rstate.ShadeMode == D3DSHADE_PHONG) ? MF_CHECKED : MF_UNCHECKED);
  732.             EnableMenuItem((HMENU)wParam, MENU_PHONG, MF_GRAYED);
  733.             CheckMenuItem((HMENU)wParam, MENU_CLEARS, myglobs.bClearsOn ? MF_CHECKED : MF_UNCHECKED);
  734.             CheckMenuItem((HMENU)wParam, MENU_POINT, (myglobs.rstate.FillMode == D3DFILL_POINT) ? MF_CHECKED : MF_UNCHECKED);
  735.             CheckMenuItem((HMENU)wParam, MENU_WIREFRAME, (myglobs.rstate.FillMode == D3DFILL_WIREFRAME) ? MF_CHECKED : MF_UNCHECKED);
  736.             CheckMenuItem((HMENU)wParam, MENU_SOLID, (myglobs.rstate.FillMode == D3DFILL_SOLID) ? MF_CHECKED : MF_UNCHECKED);
  737.             CheckMenuItem((HMENU)wParam, MENU_DITHERING, myglobs.rstate.bDithering ? MF_CHECKED : MF_UNCHECKED);
  738.             CheckMenuItem((HMENU)wParam, MENU_SPECULAR, myglobs.rstate.bSpecular ? MF_CHECKED : MF_UNCHECKED);
  739.             EnableMenuItem((HMENU)wParam, MENU_SPECULAR, MF_ENABLED);
  740.             CheckMenuItem((HMENU)wParam, MENU_FOG, myglobs.rstate.bFogEnabled ? MF_CHECKED : MF_UNCHECKED);
  741.             CheckMenuItem((HMENU)wParam, MENU_ANTIALIAS, myglobs.rstate.bAntialiasing ? MF_CHECKED : MF_UNCHECKED);
  742.             if (d3dapp->ThisDriver.bDoesTextures) {
  743.                 CheckMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, (!d3dapp->bTexturesDisabled) ? MF_CHECKED : MF_UNCHECKED);
  744.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, MF_ENABLED);
  745.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_SWAP, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  746.                 CheckMenuItem((HMENU)wParam, MENU_PERSPCORRECT, myglobs.rstate.bPerspCorrect ? MF_CHECKED : MF_UNCHECKED);
  747.                 EnableMenuItem((HMENU)wParam, MENU_PERSPCORRECT, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  748.                 CheckMenuItem((HMENU)wParam, MENU_POINT_FILTER, (myglobs.rstate.TextureFilter == D3DFILTER_NEAREST) ? MF_CHECKED : MF_UNCHECKED);
  749.                 EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  750.                 CheckMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (myglobs.rstate.TextureFilter == D3DFILTER_LINEAR) ? MF_CHECKED : MF_UNCHECKED);
  751.                 EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  752.                 for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  753.                     CheckMenuItem((HMENU)wParam, MENU_FIRST_FORMAT + i, (i == d3dapp->CurrTextureFormat) ? MF_CHECKED : MF_UNCHECKED);
  754.                     EnableMenuItem((HMENU)wParam, MENU_FIRST_FORMAT + i, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  755.                 }
  756.             } else {
  757.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_SWAP, MF_GRAYED);
  758.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, MF_GRAYED);
  759.                 EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, MF_GRAYED);
  760.                 EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, MF_GRAYED);
  761.                 EnableMenuItem((HMENU)wParam, MENU_PERSPCORRECT, MF_GRAYED);
  762.             }
  763.             if (d3dapp->bIsPrimary) {
  764.                 CheckMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen ? MF_CHECKED : MF_UNCHECKED);
  765.                 EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen && !d3dapp->ThisDriver.bCanDoWindow ? MF_GRAYED : MF_ENABLED);
  766.                 EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  767.                 EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  768.             } else {
  769.                 EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, MF_GRAYED);
  770.                 EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, MF_GRAYED);
  771.                 EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, MF_GRAYED);
  772.             }
  773.             for (i = 0; i < d3dapp->NumModes; i++) {
  774.                 CheckMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (i == d3dapp->CurrMode) ? MF_CHECKED : MF_UNCHECKED);
  775.                 EnableMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (d3dapp->Mode[i].bThisDriverCanDo) ? MF_ENABLED : MF_GRAYED);
  776.             }
  777.             for (i = 0; i < d3dapp->NumDrivers; i++) {
  778.                 CheckMenuItem((HMENU)wParam, MENU_FIRST_DRIVER + i, (i == d3dapp->CurrDriver) ? MF_CHECKED : MF_UNCHECKED);
  779.             }
  780.             break;
  781.         case WM_GETMINMAXINFO:
  782.             /*
  783.              * Some samples don't like being resized, such as those which use
  784.              * screen coordinates (TLVERTEXs).
  785.              */
  786.             if (myglobs.bResizingDisabled) {
  787.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = START_WIN_SIZE;
  788.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = START_WIN_SIZE;
  789.                 ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = START_WIN_SIZE;
  790.                 ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = START_WIN_SIZE;
  791.                 return 0;
  792.             }
  793.             break;
  794.         case WM_COMMAND:
  795.             switch(LOWORD(wParam)) {
  796.                 case MENU_ABOUT:
  797.                     AppPause(TRUE);
  798.                     DialogBox(myglobs.hInstApp, "AppAbout", myglobs.hWndMain, (DLGPROC)AppAbout);
  799.                     AppPause(FALSE);
  800.                     break;
  801.                 case MENU_EXIT:
  802.                     CleanUpAndPostQuit();
  803.                     break;
  804.                 case MENU_STEP:
  805.                     /*
  806.                      * Begin single step more or draw a frame if in single
  807.                      * step mode
  808.                      */
  809.                     if (!myglobs.bSingleStepMode) {
  810.                         myglobs.bSingleStepMode = TRUE;
  811.                         myglobs.bDrawAFrame = TRUE;
  812.                     } else if (!myglobs.bDrawAFrame) {
  813.                         myglobs.bDrawAFrame = TRUE;
  814.                     }
  815.                     break;
  816.                 case MENU_GO:
  817.                     /*
  818.                      * Exit single step mode
  819.                      */
  820.                     if (myglobs.bSingleStepMode) {
  821.                         myglobs.bSingleStepMode = FALSE;
  822.                         ResetFrameRate();
  823.                     }
  824.                     break;
  825.                 case MENU_STATS:
  826.                     /*
  827.                      * Toggle output of frame rate and window info
  828.                      */
  829.                     if ((myglobs.bShowFrameRate) && (myglobs.bShowInfo)) {
  830.                         myglobs.bShowFrameRate = FALSE;
  831.                         myglobs.bShowInfo = FALSE;
  832.                         break;
  833.                     }
  834.                     if ((!myglobs.bShowFrameRate) && (!myglobs.bShowInfo)) {
  835.                         myglobs.bShowFrameRate = TRUE;
  836.                         break;
  837.                     }
  838.                     myglobs.bShowInfo = TRUE;
  839.                     break;
  840.                 case MENU_FULLSCREEN:
  841.                     if (d3dapp->bFullscreen) {
  842.                         /*
  843.                          * Return to a windowed mode.  Let D3DApp decide which
  844.                          * D3D driver to use in case this one cannot render to
  845.                          * the Windows display depth
  846.                          */
  847.                         if (!D3DAppWindow(D3DAPP_YOUDECIDE, D3DAPP_YOUDECIDE)) {
  848.                             ReportD3DAppError();
  849.                             CleanUpAndPostQuit();
  850.                             break;
  851.                         }
  852.                     } else {
  853.                         /*
  854.                          * Enter the current fullscreen mode.  D3DApp may
  855.                          * resort to another mode if this driver cannot do
  856.                          * the currently selected mode.
  857.                          */
  858.                         if (!D3DAppFullscreen(d3dapp->CurrMode)) {
  859.                             ReportD3DAppError();
  860.                             CleanUpAndPostQuit();
  861.                             break;
  862.                         }
  863.                     }
  864.                     break;
  865.                 /*
  866.                  * Texture filter method selection
  867.                  */
  868.                 case MENU_POINT_FILTER:
  869.                     if (myglobs.rstate.TextureFilter == D3DFILTER_NEAREST)
  870.                         break;
  871.                     myglobs.rstate.TextureFilter = D3DFILTER_NEAREST;
  872.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  873.                         ReportD3DAppError();
  874.                         break;
  875.                     }
  876.                     break;
  877.                 case MENU_LINEAR_FILTER:
  878.                     if (myglobs.rstate.TextureFilter == D3DFILTER_LINEAR)
  879.                         break;
  880.                     myglobs.rstate.TextureFilter = D3DFILTER_LINEAR;
  881.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  882.                         ReportD3DAppError();
  883.                         break;
  884.                     }
  885.                     break;
  886.                 /* 
  887.                  * Shading selection
  888.                  */
  889.                 case MENU_FLAT:
  890.                     if (myglobs.rstate.ShadeMode == D3DSHADE_FLAT)
  891.                         break;
  892.                     myglobs.rstate.ShadeMode = D3DSHADE_FLAT;
  893.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  894.                         ReportD3DAppError();
  895.                         break;
  896.                     }
  897.                     break;
  898.                 case MENU_GOURAUD:
  899.                     if (myglobs.rstate.ShadeMode == D3DSHADE_GOURAUD)
  900.                         break;
  901.                     myglobs.rstate.ShadeMode = D3DSHADE_GOURAUD;
  902.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  903.                         ReportD3DAppError();
  904.                         break;
  905.                     }
  906.                     break;
  907.                 case MENU_PHONG:
  908.                     if (myglobs.rstate.ShadeMode == D3DSHADE_PHONG)
  909.                         break;
  910.                     myglobs.rstate.ShadeMode = D3DSHADE_PHONG;
  911.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  912.                         ReportD3DAppError();
  913.                         break;
  914.                     }
  915.                     break;
  916.                 /*
  917.                  * Fill mode selection
  918.                  */
  919.                 case MENU_POINT:
  920.                     if (myglobs.rstate.FillMode == D3DFILL_POINT)
  921.                         break;
  922.                     myglobs.rstate.FillMode = D3DFILL_POINT;
  923.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  924.                         ReportD3DAppError();
  925.                         break;
  926.                     }
  927.                     break;
  928.                 case MENU_WIREFRAME:
  929.                     if (myglobs.rstate.FillMode == D3DFILL_WIREFRAME)
  930.                         break;
  931.                     myglobs.rstate.FillMode = D3DFILL_WIREFRAME;
  932.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  933.                         ReportD3DAppError();
  934.                         break;
  935.                     }
  936.                     break;
  937.                 case MENU_SOLID:
  938.                     if (myglobs.rstate.FillMode == D3DFILL_SOLID)
  939.                         break;
  940.                     myglobs.rstate.FillMode = D3DFILL_SOLID;
  941.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  942.                         ReportD3DAppError();
  943.                         break;
  944.                     }
  945.                     break;
  946.                 case MENU_PERSPCORRECT:
  947.                     /*
  948.                      * Toggle perspective correction
  949.                      */
  950.                     myglobs.rstate.bPerspCorrect =
  951.                         !myglobs.rstate.bPerspCorrect;
  952.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  953.                         ReportD3DAppError();
  954.                         break;
  955.                     }
  956.                     break;
  957.                 case MENU_CLEARS:
  958.                     /*
  959.                      * Toggle the clearing the the back buffer and Z-buffer
  960.                      * and set the resized flag to clear the entire window
  961.                      */
  962.                     myglobs.bClearsOn = !myglobs.bClearsOn;
  963.                     if (myglobs.bClearsOn)
  964.                         myglobs.bResized = TRUE;
  965.                     break;
  966.                 case MENU_ZBUFFER:
  967.                     /*
  968.                      * Toggle the use of a Z-buffer
  969.                      */
  970.                     myglobs.rstate.bZBufferOn = !myglobs.rstate.bZBufferOn;
  971.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  972.                         ReportD3DAppError();
  973.                         break;
  974.                     }
  975.                     break;
  976.                 case MENU_DITHERING:
  977.                     /*
  978.                      * Toggle dithering
  979.                      */
  980.                     myglobs.rstate.bDithering = !myglobs.rstate.bDithering;
  981.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  982.                         ReportD3DAppError();
  983.                         break;
  984.                     }
  985.                     break;
  986.                 case MENU_SPECULAR:
  987.                     /*
  988.                      * Toggle specular highlights
  989.                      */
  990.                     myglobs.rstate.bSpecular = !myglobs.rstate.bSpecular;
  991.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  992.                         ReportD3DAppError();
  993.                         break;
  994.                     }
  995.                     break;
  996.                 case MENU_FOG:
  997.                     /*
  998.                      * Toggle fog
  999.                      */
  1000.                     myglobs.rstate.bFogEnabled = !myglobs.rstate.bFogEnabled;
  1001.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1002.                         ReportD3DAppError();
  1003.                         break;
  1004.                     }
  1005.                     break;
  1006.                 case MENU_ANTIALIAS:
  1007.                     /*
  1008.                      * Toggle anti-aliasing
  1009.                      */
  1010.                     myglobs.rstate.bAntialiasing =
  1011.                         !myglobs.rstate.bAntialiasing;
  1012.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1013.                         ReportD3DAppError();
  1014.                         break;
  1015.                     }
  1016.                     break;
  1017.                 case MENU_TEXTURE_TOGGLE:
  1018.                     /*
  1019.                      * Release the sample's execute buffers, toggle the
  1020.                      * texture disabled state and recreate them.
  1021.                      */
  1022.                     ReleaseView(d3dapp->lpD3DViewport);
  1023.                     D3DAppDisableTextures(!d3dapp->bTexturesDisabled);
  1024.                     {
  1025.                         if (!InitView(d3dapp->lpDD, d3dapp->lpD3D,
  1026.                                       d3dapp->lpD3DDevice,
  1027.                                       d3dapp->lpD3DViewport,
  1028.                                       d3dapp->NumUsableTextures,
  1029.                                       d3dapp->TextureHandle)) {
  1030.                             Msg("InitView failed.\n");
  1031.                             CleanUpAndPostQuit();
  1032.                             break;
  1033.                         }
  1034.                     }
  1035.                     myglobs.bResized = TRUE;
  1036.                     break;
  1037.                 case MENU_TEXTURE_SWAP:
  1038.                     /*
  1039.                      * Swap textures using the load command
  1040.                      */
  1041.                     if (!D3DAppSwapTextures()) {
  1042.                         ReportD3DAppError();
  1043.                         break;
  1044.                     }
  1045.                     /*
  1046.                      * Just in case we have a texture background
  1047.                      */
  1048.                     myglobs.bResized = TRUE;
  1049.                     break;
  1050.                 case MENU_NEXT_MODE:
  1051.                     /*
  1052.                      * Enter the next usable fullscreen mode
  1053.                      */
  1054.                     i = d3dapp->CurrMode;
  1055.                     do {
  1056.                         ++i;
  1057.                         if (i >= d3dapp->NumModes)
  1058.                             i = 0;
  1059.                         if (!d3dapp->Mode[i].bThisDriverCanDo)
  1060.                             continue;
  1061.                         else {
  1062.                             if (!D3DAppFullscreen(i)) {
  1063.                                 ReportD3DAppError();
  1064.                                 CleanUpAndPostQuit();
  1065.                             }
  1066.                             break;
  1067.                         }
  1068.                     } while(i != d3dapp->CurrMode);
  1069.                     break;
  1070.                 case MENU_PREVIOUS_MODE:
  1071.                     /*
  1072.                      * Enter the previous usable fullscreen mode
  1073.                      */
  1074.                     i = d3dapp->CurrMode;
  1075.                     do {
  1076.                         --i;
  1077.                         if (i < 0)
  1078.                             i = d3dapp->NumModes - 1;
  1079.                         if (!d3dapp->Mode[i].bThisDriverCanDo)
  1080.                             continue;
  1081.                         else {
  1082.                             if (!D3DAppFullscreen(i)) {
  1083.                                 ReportD3DAppError();
  1084.                                 CleanUpAndPostQuit();
  1085.                             }
  1086.                             break;
  1087.                         }
  1088.                     } while(i != d3dapp->CurrMode);
  1089.                     break;
  1090.             }
  1091.             if (   LOWORD(wParam) >= MENU_FIRST_FORMAT
  1092.                 && LOWORD(wParam) < MENU_FIRST_FORMAT +
  1093.                     D3DAPP_MAXTEXTUREFORMATS
  1094.                 && d3dapp->CurrTextureFormat !=
  1095.                     LOWORD(wParam) - MENU_FIRST_FORMAT) {
  1096.                 /*
  1097.                  * Release the sample's execute buffers, change the texture
  1098.                  * format and recreate the view.
  1099.                  */
  1100.                 ReleaseView(d3dapp->lpD3DViewport);
  1101.                 if (!D3DAppChangeTextureFormat(LOWORD(wParam) -
  1102.                                                MENU_FIRST_FORMAT)) {
  1103.                     ReportD3DAppError();
  1104.                     CleanUpAndPostQuit();
  1105.                 }
  1106.                 {
  1107.                     if (!InitView(d3dapp->lpDD, d3dapp->lpD3D,
  1108.                                   d3dapp->lpD3DDevice, d3dapp->lpD3DViewport,
  1109.                                   d3dapp->NumUsableTextures,
  1110.                                   d3dapp->TextureHandle)) {
  1111.                         Msg("InitView failed.\n");
  1112.                         CleanUpAndPostQuit();
  1113.                         break;
  1114.                     }
  1115.                 }
  1116.                 ResetFrameRate();
  1117.             }
  1118.             if (   LOWORD(wParam) >= MENU_FIRST_DRIVER
  1119.                 && LOWORD(wParam) < MENU_FIRST_DRIVER + D3DAPP_MAXD3DDRIVERS
  1120.                 && d3dapp->CurrDriver != LOWORD(wParam) - MENU_FIRST_DRIVER) {
  1121.                 /*
  1122.                  * Change the D3D driver
  1123.                  */
  1124.                 if (!D3DAppChangeDriver(LOWORD(wParam) - MENU_FIRST_DRIVER,
  1125.                                         NULL)) {
  1126.                     ReportD3DAppError();
  1127.                     CleanUpAndPostQuit();
  1128.                 }
  1129.             }
  1130.             if (   LOWORD(wParam) >= MENU_FIRST_MODE
  1131.                 && LOWORD(wParam) < MENU_FIRST_MODE+100) {
  1132.                 /*
  1133.                  * Switch to the selected fullscreen mode
  1134.                  */
  1135.                 if (!D3DAppFullscreen(LOWORD(wParam) - MENU_FIRST_MODE)) {
  1136.                     ReportD3DAppError();
  1137.                     CleanUpAndPostQuit();
  1138.                 }
  1139.             }
  1140.             /*
  1141.              * Whenever we receive a command in single step mode, draw a frame
  1142.              */
  1143.             if (myglobs.bSingleStepMode)
  1144.                 myglobs.bDrawAFrame = TRUE;
  1145.             return 0L;
  1146.     }
  1147.     return DefWindowProc(hWnd, message, wParam, lParam);
  1148. }
  1149.  
  1150.  
  1151. /****************************************************************************/
  1152. /*                 Setting up callbacks for examples                        */
  1153. /****************************************************************************/
  1154.  /*
  1155.   * SetMouseCallback
  1156.   * Called in an example to set a callback function for all WM messages
  1157.   * dealing with the mouse.  The handler should return whether or not
  1158.   * it handled the message.
  1159.   */
  1160. BOOL
  1161. SetMouseCallback(BOOL(*Handler)(UINT, WPARAM, LPARAM))
  1162. {
  1163.     MouseHandler = Handler;
  1164.     return TRUE;
  1165. }
  1166.  
  1167. /*
  1168.  * SetKeyboardCallback
  1169.  * Called in an example to set a callback function for all WM messages
  1170.  * dealing with the keyboard. The handler should return whether or not it
  1171.  * handled the message.
  1172.  */
  1173. BOOL
  1174. SetKeyboardCallback(BOOL(*Handler)(UINT, WPARAM, LPARAM)) {
  1175.     
  1176.     KeyboardHandler = Handler;
  1177.     return TRUE;
  1178. }
  1179.  
  1180. /****************************************************************************/
  1181. /*          Initialization, error reporting and release functions.          */
  1182. /****************************************************************************/
  1183. /*
  1184.  * InitGlobals
  1185.  * Called once at program initialization to initialize global variables.
  1186.  */
  1187. static void
  1188. InitGlobals(void)
  1189. {
  1190.     d3dapp = NULL;
  1191.     memset(&myglobs.rstate, 0, sizeof(myglobs.rstate));
  1192.     memset(&myglobs, 0, sizeof(myglobs));
  1193.     myglobs.bClearsOn = TRUE;
  1194.     myglobs.bShowFrameRate = TRUE;
  1195.     myglobs.bShowInfo = TRUE;
  1196.     MouseHandler = NULL;
  1197.     KeyboardHandler = NULL;
  1198. }
  1199.  
  1200. /*
  1201.  * CleanUpAndPostQuit
  1202.  * Release all D3D objects, post a quit message and set the bQuit flag
  1203.  */
  1204. void
  1205. CleanUpAndPostQuit(void)
  1206. {
  1207.     if (myglobs.bQuit)
  1208.         return;
  1209.     if (!D3DAppDestroy())
  1210.         ReportD3DAppError();
  1211.     ReleaseScene();
  1212.     myglobs.bQuit = TRUE;
  1213.     PostQuitMessage( 0 );
  1214. }
  1215.  
  1216. /*
  1217.  * ReportD3DAppError
  1218.  * Reports an error during a d3d app call.
  1219.  */
  1220. void
  1221. ReportD3DAppError(void)
  1222. {
  1223.     Msg("%s", D3DAppLastErrorString());
  1224. }
  1225.  
  1226. /* Msg
  1227.  * Message output for error notification.
  1228.  */
  1229. void __cdecl
  1230. Msg( LPSTR fmt, ... )
  1231. {
  1232.     char buff[256];
  1233.  
  1234.     wvsprintf(buff, fmt, (char *)(&fmt+1));
  1235.     lstrcat(buff, "\r\n");
  1236.     AppPause(TRUE);
  1237.     if (d3dapp && d3dapp->bFullscreen)
  1238.         SetWindowPos(myglobs.hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
  1239.                      SWP_NOSIZE | SWP_NOMOVE);
  1240.     MessageBox( NULL, buff, "D3D Example Message", MB_OK );
  1241.     if (d3dapp && d3dapp->bFullscreen)
  1242.         SetWindowPos(myglobs.hWndMain, HWND_TOPMOST, 0, 0, 0, 0,
  1243.                      SWP_NOSIZE | SWP_NOMOVE);
  1244.     AppPause(FALSE);
  1245. }
  1246.  
  1247.