2 * DirectDraw DGA2 interface
4 * Copyright 2001 TransGaming Technologies, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifdef HAVE_LIBXXF86DGA2
26 #include "ts_xf86dga2.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
40 LPDDHALMODEINFO xf86dga2_modes;
41 unsigned xf86dga2_mode_count;
42 static XDGAMode* modes;
43 static int dga_event, dga_error;
45 static void convert_mode(XDGAMode *mode, LPDDHALMODEINFO info)
47 info->dwWidth = mode->viewportWidth;
48 info->dwHeight = mode->viewportHeight;
49 info->wRefreshRate = mode->verticalRefresh;
50 info->lPitch = mode->bytesPerScanline;
51 info->dwBPP = (mode->depth < 24) ? mode->depth : mode->bitsPerPixel;
52 info->wFlags = (mode->depth == 8) ? DDMODEINFO_PALETTIZED : 0;
53 info->dwRBitMask = mode->redMask;
54 info->dwGBitMask = mode->greenMask;
55 info->dwBBitMask = mode->blueMask;
56 info->dwAlphaBitMask = 0;
57 TRACE(" width=%ld, height=%ld, bpp=%ld, refresh=%d\n",
58 info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate);
61 void X11DRV_XF86DGA2_Init(void)
63 int nmodes, major, minor, i;
65 if (xf86dga2_modes) return; /* already initialized? */
67 /* if in desktop mode, don't use DGA */
68 if (root_window != DefaultRootWindow(gdi_display)) return;
72 if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return;
74 if (!TSXDGAQueryVersion(gdi_display, &major, &minor)) return;
76 if (major < 2) return; /* only bother with DGA 2+ */
78 /* test that it works */
79 if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) {
80 WARN("disabling XF86DGA2 (insufficient permissions?)\n");
83 TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));
86 modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
89 TRACE("DGA modes: count=%d\n", nmodes);
91 xf86dga2_mode_count = nmodes+1;
92 xf86dga2_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * (nmodes+1));
94 /* make dummy mode for exiting DGA */
95 memset(&xf86dga2_modes[0], 0, sizeof(xf86dga2_modes[0]));
97 /* convert modes to DDHALMODEINFO format */
98 for (i=0; i<nmodes; i++)
99 convert_mode(&modes[i], &xf86dga2_modes[i+1]);
101 TRACE("Enabling XF86DGA2 mode\n");
104 void X11DRV_XF86DGA2_Cleanup(void)
106 if (modes) TSXFree(modes);
109 static XDGADevice *dga_dev;
111 static VIDMEM dga_mem = {
112 VIDMEM_ISRECTANGULAR | VIDMEM_ISHEAP
115 static DWORD PASCAL X11DRV_XF86DGA2_SetMode(LPDDHAL_SETMODEDATA data)
117 LPDDRAWI_DIRECTDRAW_LCL ddlocal = data->lpDD->lpExclusiveOwner;
119 Display *display = gdi_display;
121 data->ddRVal = DD_OK;
122 if (data->dwModeIndex) {
124 XDGADevice *new_dev = NULL;
125 if (dga_dev || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
126 new_dev = TSXDGASetMode(display, DefaultScreen(display), modes[data->dwModeIndex-1].num);
128 TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
130 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
133 TSXDGASelectInput(display, DefaultScreen(display),
134 KeyPressMask|KeyReleaseMask|
135 ButtonPressMask|ButtonReleaseMask|
137 X11DRV_EVENT_SetDGAStatus(ddlocal->hWnd, dga_event);
138 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
141 vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
142 VirtualAlloc(dga_dev->data, vram, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
143 dga_mem.fpStart = (FLATPTR)dga_dev->data;
144 dga_mem.u1.dwWidth = dga_dev->mode.bytesPerScanline;
145 dga_mem.u2.dwHeight = dga_dev->mode.imageHeight;
146 X11DRV_DDHAL_SwitchMode(data->dwModeIndex, dga_dev->data, &dga_mem);
147 X11DRV_DD_IsDirect = TRUE;
151 if (!dga_dev) TSXDGACloseFramebuffer(display, DefaultScreen(display));
152 data->ddRVal = DDERR_GENERIC;
157 X11DRV_DD_IsDirect = FALSE;
158 X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
159 TSXDGASetMode(display, DefaultScreen(display), 0);
160 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
161 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
162 X11DRV_EVENT_SetDGAStatus(0, -1);
164 TSXDGACloseFramebuffer(display, DefaultScreen(display));
167 return DDHAL_DRIVER_HANDLED;
170 static LPDDHAL_CREATESURFACE X11DRV_XF86DGA2_old_create_surface;
172 static DWORD PASCAL X11DRV_XF86DGA2_CreateSurface(LPDDHAL_CREATESURFACEDATA data)
174 LPDDRAWI_DDRAWSURFACE_LCL lcl = *data->lplpSList;
175 LPDDRAWI_DDRAWSURFACE_GBL gbl = lcl->lpGbl;
176 LPDDSURFACEDESC2 desc = (LPDDSURFACEDESC2)data->lpDDSurfaceDesc;
177 HRESULT hr = DDHAL_DRIVER_NOTHANDLED;
179 if (X11DRV_XF86DGA2_old_create_surface)
180 hr = X11DRV_XF86DGA2_old_create_surface(data);
182 if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) {
183 gbl->fpVidMem = 0; /* tell ddraw to allocate the memory */
184 hr = DDHAL_DRIVER_HANDLED;
189 static DWORD PASCAL X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data)
191 Display *display = gdi_display;
192 data->lpDDPalette->u1.dwReserved1 = TSXDGACreateColormap(display, DefaultScreen(display), dga_dev, AllocAll);
193 if (data->lpColorTable)
194 X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, 0, 256,
196 data->ddRVal = DD_OK;
197 return DDHAL_DRIVER_HANDLED;
200 static DWORD PASCAL X11DRV_XF86DGA2_Flip(LPDDHAL_FLIPDATA data)
202 Display *display = gdi_display;
203 if (data->lpSurfCurr == X11DRV_DD_Primary) {
204 DWORD ofs = data->lpSurfCurr->lpGbl->fpVidMem - dga_mem.fpStart;
205 TSXDGASetViewport(display, DefaultScreen(display),
206 (ofs % dga_dev->mode.bytesPerScanline)*8/dga_dev->mode.bitsPerPixel,
207 ofs / dga_dev->mode.bytesPerScanline,
210 data->ddRVal = DD_OK;
211 return DDHAL_DRIVER_HANDLED;
214 static DWORD PASCAL X11DRV_XF86DGA2_SetPalette(LPDDHAL_SETPALETTEDATA data)
216 Display *display = gdi_display;
217 if ((data->lpDDSurface == X11DRV_DD_Primary) &&
218 data->lpDDPalette && data->lpDDPalette->u1.dwReserved1) {
219 TSXDGAInstallColormap(display, DefaultScreen(display), data->lpDDPalette->u1.dwReserved1);
221 data->ddRVal = DD_OK;
222 return DDHAL_DRIVER_HANDLED;
225 int X11DRV_XF86DGA2_CreateDriver(LPDDHALINFO info)
227 if (!xf86dga2_mode_count) return 0; /* no DGA */
229 info->dwNumModes = xf86dga2_mode_count;
230 info->lpModeInfo = xf86dga2_modes;
231 info->dwModeIndex = 0;
233 X11DRV_XF86DGA2_old_create_surface = info->lpDDCallbacks->CreateSurface;
234 info->lpDDCallbacks->SetMode = X11DRV_XF86DGA2_SetMode;
235 info->lpDDCallbacks->CreateSurface = X11DRV_XF86DGA2_CreateSurface;
236 info->lpDDCallbacks->CreatePalette = X11DRV_XF86DGA2_CreatePalette;
237 info->lpDDSurfaceCallbacks->Flip = X11DRV_XF86DGA2_Flip;
238 info->lpDDSurfaceCallbacks->SetPalette = X11DRV_XF86DGA2_SetPalette;
242 #endif /* HAVE_LIBXXF86DGA2 */