/*
 * DirectDraw DGA2 interface
 *
 * Copyright 2001 TransGaming Technologies, Inc.
 */

#include "config.h"

#ifdef HAVE_LIBXXF86DGA2

#include "ts_xlib.h"
#include "ts_xf86dga2.h"
#include "x11drv.h"
#include "x11ddraw.h"
#include "dga2.h"

#include "windef.h"
#include "wingdi.h"
#include "ddrawi.h"
#include "debugtools.h"

DEFAULT_DEBUG_CHANNEL(x11drv);

extern int usedga;

LPDDHALMODEINFO xf86dga2_modes;
unsigned xf86dga2_mode_count;
static XDGAMode* modes;
static int dga_event, dga_error;

static void convert_mode(XDGAMode *mode, LPDDHALMODEINFO info)
{
  info->dwWidth        = mode->viewportWidth;
  info->dwHeight       = mode->viewportHeight;
  info->wRefreshRate   = mode->verticalRefresh;
  info->lPitch         = mode->bytesPerScanline;
  info->dwBPP          = (mode->depth < 24) ? mode->depth : mode->bitsPerPixel;
  info->wFlags         = (mode->depth == 8) ? DDMODEINFO_PALETTIZED : 0;
  info->dwRBitMask     = mode->redMask;
  info->dwGBitMask     = mode->greenMask;
  info->dwBBitMask     = mode->blueMask;
  info->dwAlphaBitMask = 0;
  TRACE(" width=%ld, height=%ld, bpp=%ld, refresh=%d\n",
        info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate);
}

void X11DRV_XF86DGA2_Init(void)
{
  int nmodes, major, minor, i;

  if (xf86dga2_modes) return; /* already initialized? */

  /* if in desktop mode, don't use DGA */
  if (root_window != DefaultRootWindow(gdi_display)) return;

  if (!usedga) return;

  if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return;

  if (!TSXDGAQueryVersion(gdi_display, &major, &minor)) return;
  
  if (major < 2) return; /* only bother with DGA 2+ */

  /* test that it works */
  if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) {
    WARN("disabling XF86DGA2 (insufficient permissions?)\n");
    return;
  }
  TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));

  /* retrieve modes */
  modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
  if (!modes) return;

  TRACE("DGA modes: count=%d\n", nmodes);

  xf86dga2_mode_count = nmodes+1;
  xf86dga2_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * (nmodes+1));

  /* make dummy mode for exiting DGA */
  memset(&xf86dga2_modes[0], 0, sizeof(xf86dga2_modes[0]));

  /* convert modes to DDHALMODEINFO format */
  for (i=0; i<nmodes; i++)
    convert_mode(&modes[i], &xf86dga2_modes[i+1]);

  TRACE("Enabling XF86DGA2 mode\n");
}

void X11DRV_XF86DGA2_Cleanup(void)
{
  if (modes) TSXFree(modes);
}

static XDGADevice *dga_dev;

static VIDMEM dga_mem = {
  VIDMEM_ISRECTANGULAR | VIDMEM_ISHEAP
};

