655 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
 | |
|  *
 | |
|  *Permission is hereby granted, free of charge, to any person obtaining
 | |
|  * a copy of this software and associated documentation files (the
 | |
|  *"Software"), to deal in the Software without restriction, including
 | |
|  *without limitation the rights to use, copy, modify, merge, publish,
 | |
|  *distribute, sublicense, and/or sell copies of the Software, and to
 | |
|  *permit persons to whom the Software is furnished to do so, subject to
 | |
|  *the following conditions:
 | |
|  *
 | |
|  *The above copyright notice and this permission notice shall be
 | |
|  *included in all copies or substantial portions of the Software.
 | |
|  *
 | |
|  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | |
|  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | |
|  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | |
|  *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
 | |
|  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 | |
|  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | |
|  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
|  *
 | |
|  *Except as contained in this notice, the name of the XFree86 Project
 | |
|  *shall not be used in advertising or otherwise to promote the sale, use
 | |
|  *or other dealings in this Software without prior written authorization
 | |
|  *from the XFree86 Project.
 | |
|  *
 | |
|  * Authors:	Dakshinamurthy Karra
 | |
|  *		Suhaib M Siddiqi
 | |
|  *		Peter Busch
 | |
|  *		Harold L Hunt II
 | |
|  */
 | |
| /* $XFree86: xc/programs/Xserver/hw/xwin/winpfbdd.c,v 1.18 2003/07/29 21:25:18 dawes Exp $ */
 | |
| 
 | |
| #include "win.h"
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * External global variables
 | |
|  */
 | |
| 
 | |
| extern const GUID _IID_IDirectDraw2;
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Create a DirectDraw primary surface 
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| winAllocateFBPrimaryDD (ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;  
 | |
|   HRESULT		ddrval = DD_OK;
 | |
|   DDSURFACEDESC		ddsd;
 | |
|   DDSURFACEDESC		*pddsdPrimary = NULL;
 | |
|   DDSURFACEDESC		*pddsdOffscreen = NULL;
 | |
|   RECT			rcClient;
 | |
| 
 | |
|   ErrorF ("winAllocateFBPrimaryDD\n");
 | |
| 
 | |
|   /* Get client area location in screen coords */
 | |
|   GetClientRect (pScreenPriv->hwndScreen, &rcClient);
 | |
|   MapWindowPoints (pScreenPriv->hwndScreen,
 | |
| 		   HWND_DESKTOP,
 | |
| 		   (LPPOINT)&rcClient, 2);
 | |
| 
 | |
|   /* Create a DirectDraw object, store the address at lpdd */
 | |
|   ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
 | |
|   if (ddrval != DD_OK)
 | |
|     FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n");
 | |
|   
 | |
|   /* Get a DirectDraw2 interface pointer */
 | |
|   ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
 | |
| 				       &IID_IDirectDraw2,
 | |
| 				       (LPVOID*) &pScreenPriv->pdd2);
 | |
|   if (FAILED (ddrval))
 | |
|     {
 | |
|       ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
 | |
| 	      ddrval);
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
| 
 | |
|   ErrorF ("winAllocateFBPrimaryDD - Created and initialized DD\n");
 | |
| 
 | |
|   /* Are we windowed or fullscreen? */
 | |
|   if (pScreenInfo->fFullScreen)
 | |
|     {
 | |
|       /* Full screen mode */
 | |
|       ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
 | |
| 						 pScreenPriv->hwndScreen,
 | |
| 						 DDSCL_FULLSCREEN
 | |
| 						 | DDSCL_EXCLUSIVE);
 | |
|       if (FAILED (ddrval))
 | |
| 	FatalError ("winAllocateFBPrimaryDD - Could not set "
 | |
| 		    "cooperative level\n");
 | |
| 
 | |
|       /* Change the video mode to the mode requested */
 | |
|       ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
 | |
| 					    pScreenInfo->dwWidth,
 | |
| 					    pScreenInfo->dwHeight,
 | |
| 					    pScreenInfo->dwBPP,
 | |
| 					    pScreenInfo->dwRefreshRate,
 | |
| 					    0);
 | |
|        if (FAILED (ddrval))
 | |
| 	FatalError ("winAllocateFBPrimaryDD - Could not set "
 | |
| 		    "full screen display mode\n");
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       /* Windowed mode */
 | |
