| /* | |
| * 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 <X11/Xlib.h> | |
| #define NONAMELESSUNION | |
| #define NONAMELESSSTRUCT | |
| #include "x11drv.h" | |
| #include "x11ddraw.h" | |
| #include "dga2.h" | |
| #include "windef.h" | |
| #include "gdi.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=%p, 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; | |
| } | |
| wine_tsx11_lock(); | |
| XGrabPointer(display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); | |
| wine_tsx11_unlock(); | |
| } | |
| else | |
| { | |
| wine_tsx11_lock(); | |
| XUngrabPointer(display, CurrentTime); | |
| wine_tsx11_unlock(); | |
| } | |
| 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"); | |
| X11DRV_DD_GrabOldProcedure = (WNDPROC)SetWindowLongPtrA(X11DRV_DD_PrimaryWnd, | |
| GWLP_WNDPROC, (LONG_PTR)GrabWndProc); | |
| SendMessageA(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabMessage, grab ? 1 : 0, 0); | |
| if(SetWindowLongPtrA(X11DRV_DD_PrimaryWnd, GWLP_WNDPROC, | |
| (LONG_PTR)X11DRV_DD_GrabOldProcedure) != (LONG_PTR)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((HBITMAP)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) | |
| { | |
| wine_tsx11_lock(); | |
| XFreeColormap(gdi_display, pal); | |
| wine_tsx11_unlock(); | |
| } | |
| 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_CANRENDERWINDOWED | | |
| 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 | |
| { | |
| X11DRV_Settings_CreateDriver(&hal_info); | |
| } | |
| #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; | |
| unsigned int n; | |
| if (pal) { | |
| wine_tsx11_lock(); | |
| 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; | |
| XStoreColor(gdi_display, pal, &c); | |
| } | |
| XFlush(gdi_display); /* update display immediately */ | |
| wine_tsx11_unlock(); | |
| } | |
| } |