DualDispDemo.cpp
上传用户:fjqzjn
上传日期:2008-01-21
资源大小:2764k
文件大小:127k
源码类别:

Windows CE

开发平台:

Visual C++

  1. /******************************************************************************
  2. ** Copyright (c) 2004, Intel Corporation
  3. ** Copyright (c) 2003 by Imagination Technologies Limited.
  4. ** All rights reserved.
  5. **
  6. ** The source code contained or described herein and all documents related to the
  7. ** source code ("Material") are owned by Intel Corporation or its suppliers or 
  8. ** licensors. Title to the Material remains with Intel Corporation or its suppliers
  9. ** and licensors. The Material contains trade secrets and proprietary and 
  10. ** confidential information of Intel or its suppliers and licensors. The Material 
  11. ** is protected by worldwide copyright and trade secret laws and treaty provisions.
  12. ** No part of the Material may be used, copied, reproduced, modified, published, 
  13. ** uploaded, posted, transmitted, distributed, or disclosed in any way without 
  14. ** Intel抯 prior express written permission.
  15. ** 
  16. ** No license under any patent, copyright, trade secret or other intellectual 
  17. ** property right is granted to or conferred upon you by disclosure or delivery 
  18. ** of the Materials, either expressly, by implication, inducement, estoppel or 
  19. ** otherwise. Any license under such intellectual property rights must be express 
  20. ** and approved by Intel in writing.
  21. *
  22. * Description  : Dual display example application. See dualdispdemo.txt
  23.                  for further information.
  24. *
  25. * Platform     : Marathon/WinCE/PocketPC
  26. *                
  27. *                OSV_PPC must be defined in order to build for PocketPC.
  28. *
  29. ***********************************************************************************/
  30. #include <windows.h>
  31. #include <assert.h>
  32. #include <string.h>
  33. #include <memory.h>
  34. #include "dispconfig.h"
  35. #include "DDDrvEsc.h"
  36. #include "resource.h"
  37. #include <commctrl.h>
  38. //#include <pkfuncs.h>
  39. #include <aygshell.h>
  40. /* Set rotation angle of desktop for the external screen. Only an angle of 0 degrees
  41. is currently supported. */
  42. #define EXTERNALDISPLAYROTATION 0 
  43. #define DESKTOPTOXSCALEDELAY 100
  44. /* Enable/disable 'desktop transfer' efficiency test code. */
  45. #define CHECK_MEM_COPY_SPEED 0
  46. #define TEMP_BUFFER_SIZE (800 * 600)
  47. /* For Config_TestDualDisplay retain each tested configuration for this length of time. */
  48. #define TEST_DISPLAYMODEDURATION 10000
  49. static HANDLE hEvent_StopDesktopTransfer = NULL;
  50. static HANDLE hThread_DesktopTransfer = NULL;
  51. static HANDLE hEvent_StopGDIRectangles = NULL;
  52. static HANDLE hThread_GDIRectangles = NULL;
  53. static HDC hdcXScale = NULL;
  54. static HDC hdcMem = NULL;
  55. static HBITMAP hBitmap = NULL;
  56. static HGDIOBJ hOldBitmap = NULL;
  57. static HWND hwndDialog = NULL;
  58. static HDC hdcMarathon = NULL;
  59. static USHORT usTempBuffer[TEMP_BUFFER_SIZE];
  60. static LONG lInitialDesktopRotation = 0;
  61. static BOOL bSecondarySurfaceCreated = FALSE;
  62. static TCHAR szTestResults[12][200];
  63. DISPCFG_DISPLAY_SYSTEM sDisplayConfig;
  64. DISPCFG_GET_SURFACE_INFO sDesktopSurfaceInfo;
  65. DISPCFG_GET_SURFACE_INFO s2700GSecondadrySurfInfo;
  66. XSCALE_SURFACE_INFO sXScaleSurfaceInfo;
  67. FILE* gpStream = NULL;
  68. class RefreshDisplay
  69. {
  70. private:
  71.     /* Copy of WinMain parameters */
  72.     HINSTANCE m_hInstance;
  73. HINSTANCE m_hPrevInstance;
  74. LPTSTR    m_szCmdLine;
  75. int       m_iCmdShow;
  76. HWND      m_hwnd;
  77. int       m_nScreenWidth;
  78. int       m_nScreenHeight;
  79. public:
  80.     void Init(HINSTANCE hInstance,
  81.                HINSTANCE hPrevInstance,
  82.                LPTSTR    szCmdLine,
  83.                int       iCmdShow);
  84. void SetSize (int nWidth, int nHeight) { m_nScreenWidth = nWidth; m_nScreenHeight = nHeight;}
  85. void MaskDesktop();
  86. void RevealDesktop();
  87. void Close();
  88. };
  89. RefreshDisplay classRefreshDisplay;
  90. /***** Select Dual Display Configuration ******************************************/
  91. LONG Config_TestDualDisplay(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  92.                                  DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  93.                                  XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  94.                                  HDC& hdcXScale,
  95.                                  BOOL bQuickTest);
  96. LONG Config_DefaultDisplay(DISPCFG_DISPLAY_SYSTEM& sDefaultConfig);
  97. LONG Config_MirrorModeIncompatible(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  98.                        DISPCFG_GET_SURFACE_INFO& sMarathonSurfaceInfo,
  99.                        XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  100.                        HDC& hdcXScale);
  101. LONG Config_MirrorModeCompatible(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig);
  102. LONG Config_CustomGDIApplication(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  103.                              DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  104.                              DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo,
  105.                              XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  106.                              HDC& hdcXScale);
  107. LONG Config_CustomFBApplication(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  108.                              DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  109.                              DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo,
  110.                              XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  111.                              HDC& hdcXScale);
  112. LONG Config_ExternalDispOnlyDesktop(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig);
  113. LONG Config_InternalDispOnlySecSurf(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig,
  114.                                    DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo);
  115. LONG Config_ExternalDispOnlySecSurf(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig,
  116.                                     DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo);
  117. LONG Config_VideoMode(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  118.                        DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  119.                        XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  120.                        HDC& hdcXScale);
  121. /**********************************************************************************/
  122. /***** Perform Dual Display Configuration *****************************************/
  123. void LCDInternal(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  124.                  BOOL bValid, 
  125.                  BOOL bActivate, 
  126.                  DCFG_LCD_SOURCE eLcdSource, 
  127.                  DCFG_LCD_IN_FORMAT eXScaleFormat);
  128. void LCDExternal(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  129.                  BOOL bValid, 
  130.                  BOOL bActivate, 
  131.                  DCFG_LCD_SOURCE eLcdSource, 
  132.                  DCFG_LCD_IN_FORMAT eXScaleFormat);
  133. void ConfigSurfaceForPDP(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  134.                          DCFG_DISPLAY_SURFACE eSurface,
  135.                          ULONG ulBorderColor, 
  136.                          BOOL bFillScreen, 
  137.                          ULONG ulRefreshRate,
  138.                          ULONG ulPhysRotation,
  139.                          BOOL bSet);
  140. /**********************************************************************************/
  141. /***** Transfer a Display Surface from Marathon to XSCale *************************/
  142. LONG BeginDesktopToXScaleTransfer(DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  143.                                        XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  144.                                        HDC hdcXScale);
  145. DWORD WINAPI DesktopToXScaleTransfer(LPVOID lpParameter);
  146. LONG StopDesktopToXScaleTransfer();
  147. LONG CopyToXScaleFB(DISPCFG_GET_SURFACE_INFO& sMarathonSurfaceInfo,
  148.                                  XSCALE_SURFACE_INFO& sXScaleSurfaceInfo);
  149. LONG CopyAndDoubleToXScaleFB(DISPCFG_GET_SURFACE_INFO& sMarathonSurfaceInfo,
  150.                                  XSCALE_SURFACE_INFO& sXScaleSurfaceInfo);
  151. LONG RotateToBuffer(USHORT* pulDestBuffer, USHORT* pulSrcBuffer,
  152.                   ULONG ulDestWidth, ULONG ulDestHeight, ULONG ulRequiredRotation,
  153.                   ULONG ulSrcWidth, ULONG ulSrcHeight, ULONG ulSrcStride);
  154. LONG RotateAndDoubleToBuffer(USHORT* pulDestBuffer, USHORT* pulSrcBuffer,
  155.                   ULONG ulDestWidth, ULONG ulDestHeight, ULONG ulRequiredRotation,
  156.                   ULONG ulSrcWidth, ULONG ulSrcHeight, ULONG ulSrcStride);
  157. void AdjustRefreshRate(BOOL bIsDirty, 
  158.                        ULONG& nConsecutiveScreenUpdates, 
  159.                        DWORD& dwDelayInMilliseconds);
  160. /**********************************************************************************/
  161. /***** Use secondary display surface **********************************************/
  162. LONG GetSecondarySurfaceInfo(DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo);
  163. LONG WriteToSecSurfFrameBuffer(DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo);
  164. void DestroySecondarySurface();
  165. /**********************************************************************************/
  166. /*********** GDI ******************************************************************/
  167. DWORD WINAPI GDIRectangles(LPVOID lpParameter);
  168. LONG StopGDIRectangles();
  169. LONG RandomRectangles();
  170. /**********************************************************************************/
  171. /***** Miscellaneous **************************************************************/
  172. void GetCommandLineArgs(LPTSTR lpCmdLine, ULONG& ulArgc, char **argv, char* ArgBuffer);
  173. void ConvertTToC(char* pszDest, const TCHAR* pszSrc);
  174. LONG ProcessOptions(int ulArgc, char **argv, 
  175.                          SELECT_DUAL_DISP_CONFIG& SelectDualDispConfig);
  176. void CloseAllThreads();
  177. void CloseAllHDCs();
  178. LONG RestoreDefaultDisplayMode();
  179. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  180. LRESULT CALLBACK WndProcRefreshDisplay (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  181. LONG DualDisplaySetup(DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo);
  182. void DualDisplayTestSetup(DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo, BOOL& bTestSetupSuccess);
  183. void VerifyTestSuccess(TCHAR* szTestName, ULONG ulTestNumber, 
  184.                        LONG nDDRetVal, BOOL& bTestFailure);
  185. /**********************************************************************************/
  186. /***********************************************************************************
  187.  Function Name      : GDIRectangles
  188.  Inputs             : lpParameter
  189.  Outputs            : 
  190.  Returns            : Error code
  191.  Description        : Displays rectangles of random size and colour at random
  192.                       locations on the surface.
  193. ************************************************************************************/
  194. DWORD WINAPI GDIRectangles(LPVOID lpParameter)
  195. {
  196.     DWORD dwDDRetVal = DUALDISPSUCCESS;
  197.     DWORD dwDelayInMilliseconds = 50;
  198.     DWORD dwWaitObjRetVal = 0;
  199.     LONG nLeftRect;
  200.     LONG nTopRect;
  201.     LONG nRightRect;
  202.     LONG nBottomRect;
  203.     HBRUSH hBrush, hBrushOld;
  204.     LONG nRed, nGreen, nBlue;
  205.     LONG nWidth = SECONDARYSURFACEWIDTH;
  206.     LONG nHeight = SECONDARYSURFACEHEIGHT;
  207.     DISPCFG_DISPLAY_SYSTEM* sDisplayConfig;
  208.     sDisplayConfig = (DISPCFG_DISPLAY_SYSTEM*) lpParameter;
  209.     /* Make sure handle to bitmap memory is valid. */
  210.     if (hdcMem == NULL)
  211.     {
  212.         dwDDRetVal |= DUALDISPERROR;
  213.         return dwDDRetVal;
  214.     }
  215.     for (;;)
  216.     {
  217.         dwWaitObjRetVal = WaitForSingleObject(hEvent_StopGDIRectangles, dwDelayInMilliseconds);
  218.         if (dwWaitObjRetVal == WAIT_TIMEOUT)
  219.         {
  220.             nLeftRect = rand() % nWidth;
  221.             nTopRect = rand() % nHeight;
  222.             nRightRect = rand() % nWidth;
  223.             nBottomRect = rand() % nHeight;
  224.             nRed = rand() & 255;
  225.             nGreen = rand() & 255;
  226.             nBlue = rand() & 255;
  227.             hBrush = CreateSolidBrush(RGB(nRed, nGreen, nBlue));
  228.             hBrushOld = (HBRUSH) SelectObject(hdcMem, hBrush);
  229.             Rectangle(hdcMem, nLeftRect,nTopRect,  nRightRect, nBottomRect);
  230.             assert(hBrushOld != NULL);
  231.             SelectObject(hdcMem, hBrushOld);
  232.             DeleteObject(hBrush);
  233.         }
  234.         else if (dwWaitObjRetVal == WAIT_OBJECT_0)
  235.         {
  236.             /* hEvent_StopDesktopTransfer event object signalled - so stop transfer */
  237.             /* clean up first */
  238.             TEXTOUT(TEXT("DUALDISPDEMO: GDIRectangles: exited thread.n"));
  239.             /* Delete secondary surface bitmap. */
  240.             DestroySecondarySurface();
  241.             return dwDDRetVal;
  242.         }
  243.         else if (dwWaitObjRetVal == WAIT_FAILED)
  244.         {
  245.             assert(0);
  246.             dwDDRetVal |= DUALDISPERROR;
  247.             return dwDDRetVal;
  248.         }
  249.         else
  250.         {
  251.             assert(0);
  252.             dwDDRetVal |= DUALDISPERROR;
  253.             return dwDDRetVal;
  254.         }
  255.     }
  256. }
  257. /***********************************************************************************
  258.  Function Name      : RandomRectangles
  259.  Inputs             : 
  260.  Outputs            : 
  261.  Returns            : Error code
  262.  Description        : Displays rectangles of random size and colour at random
  263.                       locations on the surface.
  264. ************************************************************************************/
  265. LONG RandomRectangles()
  266. {
  267.     LONG nDDRetVal = DUALDISPSUCCESS;
  268.     DWORD dwDelayInMilliseconds = 50;
  269.     DWORD dwWaitObjRetVal = 0;
  270.     LONG i;
  271.     LONG nLeftRect;
  272.     LONG nTopRect;
  273.     LONG nRightRect;
  274.     LONG nBottomRect;
  275.     HBRUSH hBrush, hBrushOld;
  276.     LONG nRed, nGreen, nBlue;
  277.     LONG nWidth = SECONDARYSURFACEWIDTH;
  278.     LONG nHeight = SECONDARYSURFACEHEIGHT;
  279.     /* Make sure handle to bitmap memory is valid. */
  280.     if (hdcMem == NULL)
  281.     {
  282.         nDDRetVal |= DUALDISPERROR;
  283.         return nDDRetVal;
  284.     }
  285.     for (i = 0; i < 200; i++)
  286.     {
  287.         nLeftRect = rand() % nWidth;
  288.         nTopRect = rand() % nHeight;
  289.         nRightRect = rand() % nWidth;
  290.         nBottomRect = rand() % nHeight;
  291.         nRed = rand() & 255;
  292.         nGreen = rand() & 255;
  293.         nBlue = rand() & 255;
  294.         hBrush = CreateSolidBrush(RGB(nRed, nGreen, nBlue));
  295.         hBrushOld = (HBRUSH) SelectObject(hdcMem, hBrush);
  296.         Rectangle(hdcMem, nLeftRect,nTopRect,  nRightRect, nBottomRect);
  297.         assert(hBrushOld != NULL);
  298.         SelectObject(hdcMem, hBrushOld);
  299.         DeleteObject(hBrush);
  300.         Sleep(dwDelayInMilliseconds);
  301.     }
  302.     return nDDRetVal;
  303. }
  304. /***********************************************************************************
  305.  Function Name      : DestroySecondarySurface
  306.  Inputs             : 
  307.  Outputs            : 
  308.  Returns            : 
  309.  Description        : Delete the secondary surface bitmap.
  310. ************************************************************************************/
  311. void DestroySecondarySurface()
  312. {
  313.     if (bSecondarySurfaceCreated)
  314.     {
  315.         assert(((hdcMem != NULL) && (hOldBitmap != NULL) && (hBitmap != NULL)));
  316.         SelectObject(hdcMem, hOldBitmap);
  317.         DeleteObject(hBitmap);
  318.         hBitmap = NULL;
  319.     DeleteDC(hdcMem);
  320.         hdcMem = NULL;
  321.         /* Secondary surface has now been destroyed. */
  322.         bSecondarySurfaceCreated = FALSE;
  323.     }
  324. }
  325. /***********************************************************************************
  326.  Function Name      : ConvertTToC
  327.  Inputs             : pszSrc
  328.  Outputs            : pszDest
  329.  Returns            : 
  330.  Description        : Converts a unicode string to an ANSI string.
  331. ************************************************************************************/
  332. void ConvertTToC(char* pszDest, const TCHAR* pszSrc)
  333. {
  334.   unsigned int i;
  335.   for(i = 0; i <= _tcslen(pszSrc); i++)
  336.     pszDest[i] = (CHAR) pszSrc[i];
  337. }
  338. /***********************************************************************************
  339.  Function Name      : GetCommandLineArgs
  340.  Inputs             : lpCmdLine
  341.  Outputs            : ArgBuffer
  342.                       ulArgc
  343.                       argv
  344.  Returns            : 
  345.  Description        : Converts a unicode command line string into an array of ANSI
  346.                       tokens.
  347. ************************************************************************************/
  348. void GetCommandLineArgs(LPTSTR lpCmdLine, ULONG& ulArgc, char **argv, char* ArgBuffer)
  349. {
  350.   char *ptr = ArgBuffer;
  351.   ulArgc = 0;
  352.   ConvertTToC(ArgBuffer, lpCmdLine);
  353.   /* Store arguments in argv */
  354.   argv[ulArgc++] = "DualDisplayDemo.exe";
  355.   if (ArgBuffer[0])
  356.     argv[ulArgc++] = ArgBuffer;
  357.   while (*ptr != '')
  358.     {
  359.       if ((*ptr == ' ') || (*ptr == 't')) 
  360.       {
  361.             *ptr++ = '';
  362.             while ((*ptr == ' ') || (*ptr == 't'))
  363.             {
  364.                 ptr++;
  365.             }
  366.             if (*ptr != '')
  367.             {
  368.                 argv[ulArgc++] = ptr;
  369.             }
  370.       } 
  371.       else
  372.       {
  373.             ptr++;
  374.       }
  375.     }
  376. }
  377. /***********************************************************************************
  378.  Function Name      : ProcessOptions
  379.  Inputs             : ulArgc
  380.                       argv
  381.  Outputs            : SelectDualDispConfig
  382.  Returns            : 
  383.  Description        : Processes an array of tokens (command line options) in order
  384.                       to determine which 'Dual Display' mode has been selected.
  385. ************************************************************************************/
  386. LONG ProcessOptions (int ulArgc, char **argv, SELECT_DUAL_DISP_CONFIG& SelectDualDispConfig)
  387. {
  388.     LONG nDDRetVal = DUALDISPSUCCESS;
  389.     int i;
  390. if (ulArgc == 1) // if no args, go into mirror
  391. {
  392. SelectDualDispConfig = eMirrorModeIncompatible;
  393. return DUALDISPSUCCESS;
  394. }
  395.     for (i = 1; i < ulArgc; i++)
  396.     {
  397.         if (!strcmp(argv[i], "--default") || !strcmp(argv[i], "-d"))
  398.         {
  399.             SelectDualDispConfig = eDefaultDisplay;
  400.         }
  401.         else if (!strcmp(argv[i], "--mirror") || !strcmp(argv[i], "-m"))
  402.         {
  403.             SelectDualDispConfig = eMirrorModeIncompatible;
  404.         }
  405.         else if (!strcmp(argv[i], "--mirrorcompatible"))
  406.         {
  407.             SelectDualDispConfig = eMirrorModeCompatible;
  408.         }
  409.         else if (!strcmp(argv[i], "--video"))
  410.         {
  411.             SelectDualDispConfig = eVideoMode;
  412.         }
  413.         else if (!strcmp(argv[i], "--gdi") || !strcmp(argv[i], "-g"))
  414.         {
  415.             SelectDualDispConfig = eCustomGDIApplication;
  416.         }
  417.         else if (!strcmp(argv[i], "--framebuffer") || !strcmp(argv[i], "-f"))
  418.         {
  419.             SelectDualDispConfig = eCustomFBApplication;
  420.         }
  421.         else if (!strcmp(argv[i], "--extdesktop"))
  422.         {
  423.             SelectDualDispConfig = eExternalDispOnlyDesktop;
  424.         }
  425.         else if (!strcmp(argv[i], "--intsecsurf"))
  426.         {
  427.             SelectDualDispConfig = eInternalDispOnlySecSurf;
  428.         }
  429.         else if (!strcmp(argv[i], "--extsecsurf"))
  430.         {
  431.             SelectDualDispConfig = eExternalDispOnlySecSurf;
  432.         }
  433.         else if (!strcmp(argv[i], "--test"))
  434.         {
  435.             SelectDualDispConfig = eSlowTestMode;
  436.         }
  437.         else if (!strcmp(argv[i], "--quicktest"))
  438.         {
  439.             SelectDualDispConfig = eQuickTestMode;
  440.         }
  441.         else
  442.         {            
  443.             SelectDualDispConfig = eModeInvalid;
  444.             nDDRetVal = DUALDISPERROR;
  445. }
  446.     }
  447.     return nDDRetVal;
  448. }
  449. /***********************************************************************************
  450.  Function Name      : Config_TestDualDisplay
  451.  Inputs             : 
  452.                       
  453.  Outputs            : sDisplayConfig
  454.                       sDesktopSurfaceInfo
  455.                       sXScaleSurfaceInfo
  456.  Returns            : Error code
  457.  Description        : Tests all the dual display configurations defined in the 
  458.                       Config_xxxxxxx functions. Note: these tests are only performed
  459.                       for the default rotation angle and screen resolution as 
  460.                       defined in powervr.reg.
  461.                       Excerpt from powervr.reg during testing:
  462.                     
  463.                       [HKEY_LOCAL_MACHINEDriversDisplayPowerVR]
  464.                       "Width"=dword:140
  465.                       "Height"=dword:f0
  466.                       "BitsPerPixel"=dword:10
  467.                       "Prefetch"=dword:1
  468.                       #"BondConfig"=dword:3
  469.                       "Panel"=dword:00000005
  470.                       "PanelExt"=dword:C0000005    
  471.                       See dualdispdemo.txt for further information about this test.
  472. ************************************************************************************/
  473. LONG Config_TestDualDisplay(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  474.                                  DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  475.                                  XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  476.                                  HDC& hdcXScale,
  477.                                  BOOL bQuickTest)
  478. {
  479.     LONG nDDRetVal = DUALDISPSUCCESS;
  480.     ULONG ulDisplayModeDuration;
  481.     BOOL bTestFailure = FALSE;
  482.     TCHAR szBuffer[500];
  483.     LONG ulTestNumber = 0;
  484.     BOOL bTestSetupSuccess = TRUE;
  485.     if (bQuickTest == TRUE)
  486.     {
  487.         /* For a quick test, set delay to 1 millisecond */
  488.         ulDisplayModeDuration  = 1; 
  489.     }
  490.     else
  491.     {
  492.         /* This time delay should allow time for visual inspection of each display configuration. */
  493.         ulDisplayModeDuration  = TEST_DISPLAYMODEDURATION;
  494.     }
  495.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplayn"));
  496.     /* Test Config_DefaultDisplay */
  497.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST1: Config_DefaultDisplayn"));
  498.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  499.     nDDRetVal = Config_DefaultDisplay(sDisplayConfig);
  500.     Sleep(ulDisplayModeDuration);
  501.     VerifyTestSuccess(TEXT("Config_DefaultDisplay"), ulTestNumber++, nDDRetVal, bTestFailure);
  502.     /* Test Config_MirrorModeIncompatible */
  503.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST2: Config_MirrorModeIncompatiblen"));
  504.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  505.     nDDRetVal = Config_MirrorModeIncompatible(sDisplayConfig, sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  506.     Sleep(ulDisplayModeDuration);
  507.     VerifyTestSuccess(TEXT("Config_MirrorModeIncompatible"), ulTestNumber++, nDDRetVal, bTestFailure);
  508.     /* Test Config_MirrorModeCompatible */
  509.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST3: Config_MirrorModeCompatiblen"));
  510.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  511.     nDDRetVal = Config_MirrorModeCompatible(sDisplayConfig);
  512.     Sleep(ulDisplayModeDuration);
  513.     VerifyTestSuccess(TEXT("Config_MirrorModeCompatible"), ulTestNumber++, nDDRetVal, bTestFailure);
  514.     /* Test Config_CustomGDIApplication */
  515.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST4: Config_CustomGDIApplicationn"));
  516.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  517.     nDDRetVal = Config_CustomGDIApplication(sDisplayConfig, sDesktopSurfaceInfo, s2700GSecondadrySurfInfo, sXScaleSurfaceInfo, hdcXScale);
  518.     Sleep(ulDisplayModeDuration);
  519.     VerifyTestSuccess(TEXT("Config_CustomGDIApplication"), ulTestNumber++, nDDRetVal, bTestFailure);
  520.     /* Test Config_CustomFBApplication */
  521.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  522.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST5: Config_CustomFBApplicationn"));
  523.     nDDRetVal = Config_CustomFBApplication(sDisplayConfig, sDesktopSurfaceInfo, s2700GSecondadrySurfInfo, sXScaleSurfaceInfo, hdcXScale);
  524.     Sleep(ulDisplayModeDuration);
  525.     VerifyTestSuccess(TEXT("Config_CustomFBApplication"), ulTestNumber++, nDDRetVal, bTestFailure);
  526.     /* Test Config_ExternalDispOnlyDesktop */
  527.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST6: Config_ExternalDispOnlyDesktopn"));
  528.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  529.     nDDRetVal = Config_ExternalDispOnlyDesktop(sDisplayConfig);
  530.     Sleep(ulDisplayModeDuration);
  531.     VerifyTestSuccess(TEXT("Config_ExternalDispOnlyDesktop"), ulTestNumber++, nDDRetVal, bTestFailure);
  532.     /* Test Config_InternalDispOnlySecSurf - sleep not required as test has inbuilt delay. */
  533.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST7: Config_InternalDispOnlySecSurfn"));
  534.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  535.     nDDRetVal = Config_InternalDispOnlySecSurf(sDisplayConfig, s2700GSecondadrySurfInfo);
  536.     VerifyTestSuccess(TEXT("Config_InternalDispOnlySecSurf"), ulTestNumber++, nDDRetVal, bTestFailure);
  537.     /* Test Config_ExternalDispOnlySecSurf - sleep not required as test has inbuilt delay. */
  538.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST8: Config_ExternalDispOnlySecSurfn"));
  539.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  540.     nDDRetVal = Config_ExternalDispOnlySecSurf(sDisplayConfig, s2700GSecondadrySurfInfo);
  541.     VerifyTestSuccess(TEXT("Config_ExternalDispOnlySecSurf"), ulTestNumber++, nDDRetVal, bTestFailure);
  542.     /* Test Config_VideoMode */
  543.     TEXTOUT(TEXT("DUALDISPDEMO: Config_TestDualDisplay: TEST9: Config_VideoModen"));
  544.     DualDisplayTestSetup(sDesktopSurfaceInfo, bTestSetupSuccess);
  545.     nDDRetVal = Config_VideoMode(sDisplayConfig, sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  546.     Sleep(ulDisplayModeDuration);
  547.     VerifyTestSuccess(TEXT("Config_VideoMode"), ulTestNumber++, nDDRetVal, bTestFailure);
  548.     RestoreDefaultDisplayMode();
  549.     /* Output test results */
  550.     TEXTOUT(TEXT("nn****************** DUALDISPDEMO TEST ******************n"));
  551.     TEXTOUT(TEXT("For all tests to pass, suitable displays must be specified (via Panel and PanelExt in powervr.reg).n"));
  552.     if (bTestSetupSuccess == FALSE)
  553.     {
  554.         TEXTOUT(TEXT("DUALDISPDEMO: DualDisplayTestSetup FAILEDn"));
  555.     }
  556.     else
  557.     {
  558.         TEXTOUT(TEXT("DUALDISPDEMO: DualDisplayTestSetup PASSEDn"));
  559.     }
  560.     for (LONG i = 0; i < ulTestNumber; i++)
  561.     {
  562.         TEXTOUT(szTestResults[i]);
  563.     }
  564.     if (bTestFailure)
  565.     {
  566.         wsprintf(szBuffer, TEXT("nn!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!n"));
  567.         wcscat(szBuffer, TEXT      ("!!!!!!!!! FAILED: One or more DUALDISPDEMO tests FAILED !!!!!!!!!n"));
  568.         wcscat(szBuffer, TEXT      ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!nn"));
  569.         TEXTOUT(szBuffer);
  570.         nDDRetVal = DUALDISPERROR;
  571.     }
  572.     else
  573.     {
  574.         wsprintf(szBuffer, TEXT("nn*****************************************************n"));
  575.         wcscat(szBuffer, TEXT      ("********* PASSED: DUALDISPDEMO tests PASSED *********n"));
  576.         wcscat(szBuffer, TEXT      ("*****************************************************nn"));
  577.         TEXTOUT(szBuffer);
  578.     }
  579.     return nDDRetVal;
  580. }
  581. /***********************************************************************************
  582.  Function Name      : VerifyTestSuccess
  583.  Inputs             : szTestName
  584.                       nDDRetVal
  585.  Input/Output       : bTestFailure
  586.  Returns            : 
  587.  Description        : Process the return value of each test. 
  588. ************************************************************************************/
  589. void VerifyTestSuccess(TCHAR* szTestName, ULONG ulTestNumber, 
  590.                        LONG nDDRetVal, BOOL& bTestFailure)
  591. {
  592.     if (nDDRetVal != DUALDISPSUCCESS)
  593.     {
  594.         wsprintf(szTestResults[ulTestNumber], TEXT("%s: FAILEDn"), szTestName);
  595.         bTestFailure = TRUE;
  596.     }
  597.     else
  598.     {
  599.         wsprintf(szTestResults[ulTestNumber], TEXT("%s: PASSEDn"), szTestName);
  600.     }
  601. }
  602. /***********************************************************************************
  603.  Function Name      : Config_MirrorModeCompatible
  604.  Inputs             : 
  605.  Outputs            : sDisplayConfig
  606.  Returns            : 
  607.  Description        : Configures Simple Mirror Mode. In this mode, the Desktop
  608.                       is connected to the PDP which connects to both the internal
  609.                       and external displays via the LCD switch. In order to use
  610.                       this mode, the internal and external panels must have
  611.                       compatible timings.
  612. ************************************************************************************/
  613. LONG Config_MirrorModeCompatible(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig)
  614. {
  615.     LONG nDDRetVal = DUALDISPSUCCESS;
  616. /* Set default desktop rotation angle */
  617. ULONG ulPhysRotation = sDesktopSurfaceInfo.sPhysSurfaceInfo.lPhysicalRotation;
  618.     /* PDP will connect to the internal LCD */
  619.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  620.     /* PDP will connect to the external LCD */
  621.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  622.     /* Desktop will be connected to the PDP */
  623.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_DESKTOP, PARAM_NOT_APPLICABLE, FALSE, 
  624.                         PARAM_NOT_APPLICABLE, ulPhysRotation, TRUE);
  625.     /* Program LCD switch and connect PDP to the specified surface. */
  626.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  627.     if (nDDRetVal != DUALDISPSUCCESS)
  628.     {
  629.         TEXTOUT(TEXT("DUALDISPDEMO: Config_MirrorModeCompatible: returning error value.n"));
  630.     }
  631.     return nDDRetVal;
  632. }
  633. /***********************************************************************************
  634.  Function Name      : Config_DefaultDisplay
  635.  Inputs             : 
  636.  Outputs            : sDisplayConfig
  637.  Returns            : 
  638.  Description        : This function enables/restores the standard mode of operation,
  639.                       The Desktop is displayed on the internal screen. The external 
  640.                       screen is not in use. 
  641. ************************************************************************************/
  642. LONG Config_DefaultDisplay(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig)
  643. {
  644.     LONG nDDRetVal = DUALDISPSUCCESS;
  645. /* Set default rotation (i.e. rotation angle of desktop on internal panel when not in dual display mode). */
  646. ULONG ulPhysRotation = lInitialDesktopRotation;
  647.     /* PDP will connect to the internal LCD */
  648.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  649.     /* Disable external LCD */
  650.     LCDExternal(sDisplayConfig, TRUE, FALSE, DCFG_SOURCE_NOT_APPLICABLE, DCFG_FORMAT_NOT_APPLICABLE);
  651.     /* Desktop will be connected to the PDP */
  652.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_DESKTOP, PARAM_NOT_APPLICABLE, FALSE, 
  653.                         PARAM_NOT_APPLICABLE, ulPhysRotation, TRUE);
  654.     /* Program LCD switch and connect PDP to the specified surface. */
  655.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  656.     if (nDDRetVal != DUALDISPSUCCESS)
  657.     {
  658.         TEXTOUT(TEXT("DUALDISPDEMO: Config_DefaultDisplay: returning error value.n"));
  659.         assert(0);
  660.     }
  661.     return nDDRetVal;
  662. }
  663. /***********************************************************************************
  664.  Function Name      : Config_MirrorModeIncompatible
  665.  Inputs             : 
  666.  Outputs            : sDisplayConfig
  667.                       sDesktopSurfaceInfo
  668.  Returns            : Error code
  669.  Description        : Configures and executes Mirror Mode - desktop will be output
  670.                       to the internal and external displays.
  671. ************************************************************************************/
  672. LONG Config_MirrorModeIncompatible(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  673.                        DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  674.                        XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  675.                        HDC& hdcXScale)
  676. {
  677.     LONG nDDRetVal = DUALDISPSUCCESS;
  678.     /* HOST will be connected to the internal LCD */
  679.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_XSCALE, DCFG_LCD_IN_565);
  680.     /* PDP will be connected to the external LCD */
  681.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  682.     /* Desktop will be connected to PDP */
  683.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_DESKTOP, PARAM_NOT_APPLICABLE, FALSE, 
  684.                         PARAM_NOT_APPLICABLE, EXTERNALDISPLAYROTATION, TRUE);
  685.     /* Hide the existing desktop from view - it is about to be "messed up". */
  686.     classRefreshDisplay.MaskDesktop();
  687. /* Program LCD switch and connect PDP to the desktop surface. */
  688.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);  // TODO : 
  689.     if (nDDRetVal != DUALDISPSUCCESS)
  690.     {
  691.         TEXTOUT(TEXT("DUALDISPDEMO: Config_MirrorModeIncompatible: Call to DE_ConfigDisplaySystem failed.n"));
  692.         return nDDRetVal;
  693.     }
  694.     /* The desktop will now be transferred to the HOST (i.e. XScale) to be 
  695.     displayed on the internal screen. The LCD switch must be programmed 
  696.     to use the HOST as the "internal display source", before transferring 
  697.     desktop data to the HOST. */
  698.     nDDRetVal |= BeginDesktopToXScaleTransfer(sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  699.     /* Display the new "refreshed" desktop */
  700. classRefreshDisplay.RevealDesktop();
  701.     /* Marathon driver knows it is in mirror mode (i.e. DCFG_DESKTOP is connected to
  702.     PDP), therefore no further action is required here. */
  703.     if (nDDRetVal != DUALDISPSUCCESS)
  704.     {
  705.         TEXTOUT(TEXT("DUALDISPDEMO: Config_MirrorModeIncompatible: returning error value.n"));
  706.     }
  707.     return nDDRetVal;
  708. }
  709. /***********************************************************************************
  710.  Function Name      : Config_VideoMode
  711.  Inputs             : 
  712.  Outputs            : sDisplayConfig
  713.                       sDesktopSurfaceInfo
  714.                       sXScaleSurfaceInfo
  715.  Returns            : Error code
  716.  Description        : VideoMode is essentially the same thing as MirrorModeIncompatible. 
  717.                       However, the initial (default) desktop rotation angle is retained
  718.                       - thus if the desktop is rotated in default mode, it will also appear 
  719.                       rotated on the external panel. This means that it may appear
  720.                       'sideways' from the user's point of view. The purpose of this
  721.                       is to ensure that a video application has full access to the
  722.                       external screen - i.e. to allow it to be displayed in landscape
  723.                       mode. This prevents video being displayed on top of a small 'bordered 
  724.                       portrait' desktop.
  725.                       Video mode has another advantage over MirrorModeIncompatible: it is not
  726.                       necessary for the DesktopToXScale function to rotate the desktop
  727.                       greatly improving its performance.
  728. ************************************************************************************/
  729. LONG Config_VideoMode(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  730.                        DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  731.                        XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  732.                        HDC& hdcXScale)
  733. {
  734.     LONG nDDRetVal = DUALDISPSUCCESS;
  735. /* Use the default desktop rotation for the external panel. This means that
  736.     a 'portrait' desktop will be displayed on its side - allowing video to be
  737.     played full-screen. */
  738. ULONG ulPhysRotation = lInitialDesktopRotation;
  739.     /* HOST will be connected to the internal LCD */
  740.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_XSCALE, DCFG_LCD_IN_565);
  741.     /* PDP will be connected to the external LCD */
  742.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  743.     /* Desktop will be connected to PDP */
  744.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_DESKTOP, PARAM_NOT_APPLICABLE, FALSE, 
  745.                         PARAM_NOT_APPLICABLE, ulPhysRotation, TRUE);
  746.     /* Hide the existing desktop from view - it is about to be "messed up". */
  747.     classRefreshDisplay.MaskDesktop();
  748. /* Program LCD switch and connect PDP to the desktop surface. */
  749.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);  // TODO : 
  750.     if (nDDRetVal != DUALDISPSUCCESS)
  751.     {
  752.         TEXTOUT(TEXT("DUALDISPDEMO: Config_MirrorModeIncompatible: Call to DE_ConfigDisplaySystem failed.n"));
  753.         return nDDRetVal;
  754.     }
  755.     /* The desktop will now be transferred to the HOST (i.e. XScale) to be 
  756.     displayed on the internal screen. The LCD switch must be programmed 
  757.     to use the HOST as the "internal display source", before transferring 
  758.     desktop data to the HOST. */
  759.     nDDRetVal |= BeginDesktopToXScaleTransfer(sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  760.     /* Display the new "refreshed" desktop */
  761. classRefreshDisplay.RevealDesktop();
  762.     /* Marathon driver knows it is in mirror mode (i.e. DCFG_DESKTOP is connected to
  763.     PDP), therefore no further action is required here. */
  764.     if (nDDRetVal != DUALDISPSUCCESS)
  765.     {
  766.         TEXTOUT(TEXT("DUALDISPDEMO: Config_MirrorModeIncompatible: returning error value.n"));
  767.     }
  768.     return nDDRetVal;
  769. }
  770. /***********************************************************************************
  771.  Function Name      : Config_CustomGDIApplication
  772.  Inputs             : 
  773.  Outputs            : sDisplayConfig
  774.                       sDesktopSurfaceInfo
  775.                       s2700GSecondadrySurfInfo
  776.  Returns            : 
  777.  Description        : Configure dual display for "Custom application" mode. This 
  778.                       means that the desktop surface is transfered from the Marathon 
  779.                       to the XScale processor (to be displayed on the internal
  780.                       screen). A secondary surface will be created for the custom
  781.                       application to use. This surface can be accessed via an
  782.                       HDC (for GDI); or the secondary surface frame buffer can be 
  783.                       accessed directly.
  784.                       The secondary surface will be output to the external display.
  785.                       In this example, the thread GDIRectangles is created to 
  786.                       perform a GDI test-write to the secondary surface. See
  787.                       Config_CustomFBApplication for an example using the secondary
  788.                       secondary surface frame buffer.
  789. ************************************************************************************/
  790. LONG Config_CustomGDIApplication(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  791.                              DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  792.                              DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo,
  793.                              XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  794.                              HDC& hdcXScale)
  795. {
  796.     LONG nDDRetVal = DUALDISPSUCCESS;
  797.     /* Host will connect to the internal display. */
  798.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_XSCALE, DCFG_LCD_IN_565);
  799.     /* PDP will connect to the external display. */
  800.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  801.     /* "secondary display surface" will be connected to PDP */
  802.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_SECONDARYSURFACE, 0, FALSE, 60, PARAM_NOT_APPLICABLE, TRUE);
  803.     /* Create the off-screen surface. */
  804.     nDDRetVal |= DE_CreateSecondarySurfBitmap(hdcMarathon, hdcMem, hBitmap, hOldBitmap, 
  805.                                               bSecondarySurfaceCreated);
  806.     if (nDDRetVal != DUALDISPSUCCESS)
  807.     {
  808.         TEXTOUT(TEXT("DUALDISPDEMO: Config_CustomGDIApplication: Call to DE_CreateSecondarySurfBitmap failed.n"));
  809.         return nDDRetVal;
  810.     }
  811.     /* Program LCD switch and connect PDP to the off-screen surface. */
  812.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  813.     if (nDDRetVal != DUALDISPSUCCESS)
  814.     {
  815.         TEXTOUT(TEXT("DUALDISPDEMO: Config_CustomGDIApplication: Call to DE_ConfigureDisplaySystem failed.n"));
  816.         return nDDRetVal;
  817.     }
  818.     /* The desktop should not be rotated by this application - rotation is
  819.     only required in MirrorModeIncompatible. */
  820.     /* The desktop will now be transferred to the HOST (i.e. XScale) to be 
  821.     displayed on the internal screen. The LCD switch must be programmed 
  822.     to use the HOST as the "internal display source", before transferring 
  823.     desktop data to the HOST. */
  824.     nDDRetVal |= BeginDesktopToXScaleTransfer(sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  825.     nDDRetVal |= GetSecondarySurfaceInfo(s2700GSecondadrySurfInfo);
  826.     /* Perform GDI test-write to secondary surface via hdcMem */
  827.     /* Create an event to control thread termination. */
  828.     hEvent_StopGDIRectangles = CreateEvent(NULL, TRUE, FALSE, TEXT("StopCustomGDI"));
  829.     if (hEvent_StopGDIRectangles == NULL)
  830.     {
  831.         /* Failed to create event object */
  832.         nDDRetVal |= DUALDISPERROR;
  833.         return nDDRetVal;
  834.     }
  835.     /* Start GDIRectangles thread */
  836.     hThread_GDIRectangles = CreateThread(NULL, 0, GDIRectangles, 
  837.                                         (void*) &sDisplayConfig, 0, NULL);
  838.     if (hThread_GDIRectangles == NULL)
  839.     {
  840.         /* Failed to create thread */
  841.         nDDRetVal |= DUALDISPERROR;
  842.         return nDDRetVal;
  843.     }
  844.     if (nDDRetVal != DUALDISPSUCCESS)
  845.     {
  846.         TEXTOUT(TEXT("DUALDISPDEMO: Config_CustomApplication: returning error value.n"));
  847.         assert(0);
  848.     }
  849.     return nDDRetVal;
  850. }
  851. /***********************************************************************************
  852.  Function Name      : Config_CustomFBApplication
  853.  Inputs             : 
  854.  Outputs            : sDisplayConfig
  855.                       sDesktopSurfaceInfo
  856.                       s2700GSecondadrySurfInfo
  857.  Returns            : 
  858.  Description        : Configure dual display for "Custom application" mode. This 
  859.                       means that the desktop surface is transfered from the Marathon 
  860.                       to the XScale processor (to be displayed on the internal
  861.                       display). A secondary surface will be created for the custom
  862.                       application to use. This surface can be accessed via an
  863.                       HDC (for GDI); or the secondary surface frame buffer can be 
  864.                       accessed directly.
  865.                       The secondary surface will be output to the external display.
  866.                       In this example, the secondary surface frame buffer is 
  867.                       written to directly. See Config_CustomGDIApplication for
  868.                       a GDI example.
  869. ************************************************************************************/
  870. LONG Config_CustomFBApplication(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  871.                              DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  872.                              DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo,
  873.                              XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  874.                              HDC& hdcXScale)
  875. {
  876.     LONG nDDRetVal = DUALDISPSUCCESS;
  877.     /* Host will connect to the internal display. */
  878.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_XSCALE, DCFG_LCD_IN_565);
  879.     /* PDP will connect to the external display. */
  880.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  881.     /* "secondary display surface" will be connected to PDP */
  882.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_SECONDARYSURFACE, 0, FALSE, 60, PARAM_NOT_APPLICABLE, TRUE);
  883.     /* Create the off-screen surface. */
  884.     nDDRetVal |= DE_CreateSecondarySurfBitmap(hdcMarathon, hdcMem, hBitmap, hOldBitmap, 
  885.                                               bSecondarySurfaceCreated);
  886.     if (nDDRetVal != DUALDISPSUCCESS)
  887.     {
  888.         TEXTOUT(TEXT("DUALDISPDEMO: Config_CustomFBApplication: Call to DE_CreateSecondarySurfBitmap failed.n"));
  889.         return nDDRetVal;
  890.     }
  891.     /* Program LCD switch and connect PDP to the off-screen surface. */
  892.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  893.     if (nDDRetVal != DUALDISPSUCCESS)
  894.     {
  895.         TEXTOUT(TEXT("DUALDISPDEMO: Config_CustomFBApplication: Call to DE_ConfigureDisplaySystem failed.n"));
  896.         return nDDRetVal;
  897.     }
  898.     /* The desktop will now be transferred to the HOST (i.e. XScale) to be 
  899.     displayed on the internal screen. The LCD switch must be programmed 
  900.     to use the HOST as the "internal display source", before transferring 
  901.     desktop data to the HOST. */
  902.     nDDRetVal |= BeginDesktopToXScaleTransfer(sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  903.     /* Perform test-write to secondary surface frame buffer */
  904.     /* Get DISPCFG_GET_SURFACE_INFO for the secondary surface. The secondary can then be
  905.     written to via: s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress */
  906.     nDDRetVal |= GetSecondarySurfaceInfo(s2700GSecondadrySurfInfo);
  907.     nDDRetVal |= WriteToSecSurfFrameBuffer(s2700GSecondadrySurfInfo);
  908.     if (nDDRetVal != DUALDISPSUCCESS)
  909.     {
  910.         TEXTOUT(TEXT("DUALDISPDEMO: Config_CustomApplication: returning error value.n"));
  911.         assert(0);
  912.     }
  913.     return nDDRetVal;
  914. }
  915. /***********************************************************************************
  916.  Function Name      : Config_InternalDispOnlySecSurf
  917.  Inputs             :
  918.  Outputs            : sDisplayConfig
  919.                       s2700GSecondadrySurfInfo
  920.  Returns            :
  921.  Description        : Select the configuration "Internal display only with secondary
  922.                       surface". No desktop.
  923. ************************************************************************************/
  924. LONG Config_InternalDispOnlySecSurf(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig,
  925.                                    DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo)
  926. {
  927.     LONG nDDRetVal = DUALDISPSUCCESS;
  928.     /* PDP will be connected to the internal LCD */
  929.     LCDInternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  930.     /* Disable external LCD */
  931.     LCDExternal(sDisplayConfig, TRUE, FALSE, DCFG_SOURCE_NOT_APPLICABLE, DCFG_FORMAT_NOT_APPLICABLE);
  932.     /* "secondary display surface" will be connected to PDP */
  933.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_SECONDARYSURFACE, 0, FALSE, 60, PARAM_NOT_APPLICABLE, TRUE);
  934.     /* Create the off-screen surface. */
  935.     nDDRetVal |= DE_CreateSecondarySurfBitmap(hdcMarathon, hdcMem, hBitmap, hOldBitmap, 
  936.                                               bSecondarySurfaceCreated);
  937.     /* Program LCD switch and connect PDP to the off-screen surface. */
  938.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  939.     nDDRetVal |= GetSecondarySurfaceInfo(s2700GSecondadrySurfInfo);
  940.     /* Code to write to secondary surface goes here. */
  941.     /* Example write: GDI rectangles (20 seconds) */
  942.     nDDRetVal |= RandomRectangles();
  943.     /* Example write: to Secondary surface frame buffer */
  944.     nDDRetVal |= WriteToSecSurfFrameBuffer(s2700GSecondadrySurfInfo);
  945.     Sleep(4000);
  946.     /* Delete secondary surface bitmap. */
  947.     DestroySecondarySurface();
  948.     return nDDRetVal;
  949. }
  950. /***********************************************************************************
  951.  Function Name      : Config_ExternalDispOnlyDesktop
  952.  Inputs             : 
  953.  Outputs            : sDisplayConfig
  954.  Returns            : 
  955.  Description        : Select the configuration "Desktop on external display only". 
  956. ************************************************************************************/
  957. LONG Config_ExternalDispOnlyDesktop(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig)
  958. {
  959.     LONG nDDRetVal = DUALDISPSUCCESS;
  960.     /* Disable internal LCD */
  961.     LCDInternal(sDisplayConfig, TRUE, FALSE, DCFG_SOURCE_NOT_APPLICABLE, DCFG_FORMAT_NOT_APPLICABLE);
  962.     /* PDP will connect to the external display. */
  963.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  964.     /* Desktop will connect to the PDP */
  965.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_DESKTOP, 
  966.                         PARAM_NOT_APPLICABLE, FALSE, PARAM_NOT_APPLICABLE, EXTERNALDISPLAYROTATION, TRUE);
  967.     /* Hide the existing desktop from view - it is about to be "messed up". */
  968.     classRefreshDisplay.MaskDesktop();
  969.     /* Program LCD switch and connect PDP to the desktop surface. */
  970.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  971.     /* Display the new "refreshed" desktop */
  972. classRefreshDisplay.RevealDesktop();
  973.     return nDDRetVal;
  974. }
  975. /***********************************************************************************
  976.  Function Name      : Config_ExternalDispOnlySecSurf
  977.  Inputs             : 
  978.  Outputs            : sDisplayConfig
  979.                       s2700GSecondadrySurfInfo
  980.  Returns            : 
  981.  Description        : Select the configuration "External display only with secondary
  982.                       surface". No desktop.
  983. ************************************************************************************/
  984. LONG Config_ExternalDispOnlySecSurf(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig,
  985.                                     DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo)
  986. {
  987.     LONG nDDRetVal = DUALDISPSUCCESS;
  988.     /* Disable internal LCD */
  989.     LCDInternal(sDisplayConfig, TRUE, FALSE, DCFG_SOURCE_NOT_APPLICABLE, DCFG_FORMAT_NOT_APPLICABLE);
  990.     /* PDP will connect to the external display. */
  991.     LCDExternal(sDisplayConfig, TRUE, TRUE, DCFG_SOURCE_MARATHON, DCFG_FORMAT_NOT_APPLICABLE);
  992.     /* "Secondary display surface" will connect to the PDP */
  993.     ConfigSurfaceForPDP(sDisplayConfig, DCFG_SECONDARYSURFACE, 0, FALSE, 60, PARAM_NOT_APPLICABLE, TRUE);
  994.     /* Create the off-screen surface. */
  995.     nDDRetVal |= DE_CreateSecondarySurfBitmap(hdcMarathon, hdcMem, hBitmap, hOldBitmap, 
  996.                                               bSecondarySurfaceCreated);
  997.     /* Program LCD switch and connect PDP to the off-screen surface. */
  998.     nDDRetVal |= DE_ConfigureDisplaySystem(sDisplayConfig, hdcMarathon);
  999.     /* Get DISPCFG_GET_SURFACE_INFO for the secondary surface. The secondary can then be
  1000.     written to via: s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress */
  1001.     nDDRetVal |= GetSecondarySurfaceInfo(s2700GSecondadrySurfInfo);
  1002.     /* Code to write to secondary surface goes here. */
  1003.     /* Example write: GDI rectangles (5 seconds) */
  1004.     nDDRetVal |= RandomRectangles();
  1005.     /* Example write: to Secondary surface frame buffer */
  1006.     nDDRetVal |= WriteToSecSurfFrameBuffer(s2700GSecondadrySurfInfo);
  1007.     Sleep(4000);
  1008.     /* Delete the secondary surface bitmap. */
  1009.     DestroySecondarySurface();
  1010.     return nDDRetVal;
  1011. }
  1012. /***********************************************************************************
  1013.  Function Name      : LCDInternal
  1014.  Inputs             : Valid
  1015.                       bActivate
  1016.                       eLcdSource
  1017.                       eXScaleFormat
  1018.  Outputs            : sDisplayConfig
  1019.  Returns            : 
  1020.  Description        : Copy the values specified in  Valid, bActivate, eLcdSource
  1021.                       and eXScaleFormat to sDisplayConfig.sLcdInternal.
  1022. ************************************************************************************/
  1023. void LCDInternal(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  1024.                  BOOL bValid, 
  1025.                  BOOL bActivate, 
  1026.                  DCFG_LCD_SOURCE eLcdSource, 
  1027.                  DCFG_LCD_IN_FORMAT eXScaleFormat)
  1028. {
  1029.     /* Configure internal LCD */
  1030.     sDisplayConfig.sLcdInternal.bValid = bValid;
  1031.     sDisplayConfig.sLcdInternal.bActivate = bActivate;
  1032.     sDisplayConfig.sLcdInternal.eLcdSource = eLcdSource;
  1033.     sDisplayConfig.sLcdInternal.eXScaleFormat = eXScaleFormat; // only applicable when HOST is source
  1034. }
  1035. /***********************************************************************************
  1036.  Function Name      : LCDExternal
  1037.  Inputs             : Valid
  1038.                       bActivate
  1039.                       eLcdSource
  1040.                       eXScaleFormat
  1041.  Outputs            : sDisplayConfig
  1042.  Returns            : 
  1043.  Description        : Copy the values specified in Valid, bActivate, eLcdSource
  1044.                       and eXScaleFormat to sDisplayConfig.sLcdExternal.
  1045. ************************************************************************************/
  1046. void LCDExternal(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  1047.                  BOOL bValid, 
  1048.                  BOOL bActivate, 
  1049.                  DCFG_LCD_SOURCE eLcdSource, 
  1050.                  DCFG_LCD_IN_FORMAT eXScaleFormat)
  1051. {
  1052.     /* Configure external LCD */
  1053.     sDisplayConfig.sLcdExternal.bValid = bValid;
  1054.     sDisplayConfig.sLcdExternal.bActivate = bActivate;
  1055.     sDisplayConfig.sLcdExternal.eLcdSource = eLcdSource;
  1056.     sDisplayConfig.sLcdExternal.eXScaleFormat = eXScaleFormat; // only applicable when HOST is source
  1057. }
  1058. /***********************************************************************************
  1059.  Function Name      : ConfigSurfaceForPDP
  1060.  Inputs             : eSurface
  1061.                       ulBorderColor
  1062.                       bFillScreen
  1063.                       ulRefreshRate
  1064.  Outputs            : sDisplayConfig
  1065.  Returns            : 
  1066.  Description        : Copy the values specified in ulBorderColor, bFillScreen and
  1067.                       ulRefreshRate to sDisplayConfig.
  1068. ************************************************************************************/
  1069. void ConfigSurfaceForPDP(DISPCFG_DISPLAY_SYSTEM& sDisplayConfig, 
  1070.                          DCFG_DISPLAY_SURFACE eSurface,
  1071.                          ULONG ulBorderColor, 
  1072.                          BOOL bFillScreen, 
  1073.                          ULONG ulRefreshRate,
  1074.                          ULONG ulPhysRotation,
  1075.                          BOOL bSet)
  1076. {
  1077.     /* SET a display configuration or GET existing configuration? */
  1078.     sDisplayConfig.bSet = bSet;
  1079.     /* Describe surface to be connected to PDP. 
  1080.        Colour, screen and refresh rate attributes are not applicable
  1081.        when connecting PDP to a desktop surface. */
  1082.     sDisplayConfig.sConnectSurface.eSurface = eSurface;
  1083.     sDisplayConfig.sConnectSurface.ulBorderColor = ulBorderColor;
  1084.     sDisplayConfig.sConnectSurface.ulRefreshRate = ulRefreshRate;
  1085.     /* Rotation angle of Desktop (only applicable when Desktop is connected to the PDP). */
  1086.     sDisplayConfig.sConnectSurface.ulPhysRotation = ulPhysRotation;
  1087. }
  1088. /***********************************************************************************
  1089.  Function Name      : StopDesktopToXScaleTransfer
  1090.  Inputs             : 
  1091.  Outputs            : 
  1092.  Returns            : Error code
  1093.  Description        : Stops the desktop to xscale transfer mechanism
  1094. ************************************************************************************/
  1095. LONG StopDesktopToXScaleTransfer()
  1096. {
  1097.     LONG nDDRetVal = DUALDISPSUCCESS;
  1098.     BOOL bEventRetVal = 0;
  1099.     DWORD dwWaitInMilliseconds = 10000;
  1100.     DWORD nRetVal = WAIT_FAILED;
  1101.     TEXTOUT(TEXT("DUALDISPDEMO: StopDesktopToXScaleTransfer: exiting DesktopTransfer thread.n"));
  1102.     bEventRetVal = SetEvent(hEvent_StopDesktopTransfer);
  1103.     if (bEventRetVal)
  1104.     {
  1105.         /* StopDesktopTransfer event has been signalled */
  1106.         nRetVal = WaitForSingleObject(hThread_DesktopTransfer, dwWaitInMilliseconds);
  1107.         if (nRetVal == WAIT_TIMEOUT)
  1108.         {
  1109.             /* Error - DesktopToXScaleTransfer thread should have terminated by now. */
  1110.             assert(0);
  1111.             nDDRetVal |= DUALDISPERROR;
  1112.             return nDDRetVal;
  1113.         }
  1114.         else if (nRetVal == WAIT_OBJECT_0)
  1115.         {
  1116.             BOOL bCloseRetVal = 0;
  1117.             /* Thread object has signalled state. Thread has been exited. */
  1118.             bCloseRetVal = CloseHandle(hThread_DesktopTransfer);
  1119.             hThread_DesktopTransfer = NULL;
  1120.             TEXTOUT(TEXT("DUALDISPDEMO: StopDesktopToXScaleTransfer: exited DesktopTransfer thread.n"));
  1121.             if (bCloseRetVal == 0)
  1122.             {
  1123.                 /* Error - Failed to close handle */
  1124.                 assert(0);
  1125.                 nDDRetVal |= DUALDISPERROR;
  1126.                 return nDDRetVal;
  1127.             }
  1128.         }
  1129.         else if (nRetVal == WAIT_FAILED)
  1130.         {
  1131.             assert(0);
  1132.             nDDRetVal |= DUALDISPERROR;
  1133.             return nDDRetVal;
  1134.         }
  1135.     }
  1136.     else
  1137.     {
  1138.        assert(0);
  1139.        nDDRetVal |= DUALDISPERROR;
  1140.        return nDDRetVal;    
  1141.     }
  1142.     return nDDRetVal;
  1143. }
  1144. /***********************************************************************************
  1145.  Function Name      : StopGDIRectangles
  1146.  Inputs             : 
  1147.  Outputs            : 
  1148.                       
  1149.  Returns            : 
  1150.  Description        : Shuts down the GDIRectangles thread.
  1151. ************************************************************************************/
  1152. LONG StopGDIRectangles()
  1153. {
  1154.     LONG nDDRetVal = DUALDISPSUCCESS;
  1155.     BOOL bEventRetVal = 0;
  1156.     DWORD dwWaitInMilliseconds = 1000;
  1157.     DWORD nRetVal = WAIT_FAILED;
  1158.     bEventRetVal = SetEvent(hEvent_StopGDIRectangles);
  1159.     TEXTOUT(TEXT("DUALDISPDEMO: StopGDIRectangles: exiting thread.n"));
  1160.     if (bEventRetVal)
  1161.     {
  1162.         /* StopDesktopTransfer event has been signalled */
  1163.         nRetVal = WaitForSingleObject(hThread_GDIRectangles, dwWaitInMilliseconds);
  1164.         if (nRetVal == WAIT_TIMEOUT)
  1165.         {
  1166.             /* Error - thread should have terminated by now. */
  1167.             assert(0);
  1168.             nDDRetVal |= DUALDISPERROR;
  1169.             return nDDRetVal;
  1170.         }
  1171.         else if (nRetVal == WAIT_OBJECT_0)
  1172.         {
  1173.             BOOL bCloseRetVal = 0;
  1174.             /* Thread object has signalled state. Thread has been exited. */
  1175.             TEXTOUT(TEXT("DUALDISPDEMO: StopGDIRectangles: GDIRectangles thread has exited.n"));
  1176.             bCloseRetVal = CloseHandle(hThread_GDIRectangles);
  1177.             hThread_GDIRectangles = NULL;
  1178.             if (bCloseRetVal == 0)
  1179.             {
  1180.                 /* Error - Failed to close handle */
  1181.                 assert(0);
  1182.                 nDDRetVal |= DUALDISPERROR;
  1183.                 return nDDRetVal;
  1184.             }
  1185.         }
  1186.         else if (nRetVal == WAIT_FAILED)
  1187.         {
  1188.             assert(0);
  1189.             nDDRetVal |= DUALDISPERROR;
  1190.             return nDDRetVal;
  1191.         }
  1192.     }
  1193.     else
  1194.     {
  1195.        assert(0);
  1196.        nDDRetVal |= DUALDISPERROR;
  1197.        return nDDRetVal;    
  1198.     }
  1199.     return nDDRetVal;
  1200. }
  1201. /***********************************************************************************
  1202.  Function Name      : BeginDesktopToXScaleTransfer
  1203.  Inputs             : hdcXScale
  1204.  Outputs            : sDesktopSurfaceInfo
  1205.                       sXScaleSurfaceInfo
  1206.  Returns            : 
  1207.  Description        : Transfer the desktop surface from the Marathon primary 
  1208.                       surface to the XScale primary surface.
  1209. ************************************************************************************/
  1210. LONG BeginDesktopToXScaleTransfer(DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo,
  1211.                                        XSCALE_SURFACE_INFO& sXScaleSurfaceInfo,
  1212.                                        HDC hdcXScale)
  1213. {
  1214.     LONG nDDRetVal = DUALDISPSUCCESS;
  1215.     /* The LCD switch must be programmed correctly before beginning desktop transfer. */
  1216.     
  1217.     /* Get desktop surface information from Marathon, i.e. mode information,
  1218.     orientation, and physical address of Marathon frame buffer. */
  1219.     /* Note: This function should always be called twice when desktop is to be transfered: 
  1220.     firstly it is called in WinMain, and secondly here. This second call must be made after
  1221.     the call to DE_ConfigureDisplaySystem (by a Config_xxxxxx function). DE_ConfigureDisplaySystem 
  1222.     will force the Marathon driver to set a new rotation angle for the surface (if it is required).
  1223.     Thus bDriverRealigned can be correctly set (indicating whether Marathon driver has changed the
  1224.     desktop surface rotation angle in order to support the external display) by comparing the 
  1225.     'initial' desktop rotation angle with the 'current' desktop rotation angle. */
  1226.     nDDRetVal |= DE_GetMarathonSurfaceInfo(sDesktopSurfaceInfo, DCFG_DESKTOP, hdcMarathon);
  1227.    
  1228.     /* Check to see if surface has been realigned. Compare the new rotation angle with the old
  1229.     rotation angle. */
  1230.     if (sDesktopSurfaceInfo.sPhysSurfaceInfo.lPhysicalRotation == lInitialDesktopRotation)
  1231.     {
  1232.         sDesktopSurfaceInfo.sPhysSurfaceInfo.bDriverRealigned = FALSE;
  1233.     }
  1234.     else
  1235.     {
  1236.         sDesktopSurfaceInfo.sPhysSurfaceInfo.bDriverRealigned = TRUE;
  1237.     }
  1238.     /* Get destination (XScale) surface information: width, height, bpp, stride, 
  1239.     buffer address. */    
  1240.     nDDRetVal |= DE_GetXScaleSurfaceInfo(sXScaleSurfaceInfo, hdcXScale);
  1241.  
  1242.     /* Check there are no errors before starting 'Desktop to XScale' transfer thread. */
  1243.     if (nDDRetVal != DUALDISPSUCCESS)
  1244.     {
  1245.         return nDDRetVal;
  1246.     }
  1247.     /* Data transfer engine is used to copy the Desktop from the Marathon primary 
  1248.     surface to the XScale primary surface. */
  1249.     /* Create an event object to control termination of 'Desktop to XScale' Transfer thread.
  1250.     Event object has attributes: 'auto-reset', 'initially nonsignalled'. */
  1251.     hEvent_StopDesktopTransfer = CreateEvent(NULL, FALSE, FALSE, TEXT("StopDesktopTransfer"));
  1252.     if (hEvent_StopDesktopTransfer == NULL)
  1253.     {
  1254.         /* Failed to create event object */
  1255.         nDDRetVal |= DUALDISPERROR;
  1256.         return nDDRetVal;
  1257.     }
  1258.     hThread_DesktopTransfer = CreateThread(NULL, 0, DesktopToXScaleTransfer, 
  1259.                                            NULL, 0, NULL);
  1260.     if (hThread_DesktopTransfer == NULL)
  1261.     {
  1262.         /* Failed to create thread */
  1263.         nDDRetVal |= DUALDISPERROR;
  1264.         return nDDRetVal;
  1265.     }
  1266.     if (nDDRetVal != DUALDISPSUCCESS)
  1267.     {
  1268.         TEXTOUT(TEXT("DUALDISPDEMO: BeginDesktopToXScaleTransfer: Error.n"));
  1269.     }
  1270.     TEXTOUT(TEXT("DUALDISPDEMO: BeginDesktoptoXScaleTransfer exit.n"));
  1271.     return nDDRetVal;
  1272. }
  1273. /***********************************************************************************
  1274.  Function Name      : DesktopToXScaleTransfer
  1275.  Inputs             : lpParameter
  1276.  Inputs/Outputs     : 
  1277.  Returns            : Error code
  1278.  Description        : Controls Desktop to XScale transfer process. The routine will 
  1279.                       decide whether to perform line and pixel doubling. It will 
  1280.                       also perform any required rotation.
  1281. ************************************************************************************/
  1282. DWORD WINAPI DesktopToXScaleTransfer(LPVOID lpParameter)
  1283. {
  1284.     ULONG nDDRetVal = DUALDISPSUCCESS;
  1285.     BOOL bPixelDouble;
  1286.     ULONG ulSrcWidth, ulSrcHeight, ulDestWidth, ulDestHeight, ulSrcLength, ulDestLength, ulSrcStride;
  1287.     /* Make sure this surface is displaying the desktop. */
  1288.     assert(sDesktopSurfaceInfo.eDisplaySurface == DCFG_DESKTOP);
  1289.     if (sDesktopSurfaceInfo.eDisplaySurface != DCFG_DESKTOP)
  1290.     {
  1291.         /* Error: this function can only transfer a Desktop surface to the XScale. */
  1292.         TEXTOUT(TEXT("DUALDISPDEMO: DesktopToXScaleTransfer works for a Desktop surface only.n"));
  1293.         return DUALDISPERROR; 
  1294.     }
  1295.     ulDestWidth = sXScaleSurfaceInfo.ulWidth;
  1296.     ulDestHeight = sXScaleSurfaceInfo.ulHeight;
  1297.     ulSrcWidth = sDesktopSurfaceInfo.sPhysSurfaceInfo.ulWidth;
  1298.     ulSrcHeight = sDesktopSurfaceInfo.sPhysSurfaceInfo.ulHeight;
  1299.     ulSrcStride = sDesktopSurfaceInfo.sPhysSurfaceInfo.ulStride;
  1300.     /* Find out whether or not pixel doubling is required. */
  1301.     ulSrcLength = (ulSrcWidth > ulSrcHeight) ? ulSrcWidth : ulSrcHeight;
  1302.     ulDestLength = (ulDestWidth > ulDestHeight) ? ulDestWidth : ulDestHeight;
  1303.     if (ulSrcLength == ulDestLength)
  1304.     {
  1305.         /* Pixel doubling not required */
  1306.         bPixelDouble = FALSE;
  1307.     }
  1308.     else if ((ulSrcLength * 2) == ulDestLength)
  1309.     {
  1310.         /* Perform pixel doubling */
  1311.         bPixelDouble = TRUE;
  1312.     }
  1313.     else
  1314.     {
  1315.         /* Source and destination aspect ratios do not match. */
  1316.         assert(0);
  1317.         nDDRetVal |= DUALDISPERROR;
  1318.         return nDDRetVal;
  1319.     }
  1320.     /* Has the Marathon surface been re-aligned? */
  1321.     if ( sDesktopSurfaceInfo.sPhysSurfaceInfo.bDriverRealigned)
  1322.     {
  1323.         /* MIRROR MODE: Marathon surface has been realigned in order to 
  1324.         support an external display. This means that standard rotation 
  1325.         angle (used to compensate for the angle at which the internal panel
  1326.         is mounted and/or viewed), will not be applied in this case.
  1327.         
  1328.         Hence the surface must be rotated here instead. */
  1329.       
  1330.         ULONG srcAddress, destAddress, ulRequiredRotation;
  1331.         destAddress = sXScaleSurfaceInfo.ulPhysAddress;
  1332.         srcAddress = sDesktopSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress;
  1333.         ulRequiredRotation = lInitialDesktopRotation;
  1334.         /* Is Pixel/Line doubling required? */
  1335.         if (bPixelDouble)
  1336.         {
  1337.             /* Mirror mode with pixel/line doubling */
  1338.         
  1339.             /*  Rotate Marathon frame buffer to XScale frame buffer. 
  1340.             Perform pixel/line doubling. */
  1341.             nDDRetVal |= RotateAndDoubleToBuffer((USHORT*) destAddress, (USHORT*) srcAddress, 
  1342.                                     ulDestWidth, ulDestHeight, ulRequiredRotation, ulSrcWidth, ulSrcHeight, ulSrcStride);
  1343.         }
  1344.         else                                            // Mirror mode without pixel/line doubling
  1345.         { 
  1346.             /* Rotate Marathon frame buffer to the XScale frame buffer.
  1347.             Do not pixel/line double. */
  1348.             nDDRetVal |= RotateToBuffer((USHORT*) destAddress, (USHORT*) srcAddress, 
  1349.                     ulDestWidth, ulDestHeight, ulRequiredRotation, ulSrcWidth, ulSrcHeight, ulSrcStride);
  1350.         }
  1351.     }
  1352.     else  
  1353.     {
  1354.         /* Marathon surface has not been re-aligned. It should be copied to XScale frame
  1355.     buffer without rotation. */
  1356.     
  1357.         /* There are two scenarios in which the Desktop will not have been realigned and
  1358.         thus rotation is not required:
  1359.         
  1360.         (1) When the dual display mode is NOT MirrorMode
  1361.         (2) In MirrorMode when the desktop does NOT require rotation in order to be
  1362.             displayed on the internal panel. 
  1363.         
  1364.         */
  1365.         /* Is Pixel/Line doubling required? */
  1366.         if (bPixelDouble)
  1367.         {
  1368.             /* Copy Marathon frame buffer to XScale frame buffer. Perform
  1369.             pixel/line doubling. Do not rotate. */
  1370.             TEXTOUT(TEXT("DUALDISPDEMO: Copying Desktop to XScale with pixel doubling.n"));
  1371.             nDDRetVal |= CopyAndDoubleToXScaleFB(sDesktopSurfaceInfo, sXScaleSurfaceInfo);
  1372.         }
  1373.         else                             // Custom application mode without pixel/line doubling
  1374.         {
  1375.             /* Copy Marathon frame buffer to XScale frame bufer.
  1376.             Do not perform pixel/line doubling. */
  1377.             TEXTOUT(TEXT("DUALDISPDEMO: Copying Desktop to XScale without pixel doubling.n"));
  1378.             nDDRetVal |= CopyToXScaleFB(sDesktopSurfaceInfo, sXScaleSurfaceInfo);
  1379.         }
  1380.     }
  1381.     TEXTOUT(TEXT("DUALDISPDEMO: DesktopToXScaleTransfer: Exiting Desktop to XScale Transfer thread.n"));
  1382.     if (nDDRetVal != DUALDISPSUCCESS)
  1383.     {
  1384.         TEXTOUT(TEXT("DUALDISPDEMO: DesktopToXScaleTransfer: Error.n"));
  1385.     }
  1386.     return nDDRetVal;
  1387. }
  1388. /* Turn off optimization for 'Desktop to XScale copy routine' (PocketPC, release builds) to prevent underrun. */
  1389. #ifdef OSV_PPC
  1390. #ifdef NDEBUG
  1391. #pragma optimize("", off)
  1392. #endif
  1393. #endif
  1394. /***********************************************************************************
  1395.  Function Name      : CopyToXScaleFB
  1396.  Inputs/Outputs     : sMarathonSurfaceInfo
  1397.                       sXScaleSurfaceInfo
  1398.  Outputs            : 
  1399.  Returns            : Error Code
  1400.  Description        : Copies the Marathon frame buffer to the XScale frame buffer. 
  1401.                       Pixel and line doubling are not performed.
  1402. ************************************************************************************/
  1403. LONG CopyToXScaleFB(DISPCFG_GET_SURFACE_INFO& sMarathonSurfaceInfo,
  1404.                                  XSCALE_SURFACE_INFO& sXScaleSurfaceInfo)
  1405. {
  1406.     ULONG nDDRetVal = DUALDISPSUCCESS;
  1407.     DWORD dwWaitObjRetVal = 0;
  1408.     DWORD dwDelayInMilliseconds = DESKTOPTOXSCALEDELAY;
  1409.     ULONG SourceFrameBufSizeInInt32;
  1410.     ULONG* pulSourceBuf, * pulDestinationBuf;
  1411.     TCHAR wstrOutput[200];
  1412.     BOOL bIsDirty = FALSE;
  1413.     wsprintf(wstrOutput, TEXT("DUALDISPDEMO: CopyToXScaleFB: Delay = %d ms.n"), dwDelayInMilliseconds);
  1414.     TEXTOUT(wstrOutput);
  1415.     /* ulStride indicates the physical dimensions of the surface - irrespective of the intended viewing angle.
  1416.     Note: a 'portrait' image is described by the driver as having ('height' > 'width') and a landscape image is
  1417.     described as having ('width' > 'height'). Thus the driver describes the 'logical view'. However, in order to
  1418.     copy from the frame buffer, the 'logical view' must be converted to the 'physical view'. */
  1419.     if (sMarathonSurfaceInfo.sPhysSurfaceInfo.ulStride != (sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth * 2))
  1420.     {
  1421.         /* Swap width and height in order to obtain a physical description of the frame buffer. */
  1422.         ULONG ulTemp = sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth;
  1423.         sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth = sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight;
  1424.         sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight = ulTemp;
  1425.     }
  1426.     /* This function can only operate when the source and destination frame buffers have
  1427.     the same width and height. */
  1428.     assert(sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth == sXScaleSurfaceInfo.ulWidth);
  1429.     assert(sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight == sXScaleSurfaceInfo.ulHeight);
  1430.     /* Verify display aspect ratios */
  1431.     if ((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth != sXScaleSurfaceInfo.ulWidth) || 
  1432.         (sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight != sXScaleSurfaceInfo.ulHeight))
  1433.     {
  1434.         TEXTOUT(TEXT("DUALDISPDEMO: CopyToXScaleFB: Error - source and destination buffers incompatible.n"));
  1435.         return DUALDISPERROR;
  1436.     }
  1437.     /* Verify frame buffer addresses */
  1438.     if ((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress == NULL) || 
  1439.         (sXScaleSurfaceInfo.ulPhysAddress == NULL))
  1440.     {
  1441.         TEXTOUT(TEXT("DUALDISPDEMO: CopyToXScaleFB: Error - frame buffer address invalid.n"));
  1442.         return DUALDISPERROR;
  1443.     }
  1444.     SourceFrameBufSizeInInt32 = sMarathonSurfaceInfo.sPhysSurfaceInfo.ulStride * 
  1445.                              sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight / sizeof(ULONG);
  1446.     for(;;)
  1447.     {
  1448.         static ULONG nConsecutiveScreenUpdates = 0;
  1449.         dwWaitObjRetVal = WaitForSingleObject(hEvent_StopDesktopTransfer, dwDelayInMilliseconds);
  1450.         /* See if Marathon frame buffer has changed since it was last copied to the 
  1451.         XScale display surface. */
  1452.         DE_CheckForScreenUpdate(hdcMarathon, bIsDirty);
  1453.         /* Adjust the rate of screen update checks. NOTE: only use this function if GSB cannot 
  1454.         cope with bandwidth requirements of DesktopToXScaleTransfer. */
  1455.         // AdjustRefreshRate(bIsDirty, nConsecutiveScreenUpdates, dwDelayInMilliseconds);
  1456.         /* If bIsDirty is TRUE, then an attempt should be made to update the screen by 
  1457.         executing the 'if-else' statement below (which processes dwWaitObjRetVal). If 
  1458.         dwWaitObjRetVal does NOT equal WAIT_TIMEOUT, then the 'if-else' statement below 
  1459.         MUST be executed to catch WAIT_FAILED and WAIT_OBJECT_0. */
  1460.         if ((bIsDirty == FALSE) && (dwWaitObjRetVal == WAIT_TIMEOUT))
  1461.         {
  1462.             continue;
  1463.         }
  1464.         /* Marathon frame buffer has changed, therefore update XScale frame buffer. */
  1465.         if (dwWaitObjRetVal == WAIT_TIMEOUT)
  1466.         {
  1467.             pulSourceBuf = (ULONG*) sMarathonSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress;
  1468.             pulDestinationBuf = (ULONG*) sXScaleSurfaceInfo.ulPhysAddress;
  1469. #if (CHECK_MEM_COPY_SPEED == 1)
  1470.             //////////////////////// Monitor copy loop speed //////////////////////////////
  1471.             DWORD dwStart = GetTickCount();
  1472.             ///////////////////////////////////////////////////////////////////////////////
  1473. #endif
  1474.             for (ULONG i = 0; i < SourceFrameBufSizeInInt32; i++)
  1475.             {
  1476.                 *pulDestinationBuf++ = *pulSourceBuf++;
  1477.             }
  1478. #if (CHECK_MEM_COPY_SPEED == 1)
  1479.             ////////////////////////////////////////////////////////////////////////////////
  1480.             DWORD dwEnd = GetTickCount();
  1481.             DWORD timetaken = dwEnd - dwStart;
  1482.             TCHAR outstring[100];
  1483.                     wsprintf(outstring, TEXT("DUALDISPDEMO: Loop time: %dn"), timetaken);
  1484.                     TEXTOUT(outstring);
  1485.             ////////////////////////////////////////////////////////////////////////////////
  1486. #endif
  1487.         }
  1488.         else if (dwWaitObjRetVal == WAIT_OBJECT_0)
  1489.         {
  1490.             /* hEvent_StopDesktopTransfer event object signalled - therefore stop transfer */
  1491.             TEXTOUT(TEXT("DUALDISPDEMO: CopyToXScaleFB: Exiting desktop transfer.n"));
  1492.             return nDDRetVal;
  1493.         }
  1494.         else if (dwWaitObjRetVal == WAIT_FAILED)
  1495.         {
  1496.             assert(0);
  1497.             nDDRetVal |= DUALDISPERROR;
  1498.             return nDDRetVal;
  1499.         }
  1500.         else
  1501.         {
  1502.             assert(0);
  1503.             nDDRetVal |= DUALDISPERROR;
  1504.             return nDDRetVal;
  1505.         }
  1506.     }
  1507.     return nDDRetVal;
  1508. }
  1509. /* Restore optimization */
  1510. #ifdef OSV_PPC
  1511. #ifdef NDEBUG
  1512. #pragma optimize("", on)
  1513. #endif
  1514. #endif
  1515. /* Turn off optimization for 'Desktop to XScale copy routine' (PocketPC, release builds) to prevent underrun. */
  1516. #ifdef OSV_PPC
  1517. #ifdef NDEBUG
  1518. #pragma optimize("", off)
  1519. #endif
  1520. #endif
  1521. /***********************************************************************************
  1522.  Function Name      : CopyAndDoubleToXScaleFB
  1523.  Inputs/Outputs     : sMarathonSurfaceInfo
  1524.                       sXScaleSurfaceInfo
  1525.  Outputs            : 
  1526.  Returns            : Error code
  1527.  Description        : Copies the Marathon frame buffer to the XScale frame buffer.
  1528.                       Pixel and line doubling are performed.
  1529. ************************************************************************************/
  1530. LONG CopyAndDoubleToXScaleFB(DISPCFG_GET_SURFACE_INFO& sMarathonSurfaceInfo,
  1531.                                  XSCALE_SURFACE_INFO& sXScaleSurfaceInfo)
  1532. {
  1533.     ULONG nDDRetVal = DUALDISPSUCCESS;
  1534.     DWORD dwDelayInMilliseconds = DESKTOPTOXSCALEDELAY;
  1535.     DWORD dwWaitObjRetVal = 0;
  1536.     USHORT* pulSourceBuf, * pulDestinationBuf;
  1537.     BOOL bIsDirty = FALSE;
  1538.     /* ulStride indicates the physical dimensions of the surface - irrespective of the intended viewing angle.
  1539.     Note: a 'portrait' image is described by the driver as having ('height' > 'width') and a landscape image is
  1540.     described as having ('width' > 'height'). Thus the driver describes the 'logical view'. However, in order to
  1541.     copy from the frame buffer, the 'logical view' must be converted to the 'physical view'. */
  1542.     if (sMarathonSurfaceInfo.sPhysSurfaceInfo.ulStride != (sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth * 2))
  1543.     {
  1544.         /* Swap width and height in order to obtain a physical description of the frame buffer. */
  1545.         ULONG ulTemp = sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth;
  1546.         sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth = sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight;
  1547.         sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight = ulTemp;
  1548.     }
  1549.     /* This function can only operate when width and height of destination buffer are
  1550.     twice the width and height of the source buffer. */
  1551.     assert((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth * 2) == sXScaleSurfaceInfo.ulWidth);
  1552.     assert((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight * 2) == sXScaleSurfaceInfo.ulHeight);
  1553.     /* Verify display aspect ratios */
  1554.     if (((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth * 2) != sXScaleSurfaceInfo.ulWidth) || 
  1555.         ((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight * 2) != sXScaleSurfaceInfo.ulHeight))
  1556.     {
  1557.         TEXTOUT(TEXT("DUALDISPDEMO: CopyAndDoubleToXScaleFB: Error - source and destination buffers incompatible.n"));
  1558.         return DUALDISPERROR;
  1559.     }
  1560.     /* Verify frame buffer addresses */
  1561.     if ((sMarathonSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress == NULL) ||
  1562.         (sXScaleSurfaceInfo.ulPhysAddress == NULL))
  1563.     {
  1564.         TEXTOUT(TEXT("DUALDISPDEMO: CopyAndDoubleToXScaleFB: Error - frame buffer address invalid.n"));
  1565.         return DUALDISPERROR;
  1566.     }
  1567.     for(;;)
  1568.     {
  1569.         static ULONG nConsecutiveScreenUpdates = 0;
  1570.         dwWaitObjRetVal = WaitForSingleObject(hEvent_StopDesktopTransfer, dwDelayInMilliseconds);
  1571.         /* See if Marathon frame buffer has changed since it was last copied to the 
  1572.         XScale display surface. */
  1573.         DE_CheckForScreenUpdate(hdcMarathon, bIsDirty);
  1574.         /* Adjust the rate of screen update checks. NOTE: only use this function if GSB cannot 
  1575.         cope with bandwidth requirements of DesktopToXScaleTransfer. */
  1576.         // AdjustRefreshRate(bIsDirty, nConsecutiveScreenUpdates, dwDelayInMilliseconds);
  1577.         /* If bIsDirty is TRUE, then an attempt should be made to update the screen by 
  1578.         executing the 'if-else' statement below (which processes dwWaitObjRetVal). If 
  1579.         dwWaitObjRetVal does NOT equal WAIT_TIMEOUT, then the 'if-else' statement below 
  1580.         MUST be executed to catch WAIT_FAILED and WAIT_OBJECT_0. */
  1581.         if ((bIsDirty == FALSE) && (dwWaitObjRetVal == WAIT_TIMEOUT))
  1582.         {
  1583.             continue;
  1584.         }
  1585.         if (dwWaitObjRetVal == WAIT_TIMEOUT)
  1586.         {
  1587.             /* Copy one frame of desktop surface to XScale frame buffer. */
  1588.             pulSourceBuf = (USHORT*) sMarathonSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress;
  1589.             pulDestinationBuf = (USHORT*) sXScaleSurfaceInfo.ulPhysAddress;
  1590.             /* Invalidate the data cache. This must be done because the Marathon frame buffer is
  1591.             written by a different process (via a different virtual address). Hence cache
  1592.             coherency will not be maintained. Invalidating the data-cache will ensure that 
  1593.             all pixels are re-read from the Marathon frame buffer. */
  1594.             // InvalidateDataCache causing application to hang
  1595.          //   SetKMode(TRUE);    
  1596.          //   InvalidateDataCache();
  1597.          //   SetKMode(FALSE);
  1598.             /* This may not be necessary due to cache size (32KB).  
  1599.             Round-robin cache-line eviction will ensure that all cache-lines are overwritten
  1600.             before there is a possibility of a cache hit. Note: this assumes that the Marathon
  1601.             frame buffer is a least twice the size of the cache (32 KB). Frame buffer: 
  1602.             320 * 240 = 150 KB. */
  1603.     
  1604. #if (CHECK_MEM_COPY_SPEED == 1)
  1605.             //////////////////////// Monitor copy loop speed //////////////////////////////
  1606.             DWORD dwStart = GetTickCount();
  1607.             ///////////////////////////////////////////////////////////////////////////////
  1608. #endif
  1609.             /* Perform pixel/line doubling */
  1610.             for (ULONG i = 0; i < sMarathonSurfaceInfo.sPhysSurfaceInfo.ulHeight; i++)
  1611.             {
  1612.                 // Copy a line from Marathon frame buffer to XScale frame buffer
  1613.                 for (ULONG j = 0; j < sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth; j++)
  1614.                 {
  1615.                     usTempBuffer[j] = pulSourceBuf[j];
  1616.                 }
  1617.                 for (ULONG k = 0; k < sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth; k++)
  1618.                 {
  1619.                     *pulDestinationBuf = usTempBuffer[k];
  1620.                     /* Write to the corresponding pixel in the next line */
  1621.                     *(pulDestinationBuf + sXScaleSurfaceInfo.ulWidth) = usTempBuffer[k];
  1622.                     pulDestinationBuf++;
  1623.                     *pulDestinationBuf = usTempBuffer[k];
  1624.                     /* Write to the corresponding pixel in the next line */
  1625.                     *(pulDestinationBuf + sXScaleSurfaceInfo.ulWidth) = usTempBuffer[k];
  1626.                     pulDestinationBuf++;
  1627.                 }
  1628.                 pulDestinationBuf += sXScaleSurfaceInfo.ulWidth;
  1629.                 pulSourceBuf += sMarathonSurfaceInfo.sPhysSurfaceInfo.ulWidth;
  1630.             }
  1631. #if (CHECK_MEM_COPY_SPEED == 1)
  1632.             ////////////////////////////////////////////////////////////////////////////////
  1633.             DWORD dwEnd = GetTickCount();
  1634.             DWORD timetaken = dwEnd - dwStart;
  1635.             TCHAR outstring[100];
  1636.                     wsprintf(outstring, TEXT("DUALDISPDEMO: Loop time: %dn"), timetaken);
  1637.                     TEXTOUT(outstring);
  1638.             ////////////////////////////////////////////////////////////////////////////////
  1639. #endif
  1640.         }
  1641.         else if (dwWaitObjRetVal == WAIT_OBJECT_0)
  1642.         {
  1643.             /* hEvent_StopDesktopTransfer event object signalled - therefore stop transfer */
  1644.             TEXTOUT(TEXT("DUALDISPDEMO: CopyAndDoubleToXScaleFB: exiting DesktopTransfer thread.n"));
  1645.             return nDDRetVal;
  1646.         }
  1647.         else if (dwWaitObjRetVal == WAIT_FAILED)
  1648.         {
  1649.             assert(0);
  1650.             nDDRetVal |= DUALDISPERROR;
  1651.             return nDDRetVal;
  1652.         }
  1653.         else
  1654.         {
  1655.             assert(0);
  1656.             nDDRetVal |= DUALDISPERROR;
  1657.             return nDDRetVal;
  1658.         }
  1659.     }
  1660.     if (nDDRetVal != DUALDISPSUCCESS)
  1661.     {
  1662.         TEXTOUT(TEXT("DUALDISPDEMO: CopyAndDoubleToXScaleFB: returning error value.n"));
  1663.         assert(0);
  1664.     }
  1665.     return nDDRetVal;
  1666. }
  1667. /* Restore optimization */
  1668. #ifdef OSV_PPC
  1669. #ifdef NDEBUG
  1670. #pragma optimize("", on)
  1671. #endif
  1672. #endif
  1673. /* Turn off optimization for 'Desktop to XScale copy routine' (PocketPC, release builds) to prevent underrun. */
  1674. #ifdef OSV_PPC
  1675. #ifdef NDEBUG
  1676. #pragma optimize("", off)
  1677. #endif
  1678. #endif
  1679. /***********************************************************************************
  1680.  Function Name      : RotateToBuffer
  1681.  Inputs             : pulSrcBuffer
  1682.                       ulDestWidth
  1683.                       ulDestHeight
  1684.                       destRotation
  1685.                       ulSrcWidth
  1686.                       ulSrcHeight
  1687.  Outputs            : pulDestBuffer
  1688.  Returns            : Error code
  1689.  Description        : Copy the source buffer to the destination buffer. Perform the
  1690.                       required rotation. Do not pixel/line double.
  1691. ************************************************************************************/
  1692. LONG RotateToBuffer(USHORT* pulDestBuffer, USHORT* pulSrcBuffer,
  1693.                   ULONG ulDestWidth, ULONG ulDestHeight, ULONG ulRequiredRotation,
  1694.                   ULONG ulSrcWidth, ULONG ulSrcHeight, ULONG ulSrcStride)
  1695. {
  1696.     ULONG nDDRetVal = DUALDISPSUCCESS;
  1697.     DWORD dwDelayInMilliseconds = DESKTOPTOXSCALEDELAY;
  1698.     DWORD dwWaitObjRetVal = 0;
  1699.     ULONG srcX, srcY;
  1700.     LONG destX, destY;
  1701.     BOOL bIsDirty = FALSE;
  1702.     /* ulStride indicates the physical dimensions of the surface - irrespective of the intended viewing angle.
  1703.     Note: a 'portrait' image is described by the driver as having ('height' > 'width') and a landscape image is
  1704.     described as having ('width' > 'height'). Thus the driver describes the 'logical view'. However, in order to
  1705.     copy from the frame buffer, the 'logical view' must be converted to the 'physical view'. */
  1706.     if (ulSrcStride != (ulSrcWidth * 2))
  1707.     {
  1708.         /* Swap width and height in order to obtain a physical description of the frame buffer. */
  1709.         ULONG ulTemp = ulSrcWidth;
  1710.         ulSrcWidth = ulSrcHeight;
  1711.         ulSrcHeight = ulTemp;
  1712.     }
  1713.     /* Verify frame buffer addresses */
  1714.     if ((pulDestBuffer == NULL) || (pulSrcBuffer == NULL))
  1715.     {
  1716.         TEXTOUT(TEXT("DUALDISPDEMO: RotateToBuffer: Error - frame buffer address invalid.n"));
  1717.         return DUALDISPERROR;
  1718.     }
  1719.     for(;;)
  1720.     {
  1721.         static ULONG nConsecutiveScreenUpdates = 0;
  1722.         dwWaitObjRetVal = WaitForSingleObject(hEvent_StopDesktopTransfer, dwDelayInMilliseconds);
  1723.         /* See if Marathon frame buffer has changed since it was last copied to the 
  1724.         XScale display surface. */
  1725.         DE_CheckForScreenUpdate(hdcMarathon, bIsDirty);
  1726.         /* Adjust the rate of screen update checks. NOTE: only use this function if GSB cannot 
  1727.         cope with bandwidth requirements of DesktopToXScaleTransfer. */
  1728.         // AdjustRefreshRate(bIsDirty, nConsecutiveScreenUpdates, dwDelayInMilliseconds);
  1729.         /* If bIsDirty is TRUE, then an attempt should be made to update the screen by 
  1730.         executing the 'if-else' statement below (which processes dwWaitObjRetVal). If 
  1731.         dwWaitObjRetVal does NOT equal WAIT_TIMEOUT, then the 'if-else' statement below 
  1732.         MUST be executed to catch WAIT_FAILED and WAIT_OBJECT_0. */
  1733.         if ((bIsDirty == FALSE) && (dwWaitObjRetVal == WAIT_TIMEOUT))
  1734.         {
  1735.             continue;
  1736.         }
  1737.         if (dwWaitObjRetVal == WAIT_TIMEOUT)
  1738.         {
  1739.             /* Transfer one frame from Desktop surface to XScale frame buffer. */
  1740. #if (CHECK_MEM_COPY_SPEED == 1)
  1741.             //////////////////////// Monitor copy loop speed //////////////////////////////
  1742.             DWORD dwStart = GetTickCount();
  1743.             ///////////////////////////////////////////////////////////////////////////////
  1744. #endif
  1745.             if (ulRequiredRotation == 0)
  1746.             {
  1747.                 assert(ulDestWidth == ulSrcWidth);
  1748.                 assert(ulDestHeight == ulDestHeight);
  1749.                 for (srcY = 0; srcY < ulSrcHeight; srcY++)
  1750.                 {
  1751.                     destY = srcY;
  1752.                     for (srcX = 0; srcX < ulSrcWidth; srcX++)
  1753.                     {
  1754.                         destX = srcX;
  1755.                         /* copy a source pixel to a destination pixel */
  1756.                         pulDestBuffer[destY * ulDestWidth + destX] = pulSrcBuffer[srcY * ulSrcWidth + srcX];
  1757.                     }
  1758.                 }                
  1759.             }
  1760.             else if (ulRequiredRotation == 270)
  1761.             {
  1762.                 /* Perform 270 degree rotation */
  1763.                 assert(ulDestWidth == ulSrcHeight);
  1764.                 assert(ulSrcWidth == ulDestHeight);
  1765.                 destX = ulDestWidth - 1;
  1766.                 for (srcY = 0; srcY < ulSrcHeight; srcY++)
  1767.                 {
  1768.                     // get destination x co-ordinate
  1769.                     assert(destX >= 0);
  1770.                     for (srcX = 0; srcX < ulSrcWidth; srcX++)
  1771.                     {
  1772.                         /* get destination y co-ordinate */
  1773.                         destY = srcX;
  1774.                         assert(destY < ((LONG) ulDestHeight));
  1775.                         /* copy a source pixel to a destination pixel */
  1776.                         pulDestBuffer[destY * ulDestWidth + destX] = pulSrcBuffer[srcY * ulSrcWidth + srcX];
  1777.                     }
  1778.                     destX--;
  1779.                 }
  1780.             }
  1781.             else if (ulRequiredRotation == 180)
  1782.             {
  1783.                 assert(ulDestHeight == ulSrcHeight);
  1784.                 assert(ulDestWidth == ulSrcWidth);
  1785.                 destY = ulDestHeight - 1;
  1786.                 for (srcY = 0; srcY < ulSrcHeight; srcY++)
  1787.                 {
  1788.                     destX = ulDestWidth - 1;
  1789.                     assert(destY >= 0);
  1790.                     for (srcX = 0; srcX < ulSrcWidth; srcX++)
  1791.                     {
  1792.                         assert(destY >= 0);                        
  1793.                         /* copy a source pixel to a destination pixel */
  1794.                         pulDestBuffer[destY * ulDestWidth + destX] = pulSrcBuffer[srcY * ulSrcWidth + srcX];
  1795.                         destX--;
  1796.                     }
  1797.                     destY--;
  1798.                 }
  1799.             }
  1800.             else if (ulRequiredRotation == 90)
  1801.             {
  1802.                 /* Perform 90 degree rotation */
  1803.                 assert(ulDestWidth == ulSrcHeight);
  1804.                 assert(ulSrcWidth == ulDestHeight);
  1805.                 for (srcY = 0; srcY < ulSrcHeight; srcY++)
  1806.                 {   
  1807.                     /* get destination x co-ordinate */
  1808.                     destX = srcY;
  1809.                     destY = ulDestHeight - 1;
  1810.                     assert(destX < (LONG) ulDestWidth);
  1811.                     for (srcX = 0; srcX < ulSrcWidth; srcX++)
  1812.                     {
  1813.                         /* get destination y co-ordinate */
  1814.                         assert(destY >= 0);
  1815.                         /* copy source pixel to destination pixel */
  1816.                         pulDestBuffer[destY * ulDestWidth + destX] = pulSrcBuffer[srcY * ulSrcWidth + srcX];
  1817.                         destY--;
  1818.                     }
  1819.                 }
  1820.             }
  1821. #if (CHECK_MEM_COPY_SPEED == 1)
  1822.             ////////////////////////////////////////////////////////////////////////////////
  1823.             DWORD dwEnd = GetTickCount();
  1824.             DWORD timetaken = dwEnd - dwStart;
  1825.             TCHAR outstring[100];
  1826.                     wsprintf(outstring, TEXT("DUALDISPDEMO: Loop time: %dn"), timetaken);
  1827.                     TEXTOUT(outstring);
  1828.             ////////////////////////////////////////////////////////////////////////////////
  1829. #endif
  1830.         }
  1831.         else if (dwWaitObjRetVal == WAIT_OBJECT_0)
  1832.         {
  1833.             /* hEvent_StopDesktopTransfer event object signalled - therefore stop transfer */
  1834.             TEXTOUT(TEXT("DUALDISPDEMO: RotateToBuffer: Exiting desktop transfer.n"));
  1835.             return nDDRetVal;
  1836.         }
  1837.         else if (dwWaitObjRetVal == WAIT_FAILED)
  1838.         {
  1839.             assert(0);
  1840.             nDDRetVal |= DUALDISPERROR;
  1841.             return nDDRetVal;
  1842.         }
  1843.         else
  1844.         {
  1845.             assert(0);
  1846.             nDDRetVal |= DUALDISPERROR;
  1847.             return nDDRetVal;
  1848.         }
  1849.     }
  1850.     return nDDRetVal;
  1851. }
  1852. /* Restore optimization */
  1853. #ifdef OSV_PPC
  1854. #ifdef NDEBUG
  1855. #pragma optimize("", on)
  1856. #endif
  1857. #endif
  1858. /* Turn off optimization for 'Desktop to XScale copy routine' (PocketPC, release builds) to prevent underrun. */
  1859. #ifdef OSV_PPC
  1860. #ifdef NDEBUG
  1861. #pragma optimize("", off)
  1862. #endif
  1863. #endif
  1864. /***********************************************************************************
  1865.  Function Name      : RotateAndDoubleToBuffer
  1866.  Inputs             : pulSrcBuffer
  1867.                       ulDestWidth
  1868.                       ulDestHeight
  1869.                       destRotation
  1870.                       ulSrcWidth
  1871.                       ulSrcHeight
  1872.  Outputs            : DestBuffer
  1873.  Returns            : Error code
  1874.  Description        : Copy the source buffer to the destination buffer. Perform the
  1875.                       required rotation. Do pixel and line doubling.
  1876. ************************************************************************************/
  1877. LONG RotateAndDoubleToBuffer(USHORT* pulDestBuffer, USHORT* pulSrcBuffer,
  1878.                   ULONG ulDestWidth, ULONG ulDestHeight, ULONG ulRequiredRotation,
  1879.                   ULONG ulSrcWidth, ULONG ulSrcHeight, ULONG ulSrcStride)
  1880. {
  1881.     ULONG nDDRetVal = DUALDISPSUCCESS;
  1882.     DWORD dwDelayInMilliseconds = DESKTOPTOXSCALEDELAY;
  1883.     DWORD dwWaitObjRetVal = 0;
  1884.     LONG srcX, srcY, destY;
  1885.     LONG destX;
  1886.     BOOL bIsDirty = FALSE;
  1887.     /* ulStride indicates the physical dimensions of the surface - irrespective of the intended viewing angle.
  1888.     Note: a 'portrait' image is described by the driver as having ('height' > 'width') and a landscape image is
  1889.     described as having ('width' > 'height'). Thus the driver describes the 'logical view'. However, in order to
  1890.     copy from the frame buffer, the 'logical view' must be converted to the 'physical view'. */
  1891.     if (ulSrcStride != (ulSrcWidth * 2))
  1892.     {
  1893.         /* Swap width and height in order to obtain a physical description of the frame buffer. */
  1894.         ULONG ulTemp = ulSrcWidth;
  1895.         ulSrcWidth = ulSrcHeight;
  1896.         ulSrcHeight = ulTemp;
  1897.     }
  1898.     /* Verify frame buffer addresses */
  1899.     if ((pulDestBuffer == NULL) || (pulSrcBuffer == NULL))
  1900.     {
  1901.         TEXTOUT(TEXT("DUALDISPDEMO: RotateAndDoubleToBuffer: Error - frame buffer address invalid.n"));
  1902.         return DUALDISPERROR;
  1903.     }
  1904.     for(;;)
  1905.     {
  1906.         static ULONG nConsecutiveScreenUpdates = 0;
  1907.         dwWaitObjRetVal = WaitForSingleObject(hEvent_StopDesktopTransfer, dwDelayInMilliseconds);
  1908.         /* See if Marathon frame buffer has changed since it was last copied to the 
  1909.         XScale display surface. */
  1910.         DE_CheckForScreenUpdate(hdcMarathon, bIsDirty);
  1911.         /* Adjust the rate of screen update checks. NOTE: only use this function if GSB cannot 
  1912.         cope with bandwidth requirements of DesktopToXScaleTransfer. */
  1913.         // AdjustRefreshRate(bIsDirty, nConsecutiveScreenUpdates, dwDelayInMilliseconds);
  1914.         /* If bIsDirty is TRUE, then an attempt should be made to update the screen by 
  1915.         executing the 'if-else' statement below (which processes dwWaitObjRetVal). If 
  1916.         dwWaitObjRetVal does NOT equal WAIT_TIMEOUT, then the 'if-else' statement below 
  1917.         MUST be executed to catch WAIT_FAILED and WAIT_OBJECT_0. */
  1918.         if ((bIsDirty == FALSE) && (dwWaitObjRetVal == WAIT_TIMEOUT))
  1919.         {
  1920.             continue;
  1921.         }
  1922.         if (dwWaitObjRetVal == WAIT_TIMEOUT)
  1923.         {
  1924.             /* Copy one frame from desktop surface to XScale frame buffer. */
  1925. #if (CHECK_MEM_COPY_SPEED == 1)
  1926.             //////////////////////// Monitor copy loop speed //////////////////////////////
  1927.             DWORD dwStart = GetTickCount();
  1928.             ///////////////////////////////////////////////////////////////////////////////
  1929. #endif
  1930.             if (ulRequiredRotation == 0)
  1931.             {
  1932.                 assert(ulDestHeight == (2 * ulSrcHeight));
  1933.                 assert(ulDestWidth == (2 * ulSrcWidth));
  1934.                 USHORT* pSrcBuffer = pulSrcBuffer;
  1935.                 for (srcY = 0; srcY < (LONG) ulSrcHeight; srcY++)
  1936.                 {
  1937.                     destY = srcY * 2;
  1938.                     /* Copy a line from the source buffer. */
  1939.                     for (srcX = 0; srcX < (LONG) ulSrcWidth; srcX++)
  1940.                     {
  1941.                         usTempBuffer[srcX] = pSrcBuffer[srcX];
  1942.                     }
  1943.                     pSrcBuffer += ulSrcWidth;
  1944.                     for (srcX = 0; srcX < (LONG) ulSrcWidth; srcX++)
  1945.                     {
  1946.                         destX = srcX * 2;
  1947.                         /* Write the horizontal part of image */
  1948.                         pulDestBuffer[destY * ulDestWidth + destX]         = usTempBuffer[srcX];
  1949.                         pulDestBuffer[destY * ulDestWidth + destX + 1]     = usTempBuffer[srcX];
  1950.                         pulDestBuffer[(destY+1) * ulDestWidth + destX]     = usTempBuffer[srcX];
  1951.                         pulDestBuffer[(destY+1) * ulDestWidth + destX + 1] = usTempBuffer[srcX];
  1952.                     }
  1953.                 }
  1954.             }
  1955.             else if (ulRequiredRotation == 270)
  1956.             {
  1957.                 USHORT* pSrcBuffer = pulSrcBuffer;
  1958.                 /* Copy a frame from source buffer */
  1959.                 for (srcX = 0; srcX < (LONG) (ulSrcWidth * ulSrcHeight); srcX++)
  1960.                 {
  1961.                     usTempBuffer[srcX] = pSrcBuffer[srcX];
  1962.                 }
  1963.                           
  1964.                 srcX = 0;
  1965.                 for (destY = 0; destY < (LONG) ulDestHeight; destY+=2)
  1966.                 {
  1967.                     srcY = ulSrcHeight - 1;
  1968.                     
  1969.                     srcX = destY / 2;
  1970.                     
  1971.                     assert(((srcX < (LONG) ulSrcWidth) && (srcX >= 0)));
  1972.                     for (destX = 0 ; destX < (LONG) ulDestWidth; destX+=2)
  1973.                     {
  1974.                         assert(((srcY < (LONG) ulSrcHeight) && (srcY >= 0)));
  1975.                         // copy a source pixel to a destination pixel
  1976.                         pulDestBuffer[destY * ulDestWidth + destX]         = usTempBuffer[srcY * ulSrcWidth + srcX];
  1977.                         // pixel double: copy the same pixel to column 'destX - 1'
  1978.                         pulDestBuffer[destY * ulDestWidth + destX + 1]     = usTempBuffer[srcY * ulSrcWidth + srcX];
  1979.                         // line double: in the y direction
  1980.                         pulDestBuffer[(destY+1) * ulDestWidth + destX]     = usTempBuffer[srcY * ulSrcWidth + srcX];
  1981.                         // line and pixel double: copy the same pixel to column 'destx - 1'
  1982.                         pulDestBuffer[(destY+1) * ulDestWidth + destX + 1] = usTempBuffer[srcY * ulSrcWidth + srcX];
  1983.                         srcY--;
  1984.                     }
  1985.                 }
  1986.             }
  1987.             else if (ulRequiredRotation == 180)
  1988.             {
  1989.                 destY = ulDestHeight - 1;
  1990.                 assert(ulDestHeight == (2 * ulSrcHeight));
  1991.                 assert(ulDestWidth == (2 * ulSrcWidth));
  1992.                 USHORT* pSrcBuffer = pulSrcBuffer;
  1993.                 for (srcY = 0; srcY < (LONG) ulSrcHeight; srcY++)
  1994.                 {
  1995.                     destX = ulDestWidth - 1;
  1996.                     assert(destY > 0);
  1997.                     /* Copy a line from the source buffer. */
  1998.                     for (srcX = 0; srcX < (LONG) ulSrcWidth; srcX++)
  1999.                     {
  2000.                         usTempBuffer[srcX] = pSrcBuffer[srcX];
  2001.                     }
  2002.                     pSrcBuffer += ulSrcWidth;
  2003.                     for (srcX = 0; srcX < (LONG) ulSrcWidth; srcX++)
  2004.                     {
  2005.                         assert(destX > 0);
  2006.                         /* Write the horizontal part of image */
  2007.                         pulDestBuffer[destY * ulDestWidth + destX]         = usTempBuffer[srcX];
  2008.                         pulDestBuffer[destY * ulDestWidth + destX - 1]     = usTempBuffer[srcX];
  2009.                         pulDestBuffer[(destY-1) * ulDestWidth + destX]     = usTempBuffer[srcX];
  2010.                         pulDestBuffer[(destY-1) * ulDestWidth + destX - 1] = usTempBuffer[srcX];
  2011.                         destX -= 2;
  2012.                     }
  2013.                     destY -= 2;
  2014.                 }
  2015.             }
  2016.             else if (ulRequiredRotation == 90)  // no ... use the correction angle
  2017.             {
  2018.                 USHORT* pSrcBuffer = pulSrcBuffer;
  2019.                 /* Copy a frame from source buffer */
  2020.                 for (srcX = 0; srcX < (LONG) (ulSrcWidth * ulSrcHeight); srcX++)
  2021.                 {
  2022.                     usTempBuffer[srcX] = pSrcBuffer[srcX];
  2023.                 }
  2024.                           
  2025.                 srcX = ulSrcWidth - 1;
  2026.             
  2027.                 for (destY = 0; destY < (LONG) ulDestHeight; destY+=2)
  2028.                 {
  2029.                     for (destX = 0 ; destX < (LONG) ulDestWidth; destX+=2)
  2030.                     {
  2031.                         assert(srcX >= 0);
  2032.                         srcY = destX / 2;
  2033.                         assert(((srcY >= 0) && (srcY < (LONG) ulSrcHeight)));
  2034.                         // copy a source pixel to a destination pixel
  2035.                         pulDestBuffer[destY * ulDestWidth + destX]         = usTempBuffer[srcY * ulSrcWidth + srcX];
  2036.                         // pixel double: copy the same pixel to column 'destX - 1'
  2037.                         pulDestBuffer[destY * ulDestWidth + destX + 1]     = usTempBuffer[srcY * ulSrcWidth + srcX];
  2038.                         // line double: in the y direction
  2039.                         pulDestBuffer[(destY+1) * ulDestWidth + destX]     = usTempBuffer[srcY * ulSrcWidth + srcX];
  2040.                         // line and pixel double: copy the same pixel to column 'destx - 1'
  2041.                         pulDestBuffer[(destY+1) * ulDestWidth + destX + 1] = usTempBuffer[srcY * ulSrcWidth + srcX];
  2042.                     }
  2043.                     srcX--;
  2044.                 }
  2045.             }
  2046. #if (CHECK_MEM_COPY_SPEED == 1)
  2047.             ////////////////////////////////////////////////////////////////////////////////
  2048.             DWORD dwEnd = GetTickCount();
  2049.             DWORD timetaken = dwEnd - dwStart;
  2050.             TCHAR outstring[100];
  2051.                     wsprintf(outstring, TEXT("DUALDISPDEMO: Loop time: %dn"), timetaken);
  2052.                     TEXTOUT(outstring);
  2053.             ////////////////////////////////////////////////////////////////////////////////
  2054. #endif
  2055.         }
  2056.         else if (dwWaitObjRetVal == WAIT_OBJECT_0)
  2057.         {
  2058.             /* hEvent_StopDesktopTransfer event object signalled - therefore stop transfer */
  2059.             TEXTOUT(TEXT("DUALDISPDEMO: RotateAndDoubleToBuffer: Exiting desktop transfer.n"));
  2060.             return nDDRetVal;
  2061.         }
  2062.         else if (dwWaitObjRetVal == WAIT_FAILED)
  2063.         {
  2064.             assert(0);
  2065.             nDDRetVal |= DUALDISPERROR;
  2066.             return nDDRetVal;
  2067.         }
  2068.         else
  2069.         {
  2070.             assert(0);
  2071.             nDDRetVal |= DUALDISPERROR;
  2072.             return nDDRetVal;
  2073.         }
  2074.     }
  2075.     return nDDRetVal;
  2076. }
  2077. /* Restore optimization */
  2078. #ifdef OSV_PPC
  2079. #ifdef NDEBUG
  2080. #pragma optimize("", on)
  2081. #endif
  2082. #endif
  2083. /***********************************************************************************
  2084.  Function Name      : AdjustRefreshRate
  2085.  Inputs             : bIsDirty
  2086.  Inputs/Outputs     : nConsecutiveScreenUpdates
  2087.  Outputs              dwDelayInMilliseconds
  2088.  Returns            : Error code
  2089.  Description        : Monitors the frequency of updates to the XScale surface. Note: 
  2090.                       the XScale frame buffer is only updated when a change to the
  2091.                       Marathon surface is detected by DE_CheckForScreenUpdate. 
  2092.                       If it detects that the rate of screen updates is increasing,
  2093.                       AdjustRefreshRate reduces the rate of 'screen-update checks', 
  2094.                       thus limiting bandwidth consumption. As soon as a reduction in 
  2095.                       screen-updates is detected, the rate of 'screen-update checks' is 
  2096.                       restored to its default value, allowing the display to be more
  2097.                       responsive.
  2098.                       Note: The refresh rate is best controlled by the define 
  2099.                       DESKTOPTOXSCALEDELAY. AdjustRefreshRate is an experimental
  2100.                       function - and is not presently called in dualdispdemo.
  2101. ************************************************************************************/
  2102. void AdjustRefreshRate(BOOL bIsDirty, 
  2103.                        ULONG& nConsecutiveScreenUpdates, 
  2104.                        DWORD& dwDelayInMilliseconds)
  2105. {
  2106.     if (bIsDirty == FALSE)
  2107.     {
  2108.         /* Marathon frame buffer has not changed, therefore restore the rate of
  2109.         screen update checks to its default. */
  2110.         dwDelayInMilliseconds = DESKTOPTOXSCALEDELAY;
  2111.         nConsecutiveScreenUpdates = 0;
  2112.     }
  2113.     else
  2114.     {
  2115.         /* Marathon frame buffer has changed, therefore reduce the rate of screen
  2116.         update checks accordingly - in order to preserve GSB bandwidth. */
  2117.     
  2118.         switch (nConsecutiveScreenUpdates)
  2119.         {
  2120.         case 0:
  2121.         case 1:
  2122.         case 2:
  2123.             /* 0 to 2 consecutive screen updates: retain refresh rate. */
  2124.             dwDelayInMilliseconds = 250;
  2125.             TEXTOUT(TEXT("DUALDISPDEMO: UpdateXScaleFB: 250 millisecondsn"));
  2126.             break;
  2127.         
  2128.         case 3:
  2129.         case 4:
  2130.             /* 3 to 4 consecutive updates: reduce refresh rate. */
  2131.             dwDelayInMilliseconds = 500;
  2132.             TEXTOUT(TEXT("DUALDISPDEMO: UpdateXScaleFB: 500 millisecondsn"));
  2133.             break;
  2134.         default:
  2135.             /* 5 or more consecutive updates: further reduce refresh rate. */
  2136.             dwDelayInMilliseconds = 1000;
  2137.             TEXTOUT(TEXT("DUALDISPDEMO: UpdateXScaleFB: 1000 millisecondsn"));
  2138.             break;
  2139.         }
  2140.         nConsecutiveScreenUpdates++;
  2141.     }
  2142. }
  2143. /***********************************************************************************
  2144.  Function Name      : GetSecondarySurfaceInfo
  2145.  Inputs             : 
  2146.  Outputs            : s2700GSecondadrySurfInfo
  2147.  Returns            : 
  2148.  Description        : Get secondary surface information from Marathon. This will 
  2149.                       include the frame buffer address which can be written to
  2150.                       directly if desired.
  2151. ************************************************************************************/
  2152. LONG GetSecondarySurfaceInfo(DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo)
  2153. {
  2154.     ULONG nDDRetVal = DUALDISPSUCCESS;
  2155.     // Get secondary surface info
  2156.     nDDRetVal |= DE_GetMarathonSurfaceInfo(s2700GSecondadrySurfInfo, DCFG_SECONDARYSURFACE, hdcMarathon);
  2157.     /* s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress can now be used
  2158.     to access the secondary surface directly. */
  2159.     return nDDRetVal;
  2160. }
  2161. /***********************************************************************************
  2162.  Function Name      : WriteToSecSurfFrameBuffer
  2163.  Inputs             : s2700GSecondadrySurfInfo
  2164.  Outputs            : 
  2165.  Returns            : error code
  2166.  Description        : Writes directly to the secondary surface frame buffer
  2167. ************************************************************************************/
  2168. LONG WriteToSecSurfFrameBuffer(DISPCFG_GET_SURFACE_INFO& s2700GSecondadrySurfInfo)
  2169. {
  2170.     ULONG nDDRetVal = DUALDISPSUCCESS;
  2171.     USHORT nColour = 0xF0F0;
  2172.     ULONG nNumLines = 0;
  2173.     ULONG nWidth, nHeight;
  2174.     nWidth = s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulWidth;
  2175.     nHeight = s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulHeight;
  2176.     /* Write directly to the frame buffer */
  2177.     USHORT* fbuffer = (USHORT*) s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress;
  2178.     for (ULONG line = 0; line < nHeight; line++)
  2179.     {
  2180.         for (ULONG pixel = 0; pixel < nWidth; pixel++)
  2181.         {
  2182.              fbuffer[line * nWidth + pixel] = nColour;
  2183.         }
  2184.         if (nNumLines == 10)
  2185.         {
  2186.             nColour ^= 0xFFFF; // invert colour
  2187.             nNumLines = 0;
  2188.         }
  2189.         nNumLines++;
  2190.     }
  2191.     return nDDRetVal;
  2192. }
  2193. /***********************************************************************************
  2194.  Function Name      : WinMain
  2195.  Inputs             : hInstance
  2196.                       hPrevInstance
  2197.                       lpCmdLine
  2198.                       nCmdShow
  2199.  Outputs            : 
  2200.  Returns            : msg.wParam 
  2201.  Description        : WinMain processes command line options to determine the desired
  2202.                       Dual Display Mode. The specified mode is implemented
  2203.                       by one or more threads. After creating the threads, WinMain
  2204.                       creates a DialogBox (in the form of a single button). When 
  2205.                       the button is pressed, the threads are terminated, all open
  2206.                       handles are closed and the default mode of operation is 
  2207.                       restored; the application will now exit.                      
  2208. ************************************************************************************/
  2209. int WINAPI WinMain( HINSTANCE hInstance,
  2210. HINSTANCE hPrevInstance,
  2211. LPTSTR    lpCmdLine,
  2212. int       nCmdShow)
  2213. {
  2214.     LONG nDDRetVal = DUALDISPSUCCESS;
  2215.     SELECT_DUAL_DISP_CONFIG SelectDualDispConfig = eModeInvalid;
  2216.     char ArgBuffer[1024];
  2217.     char* argv[512];
  2218.     ULONG ulArgc;
  2219. #ifdef LOGGING_TO_FILE
  2220.     /* Open output stream for logfile */
  2221.     gpStream = _wfopen(TEXT("\hard disk\dualdisplog.txt"), TEXT("w"));
  2222.     if (gpStream == NULL)
  2223.     {
  2224.         nDDRetVal |= DUALDISPERROR;
  2225.         return nDDRetVal;
  2226.     }
  2227. #endif
  2228.     classRefreshDisplay.Init(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
  2229.     /* Initialize contents of sDisplayConfig and sMarathonSurfaceInfo to zero. */
  2230.     memset((void*) &sDisplayConfig, 0, sizeof(DISPCFG_DISPLAY_SYSTEM));
  2231.     memset((void*) &sDesktopSurfaceInfo, 0, sizeof(DISPCFG_GET_SURFACE_INFO));
  2232.     memset((void*) &s2700GSecondadrySurfInfo, 0, sizeof(DISPCFG_GET_SURFACE_INFO));
  2233.     GetCommandLineArgs(lpCmdLine, ulArgc, argv, ArgBuffer);
  2234.     /* Get the required dual display configuration. */
  2235.     nDDRetVal |= ProcessOptions(ulArgc, argv, SelectDualDispConfig);
  2236.     if ((nDDRetVal != DUALDISPSUCCESS) || (SelectDualDispConfig == eModeInvalid))
  2237.     {
  2238.         TEXTOUT(TEXT("DUALDISPDEMO: Error occured processing command linen"));
  2239.         /* An invalid mode has been requested - display command line options. */
  2240.         MessageBox(NULL, 
  2241.                    TEXT("Command line options: --default | --mirror | --mirrorcompatible | --gdi | --framebuffer | --extdesktop | --intsecsurf | --extsecsurf | --video | --test | --quicktest"), 
  2242.                    TEXT("Dual Display"), MB_OK);
  2243.         return nDDRetVal;
  2244.     }
  2245.     /* Get driver HDCs */
  2246.     nDDRetVal |= DualDisplaySetup(sDesktopSurfaceInfo);
  2247.     if (nDDRetVal != DUALDISPSUCCESS)
  2248.     {
  2249.         TEXTOUT(TEXT("DUALDISPDEMO: WinMain: DualDispSetup failed.n"));
  2250.         return nDDRetVal;
  2251.     }
  2252. classRefreshDisplay.SetSize(sDesktopSurfaceInfo.sPhysSurfaceInfo.ulWidth,
  2253. sDesktopSurfaceInfo.sPhysSurfaceInfo.ulHeight);
  2254.     /* Configure a Dual Display mode */
  2255.     switch (SelectDualDispConfig)
  2256.     {
  2257.     case eDefaultDisplay:
  2258.         /* Set default display mode and exit. */
  2259.         RestoreDefaultDisplayMode();
  2260.         return nDDRetVal;
  2261.     case eMirrorModeIncompatible:
  2262.         /* Display desktop on both internal and external screens. External display
  2263.         will be accelerated by marathon. Internal display will be copied from Marathon
  2264.         surface to XScale surface. */
  2265.         TEXTOUT(TEXT("DUALDISPDEMO: WinMain: Mirror Mode Selected.n"));
  2266.         nDDRetVal |= Config_MirrorModeIncompatible(sDisplayConfig, sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  2267.         break;
  2268.     case eVideoMode:
  2269.         /* Display the desktop on both internal and external screens. The external screen should
  2270.         display the desktop in landscape mode - even if the desktop surface has been rendered in
  2271.         portrait mode. This allows video to be played on the external screen in landscape mode. */
  2272.         nDDRetVal |= Config_VideoMode(sDisplayConfig, sDesktopSurfaceInfo, sXScaleSurfaceInfo, hdcXScale);
  2273.         break;
  2274.     case eMirrorModeCompatible:
  2275.         /* Display desktop on (compatible) internal and external screens by configuring the LCD SWITCH
  2276.         to mirror PDP to both panels. */
  2277.         TEXTOUT(TEXT("DUALDISPDEMO: WinMain: Mirror Mode (for compatible panels) Selected.n"));
  2278.         nDDRetVal |= Config_MirrorModeCompatible(sDisplayConfig);
  2279.         break;
  2280.     case eCustomGDIApplication:
  2281.         
  2282.         /* Display desktop on internal screen. Display a custom GDI application on the 
  2283.         external screen. */
  2284.         TEXTOUT(TEXT("DUALDISPDEMO: WinMain: Custom GDI Mode Selected"));
  2285.         nDDRetVal |= Config_CustomGDIApplication(sDisplayConfig, sDesktopSurfaceInfo, 
  2286.                                              s2700GSecondadrySurfInfo, sXScaleSurfaceInfo, hdcXScale);
  2287.         break;
  2288.     case eCustomFBApplication:
  2289.         
  2290.         /* Display Desktop on internal screen. Also perform a direct write to secondary 
  2291.         surface frame buffer displayed on external screen.*/
  2292.         nDDRetVal |= Config_CustomFBApplication(sDisplayConfig, sDesktopSurfaceInfo, 
  2293.                                              s2700GSecondadrySurfInfo, sXScaleSurfaceInfo, hdcXScale);
  2294.         break;
  2295.     case eInternalDispOnlySecSurf:
  2296.         /* Display random GDI rectangles for 20 seconds. Then write directly to secondary
  2297.         surface frame buffer before exiting - using internal screen. Finally, return from
  2298.         WinMain, because further user-interaction is not required. */
  2299.         nDDRetVal |= Config_InternalDispOnlySecSurf(sDisplayConfig, s2700GSecondadrySurfInfo);
  2300.         RestoreDefaultDisplayMode();
  2301.         return nDDRetVal;
  2302.     case eExternalDispOnlySecSurf:
  2303.         /* Display random GDI rectangles for 20 seconds. Then write directly to secondary
  2304.         surface frame buffer before exiting - using external screen. Finally, return from
  2305.         WinMain, because further user-interaction is not required. */
  2306.         nDDRetVal |= Config_ExternalDispOnlySecSurf(sDisplayConfig, s2700GSecondadrySurfInfo);
  2307.         RestoreDefaultDisplayMode();
  2308.         return nDDRetVal;
  2309.     case eExternalDispOnlyDesktop:
  2310.         /* Display desktop on the external screen only. */
  2311.         nDDRetVal |= Config_ExternalDispOnlyDesktop(sDisplayConfig);
  2312.         break;
  2313.     case eSlowTestMode:
  2314.         {
  2315.             /* Test all dual display configurations - allow time for each display to be
  2316.             visually inspected. */
  2317.             BOOL bQuickTest = FALSE;
  2318.             nDDRetVal |= Config_TestDualDisplay(sDisplayConfig, 
  2319.                                                 sDesktopSurfaceInfo,
  2320.                                                 sXScaleSurfaceInfo,
  2321.                                                 hdcXScale,
  2322.                                                 bQuickTest);
  2323.             return nDDRetVal;
  2324.         }
  2325.     case eQuickTestMode:
  2326.         {
  2327.             /* Test all dual display configurations - do not allow time for visual inspection. */
  2328.             BOOL bQuickTest = TRUE;
  2329.             nDDRetVal |= Config_TestDualDisplay(sDisplayConfig, 
  2330.                                                 sDesktopSurfaceInfo,
  2331.                                                 sXScaleSurfaceInfo,
  2332.                                                 hdcXScale,
  2333.                                                 bQuickTest);
  2334.             return nDDRetVal;
  2335.         }
  2336.     default:
  2337.         /* An invalid mode has been requested - display command line options. */
  2338.         MessageBox(NULL, 
  2339.                    TEXT("Command line options: --default | --mirror | --mirrorcompatible | --gdi | --framebuffer | --extdesktop | --intsecsurf | --extsecsurf | --video | --test | --quicktest"), 
  2340.                    TEXT("Dual Display"), MB_OK);
  2341.         return nDDRetVal;
  2342.     }
  2343.     if (nDDRetVal != DUALDISPSUCCESS)
  2344.     {
  2345.         /* Dual display failure - restore the default settings */
  2346.         TEXTOUT(TEXT("DUALDISPDEMO: WinMain: dual display error. Attempting to restore default configuration.n"));
  2347.         nDDRetVal = DUALDISPSUCCESS;
  2348.         RestoreDefaultDisplayMode();
  2349.         if (nDDRetVal != DUALDISPSUCCESS)
  2350.         {
  2351.             /* Failed to restore default settings */
  2352.             TEXTOUT(TEXT("DUALDISPDEMO: WinMain: dual display error: Attempt to restore default configuration has failed.n"));
  2353.         }
  2354.         return 0;
  2355.     }
  2356.     /* Create a dialog box. It will consist of just one button, which is used
  2357.     to close down the application. The default display mode will be restored before
  2358.     the application exits. */
  2359.     static TCHAR szAppName[] = TEXT ("DualDisp") ;
  2360.     HWND         hwnd ;
  2361.     WNDCLASS     wndclass ;
  2362. MSG msg;
  2363.     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  2364.     wndclass.lpfnWndProc   = (WNDPROC) WndProc ;
  2365.     wndclass.cbClsExtra    = 0 ;
  2366.     wndclass.cbWndExtra    = DLGWINDOWEXTRA ;
  2367.     wndclass.hInstance     = hInstance ;
  2368.     wndclass.hIcon         = NULL;
  2369.     wndclass.hCursor       = 0 ;
  2370.     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
  2371.     wndclass.lpszMenuName  = 0 ;
  2372.     wndclass.lpszClassName = szAppName ;
  2373.     RegisterClass(&wndclass);
  2374.     hwnd = CreateDialog (hInstance, szAppName, 0, NULL) ;
  2375.     ShowWindow (hwnd, nCmdShow) ;
  2376.     while (GetMessage (&msg, NULL, 0, 0))
  2377.     {
  2378.       TranslateMessage (&msg) ;
  2379.       DispatchMessage (&msg) ;
  2380.     }
  2381.     MessageBox(NULL, TEXT("Exiting dual display mode"), TEXT("Dual Display"), MB_OK);
  2382.     TEXTOUT(TEXT("DUALDISPDEMO: Exiting WinMainn"));
  2383.     if (gpStream)
  2384.     {
  2385.         fclose(gpStream);
  2386.     }
  2387.     return msg.wParam ;
  2388. }
  2389. /***********************************************************************************
  2390.  Function Name      : WndProc
  2391.  Inputs             : hwnd
  2392.                       message
  2393.                       wParam
  2394.                       lParam
  2395.  Outputs            : 
  2396.  Returns            :  
  2397.  Description        : Main window procedure - for a Dialog. Note: a Dialog has
  2398.                       been registered as a WNDCLASS.
  2399. ************************************************************************************/
  2400. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2401. {
  2402.     switch(message)
  2403.     {
  2404.     case WM_COMMAND:
  2405. {
  2406. switch (LOWORD(wParam))
  2407. {
  2408. case IDC_EXITMODE:
  2409. {
  2410.                     RestoreDefaultDisplayMode();
  2411.                     DestroyWindow(hwnd);
  2412.                     return 0;
  2413. }
  2414.             }
  2415.         }
  2416.         return 0;
  2417.         case WM_CLOSE:
  2418.             RestoreDefaultDisplayMode();
  2419.             DestroyWindow(hwnd);
  2420.             return 0;
  2421.      case WM_DESTROY:
  2422.             PostQuitMessage (0) ;
  2423.             return 0 ;
  2424.     }
  2425.     return DefWindowProc (hwnd, message, wParam, lParam);
  2426. }
  2427. /***********************************************************************************
  2428.  Function Name      : CloseAllThreads
  2429.  Inputs             : 
  2430.  Outputs            : 
  2431.  Returns            :  
  2432.  Description        : Shuts down the application's threads.
  2433. ************************************************************************************/
  2434. void CloseAllThreads()
  2435. {
  2436.     if (hThread_DesktopTransfer)
  2437.     {
  2438.         /* Shut down 'Desktop to XScale Transfer' thread */
  2439.         StopDesktopToXScaleTransfer();
  2440.         hThread_DesktopTransfer = NULL;
  2441.     }
  2442.     if (hThread_GDIRectangles)
  2443.     {
  2444.         /* Shut down GDIRectangles thread */
  2445.         StopGDIRectangles();
  2446.         hThread_GDIRectangles = NULL;
  2447.     }
  2448. }
  2449. /***********************************************************************************
  2450.  Function Name      : CloseAllHDCs
  2451.  Inputs             : 
  2452.  Outputs            : 
  2453.  Returns            : 
  2454.  Description        : Close any open HDCs.
  2455. ************************************************************************************/
  2456. void CloseAllHDCs()
  2457. {
  2458.     if (hdcMarathon)
  2459.     {
  2460.         ReleaseDC(NULL, hdcMarathon);
  2461.         hdcMarathon = NULL;
  2462.     }
  2463.     if (hdcXScale)
  2464.     {
  2465.         DeleteDC(hdcXScale);
  2466.         hdcXScale = NULL;
  2467.     }
  2468.     if (hdcMem)
  2469.     {
  2470.         DeleteDC(hdcMem);
  2471.         hdcMem = NULL;
  2472.     }
  2473. }
  2474. /***********************************************************************************
  2475.  Function Name      : RestoreDefaultDisplayMode
  2476.  Inputs             : 
  2477.  Outputs            : 
  2478.  Returns            : 
  2479.  Description        : Shuts down any the application's threads and closes HDCs.
  2480. ************************************************************************************/
  2481. LONG RestoreDefaultDisplayMode()
  2482. {
  2483.     BOOL bRetVal;
  2484.     LONG nDDRetVal = DUALDISPSUCCESS;
  2485.     TEXTOUT(TEXT("DUALDISPDEMO: RestoreDefaultDisplayMode: Restoring dual display default configuration.n"));
  2486.     /* Close down GDIRectangles and DesktopTransfer threads. */
  2487.     CloseAllThreads();
  2488.     /* Blank the desktop surface forcing it to be refreshed. */
  2489.     classRefreshDisplay.MaskDesktop();
  2490.     nDDRetVal |= Config_DefaultDisplay(sDisplayConfig);
  2491.     /* Free virtual memory to which desktop surface has been mapped. */
  2492.     if (sDesktopSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress)
  2493.     {
  2494.         TEXTOUT(TEXT("DUALDISPDEMO: RestoreDefaultDisplayMode: Deallocating virtual memory for Desktop surface.n"));
  2495.         bRetVal = VirtualFree((LPVOID) sDesktopSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress, 0, MEM_RELEASE);
  2496.         assert(bRetVal != 0);
  2497.         sDesktopSurfaceInfo.sPhysSurfaceInfo.ulPhysAddress = 0;
  2498.     }
  2499.     /* Free virtual memory to which secondary surface has been mapped */
  2500.     if (s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress)
  2501.     {
  2502.         TEXTOUT(TEXT("DUALDISPDEMO: RestoreDefaultDisplayMode: Deallocating virtual memory for Secondary surface.n"));
  2503.         bRetVal = VirtualFree((LPVOID) s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress, 0, MEM_RELEASE);
  2504.         assert(bRetVal != 0);
  2505.         s2700GSecondadrySurfInfo.sPhysSurfaceInfo.ulPhysAddress = 0;
  2506.     }
  2507.     /* Free virtual memory to which XScale Frame Buffer has been mapped. */
  2508.     if (sXScaleSurfaceInfo.ulPhysAddress)
  2509.     {
  2510.         TEXTOUT(TEXT("DUALDISPDEMO: RestoreDefaultDisplayMode: Deallocating virtual memory for XScale Frame Buffer.n"));
  2511.         bRetVal = VirtualFree((LPVOID) sXScaleSurfaceInfo.ulPageAddress, 0, MEM_RELEASE);
  2512.         assert(bRetVal != 0);
  2513.         sXScaleSurfaceInfo.ulPageAddress = 0;
  2514.         sXScaleSurfaceInfo.ulPhysAddress = 0;
  2515.     }
  2516.     /* Display the desktop */
  2517.     classRefreshDisplay.Close();
  2518.     /* If the secondary surface still exists (e.g. in case Config_FBApplication), then
  2519.     delete it. Should be called before CloseAllHDCs. */
  2520.     DestroySecondarySurface();
  2521. /* Free the dual display interface Should be called before CloseAllHDCs. */
  2522. DE_ReleaseDualDisplay(hdcMarathon);
  2523.     
  2524. /* Delete any remaining HDCs */
  2525.     CloseAllHDCs();
  2526.     if (nDDRetVal != DUALDISPSUCCESS)
  2527.     {
  2528.         TEXTOUT(TEXT("DUALDISPDEMO: RestoreDefaultDisplayMode: Error.n"));
  2529.     }
  2530.     return nDDRetVal;
  2531. }
  2532. /***********************************************************************************
  2533.  Function Name      : RefreshDisplay::Init
  2534.  Inputs             : hInstance
  2535.                       hPrevInstance
  2536.                       szCmdLine
  2537.                       iCmdShow
  2538.  Outputs            : 
  2539.  Returns            : void
  2540.  Description        : Initializes the class variables to the WinMain parameters.
  2541.                       This function should only be called by WinMain.
  2542. ************************************************************************************/
  2543. void RefreshDisplay::Init(HINSTANCE hInstance,
  2544.            HINSTANCE hPrevInstance,
  2545.            LPTSTR    szCmdLine,
  2546.            int       iCmdShow)
  2547. {
  2548.     /* Get a copy of WinMain parameters */
  2549.     m_hInstance = hInstance;
  2550. m_hPrevInstance = hPrevInstance;
  2551. m_szCmdLine = szCmdLine;
  2552. m_iCmdShow = iCmdShow;
  2553. m_hwnd = NULL;
  2554. }
  2555. /***********************************************************************************
  2556.  Function Name      : RefreshDisplay::Refresh
  2557.  Inputs             : 
  2558.  Outputs            : 
  2559.  Returns            :  
  2560.  Description        : Hides the desktop by displaying a blank window. This allows a 
  2561.                       smooth transition to mirror mode.
  2562. ************************************************************************************/
  2563. void RefreshDisplay::MaskDesktop()
  2564. {
  2565.      static TCHAR szAppName[] = TEXT ("RedrawDesktop") ;
  2566.  RECT rclRect;
  2567.  if (m_hwnd == NULL)
  2568.  {
  2569.  WNDCLASS     wndclass ;
  2570.  wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  2571.  wndclass.lpfnWndProc   = WndProcRefreshDisplay ;
  2572.  wndclass.cbClsExtra    = 0 ;
  2573.  wndclass.cbWndExtra    = 0 ;
  2574.  wndclass.hInstance     = m_hInstance ;
  2575.  wndclass.hIcon         = NULL;
  2576.  wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  2577.  wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;
  2578.  wndclass.lpszMenuName  = NULL ;
  2579.  wndclass.lpszClassName = szAppName ;
  2580.  RegisterClass (&wndclass);
  2581.  m_hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_NOANIMATION,
  2582.    szAppName,                 // window class name
  2583.   NULL,                       // window caption
  2584.   WS_VISIBLE,                       // window style
  2585.   0,              // initial x position
  2586.   0,              // initial y position
  2587.   m_nScreenWidth,              // initial x size
  2588.   m_nScreenHeight,              // initial y size
  2589.   NULL,                       // parent window handle
  2590.   NULL,                       // window menu handle
  2591.   m_hInstance,                  // program instance handle
  2592.   NULL) ;                     // creation parameters
  2593.  }
  2594. if (m_hwnd)
  2595. {
  2596. rclRect.left = 0;
  2597. rclRect.top = 0;
  2598. rclRect.right = m_nScreenWidth;
  2599. rclRect.bottom = m_nScreenHeight;
  2600. InvalidateRect(m_hwnd, &rclRect, TRUE);
  2601. #ifdef OSV_PPC
  2602.         /* This is a fix for 'Upper Taskbar' corruption bug on PocketPC */
  2603.         SetForegroundWindow(m_hwnd);
  2604.         SHFullScreen(m_hwnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON |  SHFS_HIDESTARTICON);
  2605.         MoveWindow(m_hwnd, 
  2606.                    rclRect.left, 
  2607.                    rclRect.top, 
  2608.                    rclRect.right, 
  2609.                    rclRect.bottom, 
  2610.                    TRUE);
  2611. #endif
  2612. ShowWindow(m_hwnd, m_iCmdShow); 
  2613. UpdateWindow (m_hwnd);
  2614. }
  2615. }
  2616. /***********************************************************************************
  2617.  Function Name      : RefreshDisplay::RevealDesktop
  2618.  Inputs             : 
  2619.  Outputs            : 
  2620.  Returns            :  
  2621.  Description        : Displays the desktop by hiding the 'MaskDesktop' window. This
  2622.                       causes the desktop to be refreshed.
  2623. ************************************************************************************/
  2624. void RefreshDisplay::RevealDesktop()
  2625. {
  2626. if (m_hwnd)
  2627. {
  2628. ShowWindow (m_hwnd, SW_HIDE);
  2629. UpdateWindow (m_hwnd);
  2630. }
  2631. }
  2632. /***********************************************************************************
  2633.  Function Name      : RefreshDisplay::Close
  2634.  Inputs             : 
  2635.  Outputs            : 
  2636.  Returns            :  
  2637.  Description        : Destroys the 'MaskDesktop' window.
  2638. ************************************************************************************/
  2639. void RefreshDisplay::Close()
  2640. {
  2641. if (m_hwnd)
  2642. {
  2643. DestroyWindow (m_hwnd);
  2644. m_hwnd = NULL;
  2645. }
  2646. }
  2647. /***********************************************************************************
  2648.  Function Name      : WndProcRefreshDisplay
  2649.  Inputs             : 
  2650.  Outputs            : 
  2651.  Returns            :  
  2652.  Description        : Window Procedure for window created by 
  2653.                       RefreshDisplay::MaskDesktop.
  2654. ************************************************************************************/
  2655. LRESULT CALLBACK WndProcRefreshDisplay (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2656. {
  2657.      HDC         hdc ;
  2658.      PAINTSTRUCT ps ;
  2659.      
  2660.      switch (message)
  2661.      {
  2662.      case WM_PAINT:
  2663.           hdc = BeginPaint (hwnd, &ps) ;
  2664.           EndPaint (hwnd, &ps) ;
  2665.           return 0 ;
  2666.           
  2667.      case WM_DESTROY:
  2668.           PostQuitMessage (0) ;
  2669.           return 0 ;
  2670.      }
  2671.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  2672. }
  2673. /***********************************************************************************
  2674.  Function Name      : DualDisplaySetup
  2675.  Inputs             : 
  2676.  Input/Output       : sDesktopSurfaceInfo
  2677.  Returns            :  
  2678.  Description        : Dual display initialization.
  2679. ************************************************************************************/
  2680. LONG DualDisplaySetup(DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo)
  2681. {
  2682.     LONG nDDRetVal = DUALDISPSUCCESS;
  2683.     hdcMarathon = GetDC(NULL);
  2684.     /* Load XScale as a secondary display driver */
  2685.     hdcXScale = CreateDC(TEXT("ddi.dll"), NULL, NULL, NULL);
  2686.     /* get default display settings */
  2687.     nDDRetVal = DE_GetMarathonSurfaceInfo(sDesktopSurfaceInfo, DCFG_DESKTOP, hdcMarathon);
  2688.     if (nDDRetVal != DUALDISPSUCCESS)
  2689.     {
  2690.         TEXTOUT(TEXT("DUALDISPDEMO: DualDisplaySetup: Error could not get default settingsn"));
  2691.         return nDDRetVal;
  2692.     }
  2693.     /* Preserve a copy of the initial desktop rotation angle */
  2694.     lInitialDesktopRotation = sDesktopSurfaceInfo.sPhysSurfaceInfo.lPhysicalRotation;
  2695.     if(!DE_AcquireDualDisplay(hdcMarathon))
  2696.     {
  2697.         nDDRetVal |= DUALDISPERROR;
  2698.         TEXTOUT(TEXT("DUALDISPDEMO: DualDisplaySetup: Failed to Acquire the DualDisplayInterfacen"));
  2699.         classRefreshDisplay.Close();
  2700.         /* Delete any remaining HDCs */
  2701.         CloseAllHDCs();
  2702.         return nDDRetVal;
  2703.     }
  2704.     return nDDRetVal;
  2705. }
  2706. /***********************************************************************************
  2707.  Function Name      : DualDisplayTestSetup
  2708.  Input/Output     : sDesktopSurfaceInfo
  2709.  Outputs            : bTestSetupSuccess
  2710.  Returns            :  
  2711.  Description        : Dual display test initialization.
  2712. ************************************************************************************/
  2713. void DualDisplayTestSetup(DISPCFG_GET_SURFACE_INFO& sDesktopSurfaceInfo, BOOL& bTestSetupSuccess)
  2714. {
  2715.     /* Restore the default display mode */
  2716.     RestoreDefaultDisplayMode();
  2717.     LONG nRetVal = DualDisplaySetup(sDesktopSurfaceInfo);
  2718.     if (nRetVal != DUALDISPSUCCESS)
  2719.     {
  2720.         bTestSetupSuccess = FALSE;
  2721.     }
  2722.     /* If (nRetVal == DUALDISPSUCCESS) no action is required. bTestSetupSuccess should NOT
  2723.     be overwritten with TRUE.*/
  2724. }