|  | /* | 
|  | * DirectDraw driver interface | 
|  | * | 
|  | * Copyright 2001 TransGaming Technologies, Inc. | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include "ts_xlib.h" | 
|  | #include "x11drv.h" | 
|  | #include "x11ddraw.h" | 
|  | #include "xvidmode.h" | 
|  | #include "dga2.h" | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "wingdi.h" | 
|  | #include "ddrawi.h" | 
|  | #include "bitmap.h" | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(x11drv); | 
|  |  | 
|  | extern int dxgrab; | 
|  |  | 
|  | LPDDRAWI_DDRAWSURFACE_LCL X11DRV_DD_Primary; | 
|  | LPDDRAWI_DDRAWSURFACE_GBL X11DRV_DD_PrimaryGbl; | 
|  | HWND X11DRV_DD_PrimaryWnd; | 
|  | HBITMAP X11DRV_DD_PrimaryDIB; | 
|  | Drawable X11DRV_DD_PrimaryDrawable; | 
|  | ATOM X11DRV_DD_UserClass; | 
|  | BOOL X11DRV_DD_IsDirect; | 
|  | static UINT X11DRV_DD_GrabMessage; | 
|  | static WNDPROC X11DRV_DD_GrabOldProcedure; | 
|  |  | 
|  | static void SetPrimaryDIB(HBITMAP hBmp) | 
|  | { | 
|  | X11DRV_DD_PrimaryDIB = hBmp; | 
|  | if (hBmp) { | 
|  | BITMAPOBJ *bmp; | 
|  | bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC ); | 
|  | X11DRV_DD_PrimaryDrawable = (Pixmap)bmp->physBitmap; | 
|  | GDI_ReleaseObj( hBmp ); | 
|  | } else { | 
|  | X11DRV_DD_PrimaryDrawable = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | 
|  | { | 
|  | Display *display = thread_display(); | 
|  |  | 
|  | if(message != X11DRV_DD_GrabMessage) | 
|  | return CallWindowProcA(X11DRV_DD_GrabOldProcedure, hWnd, message, wParam, lParam); | 
|  |  | 
|  | TRACE("hwnd=%d, grab=%d\n", hWnd, wParam); | 
|  |  | 
|  | if (wParam) | 
|  | { | 
|  | /* find the X11 window that ddraw uses */ | 
|  | Window win = X11DRV_get_whole_window(hWnd); | 
|  | TRACE("X11 window: %ld\n", win); | 
|  | if (!win) { | 
|  | TRACE("host off desktop\n"); | 
|  | win = root_window; | 
|  | } | 
|  |  | 
|  | TSXGrabPointer(display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); | 
|  | } | 
|  | else | 
|  | { | 
|  | TSXUngrabPointer(display, CurrentTime); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void GrabPointer(BOOL grab) | 
|  | { | 
|  | if(grab) { | 
|  | Window window = X11DRV_get_whole_window(GetFocus()); | 
|  | if(window) | 
|  | XSetInputFocus(thread_display(), window, RevertToParent, CurrentTime); | 
|  | } | 
|  |  | 
|  | if(!X11DRV_DD_GrabMessage) | 
|  | X11DRV_DD_GrabMessage = RegisterWindowMessageA("WINE_X11DRV_GRABPOINTER"); | 
|  |  | 
|  | /* FIXME: Replace with SetWindowLongPtrA when available */ | 
|  | X11DRV_DD_GrabOldProcedure = (WNDPROC)SetWindowLongA(X11DRV_DD_PrimaryWnd, | 
|  | GWL_WNDPROC, (LONG)GrabWndProc); | 
|  |  | 
|  | SendMessageA(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabMessage, grab ? 1 : 0, 0); | 
|  |  | 
|  | /* FIXME: Replace with SetWindowLongPtrA when available */ | 
|  | if(SetWindowLongA(X11DRV_DD_PrimaryWnd, GWL_WNDPROC, | 
|  | (LONG)X11DRV_DD_GrabOldProcedure) != (LONG)GrabWndProc) | 
|  | ERR("Window procedure has been changed!\n"); | 
|  | } | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_DestroyDriver(LPDDHAL_DESTROYDRIVERDATA data) | 
|  | { | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_CreateSurface(LPDDHAL_CREATESURFACEDATA data) | 
|  | { | 
|  | if (data->lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { | 
|  | X11DRV_DD_Primary = *data->lplpSList; | 
|  | X11DRV_DD_PrimaryWnd = (HWND)X11DRV_DD_Primary->lpSurfMore->lpDDRAWReserved; | 
|  | X11DRV_DD_PrimaryGbl = X11DRV_DD_Primary->lpGbl; | 
|  | SetPrimaryDIB(GET_LPDDRAWSURFACE_GBL_MORE(X11DRV_DD_PrimaryGbl)->hKernelSurface); | 
|  | X11DRV_DD_UserClass = GlobalFindAtomA("WINE_DDRAW"); | 
|  | if (dxgrab) GrabPointer(TRUE); | 
|  | } | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_NOTHANDLED; | 
|  | } | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_CreatePalette(LPDDHAL_CREATEPALETTEDATA data) | 
|  | { | 
|  | FIXME("stub\n"); | 
|  | /* only makes sense to do anything if the X server is running at 8bpp, | 
|  | * which few people do nowadays */ | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DDHAL_DDCALLBACKS hal_ddcallbacks = { | 
|  | sizeof(DDHAL_DDCALLBACKS), | 
|  | 0x3ff, /* all callbacks are 32-bit */ | 
|  | X11DRV_DDHAL_DestroyDriver, | 
|  | X11DRV_DDHAL_CreateSurface, | 
|  | NULL, /* SetColorKey */ | 
|  | NULL, /* SetMode */ | 
|  | NULL, /* WaitForVerticalBlank */ | 
|  | NULL, /* CanCreateSurface */ | 
|  | X11DRV_DDHAL_CreatePalette, | 
|  | NULL, /* GetScanLine */ | 
|  | NULL, /* SetExclusiveMode */ | 
|  | NULL  /* FlipToGDISurface */ | 
|  | }; | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_DestroySurface(LPDDHAL_DESTROYSURFACEDATA data) | 
|  | { | 
|  | if (data->lpDDSurface == X11DRV_DD_Primary) { | 
|  | if (dxgrab) GrabPointer(FALSE); | 
|  | X11DRV_DD_Primary = NULL; | 
|  | X11DRV_DD_PrimaryWnd = 0; | 
|  | X11DRV_DD_PrimaryGbl = NULL; | 
|  | SetPrimaryDIB(0); | 
|  | X11DRV_DD_UserClass = 0; | 
|  | } | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_SetPalette(LPDDHAL_SETPALETTEDATA data) | 
|  | { | 
|  | if (data->lpDDPalette && data->lpDDPalette->u1.dwReserved1) { | 
|  | if (data->lpDDSurface == X11DRV_DD_Primary) { | 
|  | FIXME("stub\n"); | 
|  | /* we should probably find the ddraw window (maybe data->lpDD->lpExclusiveOwner->hWnd), | 
|  | * and attach the palette to it | 
|  | * | 
|  | * Colormap pal = data->lpDDPalette->u1.dwReserved1; | 
|  | */ | 
|  | } | 
|  | } | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DDHAL_DDSURFACECALLBACKS hal_ddsurfcallbacks = { | 
|  | sizeof(DDHAL_DDSURFACECALLBACKS), | 
|  | 0x3fff, /* all callbacks are 32-bit */ | 
|  | X11DRV_DDHAL_DestroySurface, | 
|  | NULL, /* Flip */ | 
|  | NULL, /* SetClipList */ | 
|  | NULL, /* Lock */ | 
|  | NULL, /* Unlock */ | 
|  | NULL, /* Blt */ | 
|  | NULL, /* SetColorKey */ | 
|  | NULL, /* AddAttachedSurface */ | 
|  | NULL, /* GetBltStatus */ | 
|  | NULL, /* GetFlipStatus */ | 
|  | NULL, /* UpdateOverlay */ | 
|  | NULL, /* SetOverlayPosition */ | 
|  | NULL, /* reserved4 */ | 
|  | X11DRV_DDHAL_SetPalette | 
|  | }; | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_DestroyPalette(LPDDHAL_DESTROYPALETTEDATA data) | 
|  | { | 
|  | Colormap pal = data->lpDDPalette->u1.dwReserved1; | 
|  | if (pal) TSXFreeColormap(gdi_display, pal); | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_SetPaletteEntries(LPDDHAL_SETENTRIESDATA data) | 
|  | { | 
|  | X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, | 
|  | data->dwBase, data->dwNumEntries, | 
|  | data->lpEntries); | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DDHAL_DDPALETTECALLBACKS hal_ddpalcallbacks = { | 
|  | sizeof(DDHAL_DDPALETTECALLBACKS), | 
|  | 0x3, /* all callbacks are 32-bit */ | 
|  | X11DRV_DDHAL_DestroyPalette, | 
|  | X11DRV_DDHAL_SetPaletteEntries | 
|  | }; | 
|  |  | 
|  | static X11DEVICE x11device = { | 
|  | NULL | 
|  | }; | 
|  |  | 
|  | static DWORD PASCAL X11DRV_DDHAL_GetDriverInfo(LPDDHAL_GETDRIVERINFODATA data) | 
|  | { | 
|  | LPX11DRIVERINFO info = x11device.lpInfo; | 
|  | while (info) { | 
|  | if (IsEqualGUID(&data->guidInfo, info->lpGuid)) { | 
|  | DWORD dwSize = info->dwSize; | 
|  | data->dwActualSize = dwSize; | 
|  | if (data->dwExpectedSize < dwSize) dwSize = data->dwExpectedSize; | 
|  | memcpy(data->lpvData, info->lpvData, dwSize); | 
|  | data->ddRVal = DD_OK; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  | info = info->lpNext; | 
|  | } | 
|  | data->ddRVal = DDERR_CURRENTLYNOTAVAIL; | 
|  | return DDHAL_DRIVER_HANDLED; | 
|  | } | 
|  |  | 
|  | static DDHALINFO hal_info = { | 
|  | sizeof(DDHALINFO), | 
|  | &hal_ddcallbacks, | 
|  | &hal_ddsurfcallbacks, | 
|  | &hal_ddpalcallbacks, | 
|  | {	/* vmiData */ | 
|  | 0	 /* fpPrimary */ | 
|  | }, | 
|  | {	/* ddCaps (only stuff the HAL implements here) */ | 
|  | sizeof(DDCORECAPS),							/* dwSize */ | 
|  | DDCAPS_GDI | DDCAPS_PALETTE,						/* dwCaps */ | 
|  | DDCAPS2_CERTIFIED | DDCAPS2_NONLOCALVIDMEM | DDCAPS2_NOPAGELOCKREQUIRED | | 
|  | DDCAPS2_WIDESURFACES | DDCAPS2_PRIMARYGAMMA | DDCAPS2_FLIPNOVSYNC,   /* dwCaps2 */ | 
|  | 0,									/* dwCKeyCaps */ | 
|  | 0,									/* dwFXCaps */ | 
|  | 0,									/* dwFXAlphaCaps */ | 
|  | DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE,				/* dwPalCaps */ | 
|  | 0,									/* dwSVCaps */ | 
|  | 0,									/* dwAlphaBltConstBitDepths */ | 
|  | 0,									/* dwAlphaBltPixelBitDepths */ | 
|  | 0,									/* dwAlphaBltSurfaceBitDepths */ | 
|  | 0,									/* dwAlphaOverlayBltConstBitDepths */ | 
|  | 0,									/* dwAlphaOverlayBltPixelBitDepths */ | 
|  | 0,									/* dwAlphaOverlayBltSurfaceBitDepths */ | 
|  | 0,									/* dwZBufferBitDepths */ | 
|  | 16*1024*1024,							/* dwVidMemTotal */ | 
|  | 16*1024*1024,							/* dwVidMemFree */ | 
|  | 0,									/* dwMaxVisibleOverlays */ | 
|  | 0,									/* dwCurrVisibleOverlays */ | 
|  | 0,									/* dwNumFourCCCodes */ | 
|  | 0,									/* dwAlignBoundarySrc */ | 
|  | 0,									/* dwAlignSizeSrc */ | 
|  | 0,									/* dwAlignBoundaryDest */ | 
|  | 0,									/* dwAlignSizeDest */ | 
|  | 0,									/* dwAlignStrideAlign */ | 
|  | {0},									/* dwRops */ | 
|  | {									/* ddsCaps */ | 
|  | DDSCAPS_BACKBUFFER | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER | | 
|  | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | | 
|  | DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | | 
|  | DDSCAPS_VISIBLE | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM	/* dwCaps */ | 
|  | }, | 
|  | 0,									/* dwMinOverlayStretch */ | 
|  | 0,									/* dwMaxOverlayStretch */ | 
|  | 0,									/* dwMinLiveVideoStretch */ | 
|  | 0,									/* dwMaxLiveVideoStretch */ | 
|  | 0,									/* dwMinHwCodecStretch */ | 
|  | 0,									/* dwMaxHwCodecStretch */ | 
|  | 0,									/* dwReserved1 */ | 
|  | 0,									/* dwReserved2 */ | 
|  | 0,									/* dwReserved2 */ | 
|  | 0,									/* dwSVBCaps */ | 
|  | 0,									/* dwSVBCKeyCaps */ | 
|  | 0,									/* dwSVBFXCaps */ | 
|  | {0},									/* dwSVBRops */ | 
|  | 0,									/* dwVSBCaps */ | 
|  | 0,									/* dwVSBCKeyCaps */ | 
|  | 0,									/* dwVSBFXCaps */ | 
|  | {0},									/* dwVSBRops */ | 
|  | 0,									/* dwSSBCaps */ | 
|  | 0,									/* dwSSBCKeyCaps */ | 
|  | 0,									/* dwSSBFXCaps */ | 
|  | {0},									/* dwSSBRops */ | 
|  | 0,									/* dwMaxVideoPorts */ | 
|  | 0,									/* dwCurrVideoPorts */ | 
|  | 0									/* dwSVBCaps */ | 
|  | }, | 
|  | 0,	/* dwMonitorFrequency */ | 
|  | X11DRV_DDHAL_GetDriverInfo, | 
|  | 0,	/* dwModeIndex */ | 
|  | NULL,	/* lpdwFourCC */ | 
|  | 0,	/* dwNumModes */ | 
|  | NULL,	/* lpModeInfo */ | 
|  | DDHALINFO_ISPRIMARYDISPLAY | DDHALINFO_MODEXILLEGAL | DDHALINFO_GETDRIVERINFOSET, /* dwFlags */ | 
|  | &x11device, | 
|  | 0,	/* hInstance */ | 
|  | 0,	/* lpD3DGlobalDriverData */ | 
|  | 0,	/* lpD3DHALCallbacks */ | 
|  | NULL	/* lpDDExeBufCallbacks */ | 
|  | }; | 
|  |  | 
|  | static LPDDHALDDRAWFNS ddraw_fns; | 
|  | static DWORD ddraw_ver; | 
|  |  | 
|  | static void X11DRV_DDHAL_SetInfo(void) | 
|  | { | 
|  | (ddraw_fns->lpSetInfo)(&hal_info, FALSE); | 
|  | } | 
|  |  | 
|  | INT X11DRV_DCICommand(INT cbInput, const DCICMD *lpCmd, LPVOID lpOutData) | 
|  | { | 
|  | TRACE("(%d,(%ld,%ld,%ld),%p)\n", cbInput, lpCmd->dwCommand, | 
|  | lpCmd->dwParam1, lpCmd->dwParam2, lpOutData); | 
|  |  | 
|  | switch (lpCmd->dwCommand) { | 
|  | case DDNEWCALLBACKFNS: | 
|  | ddraw_fns = (LPDDHALDDRAWFNS)lpCmd->dwParam1; | 
|  | return TRUE; | 
|  | case DDVERSIONINFO: | 
|  | { | 
|  | LPDDVERSIONDATA lpVer = (LPDDVERSIONDATA)lpOutData; | 
|  | ddraw_ver = lpCmd->dwParam1; | 
|  | if (!lpVer) break; | 
|  | /* well, whatever... the DDK says so */ | 
|  | lpVer->dwHALVersion = DD_RUNTIME_VERSION; | 
|  | } | 
|  | return TRUE; | 
|  | case DDGET32BITDRIVERNAME: | 
|  | { | 
|  | LPDD32BITDRIVERDATA lpData = (LPDD32BITDRIVERDATA)lpOutData; | 
|  | /* here, we could ask ddraw to load a separate DLL, that | 
|  | * would contain the 32-bit ddraw HAL */ | 
|  | strcpy(lpData->szName,"x11drv"); | 
|  | /* the entry point named here should initialize our hal_info | 
|  | * with 32-bit entry points (ignored for now) */ | 
|  | strcpy(lpData->szEntryPoint,"DriverInit"); | 
|  | lpData->dwContext = 0; | 
|  | } | 
|  | return TRUE; | 
|  | case DDCREATEDRIVEROBJECT: | 
|  | { | 
|  | LPDWORD lpInstance = (LPDWORD)lpOutData; | 
|  |  | 
|  | /* FIXME: get x11drv's hInstance */ | 
|  | #ifdef HAVE_LIBXXF86DGA2 | 
|  | if (!X11DRV_XF86DGA2_CreateDriver(&hal_info)) | 
|  | #endif | 
|  | { | 
|  | #ifdef HAVE_LIBXXF86VM | 
|  | X11DRV_XF86VM_CreateDriver(&hal_info); | 
|  | #endif | 
|  | } | 
|  | #ifdef HAVE_OPENGL | 
|  | /*X11DRV_GLX_CreateDriver(&hal_info);*/ | 
|  | #endif | 
|  |  | 
|  | (ddraw_fns->lpSetInfo)(&hal_info, FALSE); | 
|  | *lpInstance = hal_info.hInstance; | 
|  | } | 
|  | return TRUE; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void X11DRV_DDHAL_SwitchMode(DWORD dwModeIndex, LPVOID fb_addr, LPVIDMEM fb_mem) | 
|  | { | 
|  | LPDDHALMODEINFO info = &hal_info.lpModeInfo[dwModeIndex]; | 
|  |  | 
|  | hal_info.dwModeIndex        = dwModeIndex; | 
|  | hal_info.dwMonitorFrequency = info->wRefreshRate; | 
|  | hal_info.vmiData.fpPrimary  = (FLATPTR)fb_addr; | 
|  | hal_info.vmiData.dwDisplayWidth  = info->dwWidth; | 
|  | hal_info.vmiData.dwDisplayHeight = info->dwHeight; | 
|  | hal_info.vmiData.lDisplayPitch   = info->lPitch; | 
|  | hal_info.vmiData.ddpfDisplay.dwSize = info->dwBPP ? sizeof(hal_info.vmiData.ddpfDisplay) : 0; | 
|  | hal_info.vmiData.ddpfDisplay.dwFlags = (info->wFlags & DDMODEINFO_PALETTIZED) ? DDPF_PALETTEINDEXED8 : 0; | 
|  | hal_info.vmiData.ddpfDisplay.u1.dwRGBBitCount = (info->dwBPP > 24) ? 24 : info->dwBPP; | 
|  | hal_info.vmiData.ddpfDisplay.u2.dwRBitMask = info->dwRBitMask; | 
|  | hal_info.vmiData.ddpfDisplay.u3.dwGBitMask = info->dwGBitMask; | 
|  | hal_info.vmiData.ddpfDisplay.u4.dwBBitMask = info->dwBBitMask; | 
|  | hal_info.vmiData.dwNumHeaps = fb_mem ? 1 : 0; | 
|  | hal_info.vmiData.pvmList = fb_mem; | 
|  |  | 
|  | X11DRV_DDHAL_SetInfo(); | 
|  | } | 
|  |  | 
|  | void X11DRV_DDHAL_SetPalEntries(Colormap pal, DWORD dwBase, DWORD dwNumEntries, | 
|  | LPPALETTEENTRY lpEntries) | 
|  | { | 
|  | XColor c; | 
|  | int n; | 
|  |  | 
|  | if (pal) { | 
|  | c.flags = DoRed|DoGreen|DoBlue; | 
|  | c.pixel = dwBase; | 
|  | for (n=0; n<dwNumEntries; n++,c.pixel++) { | 
|  | c.red   = lpEntries[n].peRed   << 8; | 
|  | c.green = lpEntries[n].peGreen << 8; | 
|  | c.blue  = lpEntries[n].peBlue  << 8; | 
|  | TSXStoreColor(gdi_display, pal, &c); | 
|  | } | 
|  | TSXFlush(gdi_display); /* update display immediately */ | 
|  | } | 
|  | } |