2001-04-16 21:54:07 +02:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
2001-04-27 20:00:06 +02:00
|
|
|
extern int usedga;
|
|
|
|
|
2001-04-16 21:54:07 +02:00
|
|
|
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;
|
2001-09-11 02:32:32 +02:00
|
|
|
TRACE(" width=%ld, height=%ld, bpp=%ld, refresh=%d\n",
|
|
|
|
info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate);
|
2001-04-16 21:54:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void X11DRV_XF86DGA2_Init(void)
|
|
|
|
{
|
|
|
|
int nmodes, major, minor, i;
|
|
|
|
|
|
|
|
if (xf86dga2_modes) return; /* already initialized? */
|
|
|
|
|
|
|
|
/* if in desktop mode, don't use DGA */
|
2001-05-16 23:01:06 +02:00
|
|
|
if (root_window != DefaultRootWindow(gdi_display)) return;
|
2001-04-16 21:54:07 +02:00
|
|
|
|
2001-04-27 20:00:06 +02:00
|
|
|
if (!usedga) return;
|
2001-04-16 21:54:07 +02:00
|
|
|
|
2001-05-16 23:01:06 +02:00
|
|
|
if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return;
|
2001-04-16 21:54:07 +02:00
|
|
|
|
2001-05-16 23:01:06 +02:00
|
|
|
if (!TSXDGAQueryVersion(gdi_display, &major, &minor)) return;
|
2001-04-16 21:54:07 +02:00
|
|
|
|
|
|
|
if (major < 2) return; /* only bother with DGA 2+ */
|
|
|
|
|
|
|
|
/* test that it works */
|
2001-05-16 23:01:06 +02:00
|
|
|
if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) {
|
2001-04-16 21:54:07 +02:00
|
|
|
TRACE("disabling XF86DGA2 (insufficient permissions?)\n");
|
|
|
|
return;
|
|
|
|
}
|
2001-05-16 23:01:06 +02:00
|
|
|
TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));
|
2001-04-16 21:54:07 +02:00
|
|
|
|
|
|
|
/* retrieve modes */
|
2001-05-16 23:01:06 +02:00
|
|
|
modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
|
2001-04-16 21:54:07 +02:00
|
|
|
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 DGA\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;
|
2001-05-16 23:01:06 +02:00
|
|
|
Display *display = thread_display();
|
2001-04-16 21:54:07 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2001-05-16 23:01:06 +02:00
|
|
|
Display *display = thread_display();
|
2001-04-16 21:54:07 +02:00
|
|
|
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)
|
|
|
|
{
|
2001-05-16 23:01:06 +02:00
|
|
|
Display *display = thread_display();
|
2001-04-16 21:54:07 +02:00
|
|
|
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)
|
|
|
|
{
|
2001-05-16 23:01:06 +02:00
|
|
|
Display *display = thread_display();
|
2001-04-16 21:54:07 +02:00
|
|
|
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 */
|