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