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>
39 #define FAIL_MSG_MAX_BLT 10
46 winAllocateFBShadowDDNL(ScreenPtr pScreen
);
49 winShadowUpdateDDNL(ScreenPtr pScreen
, shadowBufPtr pBuf
);
52 winCloseScreenShadowDDNL(ScreenPtr pScreen
);
55 winInitVisualsShadowDDNL(ScreenPtr pScreen
);
58 winAdjustVideoModeShadowDDNL(ScreenPtr pScreen
);
61 winBltExposedRegionsShadowDDNL(ScreenPtr pScreen
);
64 winActivateAppShadowDDNL(ScreenPtr pScreen
);
67 winRedrawScreenShadowDDNL(ScreenPtr pScreen
);
70 winRealizeInstalledPaletteShadowDDNL(ScreenPtr pScreen
);
73 winInstallColormapShadowDDNL(ColormapPtr pColormap
);
76 winStoreColorsShadowDDNL(ColormapPtr pmap
, int ndef
, xColorItem
* pdefs
);
79 winCreateColormapShadowDDNL(ColormapPtr pColormap
);
82 winDestroyColormapShadowDDNL(ColormapPtr pColormap
);
85 winCreatePrimarySurfaceShadowDDNL(ScreenPtr pScreen
);
88 winReleasePrimarySurfaceShadowDDNL(ScreenPtr pScreen
);
91 * Create the primary surface and attach the clipper.
92 * Used for both the initial surface creation and during
93 * WM_DISPLAYCHANGE messages.
97 winCreatePrimarySurfaceShadowDDNL(ScreenPtr pScreen
)
99 winScreenPriv(pScreen
);
100 HRESULT ddrval
= DD_OK
;
103 winDebug("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n");
105 /* Describe the primary surface */
106 ZeroMemory(&ddsd
, sizeof(ddsd
));
107 ddsd
.dwSize
= sizeof(ddsd
);
108 ddsd
.dwFlags
= DDSD_CAPS
;
109 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
111 /* Create the primary surface */
112 ddrval
= IDirectDraw4_CreateSurface(pScreenPriv
->pdd4
,
114 &pScreenPriv
->pddsPrimary4
, NULL
);
115 pScreenPriv
->fRetryCreateSurface
= FALSE
;
116 if (FAILED(ddrval
)) {
117 if (ddrval
== DDERR_NOEXCLUSIVEMODE
) {
118 /* Recreating the surface failed. Mark screen to retry later */
119 pScreenPriv
->fRetryCreateSurface
= TRUE
;
120 winDebug("winCreatePrimarySurfaceShadowDDNL - Could not create "
121 "primary surface: DDERR_NOEXCLUSIVEMODE\n");
124 ErrorF("winCreatePrimarySurfaceShadowDDNL - Could not create "
125 "primary surface: %08x\n", (unsigned int) ddrval
);
131 winDebug("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n");
134 /* Attach our clipper to our primary surface handle */
135 ddrval
= IDirectDrawSurface4_SetClipper(pScreenPriv
->pddsPrimary4
,
136 pScreenPriv
->pddcPrimary
);
137 if (FAILED(ddrval
)) {
138 ErrorF("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper "
139 "failed: %08x\n", (unsigned int) ddrval
);
144 winDebug("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary "
148 /* Everything was correct */
153 * Detach the clipper and release the primary surface.
154 * Called from WM_DISPLAYCHANGE.
158 winReleasePrimarySurfaceShadowDDNL(ScreenPtr pScreen
)
160 winScreenPriv(pScreen
);
162 winDebug("winReleasePrimarySurfaceShadowDDNL - Hello\n");
164 /* Release the primary surface and clipper, if they exist */
165 if (pScreenPriv
->pddsPrimary4
) {
167 * Detach the clipper from the primary surface.
168 * NOTE: We do this explicity for clarity. The Clipper is not released.
170 IDirectDrawSurface4_SetClipper(pScreenPriv
->pddsPrimary4
, NULL
);
172 winDebug("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n");
174 /* Release the primary surface */
175 IDirectDrawSurface4_Release(pScreenPriv
->pddsPrimary4
);
176 pScreenPriv
->pddsPrimary4
= NULL
;
179 winDebug("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n");
185 * Create a DirectDraw surface for the shadow framebuffer; also create
186 * a primary surface object so we can blit to the display.
188 * Install a DirectDraw clipper on our primary surface object
189 * that clips our blits to the unobscured client area of our display window.
193 winAllocateFBShadowDDNL(ScreenPtr pScreen
)
195 winScreenPriv(pScreen
);
196 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
197 HRESULT ddrval
= DD_OK
;
198 DDSURFACEDESC2 ddsdShadow
;
199 char *lpSurface
= NULL
;
200 DDPIXELFORMAT ddpfPrimary
;
203 winDebug("winAllocateFBShadowDDNL - w %d h %d d %d\n",
204 pScreenInfo
->dwWidth
, pScreenInfo
->dwHeight
, pScreenInfo
->dwDepth
);
207 /* Set the padded screen width */
208 pScreenInfo
->dwPaddedWidth
= PixmapBytePad(pScreenInfo
->dwWidth
,
211 /* Allocate memory for our shadow surface */
212 lpSurface
= malloc(pScreenInfo
->dwPaddedWidth
* pScreenInfo
->dwHeight
);
213 if (lpSurface
== NULL
) {
214 ErrorF("winAllocateFBShadowDDNL - Could not allocate bits\n");
219 * Initialize the framebuffer memory so we don't get a
220 * strange display at startup
222 ZeroMemory(lpSurface
, pScreenInfo
->dwPaddedWidth
* pScreenInfo
->dwHeight
);
224 /* Create a clipper */
225 ddrval
= (*g_fpDirectDrawCreateClipper
) (0,
226 &pScreenPriv
->pddcPrimary
, NULL
);
227 if (FAILED(ddrval
)) {
228 ErrorF("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n",
229 (unsigned int) ddrval
);
234 winDebug("winAllocateFBShadowDDNL - Created a clipper\n");
237 /* Attach the clipper to our display window */
238 ddrval
= IDirectDrawClipper_SetHWnd(pScreenPriv
->pddcPrimary
,
239 0, pScreenPriv
->hwndScreen
);
240 if (FAILED(ddrval
)) {
241 ErrorF("winAllocateFBShadowDDNL - Clipper not attached "
242 "to window: %08x\n", (unsigned int) ddrval
);
247 winDebug("winAllocateFBShadowDDNL - Attached clipper to window\n");
250 /* Create a DirectDraw object, store the address at lpdd */
251 ddrval
= (*g_fpDirectDrawCreate
) (NULL
,
252 (LPDIRECTDRAW
*) &pScreenPriv
->pdd
,
254 if (FAILED(ddrval
)) {
255 ErrorF("winAllocateFBShadowDDNL - Could not start "
256 "DirectDraw: %08x\n", (unsigned int) ddrval
);
261 winDebug("winAllocateFBShadowDDNL - Created and initialized DD\n");
264 /* Get a DirectDraw4 interface pointer */
265 ddrval
= IDirectDraw_QueryInterface(pScreenPriv
->pdd
,
267 (LPVOID
*) &pScreenPriv
->pdd4
);
268 if (FAILED(ddrval
)) {
269 ErrorF("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n",
270 (unsigned int) ddrval
);
274 /* Are we full screen? */
275 if (pScreenInfo
->fFullScreen
) {
276 DDSURFACEDESC2 ddsdCurrent
;
277 DWORD dwRefreshRateCurrent
= 0;
280 /* Set the cooperative level to full screen */
281 ddrval
= IDirectDraw4_SetCooperativeLevel(pScreenPriv
->pdd4
,
282 pScreenPriv
->hwndScreen
,
285 if (FAILED(ddrval
)) {
286 ErrorF("winAllocateFBShadowDDNL - Could not set "
287 "cooperative level: %08x\n", (unsigned int) ddrval
);
292 * We only need to get the current refresh rate for comparison
293 * if a refresh rate has been passed on the command line.
295 if (pScreenInfo
->dwRefreshRate
!= 0) {
296 ZeroMemory(&ddsdCurrent
, sizeof(ddsdCurrent
));
297 ddsdCurrent
.dwSize
= sizeof(ddsdCurrent
);
299 /* Get information about current display settings */
300 ddrval
= IDirectDraw4_GetDisplayMode(pScreenPriv
->pdd4
,
302 if (FAILED(ddrval
)) {
303 ErrorF("winAllocateFBShadowDDNL - Could not get current "
304 "refresh rate: %08x. Continuing.\n",
305 (unsigned int) ddrval
);
306 dwRefreshRateCurrent
= 0;
309 /* Grab the current refresh rate */
310 dwRefreshRateCurrent
= ddsdCurrent
.u2
.dwRefreshRate
;
314 /* Clean up the refresh rate */
315 if (dwRefreshRateCurrent
== pScreenInfo
->dwRefreshRate
) {
317 * Refresh rate is non-specified or equal to current.
319 pScreenInfo
->dwRefreshRate
= 0;
322 /* Grab a device context for the screen */
325 ErrorF("winAllocateFBShadowDDNL - GetDC () failed\n");
329 /* Only change the video mode when different than current mode */
330 if (!pScreenInfo
->fMultipleMonitors
331 && (pScreenInfo
->dwWidth
!= GetSystemMetrics(SM_CXSCREEN
)
332 || pScreenInfo
->dwHeight
!= GetSystemMetrics(SM_CYSCREEN
)
333 || pScreenInfo
->dwBPP
!= GetDeviceCaps(hdc
, BITSPIXEL
)
334 || pScreenInfo
->dwRefreshRate
!= 0)) {
335 winDebug("winAllocateFBShadowDDNL - Changing video mode\n");
337 /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
338 ddrval
= IDirectDraw4_SetDisplayMode(pScreenPriv
->pdd4
,
339 pScreenInfo
->dwWidth
,
340 pScreenInfo
->dwHeight
,
342 pScreenInfo
->dwRefreshRate
, 0);
343 if (FAILED(ddrval
)) {
344 ErrorF("winAllocateFBShadowDDNL - Could not set "
345 "full screen display mode: %08x\n",
346 (unsigned int) ddrval
);
348 ("winAllocateFBShadowDDNL - Using default driver refresh rate\n");
350 IDirectDraw4_SetDisplayMode(pScreenPriv
->pdd4
,
351 pScreenInfo
->dwWidth
,
352 pScreenInfo
->dwHeight
,
353 pScreenInfo
->dwBPP
, 0, 0);
354 if (FAILED(ddrval
)) {
356 ("winAllocateFBShadowDDNL - Could not set default refresh rate "
357 "full screen display mode: %08x\n",
358 (unsigned int) ddrval
);
364 winDebug("winAllocateFBShadowDDNL - Not changing video mode\n");
368 ReleaseDC(NULL
, hdc
);
372 /* Set the cooperative level for windowed mode */
373 ddrval
= IDirectDraw4_SetCooperativeLevel(pScreenPriv
->pdd4
,
374 pScreenPriv
->hwndScreen
,
376 if (FAILED(ddrval
)) {
377 ErrorF("winAllocateFBShadowDDNL - Could not set "
378 "cooperative level: %08x\n", (unsigned int) ddrval
);
383 /* Create the primary surface */
384 if (!winCreatePrimarySurfaceShadowDDNL(pScreen
)) {
385 ErrorF("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
390 /* Get primary surface's pixel format */
391 ZeroMemory(&ddpfPrimary
, sizeof(ddpfPrimary
));
392 ddpfPrimary
.dwSize
= sizeof(ddpfPrimary
);
393 ddrval
= IDirectDrawSurface4_GetPixelFormat(pScreenPriv
->pddsPrimary4
,
395 if (FAILED(ddrval
)) {
396 ErrorF("winAllocateFBShadowDDNL - Could not get primary "
397 "pixformat: %08x\n", (unsigned int) ddrval
);
402 winDebug("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
403 "dwRGBBitCount: %d\n",
404 ddpfPrimary
.u2
.dwRBitMask
,
405 ddpfPrimary
.u3
.dwGBitMask
,
406 ddpfPrimary
.u4
.dwBBitMask
, ddpfPrimary
.u1
.dwRGBBitCount
);
409 /* Describe the shadow surface to be created */
411 * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
412 * as drawing, locking, and unlocking take forever
413 * with video memory surfaces. In addition,
414 * video memory is a somewhat scarce resource,
415 * so you shouldn't be allocating video memory when
416 * you have the option of using system memory instead.
418 ZeroMemory(&ddsdShadow
, sizeof(ddsdShadow
));
419 ddsdShadow
.dwSize
= sizeof(ddsdShadow
);
420 ddsdShadow
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
421 | DDSD_LPSURFACE
| DDSD_PITCH
| DDSD_PIXELFORMAT
;
422 ddsdShadow
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_SYSTEMMEMORY
;
423 ddsdShadow
.dwHeight
= pScreenInfo
->dwHeight
;
424 ddsdShadow
.dwWidth
= pScreenInfo
->dwWidth
;
425 ddsdShadow
.u1
.lPitch
= pScreenInfo
->dwPaddedWidth
;
426 ddsdShadow
.lpSurface
= lpSurface
;
427 ddsdShadow
.u4
.ddpfPixelFormat
= ddpfPrimary
;
429 winDebug("winAllocateFBShadowDDNL - lPitch: %d\n",
430 (int) pScreenInfo
->dwPaddedWidth
);
432 /* Create the shadow surface */
433 ddrval
= IDirectDraw4_CreateSurface(pScreenPriv
->pdd4
,
435 &pScreenPriv
->pddsShadow4
, NULL
);
436 if (FAILED(ddrval
)) {
437 ErrorF("winAllocateFBShadowDDNL - Could not create shadow "
438 "surface: %08x\n", (unsigned int) ddrval
);
443 winDebug("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
444 (int) ddsdShadow
.u1
.lPitch
);
447 /* Grab the pitch from the surface desc */
448 pScreenInfo
->dwStride
= (ddsdShadow
.u1
.lPitch
* 8)
449 / pScreenInfo
->dwBPP
;
452 winDebug("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
453 (int) pScreenInfo
->dwStride
);
456 /* Save the pointer to our surface memory */
457 pScreenInfo
->pfb
= lpSurface
;
459 /* Grab the masks from the surface description */
460 pScreenPriv
->dwRedMask
= ddsdShadow
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
;
461 pScreenPriv
->dwGreenMask
= ddsdShadow
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
;
462 pScreenPriv
->dwBlueMask
= ddsdShadow
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
;
465 winDebug("winAllocateFBShadowDDNL - Returning\n");
472 winFreeFBShadowDDNL(ScreenPtr pScreen
)
474 winScreenPriv(pScreen
);
475 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
477 /* Free the shadow surface, if there is one */
478 if (pScreenPriv
->pddsShadow4
) {
479 IDirectDrawSurface4_Release(pScreenPriv
->pddsShadow4
);
480 free(pScreenInfo
->pfb
);
481 pScreenInfo
->pfb
= NULL
;
482 pScreenPriv
->pddsShadow4
= NULL
;
485 /* Detach the clipper from the primary surface and release the primary surface, if there is one */
486 winReleasePrimarySurfaceShadowDDNL(pScreen
);
488 /* Release the clipper object */
489 if (pScreenPriv
->pddcPrimary
) {
490 IDirectDrawClipper_Release(pScreenPriv
->pddcPrimary
);
491 pScreenPriv
->pddcPrimary
= NULL
;
494 /* Free the DirectDraw4 object, if there is one */
495 if (pScreenPriv
->pdd4
) {
496 IDirectDraw4_RestoreDisplayMode(pScreenPriv
->pdd4
);
497 IDirectDraw4_Release(pScreenPriv
->pdd4
);
498 pScreenPriv
->pdd4
= NULL
;
501 /* Free the DirectDraw object, if there is one */
502 if (pScreenPriv
->pdd
) {
503 IDirectDraw_Release(pScreenPriv
->pdd
);
504 pScreenPriv
->pdd
= NULL
;
507 /* Invalidate the ScreenInfo's fb pointer */
508 pScreenInfo
->pfb
= NULL
;
512 * Transfer the damaged regions of the shadow framebuffer to the display.
516 winShadowUpdateDDNL(ScreenPtr pScreen
, shadowBufPtr pBuf
)
518 winScreenPriv(pScreen
);
519 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
520 RegionPtr damage
= shadowDamage(pBuf
);
521 HRESULT ddrval
= DD_OK
;
524 DWORD dwBox
= RegionNumRects(damage
);
525 BoxPtr pBox
= RegionRects(damage
);
526 HRGN hrgnCombined
= NULL
;
529 * Return immediately if the app is not active
530 * and we are fullscreen, or if we have a bad display depth
532 if ((!pScreenPriv
->fActive
&& pScreenInfo
->fFullScreen
)
533 || pScreenPriv
->fBadDepth
)
536 /* Return immediately if we didn't get needed surfaces */
537 if (!pScreenPriv
->pddsPrimary4
|| !pScreenPriv
->pddsShadow4
)
540 /* Get the origin of the window in the screen coords */
541 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
542 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
543 MapWindowPoints(pScreenPriv
->hwndScreen
,
544 HWND_DESKTOP
, (LPPOINT
) &ptOrigin
, 1);
547 * Handle small regions with multiple blits,
548 * handle large regions by creating a clipping region and
549 * doing a single blit constrained to that clipping region.
551 if (pScreenInfo
->dwClipUpdatesNBoxes
== 0
552 || dwBox
< pScreenInfo
->dwClipUpdatesNBoxes
) {
553 /* Loop through all boxes in the damaged region */
555 /* Assign damage box to source rectangle */
556 rcSrc
.left
= pBox
->x1
;
557 rcSrc
.top
= pBox
->y1
;
558 rcSrc
.right
= pBox
->x2
;
559 rcSrc
.bottom
= pBox
->y2
;
561 /* Calculate destination rectangle */
562 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
563 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
564 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
565 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
567 /* Blit the damaged areas */
568 ddrval
= IDirectDrawSurface4_Blt(pScreenPriv
->pddsPrimary4
,
570 pScreenPriv
->pddsShadow4
,
571 &rcSrc
, DDBLT_WAIT
, NULL
);
572 if (FAILED(ddrval
)) {
573 static int s_iFailCount
= 0;
575 if (s_iFailCount
< FAIL_MSG_MAX_BLT
) {
576 ErrorF("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
577 "failed: %08x\n", (unsigned int) ddrval
);
581 if (s_iFailCount
== FAIL_MSG_MAX_BLT
) {
582 ErrorF("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
583 "failure message maximum (%d) reached. No "
584 "more failure messages will be printed.\n",
590 /* Get a pointer to the next box */
595 BoxPtr pBoxExtents
= RegionExtents(damage
);
597 /* Compute a GDI region from the damaged region */
599 CreateRectRgn(pBoxExtents
->x1
, pBoxExtents
->y1
, pBoxExtents
->x2
,
602 /* Install the GDI region as a clipping region */
603 SelectClipRgn(pScreenPriv
->hdcScreen
, hrgnCombined
);
604 DeleteObject(hrgnCombined
);
608 winDebug("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
609 pBoxExtents
->x1
, pBoxExtents
->y1
,
610 pBoxExtents
->x2
, pBoxExtents
->y2
);
613 /* Calculating a bounding box for the source is easy */
614 rcSrc
.left
= pBoxExtents
->x1
;
615 rcSrc
.top
= pBoxExtents
->y1
;
616 rcSrc
.right
= pBoxExtents
->x2
;
617 rcSrc
.bottom
= pBoxExtents
->y2
;
619 /* Calculating a bounding box for the destination is trickier */
620 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
621 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
622 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
623 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
625 /* Our Blt should be clipped to the invalidated region */
626 ddrval
= IDirectDrawSurface4_Blt(pScreenPriv
->pddsPrimary4
,
628 pScreenPriv
->pddsShadow4
,
629 &rcSrc
, DDBLT_WAIT
, NULL
);
631 /* Reset the clip region */
632 SelectClipRgn(pScreenPriv
->hdcScreen
, NULL
);
637 winInitScreenShadowDDNL(ScreenPtr pScreen
)
639 winScreenPriv(pScreen
);
641 /* Get a device context for the screen */
642 pScreenPriv
->hdcScreen
= GetDC(pScreenPriv
->hwndScreen
);
644 return winAllocateFBShadowDDNL(pScreen
);
648 * Call the wrapped CloseScreen function.
650 * Free our resources and private structures.
654 winCloseScreenShadowDDNL(ScreenPtr pScreen
)
656 winScreenPriv(pScreen
);
657 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
661 winDebug("winCloseScreenShadowDDNL - Freeing screen resources\n");
664 /* Flag that the screen is closed */
665 pScreenPriv
->fClosed
= TRUE
;
666 pScreenPriv
->fActive
= FALSE
;
668 /* Call the wrapped CloseScreen procedure */
669 WIN_UNWRAP(CloseScreen
);
670 if (pScreen
->CloseScreen
)
671 fReturn
= (*pScreen
->CloseScreen
) (pScreen
);
673 winFreeFBShadowDDNL(pScreen
);
675 /* Free the screen DC */
676 ReleaseDC(pScreenPriv
->hwndScreen
, pScreenPriv
->hdcScreen
);
678 /* Delete the window property */
679 RemoveProp(pScreenPriv
->hwndScreen
, WIN_SCR_PROP
);
681 /* Delete tray icon, if we have one */
682 if (!pScreenInfo
->fNoTrayIcon
)
683 winDeleteNotifyIcon(pScreenPriv
);
685 /* Free the exit confirmation dialog box, if it exists */
686 if (g_hDlgExit
!= NULL
) {
687 DestroyWindow(g_hDlgExit
);
691 /* Kill our window */
692 if (pScreenPriv
->hwndScreen
) {
693 DestroyWindow(pScreenPriv
->hwndScreen
);
694 pScreenPriv
->hwndScreen
= NULL
;
697 #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
698 /* Destroy the thread startup mutex */
699 pthread_mutex_destroy(&pScreenPriv
->pmServerStarted
);
702 /* Kill our screeninfo's pointer to the screen */
703 pScreenInfo
->pScreen
= NULL
;
705 /* Free the screen privates for this screen */
706 free((pointer
) pScreenPriv
);
712 * Tell mi what sort of visuals we need.
714 * Generally we only need one visual, as our screen can only
715 * handle one format at a time, I believe. You may want
716 * to verify that last sentence.
720 winInitVisualsShadowDDNL(ScreenPtr pScreen
)
722 winScreenPriv(pScreen
);
723 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
724 DWORD dwRedBits
, dwGreenBits
, dwBlueBits
;
726 /* Count the number of ones in each color mask */
727 dwRedBits
= winCountBits(pScreenPriv
->dwRedMask
);
728 dwGreenBits
= winCountBits(pScreenPriv
->dwGreenMask
);
729 dwBlueBits
= winCountBits(pScreenPriv
->dwBlueMask
);
731 /* Store the maximum number of ones in a color mask as the bitsPerRGB */
732 if (dwRedBits
== 0 || dwGreenBits
== 0 || dwBlueBits
== 0)
733 pScreenPriv
->dwBitsPerRGB
= 8;
734 else if (dwRedBits
> dwGreenBits
&& dwRedBits
> dwBlueBits
)
735 pScreenPriv
->dwBitsPerRGB
= dwRedBits
;
736 else if (dwGreenBits
> dwRedBits
&& dwGreenBits
> dwBlueBits
)
737 pScreenPriv
->dwBitsPerRGB
= dwGreenBits
;
739 pScreenPriv
->dwBitsPerRGB
= dwBlueBits
;
741 winDebug("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
743 (unsigned int) pScreenPriv
->dwRedMask
,
744 (unsigned int) pScreenPriv
->dwGreenMask
,
745 (unsigned int) pScreenPriv
->dwBlueMask
,
746 (int) pScreenPriv
->dwBitsPerRGB
,
747 (int) pScreenInfo
->dwDepth
, (int) pScreenInfo
->dwBPP
);
749 /* Create a single visual according to the Windows screen depth */
750 switch (pScreenInfo
->dwDepth
) {
754 /* Setup the real visual */
755 if (!miSetVisualTypesAndMasks(pScreenInfo
->dwDepth
,
757 pScreenPriv
->dwBitsPerRGB
,
759 pScreenPriv
->dwRedMask
,
760 pScreenPriv
->dwGreenMask
,
761 pScreenPriv
->dwBlueMask
)) {
762 ErrorF("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
763 "failed for TrueColor\n");
767 #ifdef XWIN_EMULATEPSEUDO
768 if (!pScreenInfo
->fEmulatePseudo
)
771 /* Setup a pseudocolor visual */
772 if (!miSetVisualTypesAndMasks(8, PseudoColorMask
, 8, -1, 0, 0, 0)) {
773 ErrorF("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
774 "failed for PseudoColor\n");
781 if (!miSetVisualTypesAndMasks(pScreenInfo
->dwDepth
,
782 pScreenInfo
->fFullScreen
783 ? PseudoColorMask
: StaticColorMask
,
784 pScreenPriv
->dwBitsPerRGB
,
785 pScreenInfo
->fFullScreen
786 ? PseudoColor
: StaticColor
,
787 pScreenPriv
->dwRedMask
,
788 pScreenPriv
->dwGreenMask
,
789 pScreenPriv
->dwBlueMask
)) {
790 ErrorF("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
797 ErrorF("winInitVisualsShadowDDNL - Unknown screen depth\n");
802 winDebug("winInitVisualsShadowDDNL - Returning\n");
809 * Adjust the user proposed video mode
813 winAdjustVideoModeShadowDDNL(ScreenPtr pScreen
)
815 winScreenPriv(pScreen
);
816 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
820 /* We're in serious trouble if we can't get a DC */
823 ErrorF("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
827 /* Query GDI for current display depth */
828 dwBPP
= GetDeviceCaps(hdc
, BITSPIXEL
);
830 /* DirectDraw can only change the depth in fullscreen mode */
831 if (!(pScreenInfo
->fFullScreen
&& (pScreenInfo
->dwBPP
!= WIN_DEFAULT_BPP
))) {
832 /* Otherwise, We'll use GDI's depth */
833 pScreenInfo
->dwBPP
= dwBPP
;
837 ReleaseDC(NULL
, hdc
);
843 * Blt exposed regions to the screen
847 winBltExposedRegionsShadowDDNL(ScreenPtr pScreen
)
849 winScreenPriv(pScreen
);
850 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
855 HRESULT ddrval
= DD_OK
;
859 /* Quite common case. The primary surface was lost (maybe because of depth
860 * change). Try to create a new primary surface. Bail out if this fails */
861 if (pScreenPriv
->pddsPrimary4
== NULL
&& pScreenPriv
->fRetryCreateSurface
&&
862 !winCreatePrimarySurfaceShadowDDNL(pScreen
)) {
866 if (pScreenPriv
->pddsPrimary4
== NULL
)
869 /* BeginPaint gives us an hdc that clips to the invalidated region */
870 hdcUpdate
= BeginPaint(pScreenPriv
->hwndScreen
, &ps
);
871 if (hdcUpdate
== NULL
) {
873 ErrorF("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
874 "a NULL device context handle. Aborting blit attempt.\n");
875 goto winBltExposedRegionsShadowDDNL_Exit
;
878 /* Get the origin of the window in the screen coords */
879 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
880 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
882 MapWindowPoints(pScreenPriv
->hwndScreen
,
883 HWND_DESKTOP
, (LPPOINT
) &ptOrigin
, 1);
884 rcDest
.left
= ptOrigin
.x
;
885 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
886 rcDest
.top
= ptOrigin
.y
;
887 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
889 /* Source can be entire shadow surface, as Blt should clip for us */
892 rcSrc
.right
= pScreenInfo
->dwWidth
;
893 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
895 /* Try to regain the primary surface and blit again if we've lost it */
896 for (i
= 0; i
<= WIN_REGAIN_SURFACE_RETRIES
; ++i
) {
897 /* Our Blt should be clipped to the invalidated region */
898 ddrval
= IDirectDrawSurface4_Blt(pScreenPriv
->pddsPrimary4
,
900 pScreenPriv
->pddsShadow4
,
901 &rcSrc
, DDBLT_WAIT
, NULL
);
902 if (ddrval
== DDERR_SURFACELOST
) {
903 /* Surface was lost */
904 winErrorFVerb(1, "winBltExposedRegionsShadowDDNL - "
905 "IDirectDrawSurface4_Blt reported that the primary "
906 "surface was lost, trying to restore, retry: %d\n",
909 /* Try to restore the surface, once */
911 ddrval
= IDirectDrawSurface4_Restore(pScreenPriv
->pddsPrimary4
);
912 winDebug("winBltExposedRegionsShadowDDNL - "
913 "IDirectDrawSurface4_Restore returned: ");
916 else if (ddrval
== DDERR_WRONGMODE
)
917 winDebug("DDERR_WRONGMODE\n");
918 else if (ddrval
== DDERR_INCOMPATIBLEPRIMARY
)
919 winDebug("DDERR_INCOMPATIBLEPRIMARY\n");
920 else if (ddrval
== DDERR_UNSUPPORTED
)
921 winDebug("DDERR_UNSUPPORTED\n");
922 else if (ddrval
== DDERR_INVALIDPARAMS
)
923 winDebug("DDERR_INVALIDPARAMS\n");
924 else if (ddrval
== DDERR_INVALIDOBJECT
)
925 winDebug("DDERR_INVALIDOBJECT\n");
927 winDebug("unknown error: %08x\n", (unsigned int) ddrval
);
929 /* Loop around to try the blit one more time */
932 else if (FAILED(ddrval
)) {
934 winErrorFVerb(1, "winBltExposedRegionsShadowDDNL - "
935 "IDirectDrawSurface4_Blt failed, but surface not "
937 (unsigned int) ddrval
, (int) ddrval
);
938 goto winBltExposedRegionsShadowDDNL_Exit
;
941 /* Success, stop looping */
946 winBltExposedRegionsShadowDDNL_Exit
:
947 /* EndPaint frees the DC */
948 if (hdcUpdate
!= NULL
)
949 EndPaint(pScreenPriv
->hwndScreen
, &ps
);
954 * Do any engine-specific application-activation processing
958 winActivateAppShadowDDNL(ScreenPtr pScreen
)
960 winScreenPriv(pScreen
);
963 * Do we have a surface?
965 * Are we full screen?
967 if (pScreenPriv
!= NULL
968 && pScreenPriv
->pddsPrimary4
!= NULL
&& pScreenPriv
->fActive
) {
969 /* Primary surface was lost, restore it */
970 IDirectDrawSurface4_Restore(pScreenPriv
->pddsPrimary4
);
977 * Reblit the shadow framebuffer to the screen.
981 winRedrawScreenShadowDDNL(ScreenPtr pScreen
)
983 winScreenPriv(pScreen
);
984 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
985 HRESULT ddrval
= DD_OK
;
989 /* Get the origin of the window in the screen coords */
990 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
991 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
992 MapWindowPoints(pScreenPriv
->hwndScreen
,
993 HWND_DESKTOP
, (LPPOINT
) &ptOrigin
, 1);
994 rcDest
.left
= ptOrigin
.x
;
995 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
996 rcDest
.top
= ptOrigin
.y
;
997 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
999 /* Source can be entire shadow surface, as Blt should clip for us */
1002 rcSrc
.right
= pScreenInfo
->dwWidth
;
1003 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
1005 /* Redraw the whole window, to take account for the new colors */
1006 ddrval
= IDirectDrawSurface4_Blt(pScreenPriv
->pddsPrimary4
,
1008 pScreenPriv
->pddsShadow4
,
1009 &rcSrc
, DDBLT_WAIT
, NULL
);
1010 if (FAILED(ddrval
)) {
1011 ErrorF("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
1012 "failed: %08x\n", (unsigned int) ddrval
);
1019 * Realize the currently installed colormap
1023 winRealizeInstalledPaletteShadowDDNL(ScreenPtr pScreen
)
1029 * Install the specified colormap
1033 winInstallColormapShadowDDNL(ColormapPtr pColormap
)
1035 ScreenPtr pScreen
= pColormap
->pScreen
;
1037 winScreenPriv(pScreen
);
1038 winCmapPriv(pColormap
);
1039 HRESULT ddrval
= DD_OK
;
1041 /* Install the DirectDraw palette on the primary surface */
1042 ddrval
= IDirectDrawSurface4_SetPalette(pScreenPriv
->pddsPrimary4
,
1043 pCmapPriv
->lpDDPalette
);
1044 if (FAILED(ddrval
)) {
1045 ErrorF("winInstallColormapShadowDDNL - Failed installing the "
1046 "DirectDraw palette.\n");
1050 /* Save a pointer to the newly installed colormap */
1051 pScreenPriv
->pcmapInstalled
= pColormap
;
1057 * Store the specified colors in the specified colormap
1061 winStoreColorsShadowDDNL(ColormapPtr pColormap
, int ndef
, xColorItem
* pdefs
)
1063 ScreenPtr pScreen
= pColormap
->pScreen
;
1065 winScreenPriv(pScreen
);
1066 winCmapPriv(pColormap
);
1067 ColormapPtr curpmap
= pScreenPriv
->pcmapInstalled
;
1068 HRESULT ddrval
= DD_OK
;
1070 /* Put the X colormap entries into the Windows logical palette */
1071 ddrval
= IDirectDrawPalette_SetEntries(pCmapPriv
->lpDDPalette
,
1077 if (FAILED(ddrval
)) {
1078 ErrorF("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n",
1079 (unsigned int) ddrval
);
1083 /* Don't install the DirectDraw palette if the colormap is not installed */
1084 if (pColormap
!= curpmap
) {
1088 if (!winInstallColormapShadowDDNL(pColormap
)) {
1089 ErrorF("winStoreColorsShadowDDNL - Failed installing colormap\n");
1097 * Colormap initialization procedure
1101 winCreateColormapShadowDDNL(ColormapPtr pColormap
)
1103 HRESULT ddrval
= DD_OK
;
1104 ScreenPtr pScreen
= pColormap
->pScreen
;
1106 winScreenPriv(pScreen
);
1107 winCmapPriv(pColormap
);
1109 /* Create a DirectDraw palette */
1110 ddrval
= IDirectDraw4_CreatePalette(pScreenPriv
->pdd4
,
1111 DDPCAPS_8BIT
| DDPCAPS_ALLOW256
,
1112 pCmapPriv
->peColors
,
1113 &pCmapPriv
->lpDDPalette
, NULL
);
1114 if (FAILED(ddrval
)) {
1115 ErrorF("winCreateColormapShadowDDNL - CreatePalette failed\n");
1123 * Colormap destruction procedure
1127 winDestroyColormapShadowDDNL(ColormapPtr pColormap
)
1129 winScreenPriv(pColormap
->pScreen
);
1130 winCmapPriv(pColormap
);
1131 HRESULT ddrval
= DD_OK
;
1134 * Is colormap to be destroyed the default?
1136 * Non-default colormaps should have had winUninstallColormap
1137 * called on them before we get here. The default colormap
1138 * will not have had winUninstallColormap called on it. Thus,
1139 * we need to handle the default colormap in a special way.
1141 if (pColormap
->flags
& IsDefault
) {
1144 ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
1148 * FIXME: Walk the list of all screens, popping the default
1149 * palette out of each screen device context.
1152 /* Pop the palette out of the primary surface */
1153 ddrval
= IDirectDrawSurface4_SetPalette(pScreenPriv
->pddsPrimary4
,
1155 if (FAILED(ddrval
)) {
1156 ErrorF("winDestroyColormapShadowDDNL - Failed freeing the "
1157 "default colormap DirectDraw palette.\n");
1161 /* Clear our private installed colormap pointer */
1162 pScreenPriv
->pcmapInstalled
= NULL
;
1165 /* Release the palette */
1166 IDirectDrawPalette_Release(pCmapPriv
->lpDDPalette
);
1168 /* Invalidate the colormap privates */
1169 pCmapPriv
->lpDDPalette
= NULL
;
1175 * Set pointers to our engine specific functions
1179 winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen
)
1181 winScreenPriv(pScreen
);
1182 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1184 /* Set our pointers */
1185 pScreenPriv
->pwinAllocateFB
= winAllocateFBShadowDDNL
;
1186 pScreenPriv
->pwinFreeFB
= winFreeFBShadowDDNL
;
1187 pScreenPriv
->pwinShadowUpdate
= winShadowUpdateDDNL
;
1188 pScreenPriv
->pwinInitScreen
= winInitScreenShadowDDNL
;
1189 pScreenPriv
->pwinCloseScreen
= winCloseScreenShadowDDNL
;
1190 pScreenPriv
->pwinInitVisuals
= winInitVisualsShadowDDNL
;
1191 pScreenPriv
->pwinAdjustVideoMode
= winAdjustVideoModeShadowDDNL
;
1192 if (pScreenInfo
->fFullScreen
)
1193 pScreenPriv
->pwinCreateBoundingWindow
=
1194 winCreateBoundingWindowFullScreen
;
1196 pScreenPriv
->pwinCreateBoundingWindow
= winCreateBoundingWindowWindowed
;
1197 pScreenPriv
->pwinFinishScreenInit
= winFinishScreenInitFB
;
1198 pScreenPriv
->pwinBltExposedRegions
= winBltExposedRegionsShadowDDNL
;
1199 pScreenPriv
->pwinActivateApp
= winActivateAppShadowDDNL
;
1200 pScreenPriv
->pwinRedrawScreen
= winRedrawScreenShadowDDNL
;
1201 pScreenPriv
->pwinRealizeInstalledPalette
1202 = winRealizeInstalledPaletteShadowDDNL
;
1203 pScreenPriv
->pwinInstallColormap
= winInstallColormapShadowDDNL
;
1204 pScreenPriv
->pwinStoreColors
= winStoreColorsShadowDDNL
;
1205 pScreenPriv
->pwinCreateColormap
= winCreateColormapShadowDDNL
;
1206 pScreenPriv
->pwinDestroyColormap
= winDestroyColormapShadowDDNL
;
1207 pScreenPriv
->pwinHotKeyAltTab
=
1208 (winHotKeyAltTabProcPtr
) (void (*)(void)) NoopDDA
;
1209 pScreenPriv
->pwinCreatePrimarySurface
= winCreatePrimarySurfaceShadowDDNL
;
1210 pScreenPriv
->pwinReleasePrimarySurface
= winReleasePrimarySurfaceShadowDDNL
;
1211 #ifdef XWIN_MULTIWINDOW
1212 pScreenPriv
->pwinFinishCreateWindowsWindow
1213 = (winFinishCreateWindowsWindowProcPtr
) (void (*)(void)) NoopDDA
;