|       ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
 | |
| 						 pScreenPriv->hwndScreen,
 | |
| 						 DDSCL_NORMAL);
 | |
|       if (FAILED (ddrval))
 | |
| 	FatalError ("winAllocateFBPrimaryDD - Could not set "
 | |
| 		    "cooperative level\n");
 | |
|     }
 | |
| 
 | |
|   /* Describe the primary surface */
 | |
|   ZeroMemory (&ddsd, sizeof (ddsd));
 | |
|   ddsd.dwSize = sizeof (ddsd);
 | |
|   ddsd.dwFlags = DDSD_CAPS;
 | |
|   ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
 | |
|   
 | |
|   /* Create the primary surface */
 | |
|   ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
 | |
| 				       &ddsd,
 | |
| 				       &pScreenPriv->pddsPrimary,
 | |
| 				       NULL);
 | |
|   if (FAILED (ddrval))
 | |
|        FatalError ("winAllocateFBPrimaryDD - Could not create primary "
 | |
| 		  "surface %08x\n", ddrval);
 | |
| 
 | |
|   ErrorF ("winAllocateFBPrimaryDD - Created primary\n");
 | |
| 
 | |
|   /* Allocate a DD surface description for our screen privates */
 | |
|   pddsdPrimary = pScreenPriv->pddsdPrimary
 | |
|     = malloc (sizeof (DDSURFACEDESC));
 | |
|   if (pddsdPrimary == NULL)
 | |
|     FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
 | |
| 		"description memory\n");
 | |
|   ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary));
 | |
|   pddsdPrimary->dwSize = sizeof (*pddsdPrimary);
 | |
| 
 | |
|   /* Describe the offscreen surface to be created */
 | |
|   /*
 | |
|    * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
 | |
|    * as drawing, locking, and unlocking take forever
 | |
|    * with video memory surfaces.  In addition,
 | |
|    * video memory is a somewhat scarce resource,
 | |
|    * so you shouldn't be allocating video memory when
 | |
|    * you have the option of using system memory instead.
 | |
|    */
 | |
|   ZeroMemory (&ddsd, sizeof (ddsd));
 | |
|   ddsd.dwSize = sizeof (ddsd);
 | |
|   ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
 | |
|   ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
 | |
|   ddsd.dwHeight = pScreenInfo->dwHeight;
 | |
|   ddsd.dwWidth = pScreenInfo->dwWidth;
 | |
| 
 | |
|   /* Create the shadow surface */
 | |
|   ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
 | |
| 				       &ddsd,
 | |
| 				       &pScreenPriv->pddsOffscreen,
 | |
| 				       NULL);
 | |
|   if (ddrval != DD_OK)
 | |
|     FatalError ("winAllocateFBPrimaryDD - Could not create shadow "
 | |
| 		"surface\n");
 | |
|   
 | |
|   ErrorF ("winAllocateFBPrimaryDD - Created offscreen\n");
 | |
| 
 | |
|   /* Allocate a DD surface description for our screen privates */
 | |
|   pddsdOffscreen = pScreenPriv->pddsdOffscreen
 | |
|     = malloc (sizeof (DDSURFACEDESC));
 | |
|   if (pddsdOffscreen == NULL)
 | |
|     FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
 | |
| 		"description memory\n");
 | |
|   ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen));
 | |
|   pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen);
 | |
| 
 | |
|   ErrorF ("winAllocateFBPrimaryDD - Locking primary\n");
 | |
| 
 | |
|   /* Lock the primary surface */
 | |
|   ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
 | |
| 				    pScreenInfo->fFullScreen ? NULL:&rcClient,
 | |
| 				    pddsdPrimary,
 | |
| 				    DDLOCK_WAIT,
 | |
| 				    NULL);
 | |
|   if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL)
 | |
|     FatalError ("winAllocateFBPrimaryDD - Could not lock "
 | |
| 		"primary surface\n");
 | |
| 
 | |
|   ErrorF ("winAllocateFBPrimaryDD - Locked primary\n");
 | |
| 
 | |
|   /* We don't know how to deal with anything other than RGB */
 | |
|   if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB))
 | |
|     FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n");
 | |
| 
 | |
|   /* Grab the pitch from the surface desc */
 | |
