Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xwin / winshadgdi.c
CommitLineData
a09e091a
JB
1/*
2 *Copyright (C) 2001-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II
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 Harold L Hunt II.
27 *
28 * Authors: Harold L Hunt II
29 */
30
31#ifdef HAVE_XWIN_CONFIG_H
32#include <xwin-config.h>
33#endif
34#include "win.h"
35
36/*
37 * Local function prototypes
38 */
39
40#ifdef XWIN_MULTIWINDOW
41static wBOOL CALLBACK winRedrawAllProcShadowGDI(HWND hwnd, LPARAM lParam);
42
43static wBOOL CALLBACK winRedrawDamagedWindowShadowGDI(HWND hwnd, LPARAM lParam);
44#endif
45
46static Bool
47 winAllocateFBShadowGDI(ScreenPtr pScreen);
48
49static void
50 winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf);
51
52static Bool
53 winCloseScreenShadowGDI(ScreenPtr pScreen);
54
55static Bool
56 winInitVisualsShadowGDI(ScreenPtr pScreen);
57
58static Bool
59 winAdjustVideoModeShadowGDI(ScreenPtr pScreen);
60
61static Bool
62 winBltExposedRegionsShadowGDI(ScreenPtr pScreen);
63
64static Bool
65 winActivateAppShadowGDI(ScreenPtr pScreen);
66
67static Bool
68 winRedrawScreenShadowGDI(ScreenPtr pScreen);
69
70static Bool
71 winRealizeInstalledPaletteShadowGDI(ScreenPtr pScreen);
72
73static Bool
74 winInstallColormapShadowGDI(ColormapPtr pColormap);
75
76static Bool
77 winStoreColorsShadowGDI(ColormapPtr pmap, int ndef, xColorItem * pdefs);
78
79static Bool
80 winCreateColormapShadowGDI(ColormapPtr pColormap);
81
82static Bool
83 winDestroyColormapShadowGDI(ColormapPtr pColormap);
84
85/*
86 * Internal function to get the DIB format that is compatible with the screen
87 */
88
89static
90 Bool
91winQueryScreenDIBFormat(ScreenPtr pScreen, BITMAPINFOHEADER * pbmih)
92{
93 winScreenPriv(pScreen);
94 HBITMAP hbmp;
95
96#if CYGDEBUG
97 LPDWORD pdw = NULL;
98#endif
99
100 /* Create a memory bitmap compatible with the screen */
101 hbmp = CreateCompatibleBitmap(pScreenPriv->hdcScreen, 1, 1);
102 if (hbmp == NULL) {
103 ErrorF("winQueryScreenDIBFormat - CreateCompatibleBitmap failed\n");
104 return FALSE;
105 }
106
107 /* Initialize our bitmap info header */
108 ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
109 pbmih->biSize = sizeof(BITMAPINFOHEADER);
110
111 /* Get the biBitCount */
112 if (!GetDIBits(pScreenPriv->hdcScreen,
113 hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) {
114 ErrorF("winQueryScreenDIBFormat - First call to GetDIBits failed\n");
115 DeleteObject(hbmp);
116 return FALSE;
117 }
118
119#if CYGDEBUG
120 /* Get a pointer to bitfields */
121 pdw = (DWORD *) ((CARD8 *) pbmih + sizeof(BITMAPINFOHEADER));
122
123 winDebug("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n",
124 pdw[0], pdw[1], pdw[2]);
125#endif
126
127 /* Get optimal color table, or the optimal bitfields */
128 if (!GetDIBits(pScreenPriv->hdcScreen,
129 hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) {
130 ErrorF("winQueryScreenDIBFormat - Second call to GetDIBits "
131 "failed\n");
132 DeleteObject(hbmp);
133 return FALSE;
134 }
135
136 /* Free memory */
137 DeleteObject(hbmp);
138
139 return TRUE;
140}
141
142/*
143 * Internal function to determine the GDI bits per rgb and bit masks
144 */
145
146static
147 Bool
148winQueryRGBBitsAndMasks(ScreenPtr pScreen)
149{
150 winScreenPriv(pScreen);
151 BITMAPINFOHEADER *pbmih = NULL;
152 Bool fReturn = TRUE;
153 LPDWORD pdw = NULL;
154 DWORD dwRedBits, dwGreenBits, dwBlueBits;
155
156 /* Color masks for 8 bpp are standardized */
157 if (GetDeviceCaps(pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE) {
158 /*
159 * RGB BPP for 8 bit palletes is always 8
160 * and the color masks are always 0.
161 */
162 pScreenPriv->dwBitsPerRGB = 8;
163 pScreenPriv->dwRedMask = 0x0L;
164 pScreenPriv->dwGreenMask = 0x0L;
165 pScreenPriv->dwBlueMask = 0x0L;
166 return TRUE;
167 }
168
169 /* Color masks for 24 bpp are standardized */
170 if (GetDeviceCaps(pScreenPriv->hdcScreen, PLANES)
171 * GetDeviceCaps(pScreenPriv->hdcScreen, BITSPIXEL) == 24) {
172 ErrorF("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) "
173 "returned 24 for the screen. Using default 24bpp masks.\n");
174
175 /* 8 bits per primary color */
176 pScreenPriv->dwBitsPerRGB = 8;
177
178 /* Set screen privates masks */
179 pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED;
180 pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN;
181 pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE;
182
183 return TRUE;
184 }
185
186 /* Allocate a bitmap header and color table */
187 pbmih = (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
188 + 256 * sizeof(RGBQUAD));
189 if (pbmih == NULL) {
190 ErrorF("winQueryRGBBitsAndMasks - malloc failed\n");
191 return FALSE;
192 }
193
194 /* Get screen description */
195 if (winQueryScreenDIBFormat(pScreen, pbmih)) {
196 /* Get a pointer to bitfields */
197 pdw = (DWORD *) ((CARD8 *) pbmih + sizeof(BITMAPINFOHEADER));
198
199#if CYGDEBUG
200 winDebug("%s - Masks: %08x %08x %08x\n", __FUNCTION__,
201 pdw[0], pdw[1], pdw[2]);
202 winDebug("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__,
203 pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount,
204 pbmih->biPlanes);
205 winDebug("%s - Compression: %d %s\n", __FUNCTION__,
206 pbmih->biCompression,
207 (pbmih->biCompression ==
208 BI_RGB ? "(BI_RGB)" : (pbmih->biCompression ==
209 BI_RLE8 ? "(BI_RLE8)" : (pbmih->
210 biCompression
211 ==
212 BI_RLE4 ?
213 "(BI_RLE4)"
214 : (pbmih->
215 biCompression
216 ==
217 BI_BITFIELDS
218 ?
219 "(BI_BITFIELDS)"
220 : "")))));
221#endif
222
223 /* Handle BI_RGB case, which is returned by Wine */
224 if (pbmih->biCompression == BI_RGB) {
225 dwRedBits = 5;
226 dwGreenBits = 5;
227 dwBlueBits = 5;
228
229 pScreenPriv->dwBitsPerRGB = 5;
230
231 /* Set screen privates masks */
232 pScreenPriv->dwRedMask = 0x7c00;
233 pScreenPriv->dwGreenMask = 0x03e0;
234 pScreenPriv->dwBlueMask = 0x001f;
235 }
236 else {
237 /* Count the number of bits in each mask */
238 dwRedBits = winCountBits(pdw[0]);
239 dwGreenBits = winCountBits(pdw[1]);
240 dwBlueBits = winCountBits(pdw[2]);
241
242 /* Find maximum bits per red, green, blue */
243 if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
244 pScreenPriv->dwBitsPerRGB = dwRedBits;
245 else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
246 pScreenPriv->dwBitsPerRGB = dwGreenBits;
247 else
248 pScreenPriv->dwBitsPerRGB = dwBlueBits;
249
250 /* Set screen privates masks */
251 pScreenPriv->dwRedMask = pdw[0];
252 pScreenPriv->dwGreenMask = pdw[1];
253 pScreenPriv->dwBlueMask = pdw[2];
254 }
255 }
256 else {
257 ErrorF("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n");
258 fReturn = FALSE;
259 }
260
261 /* Free memory */
262 free(pbmih);
263
264 return fReturn;
265}
266
267#ifdef XWIN_MULTIWINDOW
268/*
269 * Redraw all ---?
270 */
271
272static wBOOL CALLBACK
273winRedrawAllProcShadowGDI(HWND hwnd, LPARAM lParam)
274{
275 if (hwnd == (HWND) lParam)
276 return TRUE;
277 InvalidateRect(hwnd, NULL, FALSE);
278 UpdateWindow(hwnd);
279 return TRUE;
280}
281
282static wBOOL CALLBACK
283winRedrawDamagedWindowShadowGDI(HWND hwnd, LPARAM lParam)
284{
285 BoxPtr pDamage = (BoxPtr) lParam;
286 RECT rcClient, rcDamage, rcRedraw;
287 POINT topLeft, bottomRight;
288
289 if (IsIconic(hwnd))
290 return TRUE; /* Don't care minimized windows */
291
292 /* Convert the damaged area from Screen coords to Client coords */
293 topLeft.x = pDamage->x1;
294 topLeft.y = pDamage->y1;
295 bottomRight.x = pDamage->x2;
296 bottomRight.y = pDamage->y2;
297 topLeft.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
298 bottomRight.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
299 topLeft.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
300 bottomRight.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
301 ScreenToClient(hwnd, &topLeft);
302 ScreenToClient(hwnd, &bottomRight);
303 SetRect(&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
304
305 GetClientRect(hwnd, &rcClient);
306
307 if (IntersectRect(&rcRedraw, &rcClient, &rcDamage)) {
308 InvalidateRect(hwnd, &rcRedraw, FALSE);
309 UpdateWindow(hwnd);
310 }
311 return TRUE;
312}
313#endif
314
315/*
316 * Allocate a DIB for the shadow framebuffer GDI server
317 */
318
319static Bool
320winAllocateFBShadowGDI(ScreenPtr pScreen)
321{
322 winScreenPriv(pScreen);
323 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
324 DIBSECTION dibsection;
325 Bool fReturn = TRUE;
326
327 /* Describe shadow bitmap to be created */
328 pScreenPriv->pbmih->biWidth = pScreenInfo->dwWidth;
329 pScreenPriv->pbmih->biHeight = -pScreenInfo->dwHeight;
330
331 ErrorF("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d "
332 "depth: %d\n",
333 (int) pScreenPriv->pbmih->biWidth,
334 (int) -pScreenPriv->pbmih->biHeight, pScreenPriv->pbmih->biBitCount);
335
336 /* Create a DI shadow bitmap with a bit pointer */
337 pScreenPriv->hbmpShadow = CreateDIBSection(pScreenPriv->hdcScreen,
338 (BITMAPINFO *) pScreenPriv->
339 pbmih, DIB_RGB_COLORS,
340 (VOID **) &pScreenInfo->pfb,
341 NULL, 0);
342 if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL) {
343 winW32Error(2, "winAllocateFBShadowGDI - CreateDIBSection failed:");
344 return FALSE;
345 }
346 else {
347#if CYGDEBUG
348 winDebug("winAllocateFBShadowGDI - Shadow buffer allocated\n");
349#endif
350 }
351
352 /* Get information about the bitmap that was allocated */
353 GetObject(pScreenPriv->hbmpShadow, sizeof(dibsection), &dibsection);
354
355#if CYGDEBUG || YES
356 /* Print information about bitmap allocated */
357 winDebug("winAllocateFBShadowGDI - Dibsection width: %d height: %d "
358 "depth: %d size image: %d\n",
359 (int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight,
360 dibsection.dsBmih.biBitCount, (int) dibsection.dsBmih.biSizeImage);
361#endif
362
363 /* Select the shadow bitmap into the shadow DC */
364 SelectObject(pScreenPriv->hdcShadow, pScreenPriv->hbmpShadow);
365
366#if CYGDEBUG
367 winDebug("winAllocateFBShadowGDI - Attempting a shadow blit\n");
368#endif
369
370 /* Do a test blit from the shadow to the screen, I think */
371 fReturn = BitBlt(pScreenPriv->hdcScreen,
372 0, 0,
373 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
374 pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
375 if (fReturn) {
376#if CYGDEBUG
377 winDebug("winAllocateFBShadowGDI - Shadow blit success\n");
378#endif
379 }
380 else {
381 winW32Error(2, "winAllocateFBShadowGDI - Shadow blit failure\n");
382#if 0
383 return FALSE;
384#else
385 /* ago: ignore this error. The blit fails with wine, but does not
386 * cause any problems later. */
387
388 fReturn = TRUE;
389#endif
390 }
391
392 /* Look for height weirdness */
393 if (dibsection.dsBmih.biHeight < 0) {
394 dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
395 }
396
397 /* Set screeninfo stride */
398 pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage
399 / dibsection.dsBmih.biHeight)
400 * 8) / pScreenInfo->dwBPP;
401
402#if CYGDEBUG || YES
403 winDebug("winAllocateFBShadowGDI - Created shadow stride: %d\n",
404 (int) pScreenInfo->dwStride);
405#endif
406
407#ifdef XWIN_MULTIWINDOW
408 /* Redraw all windows */
409 if (pScreenInfo->fMultiWindow)
410 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
411#endif
412
413 return fReturn;
414}
415
416static void
417winFreeFBShadowGDI(ScreenPtr pScreen)
418{
419 winScreenPriv(pScreen);
420 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
421
422 /* Free the shadow bitmap */
423 DeleteObject(pScreenPriv->hbmpShadow);
424
425 /* Invalidate the ScreenInfo's fb pointer */
426 pScreenInfo->pfb = NULL;
427}
428
429/*
430 * Blit the damaged regions of the shadow fb to the screen
431 */
432
433static void
434winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf)
435{
436 winScreenPriv(pScreen);
437 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
438 RegionPtr damage = shadowDamage(pBuf);
439 DWORD dwBox = RegionNumRects(damage);
440 BoxPtr pBox = RegionRects(damage);
441 int x, y, w, h;
442 HRGN hrgnCombined = NULL;
443
444#ifdef XWIN_UPDATESTATS
445 static DWORD s_dwNonUnitRegions = 0;
446 static DWORD s_dwTotalUpdates = 0;
447 static DWORD s_dwTotalBoxes = 0;
448#endif
449 BoxPtr pBoxExtents = RegionExtents(damage);
450
451 /*
452 * Return immediately if the app is not active
453 * and we are fullscreen, or if we have a bad display depth
454 */
455 if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
456 || pScreenPriv->fBadDepth)
457 return;
458
459#ifdef XWIN_UPDATESTATS
460 ++s_dwTotalUpdates;
461 s_dwTotalBoxes += dwBox;
462
463 if (dwBox != 1) {
464 ++s_dwNonUnitRegions;
465 ErrorF("winShadowUpdatGDI - dwBox: %d\n", dwBox);
466 }
467
468 if ((s_dwTotalUpdates % 100) == 0)
469 ErrorF("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d "
470 "nu: %d tu: %d\n",
471 (s_dwNonUnitRegions * 100) / s_dwTotalUpdates,
472 s_dwTotalBoxes / s_dwTotalUpdates,
473 s_dwNonUnitRegions, s_dwTotalUpdates);
474#endif /* XWIN_UPDATESTATS */
475
476 /*
477 * Handle small regions with multiple blits,
478 * handle large regions by creating a clipping region and
479 * doing a single blit constrained to that clipping region.
480 */
481 if (!pScreenInfo->fMultiWindow &&
482 (pScreenInfo->dwClipUpdatesNBoxes == 0 ||
483 dwBox < pScreenInfo->dwClipUpdatesNBoxes)) {
484 /* Loop through all boxes in the damaged region */
485 while (dwBox--) {
486 /*
487 * Calculate x offset, y offset, width, and height for
488 * current damage box
489 */
490 x = pBox->x1;
491 y = pBox->y1;
492 w = pBox->x2 - pBox->x1;
493 h = pBox->y2 - pBox->y1;
494
495 BitBlt(pScreenPriv->hdcScreen,
496 x, y, w, h, pScreenPriv->hdcShadow, x, y, SRCCOPY);
497
498 /* Get a pointer to the next box */
499 ++pBox;
500 }
501 }
502 else if (!pScreenInfo->fMultiWindow) {
503
504 /* Compute a GDI region from the damaged region */
505 hrgnCombined =
506 CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2,
507 pBoxExtents->y2);
508
509 /* Install the GDI region as a clipping region */
510 SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined);
511 DeleteObject(hrgnCombined);
512 hrgnCombined = NULL;
513
514 /*
515 * Blit the shadow buffer to the screen,
516 * constrained to the clipping region.
517 */
518 BitBlt(pScreenPriv->hdcScreen,
519 pBoxExtents->x1, pBoxExtents->y1,
520 pBoxExtents->x2 - pBoxExtents->x1,
521 pBoxExtents->y2 - pBoxExtents->y1,
522 pScreenPriv->hdcShadow,
523 pBoxExtents->x1, pBoxExtents->y1, SRCCOPY);
524
525 /* Reset the clip region */
526 SelectClipRgn(pScreenPriv->hdcScreen, NULL);
527 }
528
529#ifdef XWIN_MULTIWINDOW
530 /* Redraw all multiwindow windows */
531 if (pScreenInfo->fMultiWindow)
532 EnumThreadWindows(g_dwCurrentThreadID,
533 winRedrawDamagedWindowShadowGDI,
534 (LPARAM) pBoxExtents);
535#endif
536}
537
538static Bool
539winInitScreenShadowGDI(ScreenPtr pScreen)
540{
541 winScreenPriv(pScreen);
542
543 /* Get device contexts for the screen and shadow bitmap */
544 pScreenPriv->hdcScreen = GetDC(pScreenPriv->hwndScreen);
545 pScreenPriv->hdcShadow = CreateCompatibleDC(pScreenPriv->hdcScreen);
546
547 /* Allocate bitmap info header */
548 pScreenPriv->pbmih = (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
549 + 256 * sizeof(RGBQUAD));
550 if (pScreenPriv->pbmih == NULL) {
551 ErrorF("winInitScreenShadowGDI - malloc () failed\n");
552 return FALSE;
553 }
554
555 /* Query the screen format */
556 if (!winQueryScreenDIBFormat(pScreen, pScreenPriv->pbmih)) {
557 ErrorF("winInitScreenShadowGDI - winQueryScreenDIBFormat failed\n");
558 return FALSE;
559 }
560
561 /* Determine our color masks */
562 if (!winQueryRGBBitsAndMasks(pScreen)) {
563 ErrorF("winInitScreenShadowGDI - winQueryRGBBitsAndMasks failed\n");
564 return FALSE;
565 }
566
567 return winAllocateFBShadowGDI(pScreen);
568}
569
570/* See Porting Layer Definition - p. 33 */
571/*
572 * We wrap whatever CloseScreen procedure was specified by fb;
573 * a pointer to said procedure is stored in our privates.
574 */
575
576static Bool
577winCloseScreenShadowGDI(ScreenPtr pScreen)
578{
579 winScreenPriv(pScreen);
580 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
581 Bool fReturn;
582
583#if CYGDEBUG
584 winDebug("winCloseScreenShadowGDI - Freeing screen resources\n");
585#endif
586
587 /* Flag that the screen is closed */
588 pScreenPriv->fClosed = TRUE;
589 pScreenPriv->fActive = FALSE;
590
591 /* Call the wrapped CloseScreen procedure */
592 WIN_UNWRAP(CloseScreen);
593 if (pScreen->CloseScreen)
594 fReturn = (*pScreen->CloseScreen) (pScreen);
595
596 /* Delete the window property */
597 RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP);
598
599 /* Free the shadow DC; which allows the bitmap to be freed */
600 DeleteDC(pScreenPriv->hdcShadow);
601
602 winFreeFBShadowGDI(pScreen);
603
604 /* Free the screen DC */
605 ReleaseDC(pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
606
607 /* Delete tray icon, if we have one */
608 if (!pScreenInfo->fNoTrayIcon)
609 winDeleteNotifyIcon(pScreenPriv);
610
611 /* Free the exit confirmation dialog box, if it exists */
612 if (g_hDlgExit != NULL) {
613 DestroyWindow(g_hDlgExit);
614 g_hDlgExit = NULL;
615 }
616
617 /* Kill our window */
618 if (pScreenPriv->hwndScreen) {
619 DestroyWindow(pScreenPriv->hwndScreen);
620 pScreenPriv->hwndScreen = NULL;
621 }
622
623#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
624 /* Destroy the thread startup mutex */
625 pthread_mutex_destroy(&pScreenPriv->pmServerStarted);
626#endif
627
628 /* Invalidate our screeninfo's pointer to the screen */
629 pScreenInfo->pScreen = NULL;
630
631 /* Free the screen privates for this screen */
632 free((pointer) pScreenPriv);
633
634 return fReturn;
635}
636
637/*
638 * Tell mi what sort of visuals we need.
639 *
640 * Generally we only need one visual, as our screen can only
641 * handle one format at a time, I believe. You may want
642 * to verify that last sentence.
643 */
644
645static Bool
646winInitVisualsShadowGDI(ScreenPtr pScreen)
647{
648 winScreenPriv(pScreen);
649 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
650
651 /* Display debugging information */
652 ErrorF("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d "
653 "bpp %d\n",
654 (unsigned int) pScreenPriv->dwRedMask,
655 (unsigned int) pScreenPriv->dwGreenMask,
656 (unsigned int) pScreenPriv->dwBlueMask,
657 (int) pScreenPriv->dwBitsPerRGB,
658 (int) pScreenInfo->dwDepth, (int) pScreenInfo->dwBPP);
659
660 /* Create a single visual according to the Windows screen depth */
661 switch (pScreenInfo->dwDepth) {
662 case 24:
663 case 16:
664 case 15:
665 /* Setup the real visual */
666 if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
667 TrueColorMask,
668 pScreenPriv->dwBitsPerRGB,
669 -1,
670 pScreenPriv->dwRedMask,
671 pScreenPriv->dwGreenMask,
672 pScreenPriv->dwBlueMask)) {
673 ErrorF("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
674 "failed\n");
675 return FALSE;
676 }
677
678#ifdef XWIN_EMULATEPSEUDO
679 if (!pScreenInfo->fEmulatePseudo)
680 break;
681
682 /* Setup a pseudocolor visual */
683 if (!miSetVisualTypesAndMasks(8, PseudoColorMask, 8, -1, 0, 0, 0)) {
684 ErrorF("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
685 "failed for PseudoColor\n");
686 return FALSE;
687 }
688#endif
689 break;
690
691 case 8:
692 if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
693 PseudoColorMask,
694 pScreenPriv->dwBitsPerRGB,
695 PseudoColor,
696 pScreenPriv->dwRedMask,
697 pScreenPriv->dwGreenMask,
698 pScreenPriv->dwBlueMask)) {
699 ErrorF("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
700 "failed\n");
701 return FALSE;
702 }
703 break;
704
705 default:
706 ErrorF("winInitVisualsShadowGDI - Unknown screen depth\n");
707 return FALSE;
708 }
709
710#if CYGDEBUG
711 winDebug("winInitVisualsShadowGDI - Returning\n");
712#endif
713
714 return TRUE;
715}
716
717/*
718 * Adjust the proposed video mode
719 */
720
721static Bool
722winAdjustVideoModeShadowGDI(ScreenPtr pScreen)
723{
724 winScreenPriv(pScreen);
725 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
726 HDC hdc;
727 DWORD dwBPP;
728
729 hdc = GetDC(NULL);
730
731 /* We're in serious trouble if we can't get a DC */
732 if (hdc == NULL) {
733 ErrorF("winAdjustVideoModeShadowGDI - GetDC () failed\n");
734 return FALSE;
735 }
736
737 /* Query GDI for current display depth */
738 dwBPP = GetDeviceCaps(hdc, BITSPIXEL);
739
740 /* GDI cannot change the screen depth, so always use GDI's depth */
741 pScreenInfo->dwBPP = dwBPP;
742
743 /* Release our DC */
744 ReleaseDC(NULL, hdc);
745 hdc = NULL;
746
747 return TRUE;
748}
749
750/*
751 * Blt exposed regions to the screen
752 */
753
754static Bool
755winBltExposedRegionsShadowGDI(ScreenPtr pScreen)
756{
757 winScreenPriv(pScreen);
758 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
759 winPrivCmapPtr pCmapPriv = NULL;
760 HDC hdcUpdate;
761 PAINTSTRUCT ps;
762
763 /* BeginPaint gives us an hdc that clips to the invalidated region */
764 hdcUpdate = BeginPaint(pScreenPriv->hwndScreen, &ps);
765
766 /* Realize the palette, if we have one */
767 if (pScreenPriv->pcmapInstalled != NULL) {
768 pCmapPriv = winGetCmapPriv(pScreenPriv->pcmapInstalled);
769
770 SelectPalette(hdcUpdate, pCmapPriv->hPalette, FALSE);
771 RealizePalette(hdcUpdate);
772 }
773
774 /* Our BitBlt will be clipped to the invalidated region */
775 BitBlt(hdcUpdate,
776 0, 0,
777 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
778 pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
779
780 /* EndPaint frees the DC */
781 EndPaint(pScreenPriv->hwndScreen, &ps);
782
783#ifdef XWIN_MULTIWINDOW
784 /* Redraw all windows */
785 if (pScreenInfo->fMultiWindow)
786 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI,
787 (LPARAM) pScreenPriv->hwndScreen);
788#endif
789
790 return TRUE;
791}
792
793/*
794 * Do any engine-specific appliation-activation processing
795 */
796
797static Bool
798winActivateAppShadowGDI(ScreenPtr pScreen)
799{
800 winScreenPriv(pScreen);
801 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
802
803 /*
804 * 2004/04/12 - Harold - We perform the restoring or minimizing
805 * manually for ShadowGDI in fullscreen modes so that this engine
806 * will perform just like ShadowDD and ShadowDDNL in fullscreen mode;
807 * if we do not do this then our fullscreen window will appear in the
808 * z-order when it is deactivated and it can be uncovered by resizing
809 * or minimizing another window that is on top of it, which is not how
810 * the DirectDraw engines work. Therefore we keep this code here to
811 * make sure that all engines work the same in fullscreen mode.
812 */
813
814 /*
815 * Are we active?
816 * Are we fullscreen?
817 */
818 if (pScreenPriv->fActive && pScreenInfo->fFullScreen) {
819 /*
820 * Activating, attempt to bring our window
821 * to the top of the display
822 */
823 ShowWindow(pScreenPriv->hwndScreen, SW_RESTORE);
824 }
825 else if (!pScreenPriv->fActive && pScreenInfo->fFullScreen) {
826 /*
827 * Deactivating, stuff our window onto the
828 * task bar.
829 */
830 ShowWindow(pScreenPriv->hwndScreen, SW_MINIMIZE);
831 }
832
833 return TRUE;
834}
835
836/*
837 * Reblit the shadow framebuffer to the screen.
838 */
839
840static Bool
841winRedrawScreenShadowGDI(ScreenPtr pScreen)
842{
843 winScreenPriv(pScreen);
844 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
845
846 /* Redraw the whole window, to take account for the new colors */
847 BitBlt(pScreenPriv->hdcScreen,
848 0, 0,
849 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
850 pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
851
852#ifdef XWIN_MULTIWINDOW
853 /* Redraw all windows */
854 if (pScreenInfo->fMultiWindow)
855 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
856#endif
857
858 return TRUE;
859}
860
861/*
862 * Realize the currently installed colormap
863 */
864
865static Bool
866winRealizeInstalledPaletteShadowGDI(ScreenPtr pScreen)
867{
868 winScreenPriv(pScreen);
869 winPrivCmapPtr pCmapPriv = NULL;
870
871#if CYGDEBUG
872 winDebug("winRealizeInstalledPaletteShadowGDI\n");
873#endif
874
875 /* Don't do anything if there is not a colormap */
876 if (pScreenPriv->pcmapInstalled == NULL) {
877#if CYGDEBUG
878 winDebug("winRealizeInstalledPaletteShadowGDI - No colormap "
879 "installed\n");
880#endif
881 return TRUE;
882 }
883
884 pCmapPriv = winGetCmapPriv(pScreenPriv->pcmapInstalled);
885
886 /* Realize our palette for the screen */
887 if (RealizePalette(pScreenPriv->hdcScreen) == GDI_ERROR) {
888 ErrorF("winRealizeInstalledPaletteShadowGDI - RealizePalette () "
889 "failed\n");
890 return FALSE;
891 }
892
893 /* Set the DIB color table */
894 if (SetDIBColorTable(pScreenPriv->hdcShadow,
895 0,
896 WIN_NUM_PALETTE_ENTRIES, pCmapPriv->rgbColors) == 0) {
897 ErrorF("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () "
898 "failed\n");
899 return FALSE;
900 }
901
902 return TRUE;
903}
904
905/*
906 * Install the specified colormap
907 */
908
909static Bool
910winInstallColormapShadowGDI(ColormapPtr pColormap)
911{
912 ScreenPtr pScreen = pColormap->pScreen;
913
914 winScreenPriv(pScreen);
915 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
916
917 winCmapPriv(pColormap);
918
919 /*
920 * Tell Windows to install the new colormap
921 */
922 if (SelectPalette(pScreenPriv->hdcScreen,
923 pCmapPriv->hPalette, FALSE) == NULL) {
924 ErrorF("winInstallColormapShadowGDI - SelectPalette () failed\n");
925 return FALSE;
926 }
927
928 /* Realize the palette */
929 if (GDI_ERROR == RealizePalette(pScreenPriv->hdcScreen)) {
930 ErrorF("winInstallColormapShadowGDI - RealizePalette () failed\n");
931 return FALSE;
932 }
933
934 /* Set the DIB color table */
935 if (SetDIBColorTable(pScreenPriv->hdcShadow,
936 0,
937 WIN_NUM_PALETTE_ENTRIES, pCmapPriv->rgbColors) == 0) {
938 ErrorF("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
939 return FALSE;
940 }
941
942 /* Redraw the whole window, to take account for the new colors */
943 BitBlt(pScreenPriv->hdcScreen,
944 0, 0,
945 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
946 pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
947
948 /* Save a pointer to the newly installed colormap */
949 pScreenPriv->pcmapInstalled = pColormap;
950
951#ifdef XWIN_MULTIWINDOW
952 /* Redraw all windows */
953 if (pScreenInfo->fMultiWindow)
954 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
955#endif
956
957 return TRUE;
958}
959
960/*
961 * Store the specified colors in the specified colormap
962 */
963
964static Bool
965winStoreColorsShadowGDI(ColormapPtr pColormap, int ndef, xColorItem * pdefs)
966{
967 ScreenPtr pScreen = pColormap->pScreen;
968
969 winScreenPriv(pScreen);
970 winCmapPriv(pColormap);
971 ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
972
973 /* Put the X colormap entries into the Windows logical palette */
974 if (SetPaletteEntries(pCmapPriv->hPalette,
975 pdefs[0].pixel,
976 ndef, pCmapPriv->peColors + pdefs[0].pixel) == 0) {
977 ErrorF("winStoreColorsShadowGDI - SetPaletteEntries () failed\n");
978 return FALSE;
979 }
980
981 /* Don't install the Windows palette if the colormap is not installed */
982 if (pColormap != curpmap) {
983 return TRUE;
984 }
985
986 /* Try to install the newly modified colormap */
987 if (!winInstallColormapShadowGDI(pColormap)) {
988 ErrorF("winInstallColormapShadowGDI - winInstallColormapShadowGDI "
989 "failed\n");
990 return FALSE;
991 }
992
993#if 0
994 /* Tell Windows that the palette has changed */
995 RealizePalette(pScreenPriv->hdcScreen);
996
997 /* Set the DIB color table */
998 if (SetDIBColorTable(pScreenPriv->hdcShadow,
999 pdefs[0].pixel,
1000 ndef, pCmapPriv->rgbColors + pdefs[0].pixel) == 0) {
1001 ErrorF("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
1002 return FALSE;
1003 }
1004
1005 /* Save a pointer to the newly installed colormap */
1006 pScreenPriv->pcmapInstalled = pColormap;
1007#endif
1008
1009 return TRUE;
1010}
1011
1012/*
1013 * Colormap initialization procedure
1014 */
1015
1016static Bool
1017winCreateColormapShadowGDI(ColormapPtr pColormap)
1018{
1019 LPLOGPALETTE lpPaletteNew = NULL;
1020 DWORD dwEntriesMax;
1021 VisualPtr pVisual;
1022 HPALETTE hpalNew = NULL;
1023
1024 winCmapPriv(pColormap);
1025
1026 /* Get a pointer to the visual that the colormap belongs to */
1027 pVisual = pColormap->pVisual;
1028
1029 /* Get the maximum number of palette entries for this visual */
1030 dwEntriesMax = pVisual->ColormapEntries;
1031
1032 /* Allocate a Windows logical color palette with max entries */
1033 lpPaletteNew = malloc(sizeof(LOGPALETTE)
1034 + (dwEntriesMax - 1) * sizeof(PALETTEENTRY));
1035 if (lpPaletteNew == NULL) {
1036 ErrorF("winCreateColormapShadowGDI - Couldn't allocate palette "
1037 "with %d entries\n", (int) dwEntriesMax);
1038 return FALSE;
1039 }
1040
1041 /* Zero out the colormap */
1042 ZeroMemory(lpPaletteNew, sizeof(LOGPALETTE)
1043 + (dwEntriesMax - 1) * sizeof(PALETTEENTRY));
1044
1045 /* Set the logical palette structure */
1046 lpPaletteNew->palVersion = 0x0300;
1047 lpPaletteNew->palNumEntries = dwEntriesMax;
1048
1049 /* Tell Windows to create the palette */
1050 hpalNew = CreatePalette(lpPaletteNew);
1051 if (hpalNew == NULL) {
1052 ErrorF("winCreateColormapShadowGDI - CreatePalette () failed\n");
1053 free(lpPaletteNew);
1054 return FALSE;
1055 }
1056
1057 /* Save the Windows logical palette handle in the X colormaps' privates */
1058 pCmapPriv->hPalette = hpalNew;
1059
1060 /* Free the palette initialization memory */
1061 free(lpPaletteNew);
1062
1063 return TRUE;
1064}
1065
1066/*
1067 * Colormap destruction procedure
1068 */
1069
1070static Bool
1071winDestroyColormapShadowGDI(ColormapPtr pColormap)
1072{
1073 winScreenPriv(pColormap->pScreen);
1074 winCmapPriv(pColormap);
1075
1076 /*
1077 * Is colormap to be destroyed the default?
1078 *
1079 * Non-default colormaps should have had winUninstallColormap
1080 * called on them before we get here. The default colormap
1081 * will not have had winUninstallColormap called on it. Thus,
1082 * we need to handle the default colormap in a special way.
1083 */
1084 if (pColormap->flags & IsDefault) {
1085#if CYGDEBUG
1086 winDebug("winDestroyColormapShadowGDI - Destroying default "
1087 "colormap\n");
1088#endif
1089
1090 /*
1091 * FIXME: Walk the list of all screens, popping the default
1092 * palette out of each screen device context.
1093 */
1094
1095 /* Pop the palette out of the device context */
1096 SelectPalette(pScreenPriv->hdcScreen,
1097 GetStockObject(DEFAULT_PALETTE), FALSE);
1098
1099 /* Clear our private installed colormap pointer */
1100 pScreenPriv->pcmapInstalled = NULL;
1101 }
1102
1103 /* Try to delete the logical palette */
1104 if (DeleteObject(pCmapPriv->hPalette) == 0) {
1105 ErrorF("winDestroyColormap - DeleteObject () failed\n");
1106 return FALSE;
1107 }
1108
1109 /* Invalidate the colormap privates */
1110 pCmapPriv->hPalette = NULL;
1111
1112 return TRUE;
1113}
1114
1115/*
1116 * Set engine specific funtions
1117 */
1118
1119Bool
1120winSetEngineFunctionsShadowGDI(ScreenPtr pScreen)
1121{
1122 winScreenPriv(pScreen);
1123 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
1124
1125 /* Set our pointers */
1126 pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI;
1127 pScreenPriv->pwinFreeFB = winFreeFBShadowGDI;
1128 pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI;
1129 pScreenPriv->pwinInitScreen = winInitScreenShadowGDI;
1130 pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI;
1131 pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI;
1132 pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI;
1133 if (pScreenInfo->fFullScreen)
1134 pScreenPriv->pwinCreateBoundingWindow =
1135 winCreateBoundingWindowFullScreen;
1136 else
1137 pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
1138 pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
1139 pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
1140 pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
1141 pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
1142 pScreenPriv->pwinRealizeInstalledPalette =
1143 winRealizeInstalledPaletteShadowGDI;
1144 pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI;
1145 pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI;
1146 pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI;
1147 pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI;
1148 pScreenPriv->pwinHotKeyAltTab =
1149 (winHotKeyAltTabProcPtr) (void (*)(void)) NoopDDA;
1150 pScreenPriv->pwinCreatePrimarySurface =
1151 (winCreatePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA;
1152 pScreenPriv->pwinReleasePrimarySurface =
1153 (winReleasePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA;
1154#ifdef XWIN_MULTIWINDOW
1155 pScreenPriv->pwinFinishCreateWindowsWindow =
1156 (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA;
1157#endif
1158
1159 return TRUE;
1160}