Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xwin / winshaddd.c
CommitLineData
a09e091a
JB
1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
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:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
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.
22 *
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.
27 *
28 * Authors: Dakshinamurthy Karra
29 * Suhaib M Siddiqi
30 * Peter Busch
31 * Harold L Hunt II
32 */
33
34#ifdef HAVE_XWIN_CONFIG_H
35#include <xwin-config.h>
36#endif
37#include "win.h"
38
39/*
40 * Local prototypes
41 */
42
43static Bool
44 winAllocateFBShadowDD(ScreenPtr pScreen);
45
46static void
47 winShadowUpdateDD(ScreenPtr pScreen, shadowBufPtr pBuf);
48
49static Bool
50 winCloseScreenShadowDD(ScreenPtr pScreen);
51
52static Bool
53 winInitVisualsShadowDD(ScreenPtr pScreen);
54
55static Bool
56 winAdjustVideoModeShadowDD(ScreenPtr pScreen);
57
58static Bool
59 winBltExposedRegionsShadowDD(ScreenPtr pScreen);
60
61static Bool
62 winActivateAppShadowDD(ScreenPtr pScreen);
63
64static Bool
65 winRedrawScreenShadowDD(ScreenPtr pScreen);
66
67static Bool
68 winRealizeInstalledPaletteShadowDD(ScreenPtr pScreen);
69
70static Bool
71 winInstallColormapShadowDD(ColormapPtr pColormap);
72
73static Bool
74 winStoreColorsShadowDD(ColormapPtr pmap, int ndef, xColorItem * pdefs);
75
76static Bool
77 winCreateColormapShadowDD(ColormapPtr pColormap);
78
79static Bool
80 winDestroyColormapShadowDD(ColormapPtr pColormap);
81
82static Bool
83 winCreatePrimarySurfaceShadowDD(ScreenPtr pScreen);
84
85static Bool
86 winReleasePrimarySurfaceShadowDD(ScreenPtr pScreen);
87
88/*
89 * Create the primary surface and attach the clipper.
90 * Used for both the initial surface creation and during
91 * WM_DISPLAYCHANGE messages.
92 */
93
94static Bool
95winCreatePrimarySurfaceShadowDD(ScreenPtr pScreen)
96{
97 winScreenPriv(pScreen);
98 HRESULT ddrval = DD_OK;
99 DDSURFACEDESC ddsd;
100
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;
106
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);
113 return FALSE;
114 }
115
116#if CYGDEBUG
117 winDebug("winCreatePrimarySurfaceShadowDD - Created primary surface\n");
118#endif
119
120 /*
121 * Attach a clipper to the primary surface that will clip our blits to our
122 * display window.
123 */
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);
129 return FALSE;
130 }
131
132#if CYGDEBUG
133 winDebug("winCreatePrimarySurfaceShadowDD - Attached clipper to "
134 "primary surface\n");
135#endif
136
137 /* Everything was correct */
138 return TRUE;
139}
140
141/*
142 * Detach the clipper and release the primary surface.
143 * Called from WM_DISPLAYCHANGE.
144 */
145
146static Bool
147winReleasePrimarySurfaceShadowDD(ScreenPtr pScreen)
148{
149 winScreenPriv(pScreen);
150
151 ErrorF("winReleasePrimarySurfaceShadowDD - Hello\n");
152
153 /* Release the primary surface and clipper, if they exist */
154 if (pScreenPriv->pddsPrimary) {
155 /*
156 * Detach the clipper from the primary surface.
157 * NOTE: We do this explicity for clarity. The Clipper is not released.
158 */
159 IDirectDrawSurface2_SetClipper(pScreenPriv->pddsPrimary, NULL);
160
161 ErrorF("winReleasePrimarySurfaceShadowDD - Detached clipper\n");
162
163 /* Release the primary surface */
164 IDirectDrawSurface2_Release(pScreenPriv->pddsPrimary);
165 pScreenPriv->pddsPrimary = NULL;
166 }
167
168 ErrorF("winReleasePrimarySurfaceShadowDD - Released primary surface\n");
169
170 return TRUE;
171}
172
173/*
174 * Create a DirectDraw surface for the shadow framebuffer; also create
175 * a primary surface object so we can blit to the display.
176 *
177 * Install a DirectDraw clipper on our primary surface object
178 * that clips our blits to the unobscured client area of our display window.
179 */
180
181static Bool
182winAllocateFBShadowDD(ScreenPtr pScreen)
183{
184 winScreenPriv(pScreen);
185 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
186 HRESULT ddrval = DD_OK;
187 DDSURFACEDESC ddsd;
188 DDSURFACEDESC *pddsdShadow = NULL;
189
190#if CYGDEBUG
191 winDebug("winAllocateFBShadowDD\n");
192#endif
193
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);
200 return FALSE;
201 }
202
203#if CYGDEBUG
204 winDebug("winAllocateFBShadowDD - Created a clipper\n");
205#endif
206
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);
213 return FALSE;
214 }
215
216#if CYGDEBUG
217 winDebug("winAllocateFBShadowDD - Attached clipper to window\n");
218#endif
219
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);
225 return FALSE;
226 }
227
228#if CYGDEBUG
229 winDebug("winAllocateFBShadowDD () - Created and initialized DD\n");
230#endif
231
232 /* Get a DirectDraw2 interface pointer */
233 ddrval = IDirectDraw_QueryInterface(pScreenPriv->pdd,
234 &IID_IDirectDraw2,
235 (LPVOID *) &pScreenPriv->pdd2);
236 if (FAILED(ddrval)) {
237 ErrorF("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
238 (unsigned int) ddrval);
239 return FALSE;
240 }
241
242 /* Are we full screen? */
243 if (pScreenInfo->fFullScreen) {
244 DDSURFACEDESC ddsdCurrent;
245 DWORD dwRefreshRateCurrent = 0;
246 HDC hdc = NULL;
247
248 /* Set the cooperative level to full screen */
249 ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2,
250 pScreenPriv->hwndScreen,
251 DDSCL_EXCLUSIVE
252 | DDSCL_FULLSCREEN);
253 if (FAILED(ddrval)) {
254 ErrorF("winAllocateFBShadowDD - Could not set "
255 "cooperative level: %08x\n", (unsigned int) ddrval);
256 return FALSE;
257 }
258
259 /*
260 * We only need to get the current refresh rate for comparison
261 * if a refresh rate has been passed on the command line.
262 */
263 if (pScreenInfo->dwRefreshRate != 0) {
264 ZeroMemory(&ddsdCurrent, sizeof(ddsdCurrent));
265 ddsdCurrent.dwSize = sizeof(ddsdCurrent);
266
267 /* Get information about current display settings */
268 ddrval = IDirectDraw2_GetDisplayMode(pScreenPriv->pdd2,
269 &ddsdCurrent);
270 if (FAILED(ddrval)) {
271 ErrorF("winAllocateFBShadowDD - Could not get current "
272 "refresh rate: %08x. Continuing.\n",
273 (unsigned int) ddrval);
274 dwRefreshRateCurrent = 0;
275 }
276 else {
277 /* Grab the current refresh rate */
278 dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
279 }
280 }
281
282 /* Clean up the refresh rate */
283 if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate) {
284 /*
285 * Refresh rate is non-specified or equal to current.
286 */
287 pScreenInfo->dwRefreshRate = 0;
288 }
289
290 /* Grab a device context for the screen */
291 hdc = GetDC(NULL);
292 if (hdc == NULL) {
293 ErrorF("winAllocateFBShadowDD - GetDC () failed\n");
294 return FALSE;
295 }
296
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");
304
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,
309 pScreenInfo->dwBPP,
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);
315 ErrorF
316 ("winAllocateFBShadowDD - Using default driver refresh rate\n");
317 ddrval =
318 IDirectDraw2_SetDisplayMode(pScreenPriv->pdd2,
319 pScreenInfo->dwWidth,
320 pScreenInfo->dwHeight,
321 pScreenInfo->dwBPP, 0, 0);
322 if (FAILED(ddrval)) {
323 ErrorF
324 ("winAllocateFBShadowDD - Could not set default refresh rate "
325 "full screen display mode: %08x\n",
326 (unsigned int) ddrval);
327 return FALSE;
328 }
329 }
330 }
331 else {
332 ErrorF("winAllocateFBShadowDD - Not changing video mode\n");
333 }
334
335 /* Release our DC */
336 ReleaseDC(NULL, hdc);
337 hdc = NULL;
338 }
339 else {
340 /* Set the cooperative level for windowed mode */
341 ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2,
342 pScreenPriv->hwndScreen,
343 DDSCL_NORMAL);
344 if (FAILED(ddrval)) {
345 ErrorF("winAllocateFBShadowDD - Could not set "
346 "cooperative level: %08x\n", (unsigned int) ddrval);
347 return FALSE;
348 }
349 }
350
351 /* Create the primary surface */
352 if (!winCreatePrimarySurfaceShadowDD(pScreen)) {
353 ErrorF("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD "
354 "failed\n");
355 return FALSE;
356 }
357
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.
365 */
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;
372
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);
379 return FALSE;
380 }
381
382#if CYGDEBUG
383 winDebug("winAllocateFBShadowDD - Created shadow\n");
384#endif
385
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");
391 return FALSE;
392 }
393 ZeroMemory(pddsdShadow, sizeof(*pddsdShadow));
394 pddsdShadow->dwSize = sizeof(*pddsdShadow);
395
396#if CYGDEBUG
397 winDebug("winAllocateFBShadowDD - Locking shadow\n");
398#endif
399
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);
406 return FALSE;
407 }
408
409#if CYGDEBUG
410 winDebug("winAllocateFBShadowDD - Locked shadow\n");
411#endif
412
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");
416 return FALSE;
417 }
418
419 /* Grab the pitch from the surface desc */
420 pScreenInfo->dwStride = (pddsdShadow->u1.lPitch * 8)
421 / pScreenInfo->dwBPP;
422
423 /* Save the pointer to our surface memory */
424 pScreenInfo->pfb = pddsdShadow->lpSurface;
425
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;
430
431#if CYGDEBUG
432 winDebug("winAllocateFBShadowDD - Returning\n");
433#endif
434
435 return TRUE;
436}
437
438static void
439winFreeFBShadowDD(ScreenPtr pScreen)
440{
441 winScreenPriv(pScreen);
442 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
443
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;
449 }
450
451 /* Detach the clipper from the primary surface and release the primary surface, if there is one */
452 winReleasePrimarySurfaceShadowDD(pScreen);
453
454 /* Release the clipper object */
455 if (pScreenPriv->pddcPrimary) {
456 IDirectDrawClipper_Release(pScreenPriv->pddcPrimary);
457 pScreenPriv->pddcPrimary = NULL;
458 }
459
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;
465 }
466
467 /* Free the DirectDraw object, if there is one */
468 if (pScreenPriv->pdd) {
469 IDirectDraw_Release(pScreenPriv->pdd);
470 pScreenPriv->pdd = NULL;
471 }
472
473 /* Invalidate the ScreenInfo's fb pointer */
474 pScreenInfo->pfb = NULL;
475}
476
477/*
478 * Transfer the damaged regions of the shadow framebuffer to the display.
479 */
480
481static void
482winShadowUpdateDD(ScreenPtr pScreen, shadowBufPtr pBuf)
483{
484 winScreenPriv(pScreen);
485 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
486 RegionPtr damage = shadowDamage(pBuf);
487 HRESULT ddrval = DD_OK;
488 RECT rcDest, rcSrc;
489 POINT ptOrigin;
490 DWORD dwBox = RegionNumRects(damage);
491 BoxPtr pBox = RegionRects(damage);
492 HRGN hrgnCombined = NULL;
493
494 /*
495 * Return immediately if the app is not active
496 * and we are fullscreen, or if we have a bad display depth
497 */
498 if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
499 || pScreenPriv->fBadDepth)
500 return;
501
502 /* Return immediately if we didn't get needed surfaces */
503 if (!pScreenPriv->pddsPrimary || !pScreenPriv->pddsShadow)
504 return;
505
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);
511
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");
516 return;
517 }
518
519 /*
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.
523 */
524 if (pScreenInfo->dwClipUpdatesNBoxes == 0
525 || dwBox < pScreenInfo->dwClipUpdatesNBoxes) {
526 /* Loop through all boxes in the damaged region */
527 while (dwBox--) {
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;
533
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;
539
540 /* Blit the damaged areas */
541 ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsPrimary,
542 &rcDest,
543 pScreenPriv->pddsShadow,
544 &rcSrc, DDBLT_WAIT, NULL);
545
546 /* Get a pointer to the next box */
547 ++pBox;
548 }
549 }
550 else {
551 BoxPtr pBoxExtents = RegionExtents(damage);
552
553 /* Compute a GDI region from the damaged region */
554 hrgnCombined =
555 CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2,
556 pBoxExtents->y2);
557
558 /* Install the GDI region as a clipping region */
559 SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined);
560 DeleteObject(hrgnCombined);
561 hrgnCombined = NULL;
562
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;
568
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;
574
575 /* Our Blt should be clipped to the invalidated region */
576 ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsPrimary,
577 &rcDest,
578 pScreenPriv->pddsShadow,
579 &rcSrc, DDBLT_WAIT, NULL);
580
581 /* Reset the clip region */
582 SelectClipRgn(pScreenPriv->hdcScreen, NULL);
583 }
584
585 /* Relock the shadow surface */
586 ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsShadow,
587 NULL,
588 pScreenPriv->pddsdShadow,
589 DDLOCK_WAIT, NULL);
590 if (FAILED(ddrval)) {
591 ErrorF("winShadowUpdateDD - Lock failed\n");
592 return;
593 }
594
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);
603
604 /* Location of shadow framebuffer has changed */
605 winUpdateFBPointer(pScreen, pScreenPriv->pddsdShadow->lpSurface);
606 }
607}
608
609static Bool
610winInitScreenShadowDD(ScreenPtr pScreen)
611{
612 winScreenPriv(pScreen);
613
614 /* Get a device context for the screen */
615 pScreenPriv->hdcScreen = GetDC(pScreenPriv->hwndScreen);
616
617 return winAllocateFBShadowDD(pScreen);
618}
619
620/*
621 * Call the wrapped CloseScreen function.
622 *
623 * Free our resources and private structures.
624 */
625
626static Bool
627winCloseScreenShadowDD(ScreenPtr pScreen)
628{
629 winScreenPriv(pScreen);
630 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
631 Bool fReturn;
632
633#if CYGDEBUG
634 winDebug("winCloseScreenShadowDD - Freeing screen resources\n");
635#endif
636
637 /* Flag that the screen is closed */
638 pScreenPriv->fClosed = TRUE;
639 pScreenPriv->fActive = FALSE;
640
641 /* Call the wrapped CloseScreen procedure */
642 WIN_UNWRAP(CloseScreen);
643 if (pScreen->CloseScreen)
644 fReturn = (*pScreen->CloseScreen) (pScreen);
645
646 winFreeFBShadowDD(pScreen);
647
648 /* Free the screen DC */
649 ReleaseDC(pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
650
651 /* Delete the window property */
652 RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP);
653
654 /* Delete tray icon, if we have one */
655 if (!pScreenInfo->fNoTrayIcon)
656 winDeleteNotifyIcon(pScreenPriv);
657
658 /* Free the exit confirmation dialog box, if it exists */
659 if (g_hDlgExit != NULL) {
660 DestroyWindow(g_hDlgExit);
661 g_hDlgExit = NULL;
662 }
663
664 /* Kill our window */
665 if (pScreenPriv->hwndScreen) {
666 DestroyWindow(pScreenPriv->hwndScreen);
667 pScreenPriv->hwndScreen = NULL;
668 }
669
670#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
671 /* Destroy the thread startup mutex */
672 pthread_mutex_destroy(&pScreenPriv->pmServerStarted);
673#endif
674
675 /* Kill our screeninfo's pointer to the screen */
676 pScreenInfo->pScreen = NULL;
677
678 /* Free the screen privates for this screen */
679 free((pointer) pScreenPriv);
680
681 return fReturn;
682}
683
684/*
685 * Tell mi what sort of visuals we need.
686 *
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.
690 */
691
692static Bool
693winInitVisualsShadowDD(ScreenPtr pScreen)
694{
695 winScreenPriv(pScreen);
696 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
697 DWORD dwRedBits, dwGreenBits, dwBlueBits;
698
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);
703
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;
711 else
712 pScreenPriv->dwBitsPerRGB = dwBlueBits;
713
714 ErrorF("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d "
715 "bpp %d\n",
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);
721
722 /* Create a single visual according to the Windows screen depth */
723 switch (pScreenInfo->dwDepth) {
724 case 24:
725 case 16:
726 case 15:
727 /* Create the real visual */
728 if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
729 TrueColorMask,
730 pScreenPriv->dwBitsPerRGB,
731 TrueColor,
732 pScreenPriv->dwRedMask,
733 pScreenPriv->dwGreenMask,
734 pScreenPriv->dwBlueMask)) {
735 ErrorF("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
736 "failed for TrueColor\n");
737 return FALSE;
738 }
739
740#ifdef XWIN_EMULATEPSEUDO
741 if (!pScreenInfo->fEmulatePseudo)
742 break;
743
744 /* Setup a pseudocolor visual */
745 if (!miSetVisualTypesAndMasks(8, PseudoColorMask, 8, -1, 0, 0, 0)) {
746 ErrorF("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
747 "failed for PseudoColor\n");
748 return FALSE;
749 }
750#endif
751 break;
752
753 case 8:
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 "
764 "failed\n");
765 return FALSE;
766 }
767 break;
768
769 default:
770 ErrorF("winInitVisualsShadowDD - Unknown screen depth\n");
771 return FALSE;
772 }
773
774#if CYGDEBUG
775 winDebug("winInitVisualsShadowDD - Returning\n");
776#endif
777
778 return TRUE;
779}
780
781/*
782 * Adjust the user proposed video mode
783 */
784
785static Bool
786winAdjustVideoModeShadowDD(ScreenPtr pScreen)
787{
788 winScreenPriv(pScreen);
789 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
790 HDC hdc = NULL;
791 DWORD dwBPP;
792
793 /* We're in serious trouble if we can't get a DC */
794 hdc = GetDC(NULL);
795 if (hdc == NULL) {
796 ErrorF("winAdjustVideoModeShadowDD - GetDC () failed\n");
797 return FALSE;
798 }
799
800 /* Query GDI for current display depth */
801 dwBPP = GetDeviceCaps(hdc, BITSPIXEL);
802
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;
807 }
808
809 /* Release our DC */
810 ReleaseDC(NULL, hdc);
811 return TRUE;
812}
813
814/*
815 * Blt exposed regions to the screen
816 */
817
818static Bool
819winBltExposedRegionsShadowDD(ScreenPtr pScreen)
820{
821 winScreenPriv(pScreen);
822 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
823 RECT rcSrc, rcDest;
824 POINT ptOrigin;
825 HDC hdcUpdate = NULL;
826 PAINTSTRUCT ps;
827 HRESULT ddrval = DD_OK;
828 Bool fReturn = TRUE;
829 Bool fLocked = TRUE;
830 int i;
831
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");
837 return FALSE;
838 }
839
840 /* Unlock the shadow surface, so we can blit */
841 ddrval = IDirectDrawSurface2_Unlock(pScreenPriv->pddsShadow, NULL);
842 if (FAILED(ddrval)) {
843 fReturn = FALSE;
844 goto winBltExposedRegionsShadowDD_Exit;
845 }
846 else {
847 /* Flag that we have unlocked the shadow surface */
848 fLocked = FALSE;
849 }
850
851 /* Get the origin of the window in the screen coords */
852 ptOrigin.x = pScreenInfo->dwXOffset;
853 ptOrigin.y = pScreenInfo->dwYOffset;
854
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;
861
862 /* Source can be enter shadow surface, as Blt should clip */
863 rcSrc.left = 0;
864 rcSrc.top = 0;
865 rcSrc.right = pScreenInfo->dwWidth;
866 rcSrc.bottom = pScreenInfo->dwHeight;
867
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,
872 &rcDest,
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);
880
881 /* Try to restore the surface, once */
882 ddrval = IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary);
883 ErrorF("winBltExposedRegionsShadowDD - "
884 "IDirectDrawSurface2_Restore returned: ");
885 if (ddrval == DD_OK)
886 ErrorF("DD_OK\n");
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");
897 else
898 ErrorF("unknown error: %08x\n", (unsigned int) ddrval);
899
900 /* Loop around to try the blit one more time */
901 continue;
902 }
903 else if (FAILED(ddrval)) {
904 fReturn = FALSE;
905 ErrorF("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
906 "failed, but surface not lost: %08x %d\n",
907 (unsigned int) ddrval, (int) ddrval);
908 goto winBltExposedRegionsShadowDD_Exit;
909 }
910 else {
911 /* Success, stop looping */
912 break;
913 }
914 }
915
916 /* Relock the shadow surface */
917 ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsShadow,
918 NULL,
919 pScreenPriv->pddsdShadow,
920 DDLOCK_WAIT, NULL);
921 if (FAILED(ddrval)) {
922 fReturn = FALSE;
923 ErrorF("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock "
924 "failed\n");
925 goto winBltExposedRegionsShadowDD_Exit;
926 }
927 else {
928 /* Indicate that we have relocked the shadow surface */
929 fLocked = TRUE;
930 }
931
932 /* Has our memory pointer changed? */
933 if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
934 winUpdateFBPointer(pScreen, pScreenPriv->pddsdShadow->lpSurface);
935
936 winBltExposedRegionsShadowDD_Exit:
937 /* EndPaint frees the DC */
938 if (hdcUpdate != NULL)
939 EndPaint(pScreenPriv->hwndScreen, &ps);
940
941 /*
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.
944 */
945 if (!fLocked) {
946 IDirectDrawSurface2_Lock(pScreenPriv->pddsShadow,
947 NULL,
948 pScreenPriv->pddsdShadow, DDLOCK_WAIT, NULL);
949
950 /* Has our memory pointer changed? */
951 if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
952 winUpdateFBPointer(pScreen, pScreenPriv->pddsdShadow->lpSurface);
953
954 fLocked = TRUE;
955 }
956 return fReturn;
957}
958
959/*
960 * Do any engine-specific appliation-activation processing
961 */
962
963static Bool
964winActivateAppShadowDD(ScreenPtr pScreen)
965{
966 winScreenPriv(pScreen);
967
968 /*
969 * Do we have a surface?
970 * Are we active?
971 * Are we fullscreen?
972 */
973 if (pScreenPriv != NULL
974 && pScreenPriv->pddsPrimary != NULL && pScreenPriv->fActive) {
975 /* Primary surface was lost, restore it */
976 IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary);
977 }
978
979 return TRUE;
980}
981
982/*
983 * Reblit the shadow framebuffer to the screen.
984 */
985
986static Bool
987winRedrawScreenShadowDD(ScreenPtr pScreen)
988{
989 winScreenPriv(pScreen);
990 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
991 HRESULT ddrval = DD_OK;
992 RECT rcSrc, rcDest;
993 POINT ptOrigin;
994
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;
1004
1005 /* Source can be entire shadow surface, as Blt should clip for us */
1006 rcSrc.left = 0;
1007 rcSrc.top = 0;
1008 rcSrc.right = pScreenInfo->dwWidth;
1009 rcSrc.bottom = pScreenInfo->dwHeight;
1010
1011 /* Redraw the whole window, to take account for the new colors */
1012 ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsPrimary,
1013 &rcDest,
1014 pScreenPriv->pddsShadow,
1015 &rcSrc, DDBLT_WAIT, NULL);
1016 if (FAILED(ddrval)) {
1017 ErrorF("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () "
1018 "failed: %08x\n", (unsigned int) ddrval);
1019 }
1020
1021 return TRUE;
1022}
1023
1024/*
1025 * Realize the currently installed colormap
1026 */
1027
1028static Bool
1029winRealizeInstalledPaletteShadowDD(ScreenPtr pScreen)
1030{
1031 return TRUE;
1032}
1033
1034/*
1035 * Install the specified colormap
1036 */
1037
1038static Bool
1039winInstallColormapShadowDD(ColormapPtr pColormap)
1040{
1041 ScreenPtr pScreen = pColormap->pScreen;
1042
1043 winScreenPriv(pScreen);
1044 winCmapPriv(pColormap);
1045 HRESULT ddrval = DD_OK;
1046
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");
1053 return FALSE;
1054 }
1055
1056 /* Save a pointer to the newly installed colormap */
1057 pScreenPriv->pcmapInstalled = pColormap;
1058
1059 return TRUE;
1060}
1061
1062/*
1063 * Store the specified colors in the specified colormap
1064 */
1065
1066static Bool
1067winStoreColorsShadowDD(ColormapPtr pColormap, int ndef, xColorItem * pdefs)
1068{
1069 ScreenPtr pScreen = pColormap->pScreen;
1070
1071 winScreenPriv(pScreen);
1072 winCmapPriv(pColormap);
1073 ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
1074 HRESULT ddrval = DD_OK;
1075
1076 /* Put the X colormap entries into the Windows logical palette */
1077 ddrval = IDirectDrawPalette_SetEntries(pCmapPriv->lpDDPalette,
1078 0,
1079 pdefs[0].pixel,
1080 ndef,
1081 pCmapPriv->peColors
1082 + pdefs[0].pixel);
1083 if (FAILED(ddrval)) {
1084 ErrorF("winStoreColorsShadowDD - SetEntries () failed\n");
1085 return FALSE;
1086 }
1087
1088 /* Don't install the DirectDraw palette if the colormap is not installed */
1089 if (pColormap != curpmap) {
1090 return TRUE;
1091 }
1092
1093 if (!winInstallColormapShadowDD(pColormap)) {
1094 ErrorF("winStoreColorsShadowDD - Failed installing colormap\n");
1095 return FALSE;
1096 }
1097
1098 return TRUE;
1099}
1100
1101/*
1102 * Colormap initialization procedure
1103 */
1104
1105static Bool
1106winCreateColormapShadowDD(ColormapPtr pColormap)
1107{
1108 HRESULT ddrval = DD_OK;
1109 ScreenPtr pScreen = pColormap->pScreen;
1110
1111 winScreenPriv(pScreen);
1112 winCmapPriv(pColormap);
1113
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");
1121 return FALSE;
1122 }
1123
1124 return TRUE;
1125}
1126
1127/*
1128 * Colormap destruction procedure
1129 */
1130
1131static Bool
1132winDestroyColormapShadowDD(ColormapPtr pColormap)
1133{
1134 winScreenPriv(pColormap->pScreen);
1135 winCmapPriv(pColormap);
1136 HRESULT ddrval = DD_OK;
1137
1138 /*
1139 * Is colormap to be destroyed the default?
1140 *
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.
1145 */
1146 if (pColormap->flags & IsDefault) {
1147#if CYGDEBUG
1148 winDebug("winDestroyColormapShadowDD - Destroying default "
1149 "colormap\n");
1150#endif
1151
1152 /*
1153 * FIXME: Walk the list of all screens, popping the default
1154 * palette out of each screen device context.
1155 */
1156
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");
1162 return FALSE;
1163 }
1164
1165 /* Clear our private installed colormap pointer */
1166 pScreenPriv->pcmapInstalled = NULL;
1167 }
1168
1169 /* Release the palette */
1170 IDirectDrawPalette_Release(pCmapPriv->lpDDPalette);
1171
1172 /* Invalidate the colormap privates */
1173 pCmapPriv->lpDDPalette = NULL;
1174
1175 return TRUE;
1176}
1177
1178/*
1179 * Set engine specific functions
1180 */
1181
1182Bool
1183winSetEngineFunctionsShadowDD(ScreenPtr pScreen)
1184{
1185 winScreenPriv(pScreen);
1186 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
1187
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;
1199 else
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;
1218#endif
1219
1220 return TRUE;
1221}