|   pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8)
 | |
|     / pScreenInfo->dwBPP;
 | |
| 
 | |
|   /* Save the pointer to our surface memory */
 | |
|   pScreenInfo->pfb = pddsdPrimary->lpSurface;
 | |
|   
 | |
|   /* Grab the color depth and masks from the surface description */
 | |
|   pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask;
 | |
|   pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask;
 | |
|   pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask;
 | |
| 
 | |
|   ErrorF ("winAllocateFBPrimaryDD - Returning\n");
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Call the wrapped CloseScreen function.
 | |
|  * 
 | |
|  * Free our resources and private structures.
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
 | |
|   Bool			fReturn;
 | |
|   
 | |
|   ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n");
 | |
| 
 | |
|   /* Flag that the screen is closed */
 | |
|   pScreenPriv->fClosed = TRUE;
 | |
|   pScreenPriv->fActive = FALSE;
 | |
| 
 | |
|   /* Call the wrapped CloseScreen procedure */
 | |
|   pScreen->CloseScreen = pScreenPriv->CloseScreen;
 | |
|   fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
 | |
| 
 | |
|   /* Delete the window property */
 | |
|   RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
 | |
| 
 | |
|   /* Free the offscreen surface, if there is one */
 | |
|   if (pScreenPriv->pddsOffscreen)
 | |
|     {
 | |
|       IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL);
 | |
|       IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen);
 | |
|       pScreenPriv->pddsOffscreen = NULL;
 | |
|     }
 | |
| 
 | |
|   /* Release the primary surface, if there is one */
 | |
|   if (pScreenPriv->pddsPrimary)
 | |
|     {
 | |
|       IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL);
 | |
|       IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
 | |
|       pScreenPriv->pddsPrimary = NULL;
 | |
|     }
 | |
| 
 | |
|   /* Free the DirectDraw object, if there is one */
 | |
|   if (pScreenPriv->pdd)
 | |
|     {
 | |
|       IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd);
 | |
|       IDirectDraw2_Release (pScreenPriv->pdd);
 | |
|       pScreenPriv->pdd = NULL;
 | |
|     }
 | |
| 
 | |
|   /* Delete tray icon, if we have one */
 | |
|   if (!pScreenInfo->fNoTrayIcon)
 | |
|     winDeleteNotifyIcon (pScreenPriv);
 | |
| 
 | |
|   /* Free the exit confirmation dialog box, if it exists */
 | |
|   if (g_hDlgExit != NULL)
 | |
|     {
 | |
|       DestroyWindow (g_hDlgExit);
 | |
|       g_hDlgExit = NULL;
 | |
|     }
 | |
| 
 | |
|   /* Kill our window */
 | |
|   if (pScreenPriv->hwndScreen)
 | |
|     {
 | |
|       DestroyWindow (pScreenPriv->hwndScreen);
 | |
|       pScreenPriv->hwndScreen = NULL;
 | |
|     }
 | |
| 
 | |
|   /* Kill our screeninfo's pointer to the screen */
 | |
|   pScreenInfo->pScreen = NULL;
 | |
| 
 | |
|   /* Invalidate the ScreenInfo's fb pointer */
 | |
|   pScreenInfo->pfb = NULL;
 | |
| 
 | |
|   /* Free the screen privates for this screen */
 | |
|   free ((pointer) pScreenPriv);
 | |
| 
 | |
|   return fReturn;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Tell mi what sort of visuals we need.
 | |
|  * 
 | |
|  * Generally we only need one visual, as our screen can only
 | |
|  * handle one format at a time, I believe.  You may want
 | |
|  * to verify that last sentence.
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| winInitVisualsPrimaryDD (ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
 | |
|   DWORD			dwRedBits, dwGreenBits, dwBlueBits;
 | |
| 
 | |
|   /* Count the number of ones in each color mask */
 | |
|   dwRedBits = winCountBits (pScreenPriv->dwRedMask);
 | |
|   dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
 | |
|   dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
 | |
|   
 | |
|   /* Store the maximum number of ones in a color mask as the bitsPerRGB */
 | |
|   if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
 | |
|     pScreenPriv->dwBitsPerRGB = dwRedBits;
 | |
|   else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
 | |
|     pScreenPriv->dwBitsPerRGB = dwGreenBits;
 | |
|   else
 | |
|     pScreenPriv->dwBitsPerRGB = dwBlueBits;
 | |
|   
 | |
|   ErrorF ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n",
 | |
| 	  pScreenPriv->dwRedMask,
 | |
| 	  pScreenPriv->dwGreenMask,
 | |
| 	  pScreenPriv->dwBlueMask,
 | |
| 	  pScreenPriv->dwBitsPerRGB);
 | |
