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 */
58 * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined
59 * here manually. Should be handled by ddraw.h
61 #ifndef IID_IDirectDraw2
62 DEFINE_GUID( IID_IDirectDraw2
,0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
63 #endif /* IID_IDirectDraw2 */
71 winAllocateFBShadowDD (ScreenPtr pScreen
);
74 winShadowUpdateDD (ScreenPtr pScreen
,
78 winCloseScreenShadowDD (int nIndex
, ScreenPtr pScreen
);
81 winInitVisualsShadowDD (ScreenPtr pScreen
);
84 winAdjustVideoModeShadowDD (ScreenPtr pScreen
);
87 winBltExposedRegionsShadowDD (ScreenPtr pScreen
);
90 winActivateAppShadowDD (ScreenPtr pScreen
);
93 winRedrawScreenShadowDD (ScreenPtr pScreen
);
96 winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen
);
99 winInstallColormapShadowDD (ColormapPtr pColormap
);
102 winStoreColorsShadowDD (ColormapPtr pmap
,
107 winCreateColormapShadowDD (ColormapPtr pColormap
);
110 winDestroyColormapShadowDD (ColormapPtr pColormap
);
113 winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen
);
116 winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen
);
120 * Create the primary surface and attach the clipper.
121 * Used for both the initial surface creation and during
122 * WM_DISPLAYCHANGE messages.
126 winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen
)
128 winScreenPriv(pScreen
);
129 HRESULT ddrval
= DD_OK
;
132 /* Describe the primary surface */
133 ZeroMemory (&ddsd
, sizeof (ddsd
));
134 ddsd
.dwSize
= sizeof (ddsd
);
135 ddsd
.dwFlags
= DDSD_CAPS
;
136 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
138 /* Create the primary surface */
139 ddrval
= IDirectDraw2_CreateSurface (pScreenPriv
->pdd2
,
141 &pScreenPriv
->pddsPrimary
,
145 ErrorF ("winCreatePrimarySurfaceShadowDD - Could not create primary "
146 "surface: %08x\n", (unsigned int) ddrval
);
151 winDebug ("winCreatePrimarySurfaceShadowDD - Created primary surface\n");
155 * Attach a clipper to the primary surface that will clip our blits to our
158 ddrval
= IDirectDrawSurface2_SetClipper (pScreenPriv
->pddsPrimary
,
159 pScreenPriv
->pddcPrimary
);
162 ErrorF ("winCreatePrimarySurfaceShadowDD - Primary attach clipper "
164 (unsigned int) ddrval
);
169 winDebug ("winCreatePrimarySurfaceShadowDD - Attached clipper to "
170 "primary surface\n");
173 /* Everything was correct */
179 * Detach the clipper and release the primary surface.
180 * Called from WM_DISPLAYCHANGE.
184 winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen
)
186 winScreenPriv(pScreen
);
188 ErrorF ("winReleasePrimarySurfaceShadowDD - Hello\n");
190 /* Release the primary surface and clipper, if they exist */
191 if (pScreenPriv
->pddsPrimary
)
194 * Detach the clipper from the primary surface.
195 * NOTE: We do this explicity for clarity. The Clipper is not released.
197 IDirectDrawSurface2_SetClipper (pScreenPriv
->pddsPrimary
,
200 ErrorF ("winReleasePrimarySurfaceShadowDD - Detached clipper\n");
202 /* Release the primary surface */
203 IDirectDrawSurface2_Release (pScreenPriv
->pddsPrimary
);
204 pScreenPriv
->pddsPrimary
= NULL
;
207 ErrorF ("winReleasePrimarySurfaceShadowDD - Released primary surface\n");
214 * Create a DirectDraw surface for the shadow framebuffer; also create
215 * a primary surface object so we can blit to the display.
217 * Install a DirectDraw clipper on our primary surface object
218 * that clips our blits to the unobscured client area of our display window.
222 winAllocateFBShadowDD (ScreenPtr pScreen
)
224 winScreenPriv(pScreen
);
225 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
226 HRESULT ddrval
= DD_OK
;
228 DDSURFACEDESC
*pddsdShadow
= NULL
;
231 winDebug ("winAllocateFBShadowDD\n");
234 /* Create a clipper */
235 ddrval
= (*g_fpDirectDrawCreateClipper
) (0,
236 &pScreenPriv
->pddcPrimary
,
240 ErrorF ("winAllocateFBShadowDD - Could not create clipper: %08x\n",
241 (unsigned int) ddrval
);
246 winDebug ("winAllocateFBShadowDD - Created a clipper\n");
249 /* Get a device context for the screen */
250 pScreenPriv
->hdcScreen
= GetDC (pScreenPriv
->hwndScreen
);
252 /* Attach the clipper to our display window */
253 ddrval
= IDirectDrawClipper_SetHWnd (pScreenPriv
->pddcPrimary
,
255 pScreenPriv
->hwndScreen
);
258 ErrorF ("winAllocateFBShadowDD - Clipper not attached to "
260 (unsigned int) ddrval
);
265 winDebug ("winAllocateFBShadowDD - Attached clipper to window\n");
268 /* Create a DirectDraw object, store the address at lpdd */
269 ddrval
= (*g_fpDirectDrawCreate
) (NULL
, &pScreenPriv
->pdd
, NULL
);
272 ErrorF ("winAllocateFBShadowDD - Could not start DirectDraw: %08x\n",
273 (unsigned int) ddrval
);
278 winDebug ("winAllocateFBShadowDD () - Created and initialized DD\n");
281 /* Get a DirectDraw2 interface pointer */
282 ddrval
= IDirectDraw_QueryInterface (pScreenPriv
->pdd
,
284 (LPVOID
*) &pScreenPriv
->pdd2
);
287 ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
288 (unsigned int) ddrval
);
292 /* Are we full screen? */
293 if (pScreenInfo
->fFullScreen
)
295 DDSURFACEDESC ddsdCurrent
;
296 DWORD dwRefreshRateCurrent
= 0;
299 /* Set the cooperative level to full screen */
300 ddrval
= IDirectDraw2_SetCooperativeLevel (pScreenPriv
->pdd2
,
301 pScreenPriv
->hwndScreen
,
306 ErrorF ("winAllocateFBShadowDD - Could not set "
307 "cooperative level: %08x\n",
308 (unsigned int) ddrval
);
313 * We only need to get the current refresh rate for comparison
314 * if a refresh rate has been passed on the command line.
316 if (pScreenInfo
->dwRefreshRate
!= 0)
318 ZeroMemory (&ddsdCurrent
, sizeof (ddsdCurrent
));
319 ddsdCurrent
.dwSize
= sizeof (ddsdCurrent
);
321 /* Get information about current display settings */
322 ddrval
= IDirectDraw2_GetDisplayMode (pScreenPriv
->pdd2
,
326 ErrorF ("winAllocateFBShadowDD - Could not get current "
327 "refresh rate: %08x. Continuing.\n",
328 (unsigned int) ddrval
);
329 dwRefreshRateCurrent
= 0;
333 /* Grab the current refresh rate */
334 dwRefreshRateCurrent
= ddsdCurrent
.u2
.dwRefreshRate
;
338 /* Clean up the refresh rate */
339 if (dwRefreshRateCurrent
== pScreenInfo
->dwRefreshRate
)
342 * Refresh rate is non-specified or equal to current.
344 pScreenInfo
->dwRefreshRate
= 0;
347 /* Grab a device context for the screen */
351 ErrorF ("winAllocateFBShadowDD - GetDC () failed\n");
355 /* Only change the video mode when different than current mode */
356 if (!pScreenInfo
->fMultipleMonitors
357 && (pScreenInfo
->dwWidth
!= GetSystemMetrics (SM_CXSCREEN
)
358 || pScreenInfo
->dwHeight
!= GetSystemMetrics (SM_CYSCREEN
)
359 || pScreenInfo
->dwBPP
!= GetDeviceCaps (hdc
, BITSPIXEL
)
360 || pScreenInfo
->dwRefreshRate
!= 0))
362 ErrorF ("winAllocateFBShadowDD - Changing video mode\n");
364 /* Change the video mode to the mode requested */
365 ddrval
= IDirectDraw2_SetDisplayMode (pScreenPriv
->pdd2
,
366 pScreenInfo
->dwWidth
,
367 pScreenInfo
->dwHeight
,
369 pScreenInfo
->dwRefreshRate
,
373 ErrorF ("winAllocateFBShadowDD - Could not set "\
374 "full screen display mode: %08x\n",
375 (unsigned int) ddrval
);
381 ErrorF ("winAllocateFBShadowDD - Not changing video mode\n");
385 ReleaseDC (NULL
, hdc
);
390 /* Set the cooperative level for windowed mode */
391 ddrval
= IDirectDraw2_SetCooperativeLevel (pScreenPriv
->pdd2
,
392 pScreenPriv
->hwndScreen
,
396 ErrorF ("winAllocateFBShadowDD - Could not set "\
397 "cooperative level: %08x\n",
398 (unsigned int) ddrval
);
403 /* Create the primary surface */
404 if (!winCreatePrimarySurfaceShadowDD (pScreen
))
406 ErrorF ("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD "
411 /* Describe the shadow surface to be created */
412 /* NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
413 * as drawing, locking, and unlocking take forever
414 * with video memory surfaces. In addition,
415 * video memory is a somewhat scarce resource,
416 * so you shouldn't be allocating video memory when
417 * you have the option of using system memory instead.
419 ZeroMemory (&ddsd
, sizeof (ddsd
));
420 ddsd
.dwSize
= sizeof (ddsd
);
421 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
;
422 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_SYSTEMMEMORY
;
423 ddsd
.dwHeight
= pScreenInfo
->dwHeight
;
424 ddsd
.dwWidth
= pScreenInfo
->dwWidth
;
426 /* Create the shadow surface */
427 ddrval
= IDirectDraw2_CreateSurface (pScreenPriv
->pdd2
,
429 &pScreenPriv
->pddsShadow
,
433 ErrorF ("winAllocateFBShadowDD - Could not create shadow "\
434 "surface: %08x\n", (unsigned int) ddrval
);
439 winDebug ("winAllocateFBShadowDD - Created shadow\n");
442 /* Allocate a DD surface description for our screen privates */
443 pddsdShadow
= pScreenPriv
->pddsdShadow
= malloc (sizeof (DDSURFACEDESC
));
444 if (pddsdShadow
== NULL
)
446 ErrorF ("winAllocateFBShadowDD - Could not allocate surface "\
447 "description memory\n");
450 ZeroMemory (pddsdShadow
, sizeof (*pddsdShadow
));
451 pddsdShadow
->dwSize
= sizeof (*pddsdShadow
);
454 winDebug ("winAllocateFBShadowDD - Locking shadow\n");
457 /* Lock the shadow surface */
458 ddrval
= IDirectDrawSurface2_Lock (pScreenPriv
->pddsShadow
,
463 if (FAILED (ddrval
) || pddsdShadow
->lpSurface
== NULL
)
465 ErrorF ("winAllocateFBShadowDD - Could not lock shadow "\
466 "surface: %08x\n", (unsigned int) ddrval
);
471 winDebug ("winAllocateFBShadowDD - Locked shadow\n");
474 /* We don't know how to deal with anything other than RGB */
475 if (!(pddsdShadow
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
))
477 ErrorF ("winAllocateFBShadowDD - Color format other than RGB\n");
481 /* Grab the pitch from the surface desc */
482 pScreenInfo
->dwStride
= (pddsdShadow
->u1
.lPitch
* 8)
483 / pScreenInfo
->dwBPP
;
485 /* Save the pointer to our surface memory */
486 pScreenInfo
->pfb
= pddsdShadow
->lpSurface
;
488 /* Grab the color depth and masks from the surface description */
489 pScreenPriv
->dwRedMask
= pddsdShadow
->ddpfPixelFormat
.u2
.dwRBitMask
;
490 pScreenPriv
->dwGreenMask
= pddsdShadow
->ddpfPixelFormat
.u3
.dwGBitMask
;
491 pScreenPriv
->dwBlueMask
= pddsdShadow
->ddpfPixelFormat
.u4
.dwBBitMask
;
494 winDebug ("winAllocateFBShadowDD - Returning\n");
502 * Transfer the damaged regions of the shadow framebuffer to the display.
506 winShadowUpdateDD (ScreenPtr pScreen
,
509 winScreenPriv(pScreen
);
510 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
511 RegionPtr damage
= &pBuf
->damage
;
512 HRESULT ddrval
= DD_OK
;
515 DWORD dwBox
= REGION_NUM_RECTS (damage
);
516 BoxPtr pBox
= REGION_RECTS (damage
);
517 HRGN hrgnTemp
= NULL
, hrgnCombined
= NULL
;
520 * Return immediately if the app is not active
521 * and we are fullscreen, or if we have a bad display depth
523 if ((!pScreenPriv
->fActive
&& pScreenInfo
->fFullScreen
)
524 || pScreenPriv
->fBadDepth
) return;
526 /* Get the origin of the window in the screen coords */
527 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
528 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
529 MapWindowPoints (pScreenPriv
->hwndScreen
,
531 (LPPOINT
)&ptOrigin
, 1);
533 /* Unlock the shadow surface, so we can blit */
534 ddrval
= IDirectDrawSurface2_Unlock (pScreenPriv
->pddsShadow
, NULL
);
537 ErrorF ("winShadowUpdateProcDD - Unlock failed\n");
542 * Handle small regions with multiple blits,
543 * handle large regions by creating a clipping region and
544 * doing a single blit constrained to that clipping region.
546 if (pScreenInfo
->dwClipUpdatesNBoxes
== 0
547 || dwBox
< pScreenInfo
->dwClipUpdatesNBoxes
)
549 /* Loop through all boxes in the damaged region */
552 /* Assign damage box to source rectangle */
553 rcSrc
.left
= pBox
->x1
;
554 rcSrc
.top
= pBox
->y1
;
555 rcSrc
.right
= pBox
->x2
;
556 rcSrc
.bottom
= pBox
->y2
;
558 /* Calculate destination rectange */
559 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
560 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
561 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
562 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
564 /* Blit the damaged areas */
565 ddrval
= IDirectDrawSurface2_Blt (pScreenPriv
->pddsPrimary
,
567 pScreenPriv
->pddsShadow
,
572 /* Get a pointer to the next box */
578 BoxPtr pBoxExtents
= REGION_EXTENTS (pScreen
, damage
);
580 /* Compute a GDI region from the damaged region */
581 hrgnCombined
= CreateRectRgn (pBox
->x1
, pBox
->y1
, pBox
->x2
, pBox
->y2
);
586 hrgnTemp
= CreateRectRgn (pBox
->x1
, pBox
->y1
, pBox
->x2
, pBox
->y2
);
587 CombineRgn (hrgnCombined
, hrgnCombined
, hrgnTemp
, RGN_OR
);
588 DeleteObject (hrgnTemp
);
592 /* Install the GDI region as a clipping region */
593 SelectClipRgn (pScreenPriv
->hdcScreen
, hrgnCombined
);
594 DeleteObject (hrgnCombined
);
597 /* Calculating a bounding box for the source is easy */
598 rcSrc
.left
= pBoxExtents
->x1
;
599 rcSrc
.top
= pBoxExtents
->y1
;
600 rcSrc
.right
= pBoxExtents
->x2
;
601 rcSrc
.bottom
= pBoxExtents
->y2
;
603 /* Calculating a bounding box for the destination is trickier */
604 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
605 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
606 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
607 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
609 /* Our Blt should be clipped to the invalidated region */
610 ddrval
= IDirectDrawSurface2_Blt (pScreenPriv
->pddsPrimary
,
612 pScreenPriv
->pddsShadow
,
617 /* Reset the clip region */
618 SelectClipRgn (pScreenPriv
->hdcScreen
, NULL
);
621 /* Relock the shadow surface */
622 ddrval
= IDirectDrawSurface2_Lock (pScreenPriv
->pddsShadow
,
624 pScreenPriv
->pddsdShadow
,
629 ErrorF ("winShadowUpdateProcDD - Lock failed\n");
633 /* Has our memory pointer changed? */
634 if (pScreenInfo
->pfb
!= pScreenPriv
->pddsdShadow
->lpSurface
)
636 ErrorF ("winShadowUpdateProcDD - Memory location of the shadow "
637 "surface has changed, trying to update the root window "
638 "pixmap header to point to the new address. If you get "
639 "this message and "PROJECT_NAME
" freezes or crashes "
640 "after this message then send a problem report and your "
641 "/tmp/XWin.log file to cygwin-xfree@cygwin.com\n");
643 /* Location of shadow framebuffer has changed */
644 pScreenInfo
->pfb
= pScreenPriv
->pddsdShadow
->lpSurface
;
646 /* Update the screen pixmap */
647 if (!(*pScreen
->ModifyPixmapHeader
)(pScreen
->devPrivate
,
651 BitsPerPixel (pScreen
->rootDepth
),
652 PixmapBytePad (pScreenInfo
->dwStride
,
656 ErrorF ("winShadowUpdateProcDD - Bits changed, could not "
665 * Call the wrapped CloseScreen function.
667 * Free our resources and private structures.
671 winCloseScreenShadowDD (int nIndex
, ScreenPtr pScreen
)
673 winScreenPriv(pScreen
);
674 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
678 winDebug ("winCloseScreenShadowDD - Freeing screen resources\n");
681 /* Flag that the screen is closed */
682 pScreenPriv
->fClosed
= TRUE
;
683 pScreenPriv
->fActive
= FALSE
;
685 /* Call the wrapped CloseScreen procedure */
686 WIN_UNWRAP(CloseScreen
);
687 fReturn
= (*pScreen
->CloseScreen
) (nIndex
, pScreen
);
689 /* Free the screen DC */
690 ReleaseDC (pScreenPriv
->hwndScreen
, pScreenPriv
->hdcScreen
);
692 /* Delete the window property */
693 RemoveProp (pScreenPriv
->hwndScreen
, WIN_SCR_PROP
);
695 /* Free the shadow surface, if there is one */
696 if (pScreenPriv
->pddsShadow
)
698 IDirectDrawSurface2_Unlock (pScreenPriv
->pddsShadow
, NULL
);
699 IDirectDrawSurface2_Release (pScreenPriv
->pddsShadow
);
700 pScreenPriv
->pddsShadow
= NULL
;
703 /* Detach the clipper from the primary surface and release the clipper. */
704 if (pScreenPriv
->pddcPrimary
)
706 /* Detach the clipper */
707 IDirectDrawSurface2_SetClipper (pScreenPriv
->pddsPrimary
,
710 /* Release the clipper object */
711 IDirectDrawClipper_Release (pScreenPriv
->pddcPrimary
);
712 pScreenPriv
->pddcPrimary
= NULL
;
715 /* Release the primary surface, if there is one */
716 if (pScreenPriv
->pddsPrimary
)
718 IDirectDrawSurface2_Release (pScreenPriv
->pddsPrimary
);
719 pScreenPriv
->pddsPrimary
= NULL
;
722 /* Free the DirectDraw2 object, if there is one */
723 if (pScreenPriv
->pdd2
)
725 IDirectDraw2_RestoreDisplayMode (pScreenPriv
->pdd2
);
726 IDirectDraw2_Release (pScreenPriv
->pdd2
);
727 pScreenPriv
->pdd2
= NULL
;
730 /* Free the DirectDraw object, if there is one */
731 if (pScreenPriv
->pdd
)
733 IDirectDraw_Release (pScreenPriv
->pdd
);
734 pScreenPriv
->pdd
= NULL
;
737 /* Delete tray icon, if we have one */
738 if (!pScreenInfo
->fNoTrayIcon
)
739 winDeleteNotifyIcon (pScreenPriv
);
741 /* Free the exit confirmation dialog box, if it exists */
742 if (g_hDlgExit
!= NULL
)
744 DestroyWindow (g_hDlgExit
);
748 /* Kill our window */
749 if (pScreenPriv
->hwndScreen
)
751 DestroyWindow (pScreenPriv
->hwndScreen
);
752 pScreenPriv
->hwndScreen
= NULL
;
755 #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
756 /* Destroy the thread startup mutex */
757 pthread_mutex_destroy (&pScreenPriv
->pmServerStarted
);
760 /* Kill our screeninfo's pointer to the screen */
761 pScreenInfo
->pScreen
= NULL
;
763 /* Invalidate the ScreenInfo's fb pointer */
764 pScreenInfo
->pfb
= NULL
;
766 /* Free the screen privates for this screen */
767 free ((pointer
) pScreenPriv
);
774 * Tell mi what sort of visuals we need.
776 * Generally we only need one visual, as our screen can only
777 * handle one format at a time, I believe. You may want
778 * to verify that last sentence.
782 winInitVisualsShadowDD (ScreenPtr pScreen
)
784 winScreenPriv(pScreen
);
785 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
786 DWORD dwRedBits
, dwGreenBits
, dwBlueBits
;
788 /* Count the number of ones in each color mask */
789 dwRedBits
= winCountBits (pScreenPriv
->dwRedMask
);
790 dwGreenBits
= winCountBits (pScreenPriv
->dwGreenMask
);
791 dwBlueBits
= winCountBits (pScreenPriv
->dwBlueMask
);
793 /* Store the maximum number of ones in a color mask as the bitsPerRGB */
794 if (dwRedBits
== 0 || dwGreenBits
== 0 || dwBlueBits
== 0)
795 pScreenPriv
->dwBitsPerRGB
= 8;
796 else if (dwRedBits
> dwGreenBits
&& dwRedBits
> dwBlueBits
)
797 pScreenPriv
->dwBitsPerRGB
= dwRedBits
;
798 else if (dwGreenBits
> dwRedBits
&& dwGreenBits
> dwBlueBits
)
799 pScreenPriv
->dwBitsPerRGB
= dwGreenBits
;
801 pScreenPriv
->dwBitsPerRGB
= dwBlueBits
;
803 ErrorF ("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d "
805 (unsigned int) pScreenPriv
->dwRedMask
,
806 (unsigned int) pScreenPriv
->dwGreenMask
,
807 (unsigned int) pScreenPriv
->dwBlueMask
,
808 (int) pScreenPriv
->dwBitsPerRGB
,
809 (int) pScreenInfo
->dwDepth
,
810 (int) pScreenInfo
->dwBPP
);
812 /* Create a single visual according to the Windows screen depth */
813 switch (pScreenInfo
->dwDepth
)
818 #if defined(XFree86Server)
819 /* Create the real visual */
820 if (!miSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
822 pScreenPriv
->dwBitsPerRGB
,
824 pScreenPriv
->dwRedMask
,
825 pScreenPriv
->dwGreenMask
,
826 pScreenPriv
->dwBlueMask
))
828 ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
829 "failed for TrueColor\n");
833 #ifdef XWIN_EMULATEPSEUDO
834 if (!pScreenInfo
->fEmulatePseudo
)
837 /* Setup a pseudocolor visual */
838 if (!miSetVisualTypesAndMasks (8,
846 ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
847 "failed for PseudoColor\n");
851 #else /* XFree86Server */
852 /* Create the real visual */
853 if (!fbSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
855 pScreenPriv
->dwBitsPerRGB
,
856 pScreenPriv
->dwRedMask
,
857 pScreenPriv
->dwGreenMask
,
858 pScreenPriv
->dwBlueMask
))
860 ErrorF ("winInitVisualsShadowDD - fbSetVisualTypesAndMasks "
861 "failed for TrueColor\n");
865 #ifdef XWIN_EMULATEPSEUDO
866 if (!pScreenInfo
->fEmulatePseudo
)
869 /* Setup a pseudocolor visual */
870 if (!fbSetVisualTypesAndMasks (8,
877 ErrorF ("winInitVisualsShadowDD - fbSetVisualTypesAndMasks "
878 "failed for PseudoColor\n");
882 #endif /* XFree86Server */
886 #if defined(XFree86Server)
887 if (!miSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
888 pScreenInfo
->fFullScreen
889 ? PseudoColorMask
: StaticColorMask
,
890 pScreenPriv
->dwBitsPerRGB
,
891 pScreenInfo
->fFullScreen
892 ? PseudoColor
: StaticColor
,
893 pScreenPriv
->dwRedMask
,
894 pScreenPriv
->dwGreenMask
,
895 pScreenPriv
->dwBlueMask
))
897 ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
901 #else /* XFree86Server */
902 if (!fbSetVisualTypesAndMasks (pScreenInfo
->dwDepth
,
903 pScreenInfo
->fFullScreen
904 ? PseudoColorMask
: StaticColorMask
,
905 pScreenPriv
->dwBitsPerRGB
,
906 pScreenPriv
->dwRedMask
,
907 pScreenPriv
->dwGreenMask
,
908 pScreenPriv
->dwBlueMask
))
910 ErrorF ("winInitVisualsShadowDD - fbSetVisualTypesAndMasks "
914 #endif /* XFree86Server */
918 ErrorF ("winInitVisualsShadowDD - Unknown screen depth\n");
923 winDebug ("winInitVisualsShadowDD - Returning\n");
931 * Adjust the user proposed video mode
935 winAdjustVideoModeShadowDD (ScreenPtr pScreen
)
937 winScreenPriv(pScreen
);
938 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
942 /* We're in serious trouble if we can't get a DC */
946 ErrorF ("winAdjustVideoModeShadowDD - GetDC () failed\n");
950 /* Query GDI for current display depth */
951 dwBPP
= GetDeviceCaps (hdc
, BITSPIXEL
);
953 /* DirectDraw can only change the depth in fullscreen mode */
954 if (pScreenInfo
->dwBPP
== WIN_DEFAULT_BPP
)
956 /* No -depth parameter passed, let the user know the depth being used */
957 ErrorF ("winAdjustVideoModeShadowDD - Using Windows display "
958 "depth of %d bits per pixel\n", (int) dwBPP
);
960 /* Use GDI's depth */
961 pScreenInfo
->dwBPP
= dwBPP
;
963 else if (pScreenInfo
->fFullScreen
964 && pScreenInfo
->dwBPP
!= dwBPP
)
966 /* FullScreen, and GDI depth differs from -depth parameter */
967 ErrorF ("winAdjustVideoModeShadowDD - FullScreen, using command line "
968 "bpp: %d\n", (int) pScreenInfo
->dwBPP
);
970 else if (dwBPP
!= pScreenInfo
->dwBPP
)
972 /* Windowed, and GDI depth differs from -depth parameter */
973 ErrorF ("winAdjustVideoModeShadowDD - Windowed, command line bpp: "
974 "%d, using bpp: %d\n", (int) pScreenInfo
->dwBPP
, (int) dwBPP
);
976 /* We'll use GDI's depth */
977 pScreenInfo
->dwBPP
= dwBPP
;
980 /* See if the shadow bitmap will be larger than the DIB size limit */
981 if (pScreenInfo
->dwWidth
* pScreenInfo
->dwHeight
* pScreenInfo
->dwBPP
982 >= WIN_DIB_MAXIMUM_SIZE
)
984 ErrorF ("winAdjustVideoModeShadowDD - Requested DirectDraw surface "
985 "will be larger than %d MB. The surface may fail to be "
986 "allocated on Windows 95, 98, or Me, due to a %d MB limit in "
987 "DIB size. This limit does not apply to Windows NT/2000, and "
988 "this message may be ignored on those platforms.\n",
989 WIN_DIB_MAXIMUM_SIZE_MB
, WIN_DIB_MAXIMUM_SIZE_MB
);
993 ReleaseDC (NULL
, hdc
);
999 * Blt exposed regions to the screen
1003 winBltExposedRegionsShadowDD (ScreenPtr pScreen
)
1005 winScreenPriv(pScreen
);
1006 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1009 HDC hdcUpdate
= NULL
;
1011 HRESULT ddrval
= DD_OK
;
1012 Bool fReturn
= TRUE
;
1013 Bool fLocked
= TRUE
;
1016 /* BeginPaint gives us an hdc that clips to the invalidated region */
1017 hdcUpdate
= BeginPaint (pScreenPriv
->hwndScreen
, &ps
);
1018 if (hdcUpdate
== NULL
)
1020 ErrorF ("winBltExposedRegionsShadowDD - BeginPaint () returned "
1021 "a NULL device context handle. Aborting blit attempt.\n");
1025 /* Unlock the shadow surface, so we can blit */
1026 ddrval
= IDirectDrawSurface2_Unlock (pScreenPriv
->pddsShadow
, NULL
);
1027 if (FAILED (ddrval
))
1030 goto winBltExposedRegionsShadowDD_Exit
;
1034 /* Flag that we have unlocked the shadow surface */
1038 /* Get the origin of the window in the screen coords */
1039 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
1040 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
1042 MapWindowPoints (pScreenPriv
->hwndScreen
,
1044 (LPPOINT
)&ptOrigin
, 1);
1045 rcDest
.left
= ptOrigin
.x
;
1046 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
1047 rcDest
.top
= ptOrigin
.y
;
1048 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
1050 /* Source can be enter shadow surface, as Blt should clip */
1053 rcSrc
.right
= pScreenInfo
->dwWidth
;
1054 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
1056 /* Try to regain the primary surface and blit again if we've lost it */
1057 for (i
= 0; i
<= WIN_REGAIN_SURFACE_RETRIES
; ++i
)
1059 /* Our Blt should be clipped to the invalidated region */
1060 ddrval
= IDirectDrawSurface2_Blt (pScreenPriv
->pddsPrimary
,
1062 pScreenPriv
->pddsShadow
,
1066 if (ddrval
== DDERR_SURFACELOST
)
1068 /* Surface was lost */
1069 ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
1070 "reported that the primary surface was lost, "
1071 "trying to restore, retry: %d\n", i
+ 1);
1073 /* Try to restore the surface, once */
1074 ddrval
= IDirectDrawSurface2_Restore (pScreenPriv
->pddsPrimary
);
1075 ErrorF ("winBltExposedRegionsShadowDD - "
1076 "IDirectDrawSurface2_Restore returned: ");
1077 if (ddrval
== DD_OK
)
1079 else if (ddrval
== DDERR_WRONGMODE
)
1080 ErrorF ("DDERR_WRONGMODE\n");
1081 else if (ddrval
== DDERR_INCOMPATIBLEPRIMARY
)
1082 ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n");
1083 else if (ddrval
== DDERR_UNSUPPORTED
)
1084 ErrorF ("DDERR_UNSUPPORTED\n");
1085 else if (ddrval
== DDERR_INVALIDPARAMS
)
1086 ErrorF ("DDERR_INVALIDPARAMS\n");
1087 else if (ddrval
== DDERR_INVALIDOBJECT
)
1088 ErrorF ("DDERR_INVALIDOBJECT\n");
1090 ErrorF ("unknown error: %08x\n", (unsigned int) ddrval
);
1092 /* Loop around to try the blit one more time */
1095 else if (FAILED (ddrval
))
1098 ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
1099 "failed, but surface not lost: %08x %d\n",
1100 (unsigned int) ddrval
, (int) ddrval
);
1101 goto winBltExposedRegionsShadowDD_Exit
;
1105 /* Success, stop looping */
1110 /* Relock the shadow surface */
1111 ddrval
= IDirectDrawSurface2_Lock (pScreenPriv
->pddsShadow
,
1113 pScreenPriv
->pddsdShadow
,
1116 if (FAILED (ddrval
))
1119 ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock "
1121 goto winBltExposedRegionsShadowDD_Exit
;
1125 /* Indicate that we have relocked the shadow surface */
1129 /* Has our memory pointer changed? */
1130 if (pScreenInfo
->pfb
!= pScreenPriv
->pddsdShadow
->lpSurface
)
1131 winUpdateFBPointer (pScreen
,
1132 pScreenPriv
->pddsdShadow
->lpSurface
);
1134 winBltExposedRegionsShadowDD_Exit
:
1135 /* EndPaint frees the DC */
1136 if (hdcUpdate
!= NULL
)
1137 EndPaint (pScreenPriv
->hwndScreen
, &ps
);
1140 * Relock the surface if it is not locked. We don't care if locking fails,
1141 * as it will cause the server to shutdown within a few more operations.
1145 IDirectDrawSurface2_Lock (pScreenPriv
->pddsShadow
,
1147 pScreenPriv
->pddsdShadow
,
1151 /* Has our memory pointer changed? */
1152 if (pScreenInfo
->pfb
!= pScreenPriv
->pddsdShadow
->lpSurface
)
1153 winUpdateFBPointer (pScreen
,
1154 pScreenPriv
->pddsdShadow
->lpSurface
);
1163 * Do any engine-specific appliation-activation processing
1167 winActivateAppShadowDD (ScreenPtr pScreen
)
1169 winScreenPriv(pScreen
);
1172 * Do we have a surface?
1174 * Are we fullscreen?
1176 if (pScreenPriv
!= NULL
1177 && pScreenPriv
->pddsPrimary
!= NULL
1178 && pScreenPriv
->fActive
)
1180 /* Primary surface was lost, restore it */
1181 IDirectDrawSurface2_Restore (pScreenPriv
->pddsPrimary
);
1189 * Reblit the shadow framebuffer to the screen.
1193 winRedrawScreenShadowDD (ScreenPtr pScreen
)
1195 winScreenPriv(pScreen
);
1196 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1197 HRESULT ddrval
= DD_OK
;
1201 /* Get the origin of the window in the screen coords */
1202 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
1203 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
1204 MapWindowPoints (pScreenPriv
->hwndScreen
,
1206 (LPPOINT
)&ptOrigin
, 1);
1207 rcDest
.left
= ptOrigin
.x
;
1208 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
1209 rcDest
.top
= ptOrigin
.y
;
1210 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
1212 /* Source can be entire shadow surface, as Blt should clip for us */
1215 rcSrc
.right
= pScreenInfo
->dwWidth
;
1216 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
1218 /* Redraw the whole window, to take account for the new colors */
1219 ddrval
= IDirectDrawSurface2_Blt (pScreenPriv
->pddsPrimary
,
1221 pScreenPriv
->pddsShadow
,
1225 if (FAILED (ddrval
))
1227 ErrorF ("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () "
1229 (unsigned int) ddrval
);
1237 * Realize the currently installed colormap
1241 winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen
)
1248 * Install the specified colormap
1252 winInstallColormapShadowDD (ColormapPtr pColormap
)
1254 ScreenPtr pScreen
= pColormap
->pScreen
;
1255 winScreenPriv(pScreen
);
1256 winCmapPriv(pColormap
);
1257 HRESULT ddrval
= DD_OK
;
1259 /* Install the DirectDraw palette on the primary surface */
1260 ddrval
= IDirectDrawSurface2_SetPalette (pScreenPriv
->pddsPrimary
,
1261 pCmapPriv
->lpDDPalette
);
1262 if (FAILED (ddrval
))
1264 ErrorF ("winInstallColormapShadowDD - Failed installing the "
1265 "DirectDraw palette.\n");
1269 /* Save a pointer to the newly installed colormap */
1270 pScreenPriv
->pcmapInstalled
= pColormap
;
1277 * Store the specified colors in the specified colormap
1281 winStoreColorsShadowDD (ColormapPtr pColormap
,
1285 ScreenPtr pScreen
= pColormap
->pScreen
;
1286 winScreenPriv(pScreen
);
1287 winCmapPriv(pColormap
);
1288 ColormapPtr curpmap
= pScreenPriv
->pcmapInstalled
;
1289 HRESULT ddrval
= DD_OK
;
1291 /* Put the X colormap entries into the Windows logical palette */
1292 ddrval
= IDirectDrawPalette_SetEntries (pCmapPriv
->lpDDPalette
,
1298 if (FAILED (ddrval
))
1300 ErrorF ("winStoreColorsShadowDD - SetEntries () failed\n");
1304 /* Don't install the DirectDraw palette if the colormap is not installed */
1305 if (pColormap
!= curpmap
)
1310 if (!winInstallColormapShadowDD (pColormap
))
1312 ErrorF ("winStoreColorsShadowDD - Failed installing colormap\n");
1321 * Colormap initialization procedure
1325 winCreateColormapShadowDD (ColormapPtr pColormap
)
1327 HRESULT ddrval
= DD_OK
;
1328 ScreenPtr pScreen
= pColormap
->pScreen
;
1329 winScreenPriv(pScreen
);
1330 winCmapPriv(pColormap
);
1332 /* Create a DirectDraw palette */
1333 ddrval
= IDirectDraw2_CreatePalette (pScreenPriv
->pdd
,
1334 DDPCAPS_8BIT
| DDPCAPS_ALLOW256
,
1335 pCmapPriv
->peColors
,
1336 &pCmapPriv
->lpDDPalette
,
1338 if (FAILED (ddrval
))
1340 ErrorF ("winCreateColormapShadowDD - CreatePalette failed\n");
1349 * Colormap destruction procedure
1353 winDestroyColormapShadowDD (ColormapPtr pColormap
)
1355 winScreenPriv(pColormap
->pScreen
);
1356 winCmapPriv(pColormap
);
1357 HRESULT ddrval
= DD_OK
;
1360 * Is colormap to be destroyed the default?
1362 * Non-default colormaps should have had winUninstallColormap
1363 * called on them before we get here. The default colormap
1364 * will not have had winUninstallColormap called on it. Thus,
1365 * we need to handle the default colormap in a special way.
1367 if (pColormap
->flags
& IsDefault
)
1370 winDebug ("winDestroyColormapShadowDD - Destroying default "
1375 * FIXME: Walk the list of all screens, popping the default
1376 * palette out of each screen device context.
1379 /* Pop the palette out of the primary surface */
1380 ddrval
= IDirectDrawSurface2_SetPalette (pScreenPriv
->pddsPrimary
,
1382 if (FAILED (ddrval
))
1384 ErrorF ("winDestroyColormapShadowDD - Failed freeing the "
1385 "default colormap DirectDraw palette.\n");
1389 /* Clear our private installed colormap pointer */
1390 pScreenPriv
->pcmapInstalled
= NULL
;
1393 /* Release the palette */
1394 IDirectDrawPalette_Release (pCmapPriv
->lpDDPalette
);
1396 /* Invalidate the colormap privates */
1397 pCmapPriv
->lpDDPalette
= NULL
;
1404 * Set engine specific functions
1408 winSetEngineFunctionsShadowDD (ScreenPtr pScreen
)
1410 winScreenPriv(pScreen
);
1411 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1413 /* Set our pointers */
1414 pScreenPriv
->pwinAllocateFB
= winAllocateFBShadowDD
;
1415 pScreenPriv
->pwinShadowUpdate
= winShadowUpdateDD
;
1416 pScreenPriv
->pwinCloseScreen
= winCloseScreenShadowDD
;
1417 pScreenPriv
->pwinInitVisuals
= winInitVisualsShadowDD
;
1418 pScreenPriv
->pwinAdjustVideoMode
= winAdjustVideoModeShadowDD
;
1419 if (pScreenInfo
->fFullScreen
)
1420 pScreenPriv
->pwinCreateBoundingWindow
= winCreateBoundingWindowFullScreen
;
1422 pScreenPriv
->pwinCreateBoundingWindow
= winCreateBoundingWindowWindowed
;
1423 pScreenPriv
->pwinFinishScreenInit
= winFinishScreenInitFB
;
1424 pScreenPriv
->pwinBltExposedRegions
= winBltExposedRegionsShadowDD
;
1425 pScreenPriv
->pwinActivateApp
= winActivateAppShadowDD
;
1426 pScreenPriv
->pwinRedrawScreen
= winRedrawScreenShadowDD
;
1427 pScreenPriv
->pwinRealizeInstalledPalette
1428 = winRealizeInstalledPaletteShadowDD
;
1429 pScreenPriv
->pwinInstallColormap
= winInstallColormapShadowDD
;
1430 pScreenPriv
->pwinStoreColors
= winStoreColorsShadowDD
;
1431 pScreenPriv
->pwinCreateColormap
= winCreateColormapShadowDD
;
1432 pScreenPriv
->pwinDestroyColormap
= winDestroyColormapShadowDD
;
1433 pScreenPriv
->pwinHotKeyAltTab
= (winHotKeyAltTabProcPtr
) (void (*)(void))NoopDDA
;
1434 pScreenPriv
->pwinCreatePrimarySurface
= winCreatePrimarySurfaceShadowDD
;
1435 pScreenPriv
->pwinReleasePrimarySurface
= winReleasePrimarySurfaceShadowDD
;
1436 #ifdef XWIN_MULTIWINDOW
1437 pScreenPriv
->pwinFinishCreateWindowsWindow
=
1438 (winFinishCreateWindowsWindowProcPtr
) (void (*)(void))NoopDDA
;