xenocara/xserver/hw/xwin/winshadgdi.c

1151 lines
35 KiB
C
Raw Normal View History

2006-11-26 11:13:41 -07:00
/*
*Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
*
*Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
*"Software"), to deal in the Software without restriction, including
*without limitation the rights to use, copy, modify, merge, publish,
*distribute, sublicense, and/or sell copies of the Software, and to
*permit persons to whom the Software is furnished to do so, subject to
*the following conditions:
*
*The above copyright notice and this permission notice shall be
*included in all copies or substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
*ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
*CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
*WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*Except as contained in this notice, the name of Harold L Hunt II
*shall not be used in advertising or otherwise to promote the sale, use
*or other dealings in this Software without prior written authorization
*from Harold L Hunt II.
*
* Authors: Harold L Hunt II
*/
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"
/*
* Local function prototypes
*/
#ifdef XWIN_MULTIWINDOW
static wBOOL CALLBACK winRedrawAllProcShadowGDI(HWND hwnd, LPARAM lParam);
2006-11-26 11:13:41 -07:00
static wBOOL CALLBACK winRedrawDamagedWindowShadowGDI(HWND hwnd, LPARAM lParam);
2006-11-26 11:13:41 -07:00
#endif
static Bool
winAllocateFBShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static void
winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf);
2006-11-26 11:13:41 -07:00
static Bool
winCloseScreenShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winInitVisualsShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winAdjustVideoModeShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winBltExposedRegionsShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winActivateAppShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winRedrawScreenShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winRealizeInstalledPaletteShadowGDI(ScreenPtr pScreen);
2006-11-26 11:13:41 -07:00
static Bool
winInstallColormapShadowGDI(ColormapPtr pColormap);
2006-11-26 11:13:41 -07:00
static Bool
winStoreColorsShadowGDI(ColormapPtr pmap, int ndef, xColorItem * pdefs);
2006-11-26 11:13:41 -07:00
static Bool
winCreateColormapShadowGDI(ColormapPtr pColormap);
2006-11-26 11:13:41 -07:00
static Bool
winDestroyColormapShadowGDI(ColormapPtr pColormap);
2006-11-26 11:13:41 -07:00
/*
* Internal function to get the DIB format that is compatible with the screen
*/
static
Bool
winQueryScreenDIBFormat(ScreenPtr pScreen, BITMAPINFOHEADER * pbmih)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
HBITMAP hbmp;
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
LPDWORD pdw = NULL;
2006-11-26 11:13:41 -07:00
#endif
/* Create a memory bitmap compatible with the screen */
hbmp = CreateCompatibleBitmap(pScreenPriv->hdcScreen, 1, 1);
if (hbmp == NULL) {
ErrorF("winQueryScreenDIBFormat - CreateCompatibleBitmap failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Initialize our bitmap info header */
ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
pbmih->biSize = sizeof(BITMAPINFOHEADER);
/* Get the biBitCount */
if (!GetDIBits(pScreenPriv->hdcScreen,
hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) {
ErrorF("winQueryScreenDIBFormat - First call to GetDIBits failed\n");
DeleteObject(hbmp);
return FALSE;
2006-11-26 11:13:41 -07:00
}
#if CYGDEBUG
/* Get a pointer to bitfields */
pdw = (DWORD *) ((CARD8 *) pbmih + sizeof(BITMAPINFOHEADER));
2006-11-26 11:13:41 -07:00
winDebug("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n",
(unsigned int)pdw[0], (unsigned int)pdw[1], (unsigned int)pdw[2]);
2006-11-26 11:13:41 -07:00
#endif
/* Get optimal color table, or the optimal bitfields */
if (!GetDIBits(pScreenPriv->hdcScreen,
hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) {
ErrorF("winQueryScreenDIBFormat - Second call to GetDIBits "
"failed\n");
DeleteObject(hbmp);
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Free memory */
DeleteObject(hbmp);
2006-11-26 11:13:41 -07:00
return TRUE;
}
2006-11-26 11:13:41 -07:00
/*
* Internal function to determine the GDI bits per rgb and bit masks
*/
static
Bool
winQueryRGBBitsAndMasks(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
BITMAPINFOHEADER *pbmih = NULL;
Bool fReturn = TRUE;
LPDWORD pdw = NULL;
DWORD dwRedBits, dwGreenBits, dwBlueBits;
/* Color masks for 8 bpp are standardized */
if (GetDeviceCaps(pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE) {
/*
* RGB BPP for 8 bit palletes is always 8
* and the color masks are always 0.
*/
pScreenPriv->dwBitsPerRGB = 8;
pScreenPriv->dwRedMask = 0x0L;
pScreenPriv->dwGreenMask = 0x0L;
pScreenPriv->dwBlueMask = 0x0L;
return TRUE;
2006-11-26 11:13:41 -07:00
}
/* Color masks for 24 bpp are standardized */
if (GetDeviceCaps(pScreenPriv->hdcScreen, PLANES)
* GetDeviceCaps(pScreenPriv->hdcScreen, BITSPIXEL) == 24) {
ErrorF("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) "
"returned 24 for the screen. Using default 24bpp masks.\n");
/* 8 bits per primary color */
pScreenPriv->dwBitsPerRGB = 8;
/* Set screen privates masks */
pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED;
pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN;
pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE;
return TRUE;
2006-11-26 11:13:41 -07:00
}
/* Allocate a bitmap header and color table */
pbmih = malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
if (pbmih == NULL) {
ErrorF("winQueryRGBBitsAndMasks - malloc failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Get screen description */
if (winQueryScreenDIBFormat(pScreen, pbmih)) {
/* Get a pointer to bitfields */
pdw = (DWORD *) ((CARD8 *) pbmih + sizeof(BITMAPINFOHEADER));
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("%s - Masks: %08x %08x %08x\n", __FUNCTION__,
(unsigned int)pdw[0], (unsigned int)pdw[1], (unsigned int)pdw[2]);
winDebug("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__,
(int)pbmih->biWidth, (int)pbmih->biHeight, pbmih->biBitCount,
pbmih->biPlanes);
winDebug("%s - Compression: %u %s\n", __FUNCTION__,
(unsigned int)pbmih->biCompression,
(pbmih->biCompression ==
BI_RGB ? "(BI_RGB)" : (pbmih->biCompression ==
BI_RLE8 ? "(BI_RLE8)" : (pbmih->
biCompression
==
BI_RLE4 ?
"(BI_RLE4)"
: (pbmih->
biCompression
==
BI_BITFIELDS
?
"(BI_BITFIELDS)"
: "")))));
2006-11-26 11:13:41 -07:00
#endif
/* Handle BI_RGB case, which is returned by Wine */
if (pbmih->biCompression == BI_RGB) {
dwRedBits = 5;
dwGreenBits = 5;
dwBlueBits = 5;
pScreenPriv->dwBitsPerRGB = 5;
/* Set screen privates masks */
pScreenPriv->dwRedMask = 0x7c00;
pScreenPriv->dwGreenMask = 0x03e0;
pScreenPriv->dwBlueMask = 0x001f;
}
else {
/* Count the number of bits in each mask */
dwRedBits = winCountBits(pdw[0]);
dwGreenBits = winCountBits(pdw[1]);
dwBlueBits = winCountBits(pdw[2]);
/* Find maximum bits per red, green, blue */
if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
pScreenPriv->dwBitsPerRGB = dwRedBits;
else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
pScreenPriv->dwBitsPerRGB = dwGreenBits;
else
pScreenPriv->dwBitsPerRGB = dwBlueBits;
/* Set screen privates masks */
pScreenPriv->dwRedMask = pdw[0];
pScreenPriv->dwGreenMask = pdw[1];
pScreenPriv->dwBlueMask = pdw[2];
2006-11-26 11:13:41 -07:00
}
}
else {
ErrorF("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n");
fReturn = FALSE;
2006-11-26 11:13:41 -07:00
}
/* Free memory */
free(pbmih);
2006-11-26 11:13:41 -07:00
return fReturn;
2006-11-26 11:13:41 -07:00
}
#ifdef XWIN_MULTIWINDOW
/*
* Redraw all ---?
*/
static wBOOL CALLBACK
winRedrawAllProcShadowGDI(HWND hwnd, LPARAM lParam)
2006-11-26 11:13:41 -07:00
{
if (hwnd == (HWND) lParam)
return TRUE;
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
return TRUE;
2006-11-26 11:13:41 -07:00
}
static wBOOL CALLBACK
winRedrawDamagedWindowShadowGDI(HWND hwnd, LPARAM lParam)
2006-11-26 11:13:41 -07:00
{
BoxPtr pDamage = (BoxPtr) lParam;
RECT rcClient, rcDamage, rcRedraw;
POINT topLeft, bottomRight;
if (IsIconic(hwnd))
return TRUE; /* Don't care minimized windows */
/* Convert the damaged area from Screen coords to Client coords */
topLeft.x = pDamage->x1;
topLeft.y = pDamage->y1;
bottomRight.x = pDamage->x2;
bottomRight.y = pDamage->y2;
topLeft.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
bottomRight.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
topLeft.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
bottomRight.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
ScreenToClient(hwnd, &topLeft);
ScreenToClient(hwnd, &bottomRight);
SetRect(&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
GetClientRect(hwnd, &rcClient);
if (IntersectRect(&rcRedraw, &rcClient, &rcDamage)) {
InvalidateRect(hwnd, &rcRedraw, FALSE);
UpdateWindow(hwnd);
2006-11-26 11:13:41 -07:00
}
return TRUE;
2006-11-26 11:13:41 -07:00
}
#endif
/*
* Allocate a DIB for the shadow framebuffer GDI server
*/
static Bool
winAllocateFBShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
DIBSECTION dibsection;
Bool fReturn = TRUE;
/* Describe shadow bitmap to be created */
pScreenPriv->pbmih->biWidth = pScreenInfo->dwWidth;
pScreenPriv->pbmih->biHeight = -pScreenInfo->dwHeight;
ErrorF("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d "
"depth: %d\n",
(int) pScreenPriv->pbmih->biWidth,
(int) -pScreenPriv->pbmih->biHeight, pScreenPriv->pbmih->biBitCount);
/* Create a DI shadow bitmap with a bit pointer */
pScreenPriv->hbmpShadow = CreateDIBSection(pScreenPriv->hdcScreen,
(BITMAPINFO *) pScreenPriv->
pbmih, DIB_RGB_COLORS,
(VOID **) &pScreenInfo->pfb,
NULL, 0);
if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL) {
winW32Error(2, "winAllocateFBShadowGDI - CreateDIBSection failed:");
return FALSE;
2006-11-26 11:13:41 -07:00
}
else {
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winAllocateFBShadowGDI - Shadow buffer allocated\n");
2006-11-26 11:13:41 -07:00
#endif
}
/* Get information about the bitmap that was allocated */
GetObject(pScreenPriv->hbmpShadow, sizeof(dibsection), &dibsection);
2006-11-26 11:13:41 -07:00
#if CYGDEBUG || YES
/* Print information about bitmap allocated */
winDebug("winAllocateFBShadowGDI - Dibsection width: %d height: %d "
"depth: %d size image: %d\n",
(int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight,
dibsection.dsBmih.biBitCount, (int) dibsection.dsBmih.biSizeImage);
2006-11-26 11:13:41 -07:00
#endif
/* Select the shadow bitmap into the shadow DC */
SelectObject(pScreenPriv->hdcShadow, pScreenPriv->hbmpShadow);
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winAllocateFBShadowGDI - Attempting a shadow blit\n");
2006-11-26 11:13:41 -07:00
#endif
/* Do a test blit from the shadow to the screen, I think */
fReturn = BitBlt(pScreenPriv->hdcScreen,
0, 0,
pScreenInfo->dwWidth, pScreenInfo->dwHeight,
pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
if (fReturn) {
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winAllocateFBShadowGDI - Shadow blit success\n");
2006-11-26 11:13:41 -07:00
#endif
}
else {
winW32Error(2, "winAllocateFBShadowGDI - Shadow blit failure\n");
#if 0
return FALSE;
#else
/* ago: ignore this error. The blit fails with wine, but does not
* cause any problems later. */
fReturn = TRUE;
#endif
2006-11-26 11:13:41 -07:00
}
/* Look for height weirdness */
if (dibsection.dsBmih.biHeight < 0) {
dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
2006-11-26 11:13:41 -07:00
}
/* Set screeninfo stride */
pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage
/ dibsection.dsBmih.biHeight)
* 8) / pScreenInfo->dwBPP;
2006-11-26 11:13:41 -07:00
#if CYGDEBUG || YES
winDebug("winAllocateFBShadowGDI - Created shadow stride: %d\n",
(int) pScreenInfo->dwStride);
2006-11-26 11:13:41 -07:00
#endif
#ifdef XWIN_MULTIWINDOW
/* Redraw all windows */
if (pScreenInfo->fMultiWindow)
EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
2006-11-26 11:13:41 -07:00
#endif
return fReturn;
2006-11-26 11:13:41 -07:00
}
2011-11-05 07:32:40 -06:00
static void
winFreeFBShadowGDI(ScreenPtr pScreen)
2011-11-05 07:32:40 -06:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
2011-11-05 07:32:40 -06:00
/* Free the shadow bitmap */
DeleteObject(pScreenPriv->hbmpShadow);
2011-11-05 07:32:40 -06:00
/* Invalidate the ScreenInfo's fb pointer */
pScreenInfo->pfb = NULL;
2011-11-05 07:32:40 -06:00
}
2006-11-26 11:13:41 -07:00
/*
* Blit the damaged regions of the shadow fb to the screen
*/
static void
winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
RegionPtr damage = shadowDamage(pBuf);
DWORD dwBox = RegionNumRects(damage);
BoxPtr pBox = RegionRects(damage);
int x, y, w, h;
HRGN hrgnCombined = NULL;
2006-11-26 11:13:41 -07:00
#ifdef XWIN_UPDATESTATS
static DWORD s_dwNonUnitRegions = 0;
static DWORD s_dwTotalUpdates = 0;
static DWORD s_dwTotalBoxes = 0;
2006-11-26 11:13:41 -07:00
#endif
BoxPtr pBoxExtents = RegionExtents(damage);
2006-11-26 11:13:41 -07:00
/*
* Return immediately if the app is not active
* and we are fullscreen, or if we have a bad display depth
*/
if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
|| pScreenPriv->fBadDepth)
return;
2006-11-26 11:13:41 -07:00
#ifdef XWIN_UPDATESTATS
++s_dwTotalUpdates;
s_dwTotalBoxes += dwBox;
2006-11-26 11:13:41 -07:00
if (dwBox != 1) {
++s_dwNonUnitRegions;
ErrorF("winShadowUpdatGDI - dwBox: %d\n", dwBox);
2006-11-26 11:13:41 -07:00
}
if ((s_dwTotalUpdates % 100) == 0)
ErrorF("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d "
"nu: %d tu: %d\n",
(s_dwNonUnitRegions * 100) / s_dwTotalUpdates,
s_dwTotalBoxes / s_dwTotalUpdates,
s_dwNonUnitRegions, s_dwTotalUpdates);
#endif /* XWIN_UPDATESTATS */
/*
* Handle small regions with multiple blits,
* handle large regions by creating a clipping region and
* doing a single blit constrained to that clipping region.
*/
if (!pScreenInfo->fMultiWindow &&
(pScreenInfo->dwClipUpdatesNBoxes == 0 ||
dwBox < pScreenInfo->dwClipUpdatesNBoxes)) {
/* Loop through all boxes in the damaged region */
while (dwBox--) {
/*
* Calculate x offset, y offset, width, and height for
* current damage box
*/
x = pBox->x1;
y = pBox->y1;
w = pBox->x2 - pBox->x1;
h = pBox->y2 - pBox->y1;
BitBlt(pScreenPriv->hdcScreen,
x, y, w, h, pScreenPriv->hdcShadow, x, y, SRCCOPY);
/* Get a pointer to the next box */
++pBox;
}
2006-11-26 11:13:41 -07:00
}
else if (!pScreenInfo->fMultiWindow) {
/* Compute a GDI region from the damaged region */
hrgnCombined =
CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2,
pBoxExtents->y2);
/* Install the GDI region as a clipping region */
SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined);
DeleteObject(hrgnCombined);
hrgnCombined = NULL;
/*
* Blit the shadow buffer to the screen,
* constrained to the clipping region.
*/
BitBlt(pScreenPriv->hdcScreen,
pBoxExtents->x1, pBoxExtents->y1,
pBoxExtents->x2 - pBoxExtents->x1,
pBoxExtents->y2 - pBoxExtents->y1,
pScreenPriv->hdcShadow,
pBoxExtents->x1, pBoxExtents->y1, SRCCOPY);
/* Reset the clip region */
SelectClipRgn(pScreenPriv->hdcScreen, NULL);
2006-11-26 11:13:41 -07:00
}
#ifdef XWIN_MULTIWINDOW
/* Redraw all multiwindow windows */
if (pScreenInfo->fMultiWindow)
EnumThreadWindows(g_dwCurrentThreadID,
winRedrawDamagedWindowShadowGDI,
(LPARAM) pBoxExtents);
2006-11-26 11:13:41 -07:00
#endif
}
2011-11-05 07:32:40 -06:00
static Bool
winInitScreenShadowGDI(ScreenPtr pScreen)
2011-11-05 07:32:40 -06:00
{
winScreenPriv(pScreen);
/* Get device contexts for the screen and shadow bitmap */
pScreenPriv->hdcScreen = GetDC(pScreenPriv->hwndScreen);
pScreenPriv->hdcShadow = CreateCompatibleDC(pScreenPriv->hdcScreen);
/* Allocate bitmap info header */
pScreenPriv->pbmih = malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
if (pScreenPriv->pbmih == NULL) {
ErrorF("winInitScreenShadowGDI - malloc () failed\n");
return FALSE;
2011-11-05 07:32:40 -06:00
}
/* Query the screen format */
if (!winQueryScreenDIBFormat(pScreen, pScreenPriv->pbmih)) {
ErrorF("winInitScreenShadowGDI - winQueryScreenDIBFormat failed\n");
return FALSE;
2011-11-05 07:32:40 -06:00
}
/* Determine our color masks */
if (!winQueryRGBBitsAndMasks(pScreen)) {
ErrorF("winInitScreenShadowGDI - winQueryRGBBitsAndMasks failed\n");
return FALSE;
2011-11-05 07:32:40 -06:00
}
return winAllocateFBShadowGDI(pScreen);
2011-11-05 07:32:40 -06:00
}
2006-11-26 11:13:41 -07:00
/* See Porting Layer Definition - p. 33 */
/*
* We wrap whatever CloseScreen procedure was specified by fb;
* a pointer to said procedure is stored in our privates.
*/
static Bool
winCloseScreenShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
Bool fReturn;
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winCloseScreenShadowGDI - Freeing screen resources\n");
2006-11-26 11:13:41 -07:00
#endif
/* Flag that the screen is closed */
pScreenPriv->fClosed = TRUE;
pScreenPriv->fActive = FALSE;
2006-11-26 11:13:41 -07:00
/* Call the wrapped CloseScreen procedure */
WIN_UNWRAP(CloseScreen);
if (pScreen->CloseScreen)
fReturn = (*pScreen->CloseScreen) (pScreen);
2006-11-26 11:13:41 -07:00
/* Delete the window property */
RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP);
2006-11-26 11:13:41 -07:00
/* Free the shadow DC; which allows the bitmap to be freed */
DeleteDC(pScreenPriv->hdcShadow);
2011-11-05 07:32:40 -06:00
winFreeFBShadowGDI(pScreen);
2006-11-26 11:13:41 -07:00
/* Free the screen DC */
ReleaseDC(pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
2006-11-26 11:13:41 -07:00
/* Delete tray icon, if we have one */
if (!pScreenInfo->fNoTrayIcon)
winDeleteNotifyIcon(pScreenPriv);
2006-11-26 11:13:41 -07:00
/* Free the exit confirmation dialog box, if it exists */
if (g_hDlgExit != NULL) {
DestroyWindow(g_hDlgExit);
g_hDlgExit = NULL;
2006-11-26 11:13:41 -07:00
}
/* Kill our window */
if (pScreenPriv->hwndScreen) {
DestroyWindow(pScreenPriv->hwndScreen);
pScreenPriv->hwndScreen = NULL;
2006-11-26 11:13:41 -07:00
}
#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
/* Destroy the thread startup mutex */
pthread_mutex_destroy(&pScreenPriv->pmServerStarted);
2006-11-26 11:13:41 -07:00
#endif
/* Invalidate our screeninfo's pointer to the screen */
pScreenInfo->pScreen = NULL;
2006-11-26 11:13:41 -07:00
/* Free the screen privates for this screen */
free((void *) pScreenPriv);
2006-11-26 11:13:41 -07:00
return fReturn;
2006-11-26 11:13:41 -07:00
}
/*
* Tell mi what sort of visuals we need.
*
2006-11-26 11:13:41 -07:00
* Generally we only need one visual, as our screen can only
* handle one format at a time, I believe. You may want
* to verify that last sentence.
*/
static Bool
winInitVisualsShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
/* Display debugging information */
ErrorF("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d "
"bpp %d\n",
(unsigned int) pScreenPriv->dwRedMask,
(unsigned int) pScreenPriv->dwGreenMask,
(unsigned int) pScreenPriv->dwBlueMask,
(int) pScreenPriv->dwBitsPerRGB,
(int) pScreenInfo->dwDepth, (int) pScreenInfo->dwBPP);
/* Create a single visual according to the Windows screen depth */
switch (pScreenInfo->dwDepth) {
2006-11-26 11:13:41 -07:00
case 24:
case 16:
case 15:
/* Setup the real visual */
if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
TrueColorMask,
pScreenPriv->dwBitsPerRGB,
-1,
pScreenPriv->dwRedMask,
pScreenPriv->dwGreenMask,
pScreenPriv->dwBlueMask)) {
ErrorF("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
"failed\n");
return FALSE;
}
2006-11-26 11:13:41 -07:00
#ifdef XWIN_EMULATEPSEUDO
if (!pScreenInfo->fEmulatePseudo)
break;
/* Setup a pseudocolor visual */
if (!miSetVisualTypesAndMasks(8, PseudoColorMask, 8, -1, 0, 0, 0)) {
ErrorF("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
"failed for PseudoColor\n");
return FALSE;
}
2006-11-26 11:13:41 -07:00
#endif
break;
2006-11-26 11:13:41 -07:00
case 8:
if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
PseudoColorMask,
pScreenPriv->dwBitsPerRGB,
PseudoColor,
pScreenPriv->dwRedMask,
pScreenPriv->dwGreenMask,
pScreenPriv->dwBlueMask)) {
ErrorF("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
"failed\n");
return FALSE;
}
break;
2006-11-26 11:13:41 -07:00
default:
ErrorF("winInitVisualsShadowGDI - Unknown screen depth\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
#if CYGDEBUG
winDebug("winInitVisualsShadowGDI - Returning\n");
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Adjust the proposed video mode
*/
static Bool
winAdjustVideoModeShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
HDC hdc;
DWORD dwBPP;
hdc = GetDC(NULL);
/* We're in serious trouble if we can't get a DC */
if (hdc == NULL) {
ErrorF("winAdjustVideoModeShadowGDI - GetDC () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Query GDI for current display depth */
dwBPP = GetDeviceCaps(hdc, BITSPIXEL);
2006-11-26 11:13:41 -07:00
/* GDI cannot change the screen depth, so always use GDI's depth */
pScreenInfo->dwBPP = dwBPP;
2006-11-26 11:13:41 -07:00
/* Release our DC */
ReleaseDC(NULL, hdc);
hdc = NULL;
2006-11-26 11:13:41 -07:00
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Blt exposed regions to the screen
*/
static Bool
winBltExposedRegionsShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
winPrivCmapPtr pCmapPriv = NULL;
HDC hdcUpdate;
PAINTSTRUCT ps;
/* BeginPaint gives us an hdc that clips to the invalidated region */
hdcUpdate = BeginPaint(pScreenPriv->hwndScreen, &ps);
/* Realize the palette, if we have one */
if (pScreenPriv->pcmapInstalled != NULL) {
pCmapPriv = winGetCmapPriv(pScreenPriv->pcmapInstalled);
SelectPalette(hdcUpdate, pCmapPriv->hPalette, FALSE);
RealizePalette(hdcUpdate);
2006-11-26 11:13:41 -07:00
}
/* Our BitBlt will be clipped to the invalidated region */
BitBlt(hdcUpdate,
0, 0,
pScreenInfo->dwWidth, pScreenInfo->dwHeight,
pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
2006-11-26 11:13:41 -07:00
/* EndPaint frees the DC */
EndPaint(pScreenPriv->hwndScreen, &ps);
2006-11-26 11:13:41 -07:00
#ifdef XWIN_MULTIWINDOW
/* Redraw all windows */
if (pScreenInfo->fMultiWindow)
EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI,
(LPARAM) pScreenPriv->hwndScreen);
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Do any engine-specific appliation-activation processing
*/
static Bool
winActivateAppShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
/*
* 2004/04/12 - Harold - We perform the restoring or minimizing
* manually for ShadowGDI in fullscreen modes so that this engine
* will perform just like ShadowDD and ShadowDDNL in fullscreen mode;
* if we do not do this then our fullscreen window will appear in the
* z-order when it is deactivated and it can be uncovered by resizing
* or minimizing another window that is on top of it, which is not how
* the DirectDraw engines work. Therefore we keep this code here to
* make sure that all engines work the same in fullscreen mode.
*/
/*
* Are we active?
* Are we fullscreen?
*/
if (pScreenPriv->fActive && pScreenInfo->fFullScreen) {
/*
* Activating, attempt to bring our window
* to the top of the display
*/
ShowWindow(pScreenPriv->hwndScreen, SW_RESTORE);
2006-11-26 11:13:41 -07:00
}
else if (!pScreenPriv->fActive && pScreenInfo->fFullScreen) {
/*
* Deactivating, stuff our window onto the
* task bar.
*/
ShowWindow(pScreenPriv->hwndScreen, SW_MINIMIZE);
2006-11-26 11:13:41 -07:00
}
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Reblit the shadow framebuffer to the screen.
*/
static Bool
winRedrawScreenShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
2006-11-26 11:13:41 -07:00
/* Redraw the whole window, to take account for the new colors */
BitBlt(pScreenPriv->hdcScreen,
0, 0,
pScreenInfo->dwWidth, pScreenInfo->dwHeight,
pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
2006-11-26 11:13:41 -07:00
#ifdef XWIN_MULTIWINDOW
/* Redraw all windows */
if (pScreenInfo->fMultiWindow)
EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Realize the currently installed colormap
*/
static Bool
winRealizeInstalledPaletteShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winPrivCmapPtr pCmapPriv = NULL;
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winRealizeInstalledPaletteShadowGDI\n");
2006-11-26 11:13:41 -07:00
#endif
/* Don't do anything if there is not a colormap */
if (pScreenPriv->pcmapInstalled == NULL) {
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winRealizeInstalledPaletteShadowGDI - No colormap "
"installed\n");
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
pCmapPriv = winGetCmapPriv(pScreenPriv->pcmapInstalled);
/* Realize our palette for the screen */
if (RealizePalette(pScreenPriv->hdcScreen) == GDI_ERROR) {
ErrorF("winRealizeInstalledPaletteShadowGDI - RealizePalette () "
"failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Set the DIB color table */
if (SetDIBColorTable(pScreenPriv->hdcShadow,
0,
WIN_NUM_PALETTE_ENTRIES, pCmapPriv->rgbColors) == 0) {
ErrorF("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () "
"failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
return TRUE;
}
2006-11-26 11:13:41 -07:00
/*
* Install the specified colormap
*/
static Bool
winInstallColormapShadowGDI(ColormapPtr pColormap)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pColormap->pScreen;
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
winCmapPriv(pColormap);
/*
* Tell Windows to install the new colormap
*/
if (SelectPalette(pScreenPriv->hdcScreen,
pCmapPriv->hPalette, FALSE) == NULL) {
ErrorF("winInstallColormapShadowGDI - SelectPalette () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Realize the palette */
if (GDI_ERROR == RealizePalette(pScreenPriv->hdcScreen)) {
ErrorF("winInstallColormapShadowGDI - RealizePalette () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Set the DIB color table */
if (SetDIBColorTable(pScreenPriv->hdcShadow,
0,
WIN_NUM_PALETTE_ENTRIES, pCmapPriv->rgbColors) == 0) {
ErrorF("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Redraw the whole window, to take account for the new colors */
BitBlt(pScreenPriv->hdcScreen,
0, 0,
pScreenInfo->dwWidth, pScreenInfo->dwHeight,
pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
2006-11-26 11:13:41 -07:00
/* Save a pointer to the newly installed colormap */
pScreenPriv->pcmapInstalled = pColormap;
2006-11-26 11:13:41 -07:00
#ifdef XWIN_MULTIWINDOW
/* Redraw all windows */
if (pScreenInfo->fMultiWindow)
EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Store the specified colors in the specified colormap
*/
static Bool
winStoreColorsShadowGDI(ColormapPtr pColormap, int ndef, xColorItem * pdefs)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pColormap->pScreen;
winScreenPriv(pScreen);
winCmapPriv(pColormap);
ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
/* Put the X colormap entries into the Windows logical palette */
if (SetPaletteEntries(pCmapPriv->hPalette,
pdefs[0].pixel,
ndef, pCmapPriv->peColors + pdefs[0].pixel) == 0) {
ErrorF("winStoreColorsShadowGDI - SetPaletteEntries () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Don't install the Windows palette if the colormap is not installed */
if (pColormap != curpmap) {
return TRUE;
2006-11-26 11:13:41 -07:00
}
/* Try to install the newly modified colormap */
if (!winInstallColormapShadowGDI(pColormap)) {
ErrorF("winInstallColormapShadowGDI - winInstallColormapShadowGDI "
"failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
#if 0
/* Tell Windows that the palette has changed */
RealizePalette(pScreenPriv->hdcScreen);
/* Set the DIB color table */
if (SetDIBColorTable(pScreenPriv->hdcShadow,
pdefs[0].pixel,
ndef, pCmapPriv->rgbColors + pdefs[0].pixel) == 0) {
ErrorF("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Save a pointer to the newly installed colormap */
pScreenPriv->pcmapInstalled = pColormap;
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Colormap initialization procedure
*/
static Bool
winCreateColormapShadowGDI(ColormapPtr pColormap)
2006-11-26 11:13:41 -07:00
{
LPLOGPALETTE lpPaletteNew = NULL;
DWORD dwEntriesMax;
VisualPtr pVisual;
HPALETTE hpalNew = NULL;
winCmapPriv(pColormap);
/* Get a pointer to the visual that the colormap belongs to */
pVisual = pColormap->pVisual;
/* Get the maximum number of palette entries for this visual */
dwEntriesMax = pVisual->ColormapEntries;
/* Allocate a Windows logical color palette with max entries */
lpPaletteNew = malloc(sizeof(LOGPALETTE)
+ (dwEntriesMax - 1) * sizeof(PALETTEENTRY));
if (lpPaletteNew == NULL) {
ErrorF("winCreateColormapShadowGDI - Couldn't allocate palette "
"with %d entries\n", (int) dwEntriesMax);
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Zero out the colormap */
ZeroMemory(lpPaletteNew, sizeof(LOGPALETTE)
+ (dwEntriesMax - 1) * sizeof(PALETTEENTRY));
/* Set the logical palette structure */
lpPaletteNew->palVersion = 0x0300;
lpPaletteNew->palNumEntries = dwEntriesMax;
/* Tell Windows to create the palette */
hpalNew = CreatePalette(lpPaletteNew);
if (hpalNew == NULL) {
ErrorF("winCreateColormapShadowGDI - CreatePalette () failed\n");
free(lpPaletteNew);
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Save the Windows logical palette handle in the X colormaps' privates */
pCmapPriv->hPalette = hpalNew;
2006-11-26 11:13:41 -07:00
/* Free the palette initialization memory */
free(lpPaletteNew);
2006-11-26 11:13:41 -07:00
return TRUE;
2006-11-26 11:13:41 -07:00
}
/*
* Colormap destruction procedure
*/
static Bool
winDestroyColormapShadowGDI(ColormapPtr pColormap)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pColormap->pScreen);
winCmapPriv(pColormap);
/*
* Is colormap to be destroyed the default?
*
* Non-default colormaps should have had winUninstallColormap
* called on them before we get here. The default colormap
* will not have had winUninstallColormap called on it. Thus,
* we need to handle the default colormap in a special way.
*/
if (pColormap->flags & IsDefault) {
2006-11-26 11:13:41 -07:00
#if CYGDEBUG
winDebug("winDestroyColormapShadowGDI - Destroying default "
"colormap\n");
2006-11-26 11:13:41 -07:00
#endif
/*
* FIXME: Walk the list of all screens, popping the default
* palette out of each screen device context.
*/
/* Pop the palette out of the device context */
SelectPalette(pScreenPriv->hdcScreen,
GetStockObject(DEFAULT_PALETTE), FALSE);
/* Clear our private installed colormap pointer */
pScreenPriv->pcmapInstalled = NULL;
2006-11-26 11:13:41 -07:00
}
/* Try to delete the logical palette */
if (DeleteObject(pCmapPriv->hPalette) == 0) {
ErrorF("winDestroyColormap - DeleteObject () failed\n");
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Invalidate the colormap privates */
pCmapPriv->hPalette = NULL;
2006-11-26 11:13:41 -07:00
return TRUE;
}
2006-11-26 11:13:41 -07:00
/*
* Set engine specific funtions
*/
Bool
winSetEngineFunctionsShadowGDI(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
winScreenPriv(pScreen);
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
/* Set our pointers */
pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI;
pScreenPriv->pwinFreeFB = winFreeFBShadowGDI;
pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI;
pScreenPriv->pwinInitScreen = winInitScreenShadowGDI;
pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI;
pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI;
pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI;
if (pScreenInfo->fFullScreen)
pScreenPriv->pwinCreateBoundingWindow =
winCreateBoundingWindowFullScreen;
else
pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
pScreenPriv->pwinRealizeInstalledPalette =
winRealizeInstalledPaletteShadowGDI;
pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI;
pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI;
pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI;
pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI;
pScreenPriv->pwinCreatePrimarySurface = NULL;
pScreenPriv->pwinReleasePrimarySurface = NULL;
2006-11-26 11:13:41 -07:00
return TRUE;
2006-11-26 11:13:41 -07:00
}