| 
 | |
|   /* Create a single visual according to the Windows screen depth */
 | |
|   switch (pScreenInfo->dwDepth)
 | |
|     {
 | |
|     case 24:
 | |
|     case 16:
 | |
|     case 15:
 | |
|       if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
 | |
| 				     TrueColorMask,
 | |
| 				     pScreenPriv->dwBitsPerRGB,
 | |
| 				     TrueColor,
 | |
| 				     pScreenPriv->dwRedMask,
 | |
| 				     pScreenPriv->dwGreenMask,
 | |
| 				     pScreenPriv->dwBlueMask))
 | |
| 	{
 | |
| 	  ErrorF ("winInitVisualsPrimaryDD - " 
 | |
| 		  "miSetVisualTypesAndMasks failed\n");
 | |
| 	  return FALSE;
 | |
| 	}
 | |
|       break;
 | |
| 
 | |
|     case 8:
 | |
| #if CYGDEBUG
 | |
|       ErrorF ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
 | |
| #endif /* CYGDEBUG */
 | |
|       if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
 | |
| 				     PseudoColorMask,
 | |
| 				     pScreenPriv->dwBitsPerRGB,
 | |
| 				     PseudoColor,
 | |
| 				     pScreenPriv->dwRedMask,
 | |
| 				     pScreenPriv->dwGreenMask,
 | |
| 				     pScreenPriv->dwBlueMask))
 | |
| 	{
 | |
| 	  ErrorF ("winInitVisualsPrimaryDD - "
 | |
| 		  "miSetVisualTypesAndMasks failed\n");
 | |
| 	  return FALSE;
 | |
| 	}
 | |
| #if CYGDEBUG
 | |
|       ErrorF ("winInitVisualsPrimaryDD - Returned from "
 | |
| 	      "miSetVisualTypesAndMasks\n");
 | |
| #endif /* CYGDEBUG */
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n");
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|   ErrorF ("winInitVisualsPrimaryDD - Returning\n");
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| Bool
 | |
