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 winAllocateFBShadowDD(ScreenPtr pScreen
);
47 winShadowUpdateDD(ScreenPtr pScreen
, shadowBufPtr pBuf
);
50 winCloseScreenShadowDD(ScreenPtr pScreen
);
53 winInitVisualsShadowDD(ScreenPtr pScreen
);
56 winAdjustVideoModeShadowDD(ScreenPtr pScreen
);
59 winBltExposedRegionsShadowDD(ScreenPtr pScreen
);
62 winActivateAppShadowDD(ScreenPtr pScreen
);
65 winRedrawScreenShadowDD(ScreenPtr pScreen
);
68 winRealizeInstalledPaletteShadowDD(ScreenPtr pScreen
);
71 winInstallColormapShadowDD(ColormapPtr pColormap
);
74 winStoreColorsShadowDD(ColormapPtr pmap
, int ndef
, xColorItem
* pdefs
);
77 winCreateColormapShadowDD(ColormapPtr pColormap
);
80 winDestroyColormapShadowDD(ColormapPtr pColormap
);
83 winCreatePrimarySurfaceShadowDD(ScreenPtr pScreen
);
86 winReleasePrimarySurfaceShadowDD(ScreenPtr pScreen
);
89 * Create the primary surface and attach the clipper.
90 * Used for both the initial surface creation and during
91 * WM_DISPLAYCHANGE messages.
95 winCreatePrimarySurfaceShadowDD(ScreenPtr pScreen
)
97 winScreenPriv(pScreen
);
98 HRESULT ddrval
= DD_OK
;
101 /* Describe the primary surface */
102 ZeroMemory(&ddsd
, sizeof(ddsd
));
103 ddsd
.dwSize
= sizeof(ddsd
);
104 ddsd
.dwFlags
= DDSD_CAPS
;
105 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
107 /* Create the primary surface */
108 ddrval
= IDirectDraw2_CreateSurface(pScreenPriv
->pdd2
,
109 &ddsd
, &pScreenPriv
->pddsPrimary
, NULL
);
110 if (FAILED(ddrval
)) {
111 ErrorF("winCreatePrimarySurfaceShadowDD - Could not create primary "
112 "surface: %08x\n", (unsigned int) ddrval
);
117 winDebug("winCreatePrimarySurfaceShadowDD - Created primary surface\n");
121 * Attach a clipper to the primary surface that will clip our blits to our
124 ddrval
= IDirectDrawSurface2_SetClipper(pScreenPriv
->pddsPrimary
,
125 pScreenPriv
->pddcPrimary
);
126 if (FAILED(ddrval
)) {
127 ErrorF("winCreatePrimarySurfaceShadowDD - Primary attach clipper "
128 "failed: %08x\n", (unsigned int) ddrval
);
133 winDebug("winCreatePrimarySurfaceShadowDD - Attached clipper to "
134 "primary surface\n");
137 /* Everything was correct */
142 * Detach the clipper and release the primary surface.
143 * Called from WM_DISPLAYCHANGE.
147 winReleasePrimarySurfaceShadowDD(ScreenPtr pScreen
)
149 winScreenPriv(pScreen
);
151 ErrorF("winReleasePrimarySurfaceShadowDD - Hello\n");
153 /* Release the primary surface and clipper, if they exist */
154 if (pScreenPriv
->pddsPrimary
) {
156 * Detach the clipper from the primary surface.
157 * NOTE: We do this explicity for clarity. The Clipper is not released.
159 IDirectDrawSurface2_SetClipper(pScreenPriv
->pddsPrimary
, NULL
);
161 ErrorF("winReleasePrimarySurfaceShadowDD - Detached clipper\n");
163 /* Release the primary surface */
164 IDirectDrawSurface2_Release(pScreenPriv
->pddsPrimary
);
165 pScreenPriv
->pddsPrimary
= NULL
;
168 ErrorF("winReleasePrimarySurfaceShadowDD - Released primary surface\n");
174 * Create a DirectDraw surface for the shadow framebuffer; also create
175 * a primary surface object so we can blit to the display.
177 * Install a DirectDraw clipper on our primary surface object
178 * that clips our blits to the unobscured client area of our display window.
182 winAllocateFBShadowDD(ScreenPtr pScreen
)
184 winScreenPriv(pScreen
);
185 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
186 HRESULT ddrval
= DD_OK
;
188 DDSURFACEDESC
*pddsdShadow
= NULL
;
191 winDebug("winAllocateFBShadowDD\n");
194 /* Create a clipper */
195 ddrval
= (*g_fpDirectDrawCreateClipper
) (0,
196 &pScreenPriv
->pddcPrimary
, NULL
);
197 if (FAILED(ddrval
)) {
198 ErrorF("winAllocateFBShadowDD - Could not create clipper: %08x\n",
199 (unsigned int) ddrval
);
204 winDebug("winAllocateFBShadowDD - Created a clipper\n");
207 /* Attach the clipper to our display window */
208 ddrval
= IDirectDrawClipper_SetHWnd(pScreenPriv
->pddcPrimary
,
209 0, pScreenPriv
->hwndScreen
);
210 if (FAILED(ddrval
)) {
211 ErrorF("winAllocateFBShadowDD - Clipper not attached to "
212 "window: %08x\n", (unsigned int) ddrval
);
217 winDebug("winAllocateFBShadowDD - Attached clipper to window\n");
220 /* Create a DirectDraw object, store the address at lpdd */
221 ddrval
= (*g_fpDirectDrawCreate
) (NULL
, &pScreenPriv
->pdd
, NULL
);
222 if (FAILED(ddrval
)) {
223 ErrorF("winAllocateFBShadowDD - Could not start DirectDraw: %08x\n",
224 (unsigned int) ddrval
);
229 winDebug("winAllocateFBShadowDD () - Created and initialized DD\n");
232 /* Get a DirectDraw2 interface pointer */
233 ddrval
= IDirectDraw_QueryInterface(pScreenPriv
->pdd
,
235 (LPVOID
*) &pScreenPriv
->pdd2
);
236 if (FAILED(ddrval
)) {
237 ErrorF("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
238 (unsigned int) ddrval
);
242 /* Are we full screen? */
243 if (pScreenInfo
->fFullScreen
) {
244 DDSURFACEDESC ddsdCurrent
;
245 DWORD dwRefreshRateCurrent
= 0;
248 /* Set the cooperative level to full screen */
249 ddrval
= IDirectDraw2_SetCooperativeLevel(pScreenPriv
->pdd2
,
250 pScreenPriv
->hwndScreen
,
253 if (FAILED(ddrval
)) {
254 ErrorF("winAllocateFBShadowDD - Could not set "
255 "cooperative level: %08x\n", (unsigned int) ddrval
);
260 * We only need to get the current refresh rate for comparison
261 * if a refresh rate has been passed on the command line.
263 if (pScreenInfo
->dwRefreshRate
!= 0) {
264 ZeroMemory(&ddsdCurrent
, sizeof(ddsdCurrent
));
265 ddsdCurrent
.dwSize
= sizeof(ddsdCurrent
);
267 /* Get information about current display settings */
268 ddrval
= IDirectDraw2_GetDisplayMode(pScreenPriv
->pdd2
,
270 if (FAILED(ddrval
)) {
271 ErrorF("winAllocateFBShadowDD - Could not get current "
272 "refresh rate: %08x. Continuing.\n",
273 (unsigned int) ddrval
);
274 dwRefreshRateCurrent
= 0;
277 /* Grab the current refresh rate */
278 dwRefreshRateCurrent
= ddsdCurrent
.u2
.dwRefreshRate
;
282 /* Clean up the refresh rate */
283 if (dwRefreshRateCurrent
== pScreenInfo
->dwRefreshRate
) {
285 * Refresh rate is non-specified or equal to current.
287 pScreenInfo
->dwRefreshRate
= 0;
290 /* Grab a device context for the screen */
293 ErrorF("winAllocateFBShadowDD - GetDC () failed\n");
297 /* Only change the video mode when different than current mode */
298 if (!pScreenInfo
->fMultipleMonitors
299 && (pScreenInfo
->dwWidth
!= GetSystemMetrics(SM_CXSCREEN
)
300 || pScreenInfo
->dwHeight
!= GetSystemMetrics(SM_CYSCREEN
)
301 || pScreenInfo
->dwBPP
!= GetDeviceCaps(hdc
, BITSPIXEL
)
302 || pScreenInfo
->dwRefreshRate
!= 0)) {
303 ErrorF("winAllocateFBShadowDD - Changing video mode\n");
305 /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
306 ddrval
= IDirectDraw2_SetDisplayMode(pScreenPriv
->pdd2
,
307 pScreenInfo
->dwWidth
,
308 pScreenInfo
->dwHeight
,
310 pScreenInfo
->dwRefreshRate
, 0);
311 if (FAILED(ddrval
)) {
312 ErrorF("winAllocateFBShadowDD - Could not set "
313 "full screen display mode: %08x\n",
314 (unsigned int) ddrval
);
316 ("winAllocateFBShadowDD - Using default driver refresh rate\n");
318 IDirectDraw2_SetDisplayMode(pScreenPriv
->pdd2
,
319 pScreenInfo
->dwWidth
,
320 pScreenInfo
->dwHeight
,
321 pScreenInfo
->dwBPP
, 0, 0);
322 if (FAILED(ddrval
)) {
324 ("winAllocateFBShadowDD - Could not set default refresh rate "
325 "full screen display mode: %08x\n",
326 (unsigned int) ddrval
);
332 ErrorF("winAllocateFBShadowDD - Not changing video mode\n");
336 ReleaseDC(NULL
, hdc
);
340 /* Set the cooperative level for windowed mode */
341 ddrval
= IDirectDraw2_SetCooperativeLevel(pScreenPriv
->pdd2
,
342 pScreenPriv
->hwndScreen
,
344 if (FAILED(ddrval
)) {
345 ErrorF("winAllocateFBShadowDD - Could not set "
346 "cooperative level: %08x\n", (unsigned int) ddrval
);
351 /* Create the primary surface */
352 if (!winCreatePrimarySurfaceShadowDD(pScreen
)) {
353 ErrorF("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD "
358 /* Describe the shadow surface to be created */
359 /* NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
360 * as drawing, locking, and unlocking take forever
361 * with video memory surfaces. In addition,
362 * video memory is a somewhat scarce resource,
363 * so you shouldn't be allocating video memory when
364 * you have the option of using system memory instead.
366 ZeroMemory(&ddsd
, sizeof(ddsd
));
367 ddsd
.dwSize
= sizeof(ddsd
);
368 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
;
369 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_SYSTEMMEMORY
;
370 ddsd
.dwHeight
= pScreenInfo
->dwHeight
;
371 ddsd
.dwWidth
= pScreenInfo
->dwWidth
;
373 /* Create the shadow surface */
374 ddrval
= IDirectDraw2_CreateSurface(pScreenPriv
->pdd2
,
375 &ddsd
, &pScreenPriv
->pddsShadow
, NULL
);
376 if (FAILED(ddrval
)) {
377 ErrorF("winAllocateFBShadowDD - Could not create shadow "
378 "surface: %08x\n", (unsigned int) ddrval
);
383 winDebug("winAllocateFBShadowDD - Created shadow\n");
386 /* Allocate a DD surface description for our screen privates */
387 pddsdShadow
= pScreenPriv
->pddsdShadow
= malloc(sizeof(DDSURFACEDESC
));
388 if (pddsdShadow
== NULL
) {
389 ErrorF("winAllocateFBShadowDD - Could not allocate surface "
390 "description memory\n");
393 ZeroMemory(pddsdShadow
, sizeof(*pddsdShadow
));
394 pddsdShadow
->dwSize
= sizeof(*pddsdShadow
);
397 winDebug("winAllocateFBShadowDD - Locking shadow\n");
400 /* Lock the shadow surface */
401 ddrval
= IDirectDrawSurface2_Lock(pScreenPriv
->pddsShadow
,
402 NULL
, pddsdShadow
, DDLOCK_WAIT
, NULL
);
403 if (FAILED(ddrval
) || pddsdShadow
->lpSurface
== NULL
) {
404 ErrorF("winAllocateFBShadowDD - Could not lock shadow "
405 "surface: %08x\n", (unsigned int) ddrval
);
410 winDebug("winAllocateFBShadowDD - Locked shadow\n");
413 /* We don't know how to deal with anything other than RGB */
414 if (!(pddsdShadow
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
)) {
415 ErrorF("winAllocateFBShadowDD - Color format other than RGB\n");
419 /* Grab the pitch from the surface desc */
420 pScreenInfo
->dwStride
= (pddsdShadow
->u1
.lPitch
* 8)
421 / pScreenInfo
->dwBPP
;
423 /* Save the pointer to our surface memory */
424 pScreenInfo
->pfb
= pddsdShadow
->lpSurface
;
426 /* Grab the color depth and masks from the surface description */
427 pScreenPriv
->dwRedMask
= pddsdShadow
->ddpfPixelFormat
.u2
.dwRBitMask
;
428 pScreenPriv
->dwGreenMask
= pddsdShadow
->ddpfPixelFormat
.u3
.dwGBitMask
;
429 pScreenPriv
->dwBlueMask
= pddsdShadow
->ddpfPixelFormat
.u4
.dwBBitMask
;
432 winDebug("winAllocateFBShadowDD - Returning\n");
439 winFreeFBShadowDD(ScreenPtr pScreen
)
441 winScreenPriv(pScreen
);
442 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
444 /* Free the shadow surface, if there is one */
445 if (pScreenPriv
->pddsShadow
) {
446 IDirectDrawSurface2_Unlock(pScreenPriv
->pddsShadow
, NULL
);
447 IDirectDrawSurface2_Release(pScreenPriv
->pddsShadow
);
448 pScreenPriv
->pddsShadow
= NULL
;
451 /* Detach the clipper from the primary surface and release the primary surface, if there is one */
452 winReleasePrimarySurfaceShadowDD(pScreen
);
454 /* Release the clipper object */
455 if (pScreenPriv
->pddcPrimary
) {
456 IDirectDrawClipper_Release(pScreenPriv
->pddcPrimary
);
457 pScreenPriv
->pddcPrimary
= NULL
;
460 /* Free the DirectDraw2 object, if there is one */
461 if (pScreenPriv
->pdd2
) {
462 IDirectDraw2_RestoreDisplayMode(pScreenPriv
->pdd2
);
463 IDirectDraw2_Release(pScreenPriv
->pdd2
);
464 pScreenPriv
->pdd2
= NULL
;
467 /* Free the DirectDraw object, if there is one */
468 if (pScreenPriv
->pdd
) {
469 IDirectDraw_Release(pScreenPriv
->pdd
);
470 pScreenPriv
->pdd
= NULL
;
473 /* Invalidate the ScreenInfo's fb pointer */
474 pScreenInfo
->pfb
= NULL
;
478 * Transfer the damaged regions of the shadow framebuffer to the display.
482 winShadowUpdateDD(ScreenPtr pScreen
, shadowBufPtr pBuf
)
484 winScreenPriv(pScreen
);
485 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
486 RegionPtr damage
= shadowDamage(pBuf
);
487 HRESULT ddrval
= DD_OK
;
490 DWORD dwBox
= RegionNumRects(damage
);
491 BoxPtr pBox
= RegionRects(damage
);
492 HRGN hrgnCombined
= NULL
;
495 * Return immediately if the app is not active
496 * and we are fullscreen, or if we have a bad display depth
498 if ((!pScreenPriv
->fActive
&& pScreenInfo
->fFullScreen
)
499 || pScreenPriv
->fBadDepth
)
502 /* Return immediately if we didn't get needed surfaces */
503 if (!pScreenPriv
->pddsPrimary
|| !pScreenPriv
->pddsShadow
)
506 /* Get the origin of the window in the screen coords */
507 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
508 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
509 MapWindowPoints(pScreenPriv
->hwndScreen
,
510 HWND_DESKTOP
, (LPPOINT
) &ptOrigin
, 1);
512 /* Unlock the shadow surface, so we can blit */
513 ddrval
= IDirectDrawSurface2_Unlock(pScreenPriv
->pddsShadow
, NULL
);
514 if (FAILED(ddrval
)) {
515 ErrorF("winShadowUpdateDD - Unlock failed\n");
520 * Handle small regions with multiple blits,
521 * handle large regions by creating a clipping region and
522 * doing a single blit constrained to that clipping region.
524 if (pScreenInfo
->dwClipUpdatesNBoxes
== 0
525 || dwBox
< pScreenInfo
->dwClipUpdatesNBoxes
) {
526 /* Loop through all boxes in the damaged region */
528 /* Assign damage box to source rectangle */
529 rcSrc
.left
= pBox
->x1
;
530 rcSrc
.top
= pBox
->y1
;
531 rcSrc
.right
= pBox
->x2
;
532 rcSrc
.bottom
= pBox
->y2
;
534 /* Calculate destination rectange */
535 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
536 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
537 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
538 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
540 /* Blit the damaged areas */
541 ddrval
= IDirectDrawSurface2_Blt(pScreenPriv
->pddsPrimary
,
543 pScreenPriv
->pddsShadow
,
544 &rcSrc
, DDBLT_WAIT
, NULL
);
546 /* Get a pointer to the next box */
551 BoxPtr pBoxExtents
= RegionExtents(damage
);
553 /* Compute a GDI region from the damaged region */
555 CreateRectRgn(pBoxExtents
->x1
, pBoxExtents
->y1
, pBoxExtents
->x2
,
558 /* Install the GDI region as a clipping region */
559 SelectClipRgn(pScreenPriv
->hdcScreen
, hrgnCombined
);
560 DeleteObject(hrgnCombined
);
563 /* Calculating a bounding box for the source is easy */
564 rcSrc
.left
= pBoxExtents
->x1
;
565 rcSrc
.top
= pBoxExtents
->y1
;
566 rcSrc
.right
= pBoxExtents
->x2
;
567 rcSrc
.bottom
= pBoxExtents
->y2
;
569 /* Calculating a bounding box for the destination is trickier */
570 rcDest
.left
= ptOrigin
.x
+ rcSrc
.left
;
571 rcDest
.top
= ptOrigin
.y
+ rcSrc
.top
;
572 rcDest
.right
= ptOrigin
.x
+ rcSrc
.right
;
573 rcDest
.bottom
= ptOrigin
.y
+ rcSrc
.bottom
;
575 /* Our Blt should be clipped to the invalidated region */
576 ddrval
= IDirectDrawSurface2_Blt(pScreenPriv
->pddsPrimary
,
578 pScreenPriv
->pddsShadow
,
579 &rcSrc
, DDBLT_WAIT
, NULL
);
581 /* Reset the clip region */
582 SelectClipRgn(pScreenPriv
->hdcScreen
, NULL
);
585 /* Relock the shadow surface */
586 ddrval
= IDirectDrawSurface2_Lock(pScreenPriv
->pddsShadow
,
588 pScreenPriv
->pddsdShadow
,
590 if (FAILED(ddrval
)) {
591 ErrorF("winShadowUpdateDD - Lock failed\n");
595 /* Has our memory pointer changed? */
596 if (pScreenInfo
->pfb
!= pScreenPriv
->pddsdShadow
->lpSurface
) {
597 ErrorF("winShadowUpdateDD - Memory location of the shadow "
598 "surface has changed, trying to update the root window "
599 "pixmap header to point to the new address. If you get "
600 "this message and " PROJECT_NAME
" freezes or crashes "
601 "after this message then send a problem report and your "
602 "%s file to " BUILDERADDR
"\n", g_pszLogFile
);
604 /* Location of shadow framebuffer has changed */
605 winUpdateFBPointer(pScreen
, pScreenPriv
->pddsdShadow
->lpSurface
);
610 winInitScreenShadowDD(ScreenPtr pScreen
)
612 winScreenPriv(pScreen
);
614 /* Get a device context for the screen */
615 pScreenPriv
->hdcScreen
= GetDC(pScreenPriv
->hwndScreen
);
617 return winAllocateFBShadowDD(pScreen
);
621 * Call the wrapped CloseScreen function.
623 * Free our resources and private structures.
627 winCloseScreenShadowDD(ScreenPtr pScreen
)
629 winScreenPriv(pScreen
);
630 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
634 winDebug("winCloseScreenShadowDD - Freeing screen resources\n");
637 /* Flag that the screen is closed */
638 pScreenPriv
->fClosed
= TRUE
;
639 pScreenPriv
->fActive
= FALSE
;
641 /* Call the wrapped CloseScreen procedure */
642 WIN_UNWRAP(CloseScreen
);
643 if (pScreen
->CloseScreen
)
644 fReturn
= (*pScreen
->CloseScreen
) (pScreen
);
646 winFreeFBShadowDD(pScreen
);
648 /* Free the screen DC */
649 ReleaseDC(pScreenPriv
->hwndScreen
, pScreenPriv
->hdcScreen
);
651 /* Delete the window property */
652 RemoveProp(pScreenPriv
->hwndScreen
, WIN_SCR_PROP
);
654 /* Delete tray icon, if we have one */
655 if (!pScreenInfo
->fNoTrayIcon
)
656 winDeleteNotifyIcon(pScreenPriv
);
658 /* Free the exit confirmation dialog box, if it exists */
659 if (g_hDlgExit
!= NULL
) {
660 DestroyWindow(g_hDlgExit
);
664 /* Kill our window */
665 if (pScreenPriv
->hwndScreen
) {
666 DestroyWindow(pScreenPriv
->hwndScreen
);
667 pScreenPriv
->hwndScreen
= NULL
;
670 #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
671 /* Destroy the thread startup mutex */
672 pthread_mutex_destroy(&pScreenPriv
->pmServerStarted
);
675 /* Kill our screeninfo's pointer to the screen */
676 pScreenInfo
->pScreen
= NULL
;
678 /* Free the screen privates for this screen */
679 free((pointer
) pScreenPriv
);
685 * Tell mi what sort of visuals we need.
687 * Generally we only need one visual, as our screen can only
688 * handle one format at a time, I believe. You may want
689 * to verify that last sentence.
693 winInitVisualsShadowDD(ScreenPtr pScreen
)
695 winScreenPriv(pScreen
);
696 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
697 DWORD dwRedBits
, dwGreenBits
, dwBlueBits
;
699 /* Count the number of ones in each color mask */
700 dwRedBits
= winCountBits(pScreenPriv
->dwRedMask
);
701 dwGreenBits
= winCountBits(pScreenPriv
->dwGreenMask
);
702 dwBlueBits
= winCountBits(pScreenPriv
->dwBlueMask
);
704 /* Store the maximum number of ones in a color mask as the bitsPerRGB */
705 if (dwRedBits
== 0 || dwGreenBits
== 0 || dwBlueBits
== 0)
706 pScreenPriv
->dwBitsPerRGB
= 8;
707 else if (dwRedBits
> dwGreenBits
&& dwRedBits
> dwBlueBits
)
708 pScreenPriv
->dwBitsPerRGB
= dwRedBits
;
709 else if (dwGreenBits
> dwRedBits
&& dwGreenBits
> dwBlueBits
)
710 pScreenPriv
->dwBitsPerRGB
= dwGreenBits
;
712 pScreenPriv
->dwBitsPerRGB
= dwBlueBits
;
714 ErrorF("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d "
716 (unsigned int) pScreenPriv
->dwRedMask
,
717 (unsigned int) pScreenPriv
->dwGreenMask
,
718 (unsigned int) pScreenPriv
->dwBlueMask
,
719 (int) pScreenPriv
->dwBitsPerRGB
,
720 (int) pScreenInfo
->dwDepth
, (int) pScreenInfo
->dwBPP
);
722 /* Create a single visual according to the Windows screen depth */
723 switch (pScreenInfo
->dwDepth
) {
727 /* Create the real visual */
728 if (!miSetVisualTypesAndMasks(pScreenInfo
->dwDepth
,
730 pScreenPriv
->dwBitsPerRGB
,
732 pScreenPriv
->dwRedMask
,
733 pScreenPriv
->dwGreenMask
,
734 pScreenPriv
->dwBlueMask
)) {
735 ErrorF("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
736 "failed for TrueColor\n");
740 #ifdef XWIN_EMULATEPSEUDO
741 if (!pScreenInfo
->fEmulatePseudo
)
744 /* Setup a pseudocolor visual */
745 if (!miSetVisualTypesAndMasks(8, PseudoColorMask
, 8, -1, 0, 0, 0)) {
746 ErrorF("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
747 "failed for PseudoColor\n");
754 if (!miSetVisualTypesAndMasks(pScreenInfo
->dwDepth
,
755 pScreenInfo
->fFullScreen
756 ? PseudoColorMask
: StaticColorMask
,
757 pScreenPriv
->dwBitsPerRGB
,
758 pScreenInfo
->fFullScreen
759 ? PseudoColor
: StaticColor
,
760 pScreenPriv
->dwRedMask
,
761 pScreenPriv
->dwGreenMask
,
762 pScreenPriv
->dwBlueMask
)) {
763 ErrorF("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
770 ErrorF("winInitVisualsShadowDD - Unknown screen depth\n");
775 winDebug("winInitVisualsShadowDD - Returning\n");
782 * Adjust the user proposed video mode
786 winAdjustVideoModeShadowDD(ScreenPtr pScreen
)
788 winScreenPriv(pScreen
);
789 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
793 /* We're in serious trouble if we can't get a DC */
796 ErrorF("winAdjustVideoModeShadowDD - GetDC () failed\n");
800 /* Query GDI for current display depth */
801 dwBPP
= GetDeviceCaps(hdc
, BITSPIXEL
);
803 /* DirectDraw can only change the depth in fullscreen mode */
804 if (!(pScreenInfo
->fFullScreen
&& (pScreenInfo
->dwBPP
!= WIN_DEFAULT_BPP
))) {
805 /* Otherwise, We'll use GDI's depth */
806 pScreenInfo
->dwBPP
= dwBPP
;
810 ReleaseDC(NULL
, hdc
);
815 * Blt exposed regions to the screen
819 winBltExposedRegionsShadowDD(ScreenPtr pScreen
)
821 winScreenPriv(pScreen
);
822 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
825 HDC hdcUpdate
= NULL
;
827 HRESULT ddrval
= DD_OK
;
832 /* BeginPaint gives us an hdc that clips to the invalidated region */
833 hdcUpdate
= BeginPaint(pScreenPriv
->hwndScreen
, &ps
);
834 if (hdcUpdate
== NULL
) {
835 ErrorF("winBltExposedRegionsShadowDD - BeginPaint () returned "
836 "a NULL device context handle. Aborting blit attempt.\n");
840 /* Unlock the shadow surface, so we can blit */
841 ddrval
= IDirectDrawSurface2_Unlock(pScreenPriv
->pddsShadow
, NULL
);
842 if (FAILED(ddrval
)) {
844 goto winBltExposedRegionsShadowDD_Exit
;
847 /* Flag that we have unlocked the shadow surface */
851 /* Get the origin of the window in the screen coords */
852 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
853 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
855 MapWindowPoints(pScreenPriv
->hwndScreen
,
856 HWND_DESKTOP
, (LPPOINT
) &ptOrigin
, 1);
857 rcDest
.left
= ptOrigin
.x
;
858 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
859 rcDest
.top
= ptOrigin
.y
;
860 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
862 /* Source can be enter shadow surface, as Blt should clip */
865 rcSrc
.right
= pScreenInfo
->dwWidth
;
866 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
868 /* Try to regain the primary surface and blit again if we've lost it */
869 for (i
= 0; i
<= WIN_REGAIN_SURFACE_RETRIES
; ++i
) {
870 /* Our Blt should be clipped to the invalidated region */
871 ddrval
= IDirectDrawSurface2_Blt(pScreenPriv
->pddsPrimary
,
873 pScreenPriv
->pddsShadow
,
874 &rcSrc
, DDBLT_WAIT
, NULL
);
875 if (ddrval
== DDERR_SURFACELOST
) {
876 /* Surface was lost */
877 ErrorF("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
878 "reported that the primary surface was lost, "
879 "trying to restore, retry: %d\n", i
+ 1);
881 /* Try to restore the surface, once */
882 ddrval
= IDirectDrawSurface2_Restore(pScreenPriv
->pddsPrimary
);
883 ErrorF("winBltExposedRegionsShadowDD - "
884 "IDirectDrawSurface2_Restore returned: ");
887 else if (ddrval
== DDERR_WRONGMODE
)
888 ErrorF("DDERR_WRONGMODE\n");
889 else if (ddrval
== DDERR_INCOMPATIBLEPRIMARY
)
890 ErrorF("DDERR_INCOMPATIBLEPRIMARY\n");
891 else if (ddrval
== DDERR_UNSUPPORTED
)
892 ErrorF("DDERR_UNSUPPORTED\n");
893 else if (ddrval
== DDERR_INVALIDPARAMS
)
894 ErrorF("DDERR_INVALIDPARAMS\n");
895 else if (ddrval
== DDERR_INVALIDOBJECT
)
896 ErrorF("DDERR_INVALIDOBJECT\n");
898 ErrorF("unknown error: %08x\n", (unsigned int) ddrval
);
900 /* Loop around to try the blit one more time */
903 else if (FAILED(ddrval
)) {
905 ErrorF("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
906 "failed, but surface not lost: %08x %d\n",
907 (unsigned int) ddrval
, (int) ddrval
);
908 goto winBltExposedRegionsShadowDD_Exit
;
911 /* Success, stop looping */
916 /* Relock the shadow surface */
917 ddrval
= IDirectDrawSurface2_Lock(pScreenPriv
->pddsShadow
,
919 pScreenPriv
->pddsdShadow
,
921 if (FAILED(ddrval
)) {
923 ErrorF("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock "
925 goto winBltExposedRegionsShadowDD_Exit
;
928 /* Indicate that we have relocked the shadow surface */
932 /* Has our memory pointer changed? */
933 if (pScreenInfo
->pfb
!= pScreenPriv
->pddsdShadow
->lpSurface
)
934 winUpdateFBPointer(pScreen
, pScreenPriv
->pddsdShadow
->lpSurface
);
936 winBltExposedRegionsShadowDD_Exit
:
937 /* EndPaint frees the DC */
938 if (hdcUpdate
!= NULL
)
939 EndPaint(pScreenPriv
->hwndScreen
, &ps
);
942 * Relock the surface if it is not locked. We don't care if locking fails,
943 * as it will cause the server to shutdown within a few more operations.
946 IDirectDrawSurface2_Lock(pScreenPriv
->pddsShadow
,
948 pScreenPriv
->pddsdShadow
, DDLOCK_WAIT
, NULL
);
950 /* Has our memory pointer changed? */
951 if (pScreenInfo
->pfb
!= pScreenPriv
->pddsdShadow
->lpSurface
)
952 winUpdateFBPointer(pScreen
, pScreenPriv
->pddsdShadow
->lpSurface
);
960 * Do any engine-specific appliation-activation processing
964 winActivateAppShadowDD(ScreenPtr pScreen
)
966 winScreenPriv(pScreen
);
969 * Do we have a surface?
973 if (pScreenPriv
!= NULL
974 && pScreenPriv
->pddsPrimary
!= NULL
&& pScreenPriv
->fActive
) {
975 /* Primary surface was lost, restore it */
976 IDirectDrawSurface2_Restore(pScreenPriv
->pddsPrimary
);
983 * Reblit the shadow framebuffer to the screen.
987 winRedrawScreenShadowDD(ScreenPtr pScreen
)
989 winScreenPriv(pScreen
);
990 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
991 HRESULT ddrval
= DD_OK
;
995 /* Get the origin of the window in the screen coords */
996 ptOrigin
.x
= pScreenInfo
->dwXOffset
;
997 ptOrigin
.y
= pScreenInfo
->dwYOffset
;
998 MapWindowPoints(pScreenPriv
->hwndScreen
,
999 HWND_DESKTOP
, (LPPOINT
) &ptOrigin
, 1);
1000 rcDest
.left
= ptOrigin
.x
;
1001 rcDest
.right
= ptOrigin
.x
+ pScreenInfo
->dwWidth
;
1002 rcDest
.top
= ptOrigin
.y
;
1003 rcDest
.bottom
= ptOrigin
.y
+ pScreenInfo
->dwHeight
;
1005 /* Source can be entire shadow surface, as Blt should clip for us */
1008 rcSrc
.right
= pScreenInfo
->dwWidth
;
1009 rcSrc
.bottom
= pScreenInfo
->dwHeight
;
1011 /* Redraw the whole window, to take account for the new colors */
1012 ddrval
= IDirectDrawSurface2_Blt(pScreenPriv
->pddsPrimary
,
1014 pScreenPriv
->pddsShadow
,
1015 &rcSrc
, DDBLT_WAIT
, NULL
);
1016 if (FAILED(ddrval
)) {
1017 ErrorF("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () "
1018 "failed: %08x\n", (unsigned int) ddrval
);
1025 * Realize the currently installed colormap
1029 winRealizeInstalledPaletteShadowDD(ScreenPtr pScreen
)
1035 * Install the specified colormap
1039 winInstallColormapShadowDD(ColormapPtr pColormap
)
1041 ScreenPtr pScreen
= pColormap
->pScreen
;
1043 winScreenPriv(pScreen
);
1044 winCmapPriv(pColormap
);
1045 HRESULT ddrval
= DD_OK
;
1047 /* Install the DirectDraw palette on the primary surface */
1048 ddrval
= IDirectDrawSurface2_SetPalette(pScreenPriv
->pddsPrimary
,
1049 pCmapPriv
->lpDDPalette
);
1050 if (FAILED(ddrval
)) {
1051 ErrorF("winInstallColormapShadowDD - Failed installing the "
1052 "DirectDraw palette.\n");
1056 /* Save a pointer to the newly installed colormap */
1057 pScreenPriv
->pcmapInstalled
= pColormap
;
1063 * Store the specified colors in the specified colormap
1067 winStoreColorsShadowDD(ColormapPtr pColormap
, int ndef
, xColorItem
* pdefs
)
1069 ScreenPtr pScreen
= pColormap
->pScreen
;
1071 winScreenPriv(pScreen
);
1072 winCmapPriv(pColormap
);
1073 ColormapPtr curpmap
= pScreenPriv
->pcmapInstalled
;
1074 HRESULT ddrval
= DD_OK
;
1076 /* Put the X colormap entries into the Windows logical palette */
1077 ddrval
= IDirectDrawPalette_SetEntries(pCmapPriv
->lpDDPalette
,
1083 if (FAILED(ddrval
)) {
1084 ErrorF("winStoreColorsShadowDD - SetEntries () failed\n");
1088 /* Don't install the DirectDraw palette if the colormap is not installed */
1089 if (pColormap
!= curpmap
) {
1093 if (!winInstallColormapShadowDD(pColormap
)) {
1094 ErrorF("winStoreColorsShadowDD - Failed installing colormap\n");
1102 * Colormap initialization procedure
1106 winCreateColormapShadowDD(ColormapPtr pColormap
)
1108 HRESULT ddrval
= DD_OK
;
1109 ScreenPtr pScreen
= pColormap
->pScreen
;
1111 winScreenPriv(pScreen
);
1112 winCmapPriv(pColormap
);
1114 /* Create a DirectDraw palette */
1115 ddrval
= IDirectDraw2_CreatePalette(pScreenPriv
->pdd
,
1116 DDPCAPS_8BIT
| DDPCAPS_ALLOW256
,
1117 pCmapPriv
->peColors
,
1118 &pCmapPriv
->lpDDPalette
, NULL
);
1119 if (FAILED(ddrval
)) {
1120 ErrorF("winCreateColormapShadowDD - CreatePalette failed\n");
1128 * Colormap destruction procedure
1132 winDestroyColormapShadowDD(ColormapPtr pColormap
)
1134 winScreenPriv(pColormap
->pScreen
);
1135 winCmapPriv(pColormap
);
1136 HRESULT ddrval
= DD_OK
;
1139 * Is colormap to be destroyed the default?
1141 * Non-default colormaps should have had winUninstallColormap
1142 * called on them before we get here. The default colormap
1143 * will not have had winUninstallColormap called on it. Thus,
1144 * we need to handle the default colormap in a special way.
1146 if (pColormap
->flags
& IsDefault
) {
1148 winDebug("winDestroyColormapShadowDD - Destroying default "
1153 * FIXME: Walk the list of all screens, popping the default
1154 * palette out of each screen device context.
1157 /* Pop the palette out of the primary surface */
1158 ddrval
= IDirectDrawSurface2_SetPalette(pScreenPriv
->pddsPrimary
, NULL
);
1159 if (FAILED(ddrval
)) {
1160 ErrorF("winDestroyColormapShadowDD - Failed freeing the "
1161 "default colormap DirectDraw palette.\n");
1165 /* Clear our private installed colormap pointer */
1166 pScreenPriv
->pcmapInstalled
= NULL
;
1169 /* Release the palette */
1170 IDirectDrawPalette_Release(pCmapPriv
->lpDDPalette
);
1172 /* Invalidate the colormap privates */
1173 pCmapPriv
->lpDDPalette
= NULL
;
1179 * Set engine specific functions
1183 winSetEngineFunctionsShadowDD(ScreenPtr pScreen
)
1185 winScreenPriv(pScreen
);
1186 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
1188 /* Set our pointers */
1189 pScreenPriv
->pwinAllocateFB
= winAllocateFBShadowDD
;
1190 pScreenPriv
->pwinFreeFB
= winFreeFBShadowDD
;
1191 pScreenPriv
->pwinShadowUpdate
= winShadowUpdateDD
;
1192 pScreenPriv
->pwinInitScreen
= winInitScreenShadowDD
;
1193 pScreenPriv
->pwinCloseScreen
= winCloseScreenShadowDD
;
1194 pScreenPriv
->pwinInitVisuals
= winInitVisualsShadowDD
;
1195 pScreenPriv
->pwinAdjustVideoMode
= winAdjustVideoModeShadowDD
;
1196 if (pScreenInfo
->fFullScreen
)
1197 pScreenPriv
->pwinCreateBoundingWindow
=
1198 winCreateBoundingWindowFullScreen
;
1200 pScreenPriv
->pwinCreateBoundingWindow
= winCreateBoundingWindowWindowed
;
1201 pScreenPriv
->pwinFinishScreenInit
= winFinishScreenInitFB
;
1202 pScreenPriv
->pwinBltExposedRegions
= winBltExposedRegionsShadowDD
;
1203 pScreenPriv
->pwinActivateApp
= winActivateAppShadowDD
;
1204 pScreenPriv
->pwinRedrawScreen
= winRedrawScreenShadowDD
;
1205 pScreenPriv
->pwinRealizeInstalledPalette
1206 = winRealizeInstalledPaletteShadowDD
;
1207 pScreenPriv
->pwinInstallColormap
= winInstallColormapShadowDD
;
1208 pScreenPriv
->pwinStoreColors
= winStoreColorsShadowDD
;
1209 pScreenPriv
->pwinCreateColormap
= winCreateColormapShadowDD
;
1210 pScreenPriv
->pwinDestroyColormap
= winDestroyColormapShadowDD
;
1211 pScreenPriv
->pwinHotKeyAltTab
=
1212 (winHotKeyAltTabProcPtr
) (void (*)(void)) NoopDDA
;
1213 pScreenPriv
->pwinCreatePrimarySurface
= winCreatePrimarySurfaceShadowDD
;
1214 pScreenPriv
->pwinReleasePrimarySurface
= winReleasePrimarySurfaceShadowDD
;
1215 #ifdef XWIN_MULTIWINDOW
1216 pScreenPriv
->pwinFinishCreateWindowsWindow
=
1217 (winFinishCreateWindowsWindowProcPtr
) (void (*)(void)) NoopDDA
;