RMFULL.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:36k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: rmfull.cpp
  5.  *
  6.  *  Each of the Direct3D retained mode (D3DRM) samples may be linked with
  7.  *  this file.  It contains the code which allows them to run in the Windows
  8.  *  environment as a window or fullscreen.  It is a modified version of
  9.  *  d3dmain.cpp.  Comparing these two files is instructive.
  10.  *
  11.  *  A window is created using rmfull.res which allows the user to select the
  12.  *  Direct3D driver to use and change the render options.  The D3DApp
  13.  *  collection of functions is used to initialize DirectDraw, Direct3D and
  14.  *  keep surfaces and D3D devices available for rendering.
  15.  *
  16.  *  Frame rate and a screen mode information buffer is Blt'ed to the screen
  17.  *  by functions in rmstats.cpp.
  18.  *
  19.  *  Individual samples are executed through two functions, BuildScene and
  20.  *  OverrideDefaults, as described in rmdemo.h.  Samples can also read
  21.  *  mouse input via ReadMouse.
  22.  */
  23. #include "rmfull.h"
  24. #include <stdarg.h>
  25. /*
  26.  * GLOBAL VARIABLES
  27.  */
  28. D3DAppInfo* d3dapp;     /* Pointer to read only collection of DD and D3D
  29.        objects maintained by D3DApp */
  30. rmfullglobals myglobs;     /* collection of global variables */
  31. LPDIRECT3DRM lpD3DRM; /* Direct3DRM object */
  32. /*
  33.  *  INTERNAL FUNCTION PROTOTYPES
  34.  */
  35. static BOOL AppInit(HINSTANCE hInstance, LPSTR lpCmdLine);
  36. static BOOL CreateD3DApp(LPSTR lpCmdLine);
  37. static BOOL BeforeDeviceDestroyed(LPVOID lpContext);
  38. static BOOL AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT* lpViewport,
  39.        LPVOID lpContext);
  40. void CleanUpAndPostQuit(void);
  41. static void InitGlobals(void);
  42. static BOOL AppPause(BOOL f);
  43. void ReportD3DAppError(void);
  44. static BOOL RenderLoop(void);
  45. static BOOL RestoreSurfaces();
  46. long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  47.    LPARAM lParam );
  48. extern "C" void ReadMouse(int*, int*, int*);
  49. extern "C" char* D3DRMErrorToString(HRESULT error);
  50. BOOL CreateD3DRM(HWND win);
  51. BOOL SetRenderState(void);
  52. /****************************************************************************/
  53. /*                            WinMain                                       */
  54. /****************************************************************************/
  55. /*
  56.  * Initializes the application then enters a message loop which calls sample's
  57.  * RenderScene until a quit message is received.
  58.  */
  59. int PASCAL
  60. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  61. int nCmdShow)
  62. {
  63.     int failcount = 0; /* number of times RenderLoop has failed */
  64.     MSG msg;
  65.     HACCEL hAccelApp;
  66.     hPrevInstance;
  67.     /*
  68.      * Create the window and initialize all objects needed to begin rendering
  69.      */
  70.     if(!AppInit(hInstance, lpCmdLine))
  71.      return FALSE;
  72.     hAccelApp = LoadAccelerators(hInstance, "AppAccel");
  73.     while (!myglobs.bQuit) {
  74. /* 
  75.  * Monitor the message queue until there are no pressing
  76.  * messages
  77.  */
  78.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  79.             if (msg.message == WM_QUIT) {
  80. CleanUpAndPostQuit();
  81.                 break;
  82.     }
  83.             if (!myglobs.hWndMain || !TranslateAccelerator(myglobs.hWndMain,
  84.    hAccelApp, &msg)) {
  85.                 TranslateMessage(&msg); 
  86.                 DispatchMessage(&msg);
  87.             }
  88. /* 
  89.  * If the app is not minimized, not about to quit, not paused, either the
  90.  * active fullscreen app or in a window and D3D has been initialized,
  91.  * we can render
  92.  */
  93.         } else if (d3dapp->bRenderingIsOK && !d3dapp->bMinimized
  94.    && !d3dapp->bPaused && !myglobs.bQuit 
  95.    && (d3dapp->bAppActive || !d3dapp->bFullscreen)) {
  96.     /*
  97.      * If were are not in single step mode or if we are and the
  98.      * bDrawAFrame flag is set, render one frame
  99.      */
  100.             if (!(myglobs.bSingleStepMode && !myglobs.bDrawAFrame)) {
  101. /* 
  102.  * Attempt to render a frame, if it fails, take a note.  If
  103.  * rendering fails more than twice, abort execution.
  104.  */
  105. if (!RenderLoop()) {
  106.     ++failcount;
  107.     if (failcount == 3) {
  108. Msg("Rendering has failed too many times.  Aborting execution.n");
  109. CleanUpAndPostQuit();
  110. break;
  111.     }
  112. }
  113.     }
  114.     /*
  115.      * Reset the bDrawAFrame flag if we are in single step mode
  116.      */
  117.             if (myglobs.bSingleStepMode)
  118.                 myglobs.bDrawAFrame = FALSE;
  119.         } else {
  120.     WaitMessage();
  121. }
  122.     }
  123.     DestroyWindow(myglobs.hWndMain);
  124.     return msg.wParam;
  125. }
  126. /****************************************************************************/
  127. /*             D3DApp Initialization and callback functions                 */
  128. /****************************************************************************/
  129. /*
  130.  * AppInit
  131.  * Creates the window and initializes all objects necessary to begin rendering
  132.  */
  133. static BOOL
  134. AppInit(HINSTANCE hInstance, LPSTR lpCmdLine)
  135. {
  136.     WNDCLASS wc;
  137.     HMENU hmenu;
  138.     DWORD flags;
  139.     int i;
  140.     Defaults defaults;
  141.     /*
  142.      * Register the window class
  143.      */
  144.     wc.style = CS_HREDRAW | CS_VREDRAW;
  145.     wc.lpfnWndProc = WindowProc;
  146.     wc.cbClsExtra = 0;
  147.     wc.cbWndExtra = 0;
  148.     wc.hInstance = hInstance;
  149.     wc.hIcon = LoadIcon( hInstance, "AppIcon");
  150.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  151.     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  152.     wc.lpszMenuName = "AppMenu";
  153.     wc.lpszClassName = "Example";
  154.     if (!RegisterClass(&wc))
  155.         return FALSE;
  156.     /*
  157.      * Initialize the global variables and allow the sample code to override
  158.      * some of these default settings.
  159.      */
  160.     InitGlobals();
  161.     myglobs.hInstApp = hInstance;
  162.     defaults.bNoTextures = myglobs.bNoTextures;
  163.     defaults.bConstRenderQuality = myglobs.bConstRenderQuality;
  164.     defaults.bResizingDisabled = FALSE;
  165.     lstrcpy(defaults.Name, "D3DRM Example");
  166.     OverrideDefaults(&defaults);
  167.     myglobs.bNoTextures = defaults.bNoTextures;
  168.     myglobs.bConstRenderQuality = defaults.bConstRenderQuality;
  169.     myglobs.lpCmdLine = lpCmdLine;
  170.     /*
  171.      * Enumerate the DD drivers
  172.      */
  173.     if (!D3DAppEnumerateDDDevices(&myglobs.NumDDDrivers, &myglobs.DDDriver[0])) {
  174. ReportD3DAppError();
  175. return FALSE;
  176.     }
  177.     /*
  178.      * Choose the last device enumerated which will probably be secondary 3d hardware.
  179.      */
  180.     myglobs.CurrDDDriver = myglobs.NumDDDrivers - 1;
  181.     /*
  182.      * Create the window
  183.      */
  184.     if (defaults.bResizingDisabled)
  185. flags =  WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
  186.  WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
  187.     else
  188. flags = WS_OVERLAPPEDWINDOW;
  189.     /*
  190.      * Create a window with some default settings that may change
  191.      */
  192.     myglobs.hWndMain = CreateWindowEx(
  193.           WS_EX_APPWINDOW,
  194.  "Example",
  195.  defaults.Name,
  196.  flags,
  197.          CW_USEDEFAULT, CW_USEDEFAULT,
  198.  START_WIN_SIZE, START_WIN_SIZE,
  199.          NULL,     /* parent window */
  200.  NULL,     /* menu handle */
  201.  hInstance,     /* program handle */
  202.  NULL);     /* create parms */
  203.     if (!myglobs.hWndMain){
  204.      Msg("CreateWindowEx failed");
  205.      return FALSE;
  206.     }
  207.     /*
  208.      * Display the window
  209.      */
  210.     ShowWindow(myglobs.hWndMain, SW_SHOWNORMAL);
  211.     UpdateWindow(myglobs.hWndMain);
  212.     /*
  213.      * Add the list of DD drivers D3DApp found to the file menu
  214.      */
  215.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 0);
  216.     for (i = 0; i < myglobs.NumDDDrivers; i++) {
  217.         InsertMenu(hmenu,  6 + i, MF_BYPOSITION | MF_STRING,
  218.    MENU_FIRST_DDDRIVER + i, myglobs.DDDriver[i].Name);
  219.     }
  220.     /* 
  221.      * Create the D3DRM object which are initialized only when the program
  222.      * starts
  223.      */
  224.     if (!CreateD3DRM(myglobs.hWndMain))
  225.         return FALSE;
  226.     /*
  227.      * Call D3DApp to initialize all DD and D3D objects necessary to render.
  228.      * D3DApp will call the device creation callback which will initialize the
  229.      * viewport and the sample's execute buffers.
  230.      */
  231.     if (!CreateD3DApp(lpCmdLine))
  232. return FALSE;
  233.     /*
  234.      * Create the scene to be rendered by calling this sample's BuildScene
  235.      */
  236.     if (!BuildScene(myglobs.dev, myglobs.view, myglobs.scene, myglobs.camera))
  237. return FALSE;
  238.     return TRUE;
  239. }
  240. /*
  241.  * CreateD3DRM
  242.  * Create main D3DRM objects which are only initialized once.
  243.  */
  244. BOOL
  245. CreateD3DRM(HWND win)
  246. {
  247.     HRESULT rval;
  248.     /*
  249.      * Create the D3DRM object
  250.      */
  251.     rval = Direct3DRMCreate(&lpD3DRM);
  252.     if (rval != D3DRM_OK) {
  253. Msg("Failed to create Direct3DRM.n%s", D3DAppErrorToString(rval));
  254. return FALSE;
  255.     }
  256.     /*
  257.      * Create the master scene frame and camera frame
  258.      */
  259.     rval = lpD3DRM->CreateFrame(NULL, &myglobs.scene);
  260.     if (rval != D3DRM_OK) {
  261. Msg("Failed to create the master scene frame.n%s", D3DAppErrorToString(rval));
  262. return FALSE;
  263.     }
  264.     rval = lpD3DRM->CreateFrame(myglobs.scene, &myglobs.camera);
  265.     if (rval != D3DRM_OK) {
  266. Msg("Failed to create the camera's frame.n%s", D3DAppErrorToString(rval));
  267. return FALSE;
  268.     }
  269.     rval = myglobs.camera->SetPosition(myglobs.scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));
  270.     if (rval != D3DRM_OK) {
  271. Msg("Failed to position the camera in the frame.n%s", D3DAppErrorToString(rval));
  272. return FALSE;
  273.     }
  274.     return TRUE;
  275. }
  276. /*
  277.  * CreateD3DApp
  278.  * Create all DirectDraw and Direct3D objects necessary to begin rendering.
  279.  * Add the list of D3D drivers to the file menu.
  280.  */
  281. static BOOL
  282. CreateD3DApp(LPSTR lpCmdLine)
  283. {
  284.     HMENU hmenu;
  285.     int i;
  286.     LPSTR option;
  287.     BOOL bOnlySystemMemory, bOnlyEmulation;
  288.     DWORD flags;
  289.     /*
  290.      * Parse the command line in seach of one of the following options:
  291.      *     systemmemory  All surfaces should be created in system memory.
  292.      *                   Hardware DD and D3D devices are disabled, but
  293.      *                   debugging during the Win16 lock becomes possible.
  294.      *     emulation     Do not use hardware DD or D3D devices.
  295.      */
  296.     bOnlySystemMemory = FALSE;
  297.     bOnlyEmulation = FALSE;
  298.     option = strtok(lpCmdLine, " -");
  299.     while(option != NULL )   {
  300.         if (!lstrcmp(option, "systemmemory")) {
  301.             bOnlySystemMemory = TRUE;
  302.         } else if (!lstrcmp(option, "emulation")) {
  303.     bOnlyEmulation = TRUE;
  304. } else {
  305.             Msg("Invalid command line options given.nLegal options: -systemmemory, -emulationn");
  306.             return FALSE;
  307.         }
  308.         option = strtok(NULL, " -");
  309.     }
  310.     /*
  311.      * Set the flags to pass to the D3DApp creation based on command line
  312.      */
  313.     flags = ((bOnlySystemMemory) ? D3DAPP_ONLYSYSTEMMEMORY : 0) | 
  314.     ((bOnlyEmulation) ? (D3DAPP_ONLYD3DEMULATION |
  315.  D3DAPP_ONLYDDEMULATION) : 0);
  316.     /*
  317.      * Create all the DirectDraw and D3D objects neccesary to render.  The
  318.      * AfterDeviceCreated callback function is called by D3DApp to create the
  319.      * viewport and the example's execute buffers.
  320.      */
  321.     if (!D3DAppCreateFromHWND(flags, myglobs.hWndMain, 
  322.       myglobs.DDDriver[myglobs.CurrDDDriver].bIsPrimary ? NULL : &myglobs.DDDriver[myglobs.CurrDDDriver].Guid,
  323.       AfterDeviceCreated, NULL, BeforeDeviceDestroyed, NULL, &d3dapp)) {
  324. ReportD3DAppError();
  325. return FALSE;
  326.     }
  327.     /*
  328.      * Add the the list of display modes D3DApp found to the mode menu
  329.      */
  330.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 2);
  331.     for (i = 0; i < d3dapp->NumModes; i++) {
  332.         char ach[80];
  333.         wsprintf(ach,"%dx%dx%d", d3dapp->Mode[i].w, d3dapp->Mode[i].h,
  334.  d3dapp->Mode[i].bpp);
  335.         AppendMenu(hmenu, MF_STRING, MENU_FIRST_MODE+i, ach);
  336.     }
  337.     /*
  338.      * Add the list of D3D drivers D3DApp foudn to the file menu
  339.      */
  340.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 0);
  341.     for (i = 0; i < d3dapp->NumDrivers; i++) {
  342.         InsertMenu(hmenu, 7 + myglobs.NumDDDrivers + i, MF_BYPOSITION | MF_STRING,
  343.    MENU_FIRST_DRIVER + i, d3dapp->Driver[i].Name);
  344.     }
  345.     return TRUE;
  346. }
  347. /*
  348.  * DestroyD3DApp
  349.  *
  350.  * Destroy D3DApp and changes to menu
  351.  */
  352. static void
  353. DestroyD3DApp(void)
  354. {
  355.     HMENU hmenu;
  356.     int i;
  357.     /*
  358.      * Remove the list of display modes
  359.      */
  360.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 4);
  361.     for (i = 0; i < d3dapp->NumModes; i++) {
  362.         DeleteMenu(hmenu, MENU_FIRST_MODE + i, MF_BYCOMMAND);
  363.     }
  364.     /*
  365.      * Remove the list of D3D drivers
  366.      */
  367.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 0);
  368.     for (i = 0; i < d3dapp->NumDrivers; i++) {
  369.         DeleteMenu(hmenu, MENU_FIRST_DRIVER + i, MF_BYCOMMAND);
  370.     }
  371.     RELEASE(myglobs.lpInfoBuffer);
  372.     RELEASE(myglobs.lpFrameRateBuffer);
  373.     D3DAppDestroy();
  374. }
  375. /*
  376.  * AfterDeviceCreated
  377.  * D3DApp will call this function immediately after the D3D device has been
  378.  * created (or re-created).  D3DApp expects the D3D viewport to be created and
  379.  * returned.  In this case, we will return NULL because we only have a D3DRM
  380.  * viewport.  This is fine as long as we don't use any of the D3D viewport
  381.  * functionality of D3DApp.
  382.  */
  383. static BOOL
  384. AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT* lplpViewport, LPVOID lpContext)
  385. {
  386.     HRESULT rval;
  387.     rval = lpD3DRM->CreateDeviceFromD3D(d3dapp->lpD3D, d3dapp->lpD3DDevice,
  388. &myglobs.dev);
  389.     if (rval != D3DRM_OK) {
  390.         Msg("Creation of D3DRM device failed.n%s", D3DAppErrorToString(rval));
  391.         return FALSE;
  392.     }
  393.     /*
  394.      * Create the D3DRM viewport using the camera frame.  Set the background
  395.      * depth to a large number.  The width and height may be slightly
  396.      * adjusted, so get them from the device to be sure.
  397.      */
  398.     w = myglobs.dev->GetWidth();
  399.     h = myglobs.dev->GetHeight();
  400.     rval = lpD3DRM->CreateViewport(myglobs.dev, myglobs.camera, 0, 0, w,
  401.    h, &myglobs.view);
  402.     if (rval != D3DRM_OK) {
  403. Msg("Failed to create the D3DRM viewport.n%s",
  404.     D3DAppErrorToString(rval));
  405. RELEASE(myglobs.dev);
  406. return FALSE;
  407.     }
  408.     rval = myglobs.view->SetBack(D3DVAL(5000.0));
  409.     if (rval != D3DRM_OK) {
  410. Msg("Failed to set the background depth of the D3DRM viewport.n%s",
  411.     D3DAppErrorToString(rval));
  412. RELEASE(myglobs.dev);
  413. RELEASE(myglobs.view);
  414. return FALSE;
  415.     }
  416.     /*
  417.      * Set the render quality, fill mode, lighting state and color shade info
  418.      */
  419.     if (!SetRenderState())
  420. return FALSE;
  421.     /*
  422.      * Return NULL for the viewport
  423.      */
  424.     *lplpViewport = NULL;
  425.     /*
  426.      * Create and initialize the surfaces containing the frame rate and
  427.      * window information
  428.      */
  429.     InitFontAndTextBuffers();
  430.     return TRUE;
  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.     RELEASE(myglobs.view);
  442.     RELEASE(myglobs.dev);
  443.     return TRUE;
  444. }
  445. /****************************************************************************/
  446. /*                            Rendering loop                                */
  447. /****************************************************************************/
  448. /*
  449.  * RenderLoop
  450.  * Render the next frame and update the window
  451.  */
  452. static BOOL
  453. RenderLoop()
  454. {
  455.     D3DRECT extents[D3DAPP_MAXCLEARRECTS];
  456.     int count;
  457.     HRESULT rval;
  458.     static BOOL b = FALSE; // Clear the second buffer on also
  459.     /*
  460.      * If all the DD and D3D objects have been initialized we can render
  461.      */
  462.     if (d3dapp->bRenderingIsOK) {
  463. /*
  464.  * Restore any lost surfaces
  465.  */
  466.         if (!RestoreSurfaces()) {
  467.     /*
  468.      * Restoring surfaces sometimes fails because the surfaces cannot
  469.      * yet be restored.  If this is the case, the error will show up
  470.      * somewhere else and we should return success here to prevent
  471.      * unnecessary error's being reported.
  472.      */
  473.     return TRUE;
  474. }
  475. /*
  476.  * Force an update of the entire client window if the resized flag is set
  477.  */
  478. if (myglobs.bResized || b)
  479.     myglobs.view->ForceUpdate(0, 0, d3dapp->szClient.cx, d3dapp->szClient.cy);
  480. /*
  481.  * Use b to makesure the second buffer is cleared also
  482.  */
  483. if (b)
  484.     b = FALSE;
  485. if (myglobs.bResized)
  486.     b = TRUE;
  487. /*
  488.  * Calculate the frame rate
  489.  */
  490.         if (!CalculateFrameRate())
  491.     return FALSE;
  492. /*
  493.  * Tick the scene
  494.  */
  495. rval = myglobs.scene->Move(D3DVAL(1.0));
  496. if (rval != D3DRM_OK) {
  497.     Msg("Moving scene failed.n%s", D3DAppErrorToString(rval));
  498.     return FALSE;
  499. }
  500. /* 
  501.  * Clear the viewport
  502.  */
  503. rval = myglobs.view->Clear();
  504. if (rval != D3DRM_OK) {
  505.     Msg("Clearing viewport failed.n%s", D3DAppErrorToString(rval));
  506.     return FALSE;
  507. }
  508. /*
  509.  * Render the scene to the viewport
  510.  */
  511. rval = myglobs.view->Render(myglobs.scene);
  512. if (rval != D3DRM_OK) {
  513.     Msg("Rendering scene failed.n%s", D3DAppErrorToString(rval));
  514.     return FALSE;
  515. }
  516. /*
  517.  * Blt the frame rate and window stat text to the back buffer
  518.  */
  519. count = 0;
  520.         if (!DisplayFrameRate(&count, &extents[0]))
  521.     return FALSE;
  522. for (;count;--count)
  523.     myglobs.view->ForceUpdate(extents[count-1].x1, extents[count-1].y1,
  524.       extents[count-1].x2, extents[count-1].y2);
  525. /*
  526.  * Update the window
  527.  */
  528. rval = myglobs.dev->Update();
  529. if (rval != D3DRM_OK) {
  530.     Msg("Updating device failed.n%s", D3DAppErrorToString(rval));
  531.     return FALSE;
  532. }
  533. /*
  534.  * Blt or flip the back buffer to the front buffer.  If this fails,
  535.  * don't report an error.
  536.  */
  537. D3DAppShowBackBuffer(myglobs.bResized ? D3DAPP_SHOWALL : NULL);
  538. /*
  539.  * Reset the resize flag
  540.  */
  541.         myglobs.bResized = FALSE;
  542.     }
  543.     return TRUE;
  544. }
  545. /*
  546.  * AppPause
  547.  * Pause and unpause the application
  548.  */
  549. static BOOL
  550. AppPause(BOOL f)
  551. {
  552.     /*
  553.      * Flip to the GDI surface and halt rendering
  554.      */
  555.     if (!D3DAppPause(f))
  556. return FALSE;
  557.     /*
  558.      * When returning from a pause, reset the frame rate count
  559.      */
  560.     if (!f) {
  561.         ResetFrameRate();
  562. myglobs.bResized = TRUE;
  563.     }
  564.     return TRUE;
  565. }
  566. /*
  567.  * RestoreSurfaces
  568.  * Restores any lost surfaces.  Returns TRUE if all surfaces are not lost and
  569.  * FALSE if one or more surfaces is lost and can not be restored at the
  570.  * moment.
  571.  */
  572. static BOOL
  573. RestoreSurfaces()
  574. {
  575.     HRESULT d3drval;
  576.     /*
  577.      * Have D3DApp check all the surfaces it's in charge of
  578.      */
  579.     if (!D3DAppCheckForLostSurfaces()) {
  580.             return FALSE;
  581.     }
  582.     /*
  583.      * Check frame rate and info surfaces and re-write them if they
  584.      * were lost.
  585.      */
  586.     if (myglobs.lpFrameRateBuffer->IsLost() == DDERR_SURFACELOST) {
  587.         d3drval = myglobs.lpFrameRateBuffer->Restore();
  588.         if (d3drval != DD_OK) {
  589.             return FALSE;
  590.         }
  591. if (!WriteFrameRateBuffer(0.0f, 0))
  592.     return FALSE;
  593.     }
  594.     if (myglobs.lpInfoBuffer->IsLost() == DDERR_SURFACELOST) {
  595.         d3drval = myglobs.lpInfoBuffer->Restore();
  596.         if (d3drval != DD_OK) {
  597.             return FALSE;
  598.         }
  599. if (!WriteInfoBuffer())
  600.     return FALSE;
  601.     }
  602.     return TRUE;
  603. }
  604. /*************************************************************************
  605.   Windows message handlers
  606.  *************************************************************************/
  607. /*
  608.  * AppAbout
  609.  * About box message handler
  610.  */
  611. BOOL
  612. FAR PASCAL AppAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  613. {
  614.   switch (msg)
  615.   {
  616.     case WM_COMMAND:
  617.       if (LOWORD(wParam) == IDOK)
  618.         EndDialog(hwnd, TRUE);
  619.       break;
  620.     case WM_INITDIALOG:
  621.       return TRUE;
  622.   }
  623.   return FALSE;
  624. }
  625. /*
  626.  * WindowProc
  627.  * Main window message handler.
  628.  */
  629. long
  630. FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  631.    LPARAM lParam )
  632. {
  633.     int i;
  634.     BOOL bStop;
  635.     LRESULT lresult;
  636.     /*
  637.      * Give D3DApp an opportunity to process any messages it MUST see in order
  638.      * to perform it's function.
  639.      */
  640.     if (!D3DAppWindowProc(&bStop, &lresult, hWnd, message, wParam, lParam)) {
  641. ReportD3DAppError();
  642. CleanUpAndPostQuit();
  643. return 0;
  644.     }
  645.     /* 
  646.      * If bStop is set by D3DApp, the app should not process the message but
  647.      * return lresult.
  648.      */
  649.     if (bStop)
  650. return lresult;
  651.     if (!d3dapp || !d3dapp->bRenderingIsOK) {
  652. return DefWindowProc(hWnd, message, wParam, lParam);
  653.     }
  654.     switch( message ) {
  655. case WM_LBUTTONDOWN:
  656. case WM_LBUTTONUP:
  657. case WM_RBUTTONDOWN:
  658. case WM_RBUTTONUP:
  659. case WM_MOUSEMOVE:
  660.     /*
  661.      * Record the mouse state for ReadMouse
  662.      */
  663.     myglobs.mouse_buttons = wParam;
  664.     myglobs.mouse_x = LOWORD(lParam);
  665.     myglobs.mouse_y = HIWORD(lParam);
  666.     break;
  667.         case WM_ENTERMENULOOP:
  668.             AppPause(TRUE);
  669.             break;
  670.         case WM_EXITMENULOOP:
  671.             AppPause(FALSE);
  672.             break;
  673.      case WM_DESTROY:
  674.             myglobs.hWndMain = NULL;
  675.             CleanUpAndPostQuit();
  676.             break;
  677.         case WM_INITMENUPOPUP:
  678.     /*
  679.              * Check and enable the appropriate menu items
  680.      */
  681.             CheckMenuItem((HMENU)wParam, MENU_STEP, (myglobs.bSingleStepMode) ? MF_CHECKED : MF_UNCHECKED);
  682.             EnableMenuItem((HMENU)wParam, MENU_GO, (myglobs.bSingleStepMode) ? MF_ENABLED : MF_GRAYED);
  683.     EnableMenuItem((HMENU)wParam, MENU_PHONG, MF_GRAYED);
  684.     if (!myglobs.bConstRenderQuality) {
  685. CheckMenuItem((HMENU)wParam, MENU_LIGHTING, (myglobs.RenderQuality & D3DRMLIGHT_MASK) == D3DRMLIGHT_ON ? MF_CHECKED : MF_GRAYED);
  686. CheckMenuItem((HMENU)wParam, MENU_FLAT, (myglobs.RenderQuality & D3DRMSHADE_MASK) == D3DRMSHADE_FLAT ? MF_CHECKED : MF_UNCHECKED);
  687. CheckMenuItem((HMENU)wParam, MENU_GOURAUD, (myglobs.RenderQuality & D3DRMSHADE_MASK) == D3DRMSHADE_GOURAUD ? MF_CHECKED : MF_UNCHECKED);
  688. CheckMenuItem((HMENU)wParam, MENU_PHONG, (myglobs.RenderQuality & D3DRMSHADE_MASK) == D3DRMSHADE_PHONG ? MF_CHECKED : MF_UNCHECKED);
  689. EnableMenuItem((HMENU)wParam, MENU_PHONG, MF_GRAYED);
  690. CheckMenuItem((HMENU)wParam, MENU_POINT, (myglobs.RenderQuality & D3DRMFILL_MASK) == D3DRMFILL_POINTS ? MF_CHECKED : MF_UNCHECKED);
  691. CheckMenuItem((HMENU)wParam, MENU_WIREFRAME, (myglobs.RenderQuality & D3DRMFILL_MASK) == D3DRMFILL_WIREFRAME ? MF_CHECKED : MF_UNCHECKED);
  692. CheckMenuItem((HMENU)wParam, MENU_SOLID, (myglobs.RenderQuality & D3DRMFILL_MASK) == D3DRMFILL_SOLID ? MF_CHECKED : MF_UNCHECKED);
  693.     } else {
  694. EnableMenuItem((HMENU)wParam, MENU_LIGHTING, MF_GRAYED);
  695. EnableMenuItem((HMENU)wParam, MENU_FLAT, MF_GRAYED);
  696. EnableMenuItem((HMENU)wParam, MENU_GOURAUD, MF_GRAYED);
  697. EnableMenuItem((HMENU)wParam, MENU_PHONG, MF_GRAYED);
  698. EnableMenuItem((HMENU)wParam, MENU_POINT, MF_GRAYED);
  699. EnableMenuItem((HMENU)wParam, MENU_WIREFRAME, MF_GRAYED);
  700. EnableMenuItem((HMENU)wParam, MENU_SOLID, MF_GRAYED);
  701.     }
  702.             if (!myglobs.bNoTextures && d3dapp->ThisDriver.bDoesTextures) {
  703. CheckMenuItem((HMENU)wParam, MENU_POINT_FILTER, (myglobs.TextureQuality == D3DRMTEXTURE_NEAREST) ? MF_CHECKED : MF_UNCHECKED);
  704. CheckMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (myglobs.TextureQuality == D3DRMTEXTURE_LINEAR) ? MF_CHECKED : MF_UNCHECKED);
  705.     } else {
  706. EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, MF_GRAYED);
  707. EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, MF_GRAYED);
  708.     }
  709.             CheckMenuItem((HMENU)wParam, MENU_DITHERING, (myglobs.bDithering) ? MF_CHECKED : MF_UNCHECKED);
  710.             CheckMenuItem((HMENU)wParam, MENU_ANTIALIAS, (myglobs.bAntialiasing) ? MF_CHECKED : MF_UNCHECKED);
  711.             EnableMenuItem((HMENU)wParam, MENU_ANTIALIAS, MF_GRAYED);
  712.     if (d3dapp->bIsPrimary) {
  713. CheckMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen ? MF_CHECKED : MF_UNCHECKED);
  714. EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen && !d3dapp->ThisDriver.bCanDoWindow ? MF_GRAYED : MF_ENABLED);
  715. EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  716. EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  717.     } else {
  718. EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, MF_GRAYED);
  719. EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, MF_GRAYED);
  720. EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, MF_GRAYED);
  721.     }
  722.     for (i = 0; i < d3dapp->NumModes; i++) {
  723. CheckMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (i == d3dapp->CurrMode) ? MF_CHECKED : MF_UNCHECKED);
  724. EnableMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (d3dapp->Mode[i].bThisDriverCanDo) ? MF_ENABLED : MF_GRAYED);
  725.     }
  726.             for (i = 0; i < d3dapp->NumDrivers; i++) {
  727.                 CheckMenuItem((HMENU)wParam, MENU_FIRST_DRIVER + i, (i == d3dapp->CurrDriver) ? MF_CHECKED : MF_UNCHECKED);
  728.             }
  729.             break;
  730.         case WM_COMMAND:
  731.             switch(LOWORD(wParam)) {
  732.                 case MENU_ABOUT:
  733.                     AppPause(TRUE);
  734.                     DialogBox(myglobs.hInstApp, "AppAbout", myglobs.hWndMain, (DLGPROC)AppAbout);
  735.                     AppPause(FALSE);
  736.                     break;
  737.                 case MENU_EXIT:
  738.             CleanUpAndPostQuit();
  739.              break;
  740.                 case MENU_STEP:
  741.     /*
  742.      * Begin single step more or draw a frame if in single
  743.      * step mode
  744.      */
  745.                     if (!myglobs.bSingleStepMode) {
  746.                         myglobs.bSingleStepMode = TRUE;
  747.                         myglobs.bDrawAFrame = TRUE;
  748.                     } else if (!myglobs.bDrawAFrame) {
  749.                         myglobs.bDrawAFrame = TRUE;
  750.                     }
  751.                     break;
  752.                 case MENU_GO:
  753.     /*
  754.      * Exit single step mode
  755.      */
  756.                     if (myglobs.bSingleStepMode) {
  757.                         myglobs.bSingleStepMode = FALSE;
  758.                         ResetFrameRate();
  759.                     }
  760.                     break;
  761.                 case MENU_STATS:
  762.     /*
  763.      * Toggle output of frame rate and window info
  764.      */
  765.                     if ((myglobs.bShowFrameRate) && (myglobs.bShowInfo)) {
  766.                         myglobs.bShowFrameRate = FALSE;
  767.                         myglobs.bShowInfo = FALSE;
  768.                         break;
  769.                     }
  770.                     if ((!myglobs.bShowFrameRate) && (!myglobs.bShowInfo)) {
  771.                         myglobs.bShowFrameRate = TRUE;
  772.                         break;
  773.                     }
  774.                     myglobs.bShowInfo = TRUE;
  775.                     break;
  776.          case MENU_FULLSCREEN:
  777.     if (d3dapp->bFullscreen) {
  778. /*
  779.  * Return to a windowed mode.  Let D3DApp decide which
  780.  * D3D driver to use in case this one cannot render to
  781.  * the Windows display depth
  782.  */
  783. if (!D3DAppWindow(D3DAPP_YOUDECIDE, D3DAPP_YOUDECIDE)) {
  784.     ReportD3DAppError();
  785.     CleanUpAndPostQuit();
  786.     break;
  787. }
  788.     } else {
  789. /*
  790.  * Enter the current fullscreen mode.  D3DApp may
  791.  * resort to another mode if this driver cannot do
  792.  * the currently selected mode.
  793.  */
  794. if (!D3DAppFullscreen(d3dapp->CurrMode)) {
  795.     ReportD3DAppError();
  796.     CleanUpAndPostQuit();
  797.     break;
  798. }
  799.     }
  800.                  break;
  801. /*
  802.  * Lighting toggle
  803.  */
  804. case MENU_LIGHTING:
  805.     myglobs.RenderQuality ^= D3DRMLIGHT_ON;
  806.     SetRenderState();
  807.     break;
  808. /*
  809.  * Fill mode selection
  810.  */
  811. case MENU_POINT:
  812.     myglobs.RenderQuality = (myglobs.RenderQuality & ~D3DRMFILL_MASK) | D3DRMFILL_POINTS;
  813.     SetRenderState();
  814.     break;
  815. case MENU_WIREFRAME:
  816.     myglobs.RenderQuality = (myglobs.RenderQuality & ~D3DRMFILL_MASK) | D3DRMFILL_WIREFRAME;
  817.     SetRenderState();
  818.     break;
  819. case MENU_SOLID:
  820.     myglobs.RenderQuality = (myglobs.RenderQuality & ~D3DRMFILL_MASK) | D3DRMFILL_SOLID;
  821.     SetRenderState();
  822.     break;
  823. /*
  824.  * Shade mode selection
  825.  */
  826. case MENU_FLAT:
  827.     myglobs.RenderQuality = (myglobs.RenderQuality & ~D3DRMSHADE_MASK) | D3DRMSHADE_FLAT;
  828.     SetRenderState();
  829.     break;
  830. case MENU_GOURAUD:
  831.     myglobs.RenderQuality = (myglobs.RenderQuality & ~D3DRMSHADE_MASK) | D3DRMSHADE_GOURAUD;
  832.     SetRenderState();
  833.     break;
  834. case MENU_PHONG:
  835.     myglobs.RenderQuality = (myglobs.RenderQuality & ~D3DRMSHADE_MASK) | D3DRMSHADE_PHONG;
  836.     SetRenderState();
  837.     break;
  838. case MENU_DITHERING:
  839.     myglobs.bDithering = !myglobs.bDithering;
  840.     SetRenderState();
  841.     break;
  842. case MENU_ANTIALIAS:
  843.     myglobs.bAntialiasing = !myglobs.bAntialiasing;
  844.     SetRenderState();
  845.     break;
  846. /*
  847.  * Texture filter selection
  848.  */
  849. case MENU_POINT_FILTER:
  850.     if (myglobs.TextureQuality == D3DRMTEXTURE_NEAREST)
  851. break;
  852.     myglobs.TextureQuality = D3DRMTEXTURE_NEAREST;
  853.     SetRenderState();
  854.     break;
  855. case MENU_LINEAR_FILTER:
  856.     if (myglobs.TextureQuality == D3DRMTEXTURE_LINEAR)
  857. break;
  858.     myglobs.TextureQuality = D3DRMTEXTURE_LINEAR;
  859.     SetRenderState();
  860.     break;
  861. case MENU_NEXT_MODE:
  862.     /*
  863.      * Enter the next usable fullscreen mode
  864.      */
  865.     i = d3dapp->CurrMode;
  866.     do {
  867. ++i;
  868. if (i >= d3dapp->NumModes)
  869.     i = 0;
  870. if (!d3dapp->Mode[i].bThisDriverCanDo)
  871.     continue;
  872. else {
  873.     if (!D3DAppFullscreen(i)) {
  874. ReportD3DAppError();
  875. CleanUpAndPostQuit();
  876.     }
  877.     break;
  878. }
  879.     } while(i != d3dapp->CurrMode);
  880.     break;
  881. case MENU_PREVIOUS_MODE:
  882.     /*
  883.      * Enter the previous usable fullscreen mode
  884.      */
  885.     i = d3dapp->CurrMode;
  886.     do {
  887. --i;
  888. if (i < 0)
  889.     i = d3dapp->NumModes - 1;
  890. if (!d3dapp->Mode[i].bThisDriverCanDo)
  891.     continue;
  892. else {
  893.     if (!D3DAppFullscreen(i)) {
  894. ReportD3DAppError();
  895. CleanUpAndPostQuit();
  896.     }
  897.     break;
  898. }
  899.     } while(i != d3dapp->CurrMode);
  900.                     break;
  901.             }
  902.             if (   LOWORD(wParam) >= MENU_FIRST_DRIVER
  903. && LOWORD(wParam) < MENU_FIRST_DRIVER + D3DAPP_MAXD3DDRIVERS
  904. && d3dapp->CurrDriver != LOWORD(wParam) - MENU_FIRST_DRIVER) {
  905. /*
  906.  * Change the D3D driver
  907.  */
  908. if (!D3DAppChangeDriver(LOWORD(wParam) - MENU_FIRST_DRIVER,
  909. NULL)) {
  910.     ReportD3DAppError();
  911.     CleanUpAndPostQuit();
  912. }
  913.             }
  914.             if (   LOWORD(wParam) >= MENU_FIRST_MODE
  915. && LOWORD(wParam) < MENU_FIRST_MODE+100) {
  916. /*
  917.  * Switch to the selected fullscreen mode
  918.  */
  919. if (!D3DAppFullscreen(LOWORD(wParam) - MENU_FIRST_MODE)) {
  920.     ReportD3DAppError();
  921.     CleanUpAndPostQuit();
  922. }
  923.             }
  924.             if (   LOWORD(wParam) >= MENU_FIRST_DDDRIVER
  925. && LOWORD(wParam) < MENU_FIRST_DDDRIVER + D3DAPP_MAXDDDRIVERS
  926. && myglobs.CurrDDDriver != LOWORD(wParam) - MENU_FIRST_DDDRIVER) {
  927. /*
  928.  * Change the DD driver
  929.  */
  930. DestroyD3DApp();
  931. myglobs.CurrDDDriver = LOWORD(wParam) - MENU_FIRST_DDDRIVER;
  932. SetWindowPos(myglobs.hWndMain, HWND_NOTOPMOST, 0, 0, START_WIN_SIZE, START_WIN_SIZE, SWP_NOMOVE | SWP_SHOWWINDOW);
  933. if (!CreateD3DApp(myglobs.lpCmdLine))
  934.     return FALSE;
  935.             }
  936.     /*
  937.      * Whenever we receive a command in single step mode, draw a frame
  938.      */
  939.     if (myglobs.bSingleStepMode)
  940. myglobs.bDrawAFrame = TRUE;
  941.             return 0L;
  942.     }
  943.     return DefWindowProc(hWnd, message, wParam, lParam);
  944. }
  945. /****************************************************************************/
  946. /*                          Additional Functions                            */
  947. /****************************************************************************/
  948. /*
  949.  * ReadMouse
  950.  * Returns the mouse status for interaction with sample code
  951.  */
  952. void
  953. ReadMouse(int* b, int* x, int* y)
  954. {
  955.     *b = myglobs.mouse_buttons;
  956.     *x = myglobs.mouse_x;
  957.     *y = myglobs.mouse_y;
  958. }
  959. /*
  960.  * SetRenderState
  961.  * Set the render quality, dither toggle and shade info if any of them has
  962.  * changed
  963.  */
  964. BOOL
  965. SetRenderState(void)
  966. {
  967.     HRESULT rval;
  968.     /*
  969.      * Set the number of buffers so D3DRM can keep track of extents properly
  970.      */
  971.     rval = myglobs.dev->SetBufferCount(d3dapp->bFullscreen &&
  972.        d3dapp->bBackBufferInVideo ? 2 : 1);
  973.     if (rval != D3DRM_OK) {
  974. Msg("Setting the buffer count failed.n%s", D3DAppErrorToString(rval));
  975. return FALSE;
  976.     }
  977.     /*
  978.      * Set the render quality (light toggle, fill mode, shade mode)
  979.      */
  980.     if (myglobs.dev->GetQuality() != myglobs.RenderQuality) {
  981. rval = myglobs.dev->SetQuality(myglobs.RenderQuality);
  982. if (rval != D3DRM_OK) {
  983.     Msg("Setting the render quality failed.n%s",
  984. D3DAppErrorToString(rval));
  985.     return FALSE;
  986. }
  987.     }
  988.     /*
  989.      * Set dithering toggle
  990.      */
  991.     if (myglobs.dev->GetDither() != myglobs.bDithering) {
  992. rval = myglobs.dev->SetDither(myglobs.bDithering);
  993. if (rval != D3DRM_OK) {
  994.     Msg("Setting dither mode failed.n%s", D3DAppErrorToString(rval));
  995.     return FALSE;
  996. }
  997.     }
  998.     /*
  999.      * Set the texture quality (point or linear filtering)
  1000.      */
  1001.     if (myglobs.dev->GetTextureQuality() != myglobs.TextureQuality) {
  1002. rval = myglobs.dev->SetTextureQuality(myglobs.TextureQuality);
  1003. if (rval != D3DRM_OK) {
  1004.     Msg("Setting texture quality failed.n%s",
  1005. D3DAppErrorToString(rval));
  1006.     return FALSE;
  1007. }
  1008.     }
  1009.     /*
  1010.      * Set shade info based on current bits per pixel
  1011.      */
  1012.     switch (d3dapp->ThisMode.bpp) {
  1013. case 1:
  1014.     if (FAILED(myglobs.dev->SetShades(4)))
  1015. goto shades_error;
  1016.     if (FAILED(lpD3DRM->SetDefaultTextureShades(4)))
  1017. goto shades_error;
  1018.     break;
  1019. case 16:
  1020.     if (FAILED(myglobs.dev->SetShades(32)))
  1021. goto shades_error;
  1022.     if (FAILED(lpD3DRM->SetDefaultTextureColors(64)))
  1023. goto shades_error;
  1024.     if (FAILED(lpD3DRM->SetDefaultTextureShades(32)))
  1025. goto shades_error;
  1026.     break;
  1027. case 24:
  1028. case 32:
  1029.     if (FAILED(myglobs.dev->SetShades(256)))
  1030. goto shades_error;
  1031.     if (FAILED(lpD3DRM->SetDefaultTextureColors(64)))
  1032. goto shades_error;
  1033.     if (FAILED(lpD3DRM->SetDefaultTextureShades(256)))
  1034. goto shades_error;
  1035.     break;
  1036.     }
  1037.     return TRUE;
  1038. shades_error:
  1039.     Msg("A failure occurred while setting color shade information.n");
  1040.     return FALSE;
  1041. }
  1042. /****************************************************************************/
  1043. /*          Initialization, error reporting and release functions.          */
  1044. /****************************************************************************/
  1045. /*
  1046.  * InitGlobals
  1047.  * Called once at program initialization to initialize global variables.
  1048.  */
  1049. static void
  1050. InitGlobals(void)
  1051. {
  1052.     d3dapp = NULL;
  1053.     memset(&myglobs, 0, sizeof(myglobs));
  1054.     myglobs.bShowFrameRate = TRUE;
  1055.     myglobs.bShowInfo = TRUE;
  1056.     myglobs.RenderQuality = D3DRMLIGHT_ON | D3DRMFILL_SOLID |
  1057.     D3DRMSHADE_GOURAUD;
  1058.     myglobs.TextureQuality = D3DRMTEXTURE_NEAREST;
  1059. }
  1060. /*
  1061.  * CleanUpAndPostQuit
  1062.  * Release all D3D objects, post a quit message and set the bQuit flag
  1063.  */
  1064. void
  1065. CleanUpAndPostQuit(void)
  1066. {
  1067.     if (myglobs.bQuit)
  1068. return;
  1069.     if (!D3DAppDestroy())
  1070. ReportD3DAppError();
  1071.     RELEASE(myglobs.scene);
  1072.     RELEASE(myglobs.camera);
  1073.     RELEASE(lpD3DRM);
  1074.     myglobs.bQuit = TRUE;
  1075.     PostQuitMessage( 0 );
  1076. }
  1077. /*
  1078.  * ReportD3DAppError
  1079.  * Reports an error during a d3d app call.
  1080.  */
  1081. void
  1082. ReportD3DAppError(void)
  1083. {
  1084.     Msg("%s", D3DAppLastErrorString());
  1085. }
  1086. /* Msg
  1087.  * Message output for error notification.
  1088.  */
  1089. void __cdecl
  1090. Msg( LPSTR fmt, ... )
  1091. {
  1092.     char buff[256];
  1093.     va_list args;
  1094.     
  1095.     va_start(args, fmt);
  1096.     wvsprintf(buff, fmt, args);
  1097.     va_end(args);
  1098.     
  1099.     lstrcat(buff, "rn");
  1100.     AppPause(TRUE);
  1101.     if (d3dapp && d3dapp->bFullscreen)
  1102. SetWindowPos(myglobs.hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
  1103.      SWP_NOSIZE | SWP_NOMOVE);
  1104.     MessageBox( NULL, buff, "D3D Example Message", MB_OK );
  1105.     if (d3dapp && d3dapp->bFullscreen)
  1106. SetWindowPos(myglobs.hWndMain, HWND_TOPMOST, 0, 0, 0, 0,
  1107.      SWP_NOSIZE | SWP_NOMOVE);
  1108.     AppPause(FALSE);
  1109. }
  1110. /*
  1111.  * D3DRMErrorToString
  1112.  * Allows the samples to return error strings.
  1113.  */
  1114. char*
  1115. D3DRMErrorToString(HRESULT error)
  1116. {
  1117.     return D3DAppErrorToString(error);
  1118. }