| winAdjustVideoModePrimaryDD (ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
 | |
|   HDC			hdc = NULL;
 | |
|   DWORD			dwBPP;
 | |
| 
 | |
|   /* We're in serious trouble if we can't get a DC */
 | |
|   hdc = GetDC (NULL);
 | |
|   if (hdc == NULL)
 | |
|     {
 | |
|       ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n");
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|   /* Query GDI for current display depth */
 | |
|   dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
 | |
| 
 | |
|   /* DirectDraw can only change the depth in fullscreen mode */
 | |
|   if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
 | |
|     {
 | |
|       /* No -depth parameter passed, let the user know the depth being used */
 | |
|       ErrorF ("winAdjustVideoModePrimaryDD - Using Windows display "
 | |
| 	      "depth of %d bits per pixel\n", dwBPP);
 | |
| 
 | |
|       /* Use GDI's depth */
 | |
|       pScreenInfo->dwBPP = dwBPP;
 | |
|     }
 | |
|   else if (pScreenInfo->fFullScreen
 | |
| 	   && pScreenInfo->dwBPP != dwBPP)
 | |
|     {
 | |
|       /* FullScreen, and GDI depth differs from -depth parameter */
 | |
|       ErrorF ("winAdjustVideoModePrimaryDD - FullScreen, using command "
 | |
| 	      "line depth: %d\n", pScreenInfo->dwBPP);
 | |
|     }
 | |
|   else if (dwBPP != pScreenInfo->dwBPP)
 | |
|     {
 | |
|       /* Windowed, and GDI depth differs from -depth parameter */
 | |
|       ErrorF ("winAdjustVideoModePrimaryDD - Windowed, command line "
 | |
| 	      "depth: %d, using depth: %d\n",
 | |
| 	      pScreenInfo->dwBPP, dwBPP);
 | |
| 
 | |
|       /* We'll use GDI's depth */
 | |
|       pScreenInfo->dwBPP = dwBPP;
 | |
|     }
 | |
|   
 | |
|   /* Release our DC */
 | |
|   ReleaseDC (NULL, hdc);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * We need to blit our offscreen fb to
 | |
|  * the screen when we are activated, and we need to point
 | |
|  * the fb code back to the primary surface memory.
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| winActivateAppPrimaryDD (ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
 | |
|   RECT			rcSrc, rcClient;
 | |
|   HRESULT		ddrval = DD_OK;
 | |
| 
 | |
|   /* Check for errors */
 | |
|   if (pScreenPriv == NULL
 | |
|       || pScreenPriv->pddsPrimary == NULL
 | |
|       || pScreenPriv->pddsOffscreen == NULL)
 | |
|     return FALSE;
 | |
| 
 | |
|   /* Check for do-nothing */
 | |
|   if (!pScreenPriv->fActive)
 | |
|     return TRUE;
 | |
|   
 | |
|   /* We are activating */
 | |
|   ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen);
 | |
|   if (ddrval == DD_OK)
 | |
|     {
 | |
|       IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen,
 | |
| 				  NULL);
 | |
|       /*
 | |
|        * We don't check for an error from Unlock, because it
 | |
|        * doesn't matter if the Unlock failed.
 | |
|        */
 | |
|     }
 | |
| 
 | |
|   /* Restore both surfaces, just cause I like it that way */
 | |
|   IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
 | |
|   IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
 | |
| 			      
 | |
|   /* Get client area in screen coords */
 | |
|   GetClientRect (pScreenPriv->hwndScreen, &rcClient);
 | |
|   MapWindowPoints (pScreenPriv->hwndScreen,
 | |
| 		   HWND_DESKTOP,
 | |
| 		   (LPPOINT)&rcClient, 2);
 | |
| 
 | |
|   /* Setup a source rectangle */
 | |
|   rcSrc.left = 0;
 | |
|   rcSrc.top = 0;
 | |
|   rcSrc.right = pScreenInfo->dwWidth;
 | |
|   rcSrc.bottom = pScreenInfo->dwHeight;
 | |
| 
 | |
|   ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
 | |
| 				    &rcClient,
 | |
| 				    pScreenPriv->pddsOffscreen,
 | |
| 				    &rcSrc,
 | |
| 				    DDBLT_WAIT,
 | |
| 				    NULL);
 | |
|   if (ddrval != DD_OK)
 | |
|     FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen "
 | |
| 		"surface to primary surface %08x\n", ddrval);
 | |
|   
 | |
|   /* Lock the primary surface */
 | |
|   ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
 | |
| 				     &rcClient,
 | |
| 				     pScreenPriv->pddsdPrimary,
 | |
| 				     DDLOCK_WAIT,
 | |
| 				     NULL);
 | |
|   if (ddrval != DD_OK
 | |
|       || pScreenPriv->pddsdPrimary->lpSurface == NULL)
 | |
|     FatalError ("winActivateAppPrimaryDD () - Could not lock "
 | |
| 		"primary surface\n");
 | |
| 
 | |
|   /* Notify FB of the new memory pointer */
 | |
|   winUpdateFBPointer (pScreen,
 | |
| 		      pScreenPriv->pddsdPrimary->lpSurface);
 | |
| 
 | |
|   /*
 | |
|    * Register the Alt-Tab combo as a hotkey so we can copy
 | |
|    * the primary framebuffer before the display mode changes
 | |
|    */
 | |
|   RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Handle the Alt+Tab hotkey.
 | |
|  *
 | |
|  * We need to save the primary fb to an offscreen fb when
 | |
|  * we get deactivated, and point the fb code at the offscreen
 | |
