2 * DirectDraw DGA2 interface
4 * Copyright 2001 TransGaming Technologies, Inc.
9 #ifdef HAVE_LIBXXF86DGA2
12 #include "ts_xf86dga2.h"
20 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(x11drv);
26 LPDDHALMODEINFO xf86dga2_modes;
27 unsigned xf86dga2_mode_count;
28 static XDGAMode* modes;
29 static int dga_event, dga_error;
31 static void convert_mode(XDGAMode *mode, LPDDHALMODEINFO info)
33 info->dwWidth = mode->viewportWidth;
34 info->dwHeight = mode->viewportHeight;
35 info->wRefreshRate = mode->verticalRefresh;
36 info->lPitch = mode->bytesPerScanline;
37 info->dwBPP = (mode->depth < 24) ? mode->depth : mode->bitsPerPixel;
38 info->wFlags = (mode->depth == 8) ? DDMODEINFO_PALETTIZED : 0;
39 info->dwRBitMask = mode->redMask;
40 info->dwGBitMask = mode->greenMask;
41 info->dwBBitMask = mode->blueMask;
42 info->dwAlphaBitMask = 0;
43 TRACE(" width=%ld, height=%ld, bpp=%ld, refresh=%d\n", \
44 info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate); \
47 void X11DRV_XF86DGA2_Init(void)
49 int nmodes, major, minor, i;
51 if (xf86dga2_modes) return; /* already initialized? */
53 /* if in desktop mode, don't use DGA */
54 if (root_window != DefaultRootWindow(gdi_display)) return;
58 if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return;
60 if (!TSXDGAQueryVersion(gdi_display, &major, &minor)) return;
62 if (major < 2) return; /* only bother with DGA 2+ */
64 /* test that it works */
65 if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) {
66 TRACE("disabling XF86DGA2 (insufficient permissions?)\n");
69 TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));
72 modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
75 TRACE("DGA modes: count=%d\n", nmodes);
77 xf86dga2_mode_count = nmodes+1;
78 xf86dga2_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * (nmodes+1));
80 /* make dummy mode for exiting DGA */
81 memset(&xf86dga2_modes[0], 0, sizeof(xf86dga2_modes[0]));
83 /* convert modes to DDHALMODEINFO format */
84 for (i=0; i<nmodes; i++)
85 convert_mode(&modes[i], &xf86dga2_modes[i+1]);
87 TRACE("Enabling DGA\n");
90 void X11DRV_XF86DGA2_Cleanup(void)
92 if (modes) TSXFree(modes);
95 static XDGADevice *dga_dev;
97 static VIDMEM dga_mem = {
98 VIDMEM_ISRECTANGULAR | VIDMEM_ISHEAP
101 static DWORD PASCAL X11DRV_XF86DGA2_SetMode(LPDDHAL_SETMODEDATA data)
103 LPDDRAWI_DIRECTDRAW_LCL ddlocal = data->lpDD->lpExclusiveOwner;
105 Display *display = thread_display();
107 data->ddRVal = DD_OK;
108 if (data->dwModeIndex) {
110 XDGADevice *new_dev = NULL;
111 if (dga_dev || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
112 new_dev = TSXDGASetMode(display, DefaultScreen(display), modes[data->dwModeIndex-1].num);
114 TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
116 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
119 TSXDGASelectInput(display, DefaultScreen(display),
120 KeyPressMask|KeyReleaseMask|
121 ButtonPressMask|ButtonReleaseMask|
123 X11DRV_EVENT_SetDGAStatus(ddlocal->hWnd, dga_event);
124 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
127 vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
128 VirtualAlloc(dga_dev->data, vram, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
129 dga_mem.fpStart = (FLATPTR)dga_dev->data;
130 dga_mem.u1.dwWidth = dga_dev->mode.bytesPerScanline;
131 dga_mem.u2.dwHeight = dga_dev->mode.imageHeight;
132 X11DRV_DDHAL_SwitchMode(data->dwModeIndex, dga_dev->data, &dga_mem);
133 X11DRV_DD_IsDirect = TRUE;
137 if (!dga_dev) TSXDGACloseFramebuffer(display, DefaultScreen(display));
138 data->ddRVal = DDERR_GENERIC;
143 X11DRV_DD_IsDirect = FALSE;
144 X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
145 TSXDGASetMode(display, DefaultScreen(display), 0);
146 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
147 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
148 X11DRV_EVENT_SetDGAStatus(0, -1);
150 TSXDGACloseFramebuffer(display, DefaultScreen(display));
153 return DDHAL_DRIVER_HANDLED;
156 static LPDDHAL_CREATESURFACE X11DRV_XF86DGA2_old_create_surface;
158 static DWORD PASCAL X11DRV_XF86DGA2_CreateSurface(LPDDHAL_CREATESURFACEDATA data)
160 LPDDRAWI_DDRAWSURFACE_LCL lcl = *data->lplpSList;
161 LPDDRAWI_DDRAWSURFACE_GBL gbl = lcl->lpGbl;
162 LPDDSURFACEDESC2 desc = (LPDDSURFACEDESC2)data->lpDDSurfaceDesc;
163 HRESULT hr = DDHAL_DRIVER_NOTHANDLED;
165 if (X11DRV_XF86DGA2_old_create_surface)
166 hr = X11DRV_XF86DGA2_old_create_surface(data);
168 if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) {
169 gbl->fpVidMem = 0; /* tell ddraw to allocate the memory */
170 hr = DDHAL_DRIVER_HANDLED;
175 static DWORD PASCAL X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data)
177 Display *display = thread_display();
178 data->lpDDPalette->u1.dwReserved1 = TSXDGACreateColormap(display, DefaultScreen(display), dga_dev, AllocAll);
179 if (data->lpColorTable)
180 X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, 0, 256,
182 data->ddRVal = DD_OK;
183 return DDHAL_DRIVER_HANDLED;
186 static DWORD PASCAL X11DRV_XF86DGA2_Flip(LPDDHAL_FLIPDATA data)
188 Display *display = thread_display();
189 if (data->lpSurfCurr == X11DRV_DD_Primary) {
190 DWORD ofs = data->lpSurfCurr->lpGbl->fpVidMem - dga_mem.fpStart;
191 TSXDGASetViewport(display, DefaultScreen(display),
192 (ofs % dga_dev->mode.bytesPerScanline)*8/dga_dev->mode.bitsPerPixel,
193 ofs / dga_dev->mode.bytesPerScanline,
196 data->ddRVal = DD_OK;
197 return DDHAL_DRIVER_HANDLED;
200 static DWORD PASCAL X11DRV_XF86DGA2_SetPalette(LPDDHAL_SETPALETTEDATA data)
202 Display *display = thread_display();
203 if ((data->lpDDSurface == X11DRV_DD_Primary) &&
204 data->lpDDPalette && data->lpDDPalette->u1.dwReserved1) {
205 TSXDGAInstallColormap(display, DefaultScreen(display), data->lpDDPalette->u1.dwReserved1);
207 data->ddRVal = DD_OK;
208 return DDHAL_DRIVER_HANDLED;
211 int X11DRV_XF86DGA2_CreateDriver(LPDDHALINFO info)
213 if (!xf86dga2_mode_count) return 0; /* no DGA */
215 info->dwNumModes = xf86dga2_mode_count;
216 info->lpModeInfo = xf86dga2_modes;
217 info->dwModeIndex = 0;
219 X11DRV_XF86DGA2_old_create_surface = info->lpDDCallbacks->CreateSurface;
220 info->lpDDCallbacks->SetMode = X11DRV_XF86DGA2_SetMode;
221 info->lpDDCallbacks->CreateSurface = X11DRV_XF86DGA2_CreateSurface;
222 info->lpDDCallbacks->CreatePalette = X11DRV_XF86DGA2_CreatePalette;
223 info->lpDDSurfaceCallbacks->Flip = X11DRV_XF86DGA2_Flip;
224 info->lpDDSurfaceCallbacks->SetPalette = X11DRV_XF86DGA2_SetPalette;
228 #endif /* HAVE_LIBXXF86DGA2 */