/*
 * 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 "xvidmode.h"
#include "xrandr.h"
#include "dga2.h"

#include "windef.h"
#include "wingdi.h"
#include "ddrawi.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");

  /* 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((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();
  }
}