|  * fb for the duration of the deactivation.
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| winHotKeyAltTabPrimaryDD (ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
 | |
|   RECT			rcClient, rcSrc;
 | |
|   HRESULT		ddrval = DD_OK;
 | |
| 
 | |
|   ErrorF ("\nwinHotKeyAltTabPrimaryDD\n\n");
 | |
| 
 | |
|   /* Alt+Tab was pressed, we will lose focus very soon */
 | |
|   pScreenPriv->fActive = FALSE;
 | |
|   
 | |
|   /* Check for error conditions */
 | |
|   if (pScreenPriv->pddsPrimary == NULL
 | |
|       || pScreenPriv->pddsOffscreen == NULL)
 | |
|     return FALSE;
 | |
| 
 | |
|   /* Get client area in screen coords */
 | |
|   GetClientRect (pScreenPriv->hwndScreen, &rcClient);
 | |
|   MapWindowPoints (pScreenPriv->hwndScreen,
 | |
| 		   HWND_DESKTOP,
 | |
| 		   (LPPOINT)&rcClient, 2);
 | |
| 
 | |
|   /* Did we loose the primary surface? */
 | |
|   ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary);
 | |
|   if (ddrval == DD_OK)
 | |
|     {
 | |
|       ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary,
 | |
| 					   NULL);
 | |
|       if (FAILED (ddrval))
 | |
| 	FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary "
 | |
| 		    "surface\n");
 | |
|     }
 | |
| 
 | |
|   /* Setup a source rectangle */
 | |
|   rcSrc.left = 0;
 | |
|   rcSrc.top = 0;
 | |
|   rcSrc.right = pScreenInfo->dwWidth;
 | |
|   rcSrc.bottom = pScreenInfo->dwHeight;
 | |
| 
 | |
|       /* Blit the primary surface to the offscreen surface */
 | |
|   ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
 | |
| 				    NULL, /* should be rcDest */
 | |
| 				    pScreenPriv->pddsPrimary,
 | |
| 				    NULL,
 | |
| 				    DDBLT_WAIT,
 | |
| 				    NULL);
 | |
|   if (ddrval == DDERR_SURFACELOST)
 | |
|     {
 | |
|       IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);  
 | |
|       IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
 | |
| 		  		  
 | |
|       /* Blit the primary surface to the offscreen surface */
 | |
|       ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
 | |
| 					NULL,
 | |
| 					pScreenPriv->pddsPrimary,
 | |
| 					NULL,
 | |
| 					DDBLT_WAIT,
 | |
| 					NULL);
 | |
|       if (FAILED (ddrval))
 | |
| 	FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary "
 | |
| 		    "surface to offscreen surface: %08x\n",
 | |
| 		    ddrval);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from "
 | |
| 		  "Blt: %08dx\n", ddrval);
 | |
|     }
 | |
| 
 | |
|   /* Lock the offscreen surface */
 | |
|   ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen,
 | |
| 				     NULL,
 | |
| 				     pScreenPriv->pddsdOffscreen,
 | |
| 				     DDLOCK_WAIT,
 | |
| 				     NULL);
 | |
|   if (ddrval != DD_OK
 | |
|       || pScreenPriv->pddsdPrimary->lpSurface == NULL)
 | |
|     FatalError ("winHotKeyAltTabPrimaryDD - Could not lock "
 | |
| 		"offscreen surface\n");
 | |
| 
 | |
|   /* Notify FB of the new memory pointer */
 | |
|   winUpdateFBPointer (pScreen,
 | |
| 		      pScreenPriv->pddsdOffscreen->lpSurface);
 | |
| 
 | |
|   /* Unregister our hotkey */
 | |
|   UnregisterHotKey (pScreenPriv->hwndScreen, 1);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Set engine specific functions */
 | |
| Bool
 | |
| winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen)
 | |
| {
 | |
|   winScreenPriv(pScreen);
 | |
|   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
 | |
|   
 | |
|   /* Set our pointers */
 | |
|   pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD;
 | |
|   pScreenPriv->pwinShadowUpdate
 | |
|     = (winShadowUpdateProcPtr) (void (*)())NoopDDA;
 | |
|   pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD;
 | |
|   pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD;
 | |
|   pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD;
 | |
|   if (pScreenInfo->fFullScreen)
 | |
|     pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
 | |
|   else
 | |
|     pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
 | |
|   pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
 | |
|   pScreenPriv->pwinBltExposedRegions
 | |
|     = (winBltExposedRegionsProcPtr) (void (*)())NoopDDA;
 | |
|   pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD;
 | |
|   pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD;
 | |
| 
 | |
|   return TRUE;
 | |
| }
 |