static DWORD PASCAL X11DRV_XF86DGA2_SetMode(LPDDHAL_SETMODEDATA data)
{
  LPDDRAWI_DIRECTDRAW_LCL ddlocal = data->lpDD->lpExclusiveOwner;
  DWORD vram;
  Display *display = gdi_display;

  data->ddRVal = DD_OK;
  if (data->dwModeIndex) {
    /* enter DGA */
    XDGADevice *new_dev = NULL;
    if (dga_dev || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
      new_dev = TSXDGASetMode(display, DefaultScreen(display), modes[data->dwModeIndex-1].num);
    if (new_dev) {
      TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
      if (dga_dev) {
	VirtualFree(dga_dev->data, 0, MEM_RELEASE);
	TSXFree(dga_dev);
      } else {
	TSXDGASelectInput(display, DefaultScreen(display),
			  KeyPressMask|KeyReleaseMask|
			  ButtonPressMask|ButtonReleaseMask|
			  PointerMotionMask);
	X11DRV_EVENT_SetDGAStatus(ddlocal->hWnd, dga_event);
	X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
      }
      dga_dev = new_dev;
      vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
      VirtualAlloc(dga_dev->data, vram, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
      dga_mem.fpStart = (FLATPTR)dga_dev->data;
      dga_mem.u1.dwWidth = dga_dev->mode.bytesPerScanline;
      dga_mem.u2.dwHeight = dga_dev->mode.imageHeight;
      X11DRV_DDHAL_SwitchMode(data->dwModeIndex, dga_dev->data, &dga_mem);
      X11DRV_DD_IsDirect = TRUE;
    }
    else {
      ERR("failed\n");
      if (!dga_dev) TSXDGACloseFramebuffer(display, DefaultScreen(display));
      data->ddRVal = DDERR_GENERIC;
    }
  }
  else if (dga_dev) {
    /* exit DGA */
    X11DRV_DD_IsDirect = FALSE;
    X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
    TSXDGASetMode(display, DefaultScreen(display), 0);
    VirtualFree(dga_dev->data, 0, MEM_RELEASE);
    X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
    X11DRV_EVENT_SetDGAStatus(0, -1);
    TSXFree(dga_dev);
    TSXDGACloseFramebuffer(display, DefaultScreen(display));
    dga_dev = NULL;
  }
  return DDHAL_DRIVER_HANDLED;
}

static LPDDHAL_CREATESURFACE X11DRV_XF86DGA2_old_create_surface;

static DWORD PASCAL X11DRV_XF86DGA2_CreateSurface(LPDDHAL_CREATESURFACEDATA data)
{
  LPDDRAWI_DDRAWSURFACE_LCL lcl = *data->lplpSList;
  LPDDRAWI_DDRAWSURFACE_GBL gbl = lcl->lpGbl;
  LPDDSURFACEDESC2 desc = (LPDDSURFACEDESC2)data->lpDDSurfaceDesc;
  HRESULT hr = DDHAL_DRIVER_NOTHANDLED;

  if (X11DRV_XF86DGA2_old_create_surface)
    hr = X11DRV_XF86DGA2_old_create_surface(data);

  if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) {
    gbl->fpVidMem = 0; /* tell ddraw to allocate the memory */
    hr = DDHAL_DRIVER_HANDLED;
  }
  return hr;
}

static DWORD PASCAL X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data)
{
  Display *display = gdi_display;
  data->lpDDPalette->u1.dwReserved1 = TSXDGACreateColormap(display, DefaultScreen(display), dga_dev, AllocAll);
  if (data->lpColorTable)
    X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, 0, 256,
			       data->lpColorTable);
  data->ddRVal = DD_OK;
  return DDHAL_DRIVER_HANDLED;
}

static DWORD PASCAL X11DRV_XF86DGA2_Flip(LPDDHAL_FLIPDATA data)
{
  Display *display = gdi_display;
  if (data->lpSurfCurr == X11DRV_DD_Primary) {
    DWORD ofs = data->lpSurfCurr->lpGbl->fpVidMem - dga_mem.fpStart;
    TSXDGASetViewport(display, DefaultScreen(display),
                      (ofs % dga_dev->mode.bytesPerScanline)*8/dga_dev->mode.bitsPerPixel,
                      ofs / dga_dev->mode.bytesPerScanline,
                      XDGAFlipImmediate);
  }
  data->ddRVal = DD_OK;
  return DDHAL_DRIVER_HANDLED;
}

static DWORD PASCAL X11DRV_XF86DGA2_SetPalette(LPDDHAL_SETPALETTEDATA data)
{
  Display *display = gdi_display;
  if ((data->lpDDSurface == X11DRV_DD_Primary) &&
      data->lpDDPalette && data->lpDDPalette->u1.dwReserved1) {
    TSXDGAInstallColormap(display, DefaultScreen(display), data->lpDDPalette->u1.dwReserved1);
  }
  data->ddRVal = DD_OK;
  return DDHAL_DRIVER_HANDLED;
}

int X11DRV_XF86DGA2_CreateDriver(LPDDHALINFO info)
{
  if (!xf86dga2_mode_count) return 0; /* no DGA */

  info->dwNumModes = xf86dga2_mode_count;
  info->lpModeInfo = xf86dga2_modes;
  info->dwModeIndex = 0;

  X11DRV_XF86DGA2_old_create_surface = info->lpDDCallbacks->CreateSurface;
  info->lpDDCallbacks->SetMode = X11DRV_XF86DGA2_SetMode;
  info->lpDDCallbacks->CreateSurface = X11DRV_XF86DGA2_CreateSurface;
  info->lpDDCallbacks->CreatePalette = X11DRV_XF86DGA2_CreatePalette;
  info->lpDDSurfaceCallbacks->Flip = X11DRV_XF86DGA2_Flip;
  info->lpDDSurfaceCallbacks->SetPalette = X11DRV_XF86DGA2_SetPalette;
  return TRUE;
}

#endif /* HAVE_LIBXXF86DGA2 */
