| /* |
| * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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) { |
| X11DRV_DD_PrimaryDrawable = X11DRV_get_pixmap( hBmp ); |
| } else { |
| X11DRV_DD_PrimaryDrawable = 0; |
| } |
| } |
| |
| static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| struct x11drv_thread_data *data = x11drv_thread_data(); |
| |
| 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(data->display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); |
| wine_tsx11_unlock(); |
| data->grab_window = win; |
| } |
| else |
| { |
| wine_tsx11_lock(); |
| XUngrabPointer(data->display, CurrentTime); |
| wine_tsx11_unlock(); |
| data->grab_window = None; |
| } |
| |
| return 0; |
| } |
| |
| static void GrabPointer(BOOL grab) |
| { |
| if(grab) { |
| Window window = X11DRV_get_whole_window(GetFocus()); |
| if(window) |
| { |
| wine_tsx11_lock(); |
| XSetInputFocus(thread_display(), window, RevertToParent, CurrentTime); |
| wine_tsx11_unlock(); |
| } |
| } |
| |
| if(!X11DRV_DD_GrabMessage) |
| X11DRV_DD_GrabMessage = RegisterWindowMessageA("WINE_X11DRV_GRABPOINTER"); |
| |
| X11DRV_DD_GrabOldProcedure = (WNDPROC)SetWindowLongPtrA(X11DRV_DD_PrimaryWnd, |
| GWLP_WNDPROC, (LONG_PTR)GrabWndProc); |
| |
| SendMessageW(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabMessage, grab, 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(); |
| } |
| } |