2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
28 * Authors: Dakshinamurthy Karra
34 #ifdef HAVE_XWIN_CONFIG_H
35 #include <xwin-config.h>
44 extern HWND g_hDlgExit
;
48 * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly,
49 * so we have to redefine it here.
53 #define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
54 #endif /* DEFINE_GUID */
57 * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined
58 * here manually. Should be handled by ddraw.h
60 #ifndef IID_IDirectDraw4
61 DEFINE_GUID( IID_IDirectDraw4
, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
62 #endif /* IID_IDirectDraw4 */
64 #define FAIL_MSG_MAX_BLT 10
72 winAllocateFBShadowDDNL (ScreenPtr pScreen
);
75 winShadowUpdateDDNL (ScreenPtr pScreen
,
79 winCloseScreenShadowDDNL (int nIndex
, ScreenPtr pScreen
);
82 winInitVisualsShadowDDNL (ScreenPtr pScreen
);
85 winAdjustVideoModeShadowDDNL (ScreenPtr pScreen
);
88 winBltExposedRegionsShadowDDNL (ScreenPtr pScreen
);
91 winActivateAppShadowDDNL (ScreenPtr pScreen
);
94 winRedrawScreenShadowDDNL (ScreenPtr pScreen
);
97 winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen
);
100 winInstallColormapShadowDDNL (ColormapPtr pColormap
);
103 winStoreColorsShadowDDNL (ColormapPtr pmap
,
108 winCreateColormapShadowDDNL (ColormapPtr pColormap
);
111 winDestroyColormapShadowDDNL (ColormapPtr pColormap
);
114 winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen
);
117 winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen
);
121 * Create the primary surface and attach the clipper.
122 * Used for both the initial surface creation and during
123 * WM_DISPLAYCHANGE messages.
127 winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen
)
129 winScreenPriv(pScreen
);
130 HRESULT ddrval
= DD_OK
;
133 winDebug ("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n");
135 /* Describe the primary surface */
136 ZeroMemory (&ddsd
, sizeof (ddsd
));
137 ddsd
.dwSize
= sizeof (ddsd
);
138 ddsd
.dwFlags
= DDSD_CAPS
;
139 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
141 /* Create the primary surface */
142 ddrval
= IDirectDraw4_CreateSurface (pScreenPriv
->pdd4
,
144 &pScreenPriv
->pddsPrimary4
,
146 pScreenPriv
->fRetryCreateSurface
= FALSE
;
149 if (ddrval
== DDERR_NOEXCLUSIVEMODE
)
151 /* Recreating the surface failed. Mark screen to retry later */
152 pScreenPriv
->fRetryCreateSurface
= TRUE
;
153 winDebug ("winCreatePrimarySurfaceShadowDDNL - Could not create "
154 "primary surface: DDERR_NOEXCLUSIVEMODE\n");
158 ErrorF ("winCreatePrimarySurfaceShadowDDNL - Could not create "
159 "primary surface: %08x\n", (unsigned int) ddrval
);
165 winDebug ("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n");
168 /* Attach our clipper to our primary surface handle */
169 ddrval
= IDirectDrawSurface4_SetClipper (pScreenPriv
->pddsPrimary4
,
170 pScreenPriv
->pddcPrimary
);
173 ErrorF ("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper "
175 (unsigned int) ddrval
);
180 winDebug ("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary "
184 /* Everything was correct */
190 * Detach the clipper and release the primary surface.
191 * Called from WM_DISPLAYCHANGE.
195 winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen
)
197 winScreenPriv(pScreen
);
199 winDebug ("winReleasePrimarySurfaceShadowDDNL - Hello\n");
201 /* Release the primary surface and clipper, if they exist */
202 if (pScreenPriv
->pddsPrimary4
)
205 * Detach the clipper from the primary surface.
206 * NOTE: We do this explicity for clarity. The Clipper is not released.
208 IDirectDrawSurface4_SetClipper (pScreenPriv
->pddsPrimary4
,
211 winDebug ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n");
213 /* Release the primary surface */
214 IDirectDrawSurface4_Release (pScreenPriv
->pddsPrimary4
);
215 pScreenPriv
->pddsPrimary4
= NULL
;
218 winDebug ("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n");
225 * Create a DirectDraw surface for the shadow framebuffer; also create
226 * a primary surface object so we can blit to the display.
228 * Install a DirectDraw clipper on our primary surface object
229 * that clips our blits to the unobscured client area of our display window.
233 winAllocateFBShadowDDNL (ScreenPtr pScreen
)
235 winScreenPriv(pScreen
);
236 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
237 HRESULT ddrval
= DD_OK
;
238 DDSURFACEDESC2 ddsdShadow
;
239 char *lpSurface
= NULL
;
240 DDPIXELFORMAT ddpfPrimary
;
243 winDebug ("winAllocateFBShadowDDNL - w %d h %d d %d\n",
244 pScreenInfo
->dwWidth
, pScreenInfo
->dwHeight
, pScreenInfo
->dwDepth
);
247 /* Allocate memory for our shadow surface */
248 lpSurface
= malloc (pScreenInfo
->dwPaddedWidth
* pScreenInfo
->dwHeight
);
249 if (lpSurface
== NULL
)
251 ErrorF ("winAllocateFBShadowDDNL - Could not allocate bits\n");
256 * Initialize the framebuffer memory so we don't get a
257 * strange display at startup
259 ZeroMemory (lpSurface
, pScreenInfo
->dwPaddedWidth
* pScreenInfo
->dwHeight
);
261 /* Create a clipper */
262 ddrval
= (*g_fpDirectDrawCreateClipper
) (0,
263 &pScreenPriv
->pddcPrimary
,
267 ErrorF ("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n",
268 (unsigned int) ddrval
);
273 winDebug ("winAllocateFBShadowDDNL - Created a clipper\n");
276 /* Get a device context for the screen */
277 pScreenPriv
->hdcScreen
= GetDC (pScreenPriv
->hwndScreen
);
279 /* Attach the clipper to our display window */
280 ddrval
= IDirectDrawClipper_SetHWnd (pScreenPriv
->pddcPrimary
,
282 pScreenPriv
->hwndScreen
);
285 ErrorF ("winAllocateFBShadowDDNL - Clipper not attached "
287 (unsigned int) ddrval
);
292 winDebug ("winAllocateFBShadowDDNL - Attached clipper to window\n");
295 /* Create a DirectDraw object, store the address at lpdd */
296 ddrval
= (*g_fpDirectDrawCreate
) (NULL
,
297 (LPDIRECTDRAW
*) &pScreenPriv
->pdd
,
301 ErrorF ("winAllocateFBShadowDDNL - Could not start "
302 "DirectDraw: %08x\n",
303 (unsigned int) ddrval
);
308 winDebug ("winAllocateFBShadowDDNL - Created and initialized DD\n");
311 /* Get a DirectDraw4 interface pointer */
312 ddrval
= IDirectDraw_QueryInterface (pScreenPriv
->pdd
,
314 (LPVOID
*) &pScreenPriv
->pdd4
);
317 ErrorF ("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n",
318 (unsigned int) ddrval
);
322 /* Are we full screen? */
323 if (pScreenInfo
->fFullScreen
)
325 DDSURFACEDESC2 ddsdCurrent
;
326 DWORD dwRefreshRateCurrent
= 0;
329 /* Set the cooperative level to full screen */
330 ddrval
= IDirectDraw4_SetCooperativeLevel (pScreenPriv
->pdd4
,
331 pScreenPriv
->hwndScreen
,
336 ErrorF ("winAllocateFBShadowDDNL - Could not set "
337 "cooperative level: %08x\n",
338 (unsigned int) ddrval
);
343 * We only need to get the current refresh rate for comparison
344 * if a refresh rate has been passed on the command line.
346 if (pScreenInfo
->dwRefreshRate
!= 0)
348 ZeroMemory (&ddsdCurrent
, sizeof (ddsdCurrent
));
349 ddsdCurrent
.dwSize
= sizeof (ddsdCurrent
);
351 /* Get information about current display settings */
352 ddrval
= IDirectDraw4_GetDisplayMode (pScreenPriv
->pdd4
,
356 ErrorF ("winAllocateFBShadowDDNL - Could not get current "
357 "refresh rate: %08x. Continuing.\n",
358 (unsigned int) ddrval
);
359 dwRefreshRateCurrent
= 0;
363 /* Grab the current refresh rate */
364 dwRefreshRateCurrent
= ddsdCurrent
.u2
.dwRefreshRate
;
368 /* Clean up the refresh rate */
369 if (dwRefreshRateCurrent
== pScreenInfo
->dwRefreshRate
)
372 * Refresh rate is non-specified or equal to current.
374 pScreenInfo
->dwRefreshRate
= 0;
377 /* Grab a device context for the screen */
381 ErrorF ("winAllocateFBShadowDDNL - GetDC () failed\n");
385 /* Only change the video mode when different than current mode */
386 if (!pScreenInfo
->fMultipleMonitors
387 && (pScreenInfo
->dwWidth
!= GetSystemMetrics (SM_CXSCREEN
)
388 || pScreenInfo
->dwHeight
!= GetSystemMetrics (SM_CYSCREEN
)
389 || pScreenInfo
->dwBPP
!= GetDeviceCaps (hdc
, BITSPIXEL
)
390 || pScreenInfo
->dwRefreshRate
!= 0))
392 winDebug ("winAllocateFBShadowDDNL - Changing video mode\n");
394 /* Change the video mode to the mode requested */
395 ddrval
= IDirectDraw4_SetDisplayMode (pScreenPriv
->pdd4
,
396 pScreenInfo
->dwWidth
,
397 pScreenInfo
->dwHeight
,
399 pScreenInfo
->dwRefreshRate
,
403 ErrorF ("winAllocateFBShadowDDNL - Could not set "
404 "full screen display mode: %08x\n",
405 (unsigned int) ddrval
);
411 winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n");
415 ReleaseDC (NULL
, hdc
);
420 /* Set the cooperative level for windowed mode */
421 ddrval
= IDirectDraw4_SetCooperativeLevel (pScreenPriv
->pdd4
,
422 pScreenPriv
->hwndScreen
,
426 ErrorF ("winAllocateFBShadowDDNL - Could not set "
427 "cooperative level: %08x\n",
428 (unsigned int) ddrval
);
433 /* Create the primary surface */
434 if (!winCreatePrimarySurfaceShadowDDNL (pScreen
))
436 ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
441 /* Get primary surface's pixel format */
442 ZeroMemory (&ddpfPrimary
, sizeof (ddpfPrimary
));
443 ddpfPrimary
.dwSize
= sizeof (ddpfPrimary
);
444 ddrval
= IDirectDrawSurface4_GetPixelFormat (pScreenPriv
->pddsPrimary4
,
448 ErrorF ("winAllocateFBShadowDDNL - Could not get primary "
450 (unsigned int) ddrval
);
455 winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
456 "dwRGBBitCount: %d\n",
457 ddpfPrimary
.u2
.dwRBitMask
,
458 ddpfPrimary
.u3
.dwGBitMask
,
459 ddpfPrimary
.u4
.dwBBitMask
,
460 ddpfPrimary
.u1
.dwRGBBitCount
);
463 /* Describe the shadow surface to be created */
465 * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
466 * as drawing, locking, and unlocking take forever
467 * with video memory surfaces. In addition,
468 * video memory is a somewhat scarce resource,
469 * so you shouldn't be allocating video memory when
470 * you have the option of using system memory instead.
472 ZeroMemory (&ddsdShadow
, sizeof (ddsdShadow
));
473 ddsdShadow
.dwSize
= sizeof (ddsdShadow
);
474 ddsdShadow
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
475 | DDSD_LPSURFACE
| DDSD_PITCH
| DDSD_PIXELFORMAT
;
476 ddsdShadow
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_SYSTEMMEMORY
;
477 ddsdShadow
.dwHeight
= pScreenInfo
->dwHeight
;
478 ddsdShadow
.dwWidth
= pScreenInfo
->dwWidth
;
479 ddsdShadow
.u1
.lPitch
= pScreenInfo
->dwPaddedWidth
;
480 ddsdShadow
.lpSurface
= lpSurface
;
481 ddsdShadow
.u4
.ddpfPixelFormat
= ddpfPrimary
;
483 winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n",
484 (int) pScreenInfo
->dwPaddedWidth
);
486 /* Create the shadow surface */
487 ddrval
= IDirectDraw4_CreateSurface (pScreenPriv
->pdd4
,
489 &pScreenPriv
->pddsShadow4
,
493 ErrorF ("winAllocateFBShadowDDNL - Could not create shadow "
494 "surface: %08x\n", (unsigned int) ddrval
);
499 winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
500 (int) ddsdShadow
.u1
.lPitch
);
503 /* Grab the pitch from the surface desc */
504 pScreenInfo
->dwStride
= (ddsdShadow
.u1
.lPitch
* 8)
505 / pScreenInfo
->dwBPP
;
508 winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
509 (int) pScreenInfo
->dwStride
);
512 /* Save the pointer to our surface memory */
513 pScreenInfo
->pfb
= lpSurface
;
515 /* Grab the masks from the surface description */
516 pScreenPriv
->dwRedMask
= ddsdShadow
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
;
517 pScreenPriv
->dwGreenMask
= ddsdShadow
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
;
518 pScreenPriv
->dwBlueMask
= ddsdShadow
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
;
521 winDebug ("winAllocateFBShadowDDNL - Returning\n");
528 #if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
530 * Create a DirectDraw surface for the new multi-window window
535 winFinishCreateWindowsWindowDDNL (WindowPtr pWin
)
538 winPrivScreenPtr pScreenPriv
= pWinPriv
->pScreenPriv
;
539 HRESULT ddrval
= DD_OK
;
544 winDebug ("\nwinFinishCreateWindowsWindowDDNL!\n\n");
546 iX
= pWin
->drawable
.x
+ GetSystemMetrics (SM_XVIRTUALSCREEN
);
547 iY
= pWin
->drawable
.y
+ GetSystemMetrics (SM_YVIRTUALSCREEN
);
549 iWidth
= pWin
->drawable
.width
;
550 iHeight
= pWin
->drawable
.height
;
552 /* Describe the primary surface */
553 ZeroMemory (&ddsd
, sizeof (ddsd
));
554 ddsd
.dwSize
= sizeof (ddsd
);
555 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
556 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
557 ddsd
.dwHeight
= iHeight
;
558 ddsd
.dwWidth
= iWidth
;
560 /* Create the primary surface */
561 ddrval
= IDirectDraw4_CreateSurface (pScreenPriv
->pdd4
,
563 &pWinPriv
->pddsPrimary4
,
567 ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary "
569 (unsigned int)ddrval
);
578 * Transfer the damaged regions of the shadow framebuffer to the display.
582 winShadowUpdateDDNL (ScreenPtr pScreen
,
585 winScreenPriv(pScreen
);
586 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
587 RegionPtr damage
= &pBuf
->damage
;
588 HRESULT ddrval
= DD_OK
;
591 DWORD dwBox
= REGION_NUM_RECTS (damage
);
592 BoxPtr pBox
= REGION_RECTS (damage
);
593 HRGN hrgnTemp
= NULL
, hrgnCombined
= NULL
;
596 * Return immediately if the app is not active
597 * and we are fullscreen, or if we have a bad display depth
599 if ((!pScreenPriv
->fActive
&& pScreenInfo
->fFullScreen
)
600 || pScreenPriv
->fBadDepth
) return;
602 /* Get the origin of the window in the screen coords */
603 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
604 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
605 MapWindowPoints (pScreenPriv
->hwndScreen
,
607 (LPPOINT
)&ptOrigin
, 1);
610 * Handle small regions with multiple blits,
611 * handle large regions by creating a clipping region and
612 * doing a single blit constrained to that clipping region.
614 if (pScreenInfo
->dwClipUpdatesNBoxes
== 0
615 || dwBox
< pScreenInfo
->dwClipUpdatesNBoxes
)
617 /* Loop through all boxes in the damaged region */
620 /* Assign damage box to source rectangle */
621 rcSrc
.left
= pBox
->x1
;
622 rcSrc
.top
= pBox
->y1
;
623 rcSrc
.right
= pBox
->x2
;
624 rcSrc
.bottom
= pBox
->y2
;
626 /* Calculate destination rectangle */
627 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
628 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
629 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
630 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
632 /* Blit the damaged areas */
633 ddrval
= IDirectDrawSurface4_Blt (pScreenPriv
->pddsPrimary4
,
635 pScreenPriv
->pddsShadow4
,
641 static int s_iFailCount
= 0;
643 if (s_iFailCount
< FAIL_MSG_MAX_BLT
)
645 ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
647 (unsigned int) ddrval
);
651 if (s_iFailCount
== FAIL_MSG_MAX_BLT
)
653 ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
654 "failure message maximum (%d) reached. No "
655 "more failure messages will be printed.\n",
661 /* Get a pointer to the next box */
667 BoxPtr pBoxExtents
= REGION_EXTENTS (pScreen
, damage
);
669 /* Compute a GDI region from the damaged region */
670 hrgnCombined
= CreateRectRgn (pBox
->x1
, pBox
->y1
, pBox
->x2
, pBox
->y2
);
675 hrgnTemp
= CreateRectRgn (pBox
->x1
, pBox
->y1
, pBox
->x2
, pBox
->y2
);
676 CombineRgn (hrgnCombined
, hrgnCombined
, hrgnTemp
, RGN_OR
);
677 DeleteObject (hrgnTemp
);
681 /* Install the GDI region as a clipping region */
682 SelectClipRgn (pScreenPriv
->hdcScreen
, hrgnCombined
);
683 DeleteObject (hrgnCombined
);
687 winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
688 pBoxExtents
->x1
, pBoxExtents
->y1
,
689 pBoxExtents
->x2
, pBoxExtents
->y2
);
692 /* Calculating a bounding box for the source is easy */
693 rcSrc
.left
= pBoxExtents
->x1
;
694 rcSrc
.top
= pBoxExtents
->y1
;
695 rcSrc
.right
= pBoxExtents
->x2
;
696 rcSrc
.bottom
= pBoxExtents
->y2
;
698 /* Calculating a bounding box for the destination is trickier */
699 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
700 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
701 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
702 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
704 /* Our Blt should be clipped to the invalidated region */
705 ddrval
= IDirectDrawSurface4_Blt (pScreenPriv
->pddsPrimary4
,
707 pScreenPriv
->pddsShadow4
,
712 /* Reset the clip region */
713 SelectClipRgn (pScreenPriv
->hdcScreen
, NULL
);
719 * Call the wrapped CloseScreen function.
721 * Free our resources and private structures.
725 winCloseScreenShadowDDNL (int nIndex
, ScreenPtr pScreen
)
727 winScreenPriv(pScreen
);
728 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
732 winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n");
735 /* Flag that the screen is closed */
736 pScreenPriv
->fClosed
= TRUE
;
737 pScreenPriv
->fActive
= FALSE
;
739 /* Call the wrapped CloseScreen procedure */
740 WIN_UNWRAP(CloseScreen
);
741 fReturn
= (*pScreen
->CloseScreen
) (nIndex
, pScreen
);
743 /* Free the screen DC */
744 ReleaseDC (pScreenPriv
->hwndScreen
, pScreenPriv
->hdcScreen
);
746 /* Delete the window property */
747 RemoveProp (pScreenPriv
->hwndScreen
, WIN_SCR_PROP
);
749 /* Free the shadow surface, if there is one */
750 if (pScreenPriv
->pddsShadow4
)
752 IDirectDrawSurface4_Release (pScreenPriv
->pddsShadow4
);
753 free (pScreenInfo
->pfb
);
754 pScreenInfo
->pfb
= NULL
;
755 pScreenPriv
->pddsShadow4
= NULL
;
758 /* Detach the clipper from the primary surface and release the clipper. */
759 if (pScreenPriv
->pddcPrimary
)
761 /* Detach the clipper */
762 IDirectDrawSurface4_SetClipper (pScreenPriv
->pddsPrimary4
,
765 /* Release the clipper object */
766 IDirectDrawClipper_Release (pScreenPriv
->pddcPrimary
);
767 pScreenPriv
->pddcPrimary
= NULL
;
770 /* Release the primary surface, if there is one */
771 if (pScreenPriv
->pddsPrimary4
)
773 IDirectDrawSurface4_Release (pScreenPriv
->pddsPrimary4
);
774 pScreenPriv
->pddsPrimary4
= NULL
;
777 /* Free the DirectDraw4 object, if there is one */
778 if (pScreenPriv
->pdd4
)
780 IDirectDraw4_RestoreDisplayMode (pScreenPriv
->pdd4
);
781 IDirectDraw4_Release (pScreenPriv
->pdd4
);
782 pScreenPriv
->pdd4
= NULL
;
785 /* Free the DirectDraw object, if there is one */
786 if (pScreenPriv
->pdd
)
788 IDirectDraw_Release (pScreenPriv
->pdd
);
789 pScreenPriv
->pdd
= NULL
;
792 /* Delete tray icon, if we have one */
793 if (!pScreenInfo
->fNoTrayIcon
)
794 winDeleteNotifyIcon (pScreenPriv
);
796 /* Free the exit confirmation dialog box, if it exists */
797 if (g_hDlgExit
!= NULL
)
799 DestroyWindow (g_hDlgExit
);
803 /* Kill our window */
804 if (pScreenPriv
->hwndScreen
)
806 DestroyWindow (pScreenPriv
->hwndScreen
);
807 pScreenPriv
->hwndScreen
= NULL
;
810 #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
811 /* Destroy the thread startup mutex */
812 pthread_mutex_destroy (&pScreenPriv
->pmServerStarted
);
815 /* Kill our screeninfo's pointer to the screen */
816 pScreenInfo
->pScreen
= NULL
;
818 /* Invalidate the ScreenInfo's fb pointer */
819 pScreenInfo
->pfb
= NULL
;
821 /* Free the screen privates for this screen */
822 free ((pointer
) pScreenPriv
);
829 * Tell mi what sort of visuals we need.
831 * Generally we only need one visual, as our screen can only
832 * handle one format at a time, I believe. You may want
833 * to verify that last sentence.
837 winInitVisualsShadowDDNL (ScreenPtr pScreen
)
839 winScreenPriv(pScreen
);
840 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
841 DWORD dwRedBits
, dwGreenBits
, dwBlueBits
;
843 /* Count the number of ones in each color mask */
844 dwRedBits
= winCountBits (pScreenPriv
->dwRedMask
);
845 dwGreenBits
= winCountBits (pScreenPriv
->dwGreenMask
);
846 dwBlueBits
= winCountBits (pScreenPriv
->dwBlueMask
);
848 /* Store the maximum number of ones in a color mask as the bitsPerRGB */
849 if (dwRedBits
== 0 || dwGreenBits
== 0 || dwBlueBits
== 0)
850 pScreenPriv
->dwBitsPerRGB
= 8;
851 else if (dwRedBits
> dwGreenBits
&& dwRedBits
> dwBlueBits
)
852 pScreenPriv
->dwBitsPerRGB
= dwRedBits
;
853 else if (dwGreenBits
> dwRedBits
&& dwGreenBits
> dwBlueBits
)
854 pScreenPriv
->dwBitsPerRGB
= dwGreenBits
;
856 pScreenPriv
->dwBitsPerRGB
= dwBlueBits
;
858 winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
860 (unsigned int) pScreenPriv
->dwRedMask
,
861 (unsigned int) pScreenPriv
->dwGreenMask
,
862 (unsigned int) pScreenPriv
->dwBlueMask
,
863 (int) pScreenPriv
->dwBitsPerRGB
,
864 (int) pScreenInfo
->dwDepth
,
865 (int) pScreenInfo
->dwBPP
);
867 /* Create a single visual according to the Windows screen depth */
868 switch (pScreenInfo
->dwDepth
)
873 #if defined(XFree86Server)
874 /* Setup the real visual */
875 if (!miSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
877 pScreenPriv
->dwBitsPerRGB
,
879 pScreenPriv
->dwRedMask
,
880 pScreenPriv
->dwGreenMask
,
881 pScreenPriv
->dwBlueMask
))
883 ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
884 "failed for TrueColor\n");
888 #ifdef XWIN_EMULATEPSEUDO
889 if (!pScreenInfo
->fEmulatePseudo
)
892 /* Setup a pseudocolor visual */
893 if (!miSetVisualTypesAndMasks (8,
901 ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
902 "failed for PseudoColor\n");
906 #else /* XFree86Server */
907 /* Setup the real visual */
908 if (!fbSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
910 pScreenPriv
->dwBitsPerRGB
,
911 pScreenPriv
->dwRedMask
,
912 pScreenPriv
->dwGreenMask
,
913 pScreenPriv
->dwBlueMask
))
915 ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks "
916 "failed for TrueColor\n");
920 #ifdef XWIN_EMULATEPSEUDO
921 if (!pScreenInfo
->fEmulatePseudo
)
924 /* Setup a pseudocolor visual */
925 if (!fbSetVisualTypesAndMasks (8,
932 ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks "
933 "failed for PseudoColor\n");
937 #endif /* XFree86Server */
941 #if defined(XFree86Server)
942 if (!miSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
943 pScreenInfo
->fFullScreen
944 ? PseudoColorMask
: StaticColorMask
,
945 pScreenPriv
->dwBitsPerRGB
,
946 pScreenInfo
->fFullScreen
947 ? PseudoColor
: StaticColor
,
948 pScreenPriv
->dwRedMask
,
949 pScreenPriv
->dwGreenMask
,
950 pScreenPriv
->dwBlueMask
))
952 ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
956 #else /* XFree86Server */
957 if (!fbSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
958 pScreenInfo
->fFullScreen
959 ? PseudoColorMask
: StaticColorMask
,
960 pScreenPriv
->dwBitsPerRGB
,
961 pScreenPriv
->dwRedMask
,
962 pScreenPriv
->dwGreenMask
,
963 pScreenPriv
->dwBlueMask
))
965 ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks "
969 #endif /* XFree86Server */
973 ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n");
978 winDebug ("winInitVisualsShadowDDNL - Returning\n");
986 * Adjust the user proposed video mode
990 winAdjustVideoModeShadowDDNL (ScreenPtr pScreen
)
992 winScreenPriv(pScreen
);
993 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
997 /* We're in serious trouble if we can't get a DC */
1001 ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
1005 /* Query GDI for current display depth */
1006 dwBPP
= GetDeviceCaps (hdc
, BITSPIXEL
);
1008 /* DirectDraw can only change the depth in fullscreen mode */
1009 if (pScreenInfo
->dwBPP
== WIN_DEFAULT_BPP
)
1011 /* No -depth parameter passed, let the user know the depth being used */
1012 winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Using Windows display "
1013 "depth of %d bits per pixel\n", (int) dwBPP
);
1015 /* Use GDI's depth */
1016 pScreenInfo
->dwBPP
= dwBPP
;
1018 else if (pScreenInfo
->fFullScreen
1019 && pScreenInfo
->dwBPP
!= dwBPP
)
1021 /* FullScreen, and GDI depth differs from -depth parameter */
1022 winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - FullScreen, using command "
1023 "line bpp: %d\n", (int) pScreenInfo
->dwBPP
);
1025 else if (dwBPP
!= pScreenInfo
->dwBPP
)
1027 /* Windowed, and GDI depth differs from -depth parameter */
1028 winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Windowed, command line "
1029 "bpp: %d, using bpp: %d\n",
1030 (int) pScreenInfo
->dwBPP
, (int) dwBPP
);
1032 /* We'll use GDI's depth */
1033 pScreenInfo
->dwBPP
= dwBPP
;
1036 /* See if the shadow bitmap will be larger than the DIB size limit */
1037 if (pScreenInfo
->dwWidth
* pScreenInfo
->dwHeight
* pScreenInfo
->dwBPP
1038 >= WIN_DIB_MAXIMUM_SIZE
)
1040 winErrorFVerb (1, "winAdjustVideoModeShadowDDNL - Requested DirectDraw surface "
1041 "will be larger than %d MB. The surface may fail to be "
1042 "allocated on Windows 95, 98, or Me, due to a %d MB limit in "
1043 "DIB size. This limit does not apply to Windows NT/2000, and "
1044 "this message may be ignored on those platforms.\n",
1045 WIN_DIB_MAXIMUM_SIZE_MB
, WIN_DIB_MAXIMUM_SIZE_MB
);
1048 /* Release our DC */
1049 ReleaseDC (NULL
, hdc
);
1056 * Blt exposed regions to the screen
1060 winBltExposedRegionsShadowDDNL (ScreenPtr pScreen
)
1062 winScreenPriv(pScreen
);
1063 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1068 HRESULT ddrval
= DD_OK
;
1069 Bool fReturn
= TRUE
;
1072 /* Quite common case. The primary surface was lost (maybe because of depth
1073 * change). Try to create a new primary surface. Bail out if this fails */
1074 if (pScreenPriv
->pddsPrimary4
== NULL
&& pScreenPriv
->fRetryCreateSurface
&&
1075 !winCreatePrimarySurfaceShadowDDNL(pScreen
))
1080 if (pScreenPriv
->pddsPrimary4
== NULL
)
1083 /* BeginPaint gives us an hdc that clips to the invalidated region */
1084 hdcUpdate
= BeginPaint (pScreenPriv
->hwndScreen
, &ps
);
1085 if (hdcUpdate
== NULL
)
1088 ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
1089 "a NULL device context handle. Aborting blit attempt.\n");
1090 goto winBltExposedRegionsShadowDDNL_Exit
;
1093 /* Get the origin of the window in the screen coords */
1094 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
1095 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
1097 MapWindowPoints (pScreenPriv
->hwndScreen
,
1099 (LPPOINT
)&ptOrigin
, 1);
1100 rcDest
.left
= ptOrigin
.x
;
1101 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
1102 rcDest
.top
= ptOrigin
.y
;
1103 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
1105 /* Source can be entire shadow surface, as Blt should clip for us */
1108 rcSrc
.right
= pScreenInfo
->dwWidth
;
1109 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
1111 /* Try to regain the primary surface and blit again if we've lost it */
1112 for (i
= 0; i
<= WIN_REGAIN_SURFACE_RETRIES
; ++i
)
1114 /* Our Blt should be clipped to the invalidated region */
1115 ddrval
= IDirectDrawSurface4_Blt (pScreenPriv
->pddsPrimary4
,
1117 pScreenPriv
->pddsShadow4
,
1121 if (ddrval
== DDERR_SURFACELOST
)
1123 /* Surface was lost */
1124 winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
1125 "IDirectDrawSurface4_Blt reported that the primary "
1126 "surface was lost, trying to restore, retry: %d\n", i
+ 1);
1128 /* Try to restore the surface, once */
1130 ddrval
= IDirectDrawSurface4_Restore (pScreenPriv
->pddsPrimary4
);
1131 winDebug ("winBltExposedRegionsShadowDDNL - "
1132 "IDirectDrawSurface4_Restore returned: ");
1133 if (ddrval
== DD_OK
)
1134 winDebug ("DD_OK\n");
1135 else if (ddrval
== DDERR_WRONGMODE
)
1136 winDebug ("DDERR_WRONGMODE\n");
1137 else if (ddrval
== DDERR_INCOMPATIBLEPRIMARY
)
1138 winDebug ("DDERR_INCOMPATIBLEPRIMARY\n");
1139 else if (ddrval
== DDERR_UNSUPPORTED
)
1140 winDebug ("DDERR_UNSUPPORTED\n");
1141 else if (ddrval
== DDERR_INVALIDPARAMS
)
1142 winDebug ("DDERR_INVALIDPARAMS\n");
1143 else if (ddrval
== DDERR_INVALIDOBJECT
)
1144 winDebug ("DDERR_INVALIDOBJECT\n");
1146 winDebug ("unknown error: %08x\n", (unsigned int) ddrval
);
1148 /* Loop around to try the blit one more time */
1151 else if (FAILED (ddrval
))
1154 winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
1155 "IDirectDrawSurface4_Blt failed, but surface not "
1157 (unsigned int) ddrval
, (int) ddrval
);
1158 goto winBltExposedRegionsShadowDDNL_Exit
;
1162 /* Success, stop looping */
1167 winBltExposedRegionsShadowDDNL_Exit
:
1168 /* EndPaint frees the DC */
1169 if (hdcUpdate
!= NULL
)
1170 EndPaint (pScreenPriv
->hwndScreen
, &ps
);
1176 * Do any engine-specific application-activation processing
1180 winActivateAppShadowDDNL (ScreenPtr pScreen
)
1182 winScreenPriv(pScreen
);
1185 * Do we have a surface?
1187 * Are we full screen?
1189 if (pScreenPriv
!= NULL
1190 && pScreenPriv
->pddsPrimary4
!= NULL
1191 && pScreenPriv
->fActive
)
1193 /* Primary surface was lost, restore it */
1194 IDirectDrawSurface4_Restore (pScreenPriv
->pddsPrimary4
);
1202 * Reblit the shadow framebuffer to the screen.
1206 winRedrawScreenShadowDDNL (ScreenPtr pScreen
)
1208 winScreenPriv(pScreen
);
1209 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1210 HRESULT ddrval
= DD_OK
;
1214 /* Get the origin of the window in the screen coords */
1215 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
1216 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
1217 MapWindowPoints (pScreenPriv
->hwndScreen
,
1219 (LPPOINT
)&ptOrigin
, 1);
1220 rcDest
.left
= ptOrigin
.x
;
1221 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
1222 rcDest
.top
= ptOrigin
.y
;
1223 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
1225 /* Source can be entire shadow surface, as Blt should clip for us */
1228 rcSrc
.right
= pScreenInfo
->dwWidth
;
1229 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
1231 /* Redraw the whole window, to take account for the new colors */
1232 ddrval
= IDirectDrawSurface4_Blt (pScreenPriv
->pddsPrimary4
,
1234 pScreenPriv
->pddsShadow4
,
1238 if (FAILED (ddrval
))
1240 ErrorF ("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
1242 (unsigned int) ddrval
);
1250 * Realize the currently installed colormap
1254 winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen
)
1261 * Install the specified colormap
1265 winInstallColormapShadowDDNL (ColormapPtr pColormap
)
1267 ScreenPtr pScreen
= pColormap
->pScreen
;
1268 winScreenPriv(pScreen
);
1269 winCmapPriv(pColormap
);
1270 HRESULT ddrval
= DD_OK
;
1272 /* Install the DirectDraw palette on the primary surface */
1273 ddrval
= IDirectDrawSurface4_SetPalette (pScreenPriv
->pddsPrimary4
,
1274 pCmapPriv
->lpDDPalette
);
1275 if (FAILED (ddrval
))
1277 ErrorF ("winInstallColormapShadowDDNL - Failed installing the "
1278 "DirectDraw palette.\n");
1282 /* Save a pointer to the newly installed colormap */
1283 pScreenPriv
->pcmapInstalled
= pColormap
;
1290 * Store the specified colors in the specified colormap
1294 winStoreColorsShadowDDNL (ColormapPtr pColormap
,
1298 ScreenPtr pScreen
= pColormap
->pScreen
;
1299 winScreenPriv(pScreen
);
1300 winCmapPriv(pColormap
);
1301 ColormapPtr curpmap
= pScreenPriv
->pcmapInstalled
;
1302 HRESULT ddrval
= DD_OK
;
1304 /* Put the X colormap entries into the Windows logical palette */
1305 ddrval
= IDirectDrawPalette_SetEntries (pCmapPriv
->lpDDPalette
,
1311 if (FAILED (ddrval
))
1313 ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", ddrval
);
1317 /* Don't install the DirectDraw palette if the colormap is not installed */
1318 if (pColormap
!= curpmap
)
1323 if (!winInstallColormapShadowDDNL (pColormap
))
1325 ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n");
1334 * Colormap initialization procedure
1338 winCreateColormapShadowDDNL (ColormapPtr pColormap
)
1340 HRESULT ddrval
= DD_OK
;
1341 ScreenPtr pScreen
= pColormap
->pScreen
;
1342 winScreenPriv(pScreen
);
1343 winCmapPriv(pColormap
);
1345 /* Create a DirectDraw palette */
1346 ddrval
= IDirectDraw4_CreatePalette (pScreenPriv
->pdd4
,
1347 DDPCAPS_8BIT
| DDPCAPS_ALLOW256
,
1348 pCmapPriv
->peColors
,
1349 &pCmapPriv
->lpDDPalette
,
1351 if (FAILED (ddrval
))
1353 ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n");
1362 * Colormap destruction procedure
1366 winDestroyColormapShadowDDNL (ColormapPtr pColormap
)
1368 winScreenPriv(pColormap
->pScreen
);
1369 winCmapPriv(pColormap
);
1370 HRESULT ddrval
= DD_OK
;
1373 * Is colormap to be destroyed the default?
1375 * Non-default colormaps should have had winUninstallColormap
1376 * called on them before we get here. The default colormap
1377 * will not have had winUninstallColormap called on it. Thus,
1378 * we need to handle the default colormap in a special way.
1380 if (pColormap
->flags
& IsDefault
)
1383 winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
1387 * FIXME: Walk the list of all screens, popping the default
1388 * palette out of each screen device context.
1391 /* Pop the palette out of the primary surface */
1392 ddrval
= IDirectDrawSurface4_SetPalette (pScreenPriv
->pddsPrimary4
,
1394 if (FAILED (ddrval
))
1396 ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the "
1397 "default colormap DirectDraw palette.\n");
1401 /* Clear our private installed colormap pointer */
1402 pScreenPriv
->pcmapInstalled
= NULL
;
1405 /* Release the palette */
1406 IDirectDrawPalette_Release (pCmapPriv
->lpDDPalette
);
1408 /* Invalidate the colormap privates */
1409 pCmapPriv
->lpDDPalette
= NULL
;
1416 * Set pointers to our engine specific functions
1420 winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen
)
1422 winScreenPriv(pScreen
);
1423 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1425 /* Set our pointers */
1426 pScreenPriv
->pwinAllocateFB
= winAllocateFBShadowDDNL
;
1427 pScreenPriv
->pwinShadowUpdate
= winShadowUpdateDDNL
;
1428 pScreenPriv
->pwinCloseScreen
= winCloseScreenShadowDDNL
;
1429 pScreenPriv
->pwinInitVisuals
= winInitVisualsShadowDDNL
;
1430 pScreenPriv
->pwinAdjustVideoMode
= winAdjustVideoModeShadowDDNL
;
1431 if (pScreenInfo
->fFullScreen
)
1432 pScreenPriv
->pwinCreateBoundingWindow
= winCreateBoundingWindowFullScreen
;
1434 pScreenPriv
->pwinCreateBoundingWindow
= winCreateBoundingWindowWindowed
;
1435 pScreenPriv
->pwinFinishScreenInit
= winFinishScreenInitFB
;
1436 pScreenPriv
->pwinBltExposedRegions
= winBltExposedRegionsShadowDDNL
;
1437 pScreenPriv
->pwinActivateApp
= winActivateAppShadowDDNL
;
1438 pScreenPriv
->pwinRedrawScreen
= winRedrawScreenShadowDDNL
;
1439 pScreenPriv
->pwinRealizeInstalledPalette
1440 = winRealizeInstalledPaletteShadowDDNL
;
1441 pScreenPriv
->pwinInstallColormap
= winInstallColormapShadowDDNL
;
1442 pScreenPriv
->pwinStoreColors
= winStoreColorsShadowDDNL
;
1443 pScreenPriv
->pwinCreateColormap
= winCreateColormapShadowDDNL
;
1444 pScreenPriv
->pwinDestroyColormap
= winDestroyColormapShadowDDNL
;
1445 pScreenPriv
->pwinHotKeyAltTab
= (winHotKeyAltTabProcPtr
) (void (*)(void))NoopDDA
;
1446 pScreenPriv
->pwinCreatePrimarySurface
= winCreatePrimarySurfaceShadowDDNL
;
1447 pScreenPriv
->pwinReleasePrimarySurface
= winReleasePrimarySurfaceShadowDDNL
;
1448 #ifdef XWIN_MULTIWINDOW
1449 pScreenPriv
->pwinFinishCreateWindowsWindow
1450 = winFinishCreateWindowsWindowDDNL
;