Merged the NAS driver written by Nicolas
[wine/multimedia.git] / dlls / x11drv / dga2.c
bloba51ee5713fb46dae1d78a9b1331f3848d105f7f4
1 /*
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
21 #include "config.h"
23 #ifdef HAVE_LIBXXF86DGA2
25 #include "ts_xlib.h"
26 #include "ts_xf86dga2.h"
27 #include "x11drv.h"
28 #include "x11ddraw.h"
29 #include "dga2.h"
31 #include "windef.h"
32 #include "wingdi.h"
33 #include "ddrawi.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
38 extern int usedga;
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 static int DGA2ErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
63 return 1;
66 void X11DRV_XF86DGA2_Init(void)
68 int nmodes, major, minor, i;
69 Bool ok;
71 if (xf86dga2_modes) return; /* already initialized? */
73 /* if in desktop mode, don't use DGA */
74 if (root_window != DefaultRootWindow(gdi_display)) return;
76 if (!usedga) return;
78 if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return;
80 X11DRV_expect_error(gdi_display, DGA2ErrorHandler, NULL);
81 ok = TSXDGAQueryVersion(gdi_display, &major, &minor);
82 if (X11DRV_check_error()) ok = FALSE;
83 if (!ok) return;
85 if (major < 2) return; /* only bother with DGA 2+ */
87 /* test that it works */
88 if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) {
89 WARN("disabling XF86DGA2 (insufficient permissions?)\n");
90 return;
92 TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));
94 /* retrieve modes */
95 modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
96 if (!modes) return;
98 TRACE("DGA modes: count=%d\n", nmodes);
100 xf86dga2_mode_count = nmodes+1;
101 xf86dga2_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * (nmodes+1));
103 /* make dummy mode for exiting DGA */
104 memset(&xf86dga2_modes[0], 0, sizeof(xf86dga2_modes[0]));
106 /* convert modes to DDHALMODEINFO format */
107 for (i=0; i<nmodes; i++)
108 convert_mode(&modes[i], &xf86dga2_modes[i+1]);
110 TRACE("Enabling XF86DGA2 mode\n");
113 void X11DRV_XF86DGA2_Cleanup(void)
115 if (modes) TSXFree(modes);
118 static XDGADevice *dga_dev;
120 static VIDMEM dga_mem = {
121 VIDMEM_ISRECTANGULAR | VIDMEM_ISHEAP
124 static DWORD PASCAL X11DRV_XF86DGA2_SetMode(LPDDHAL_SETMODEDATA data)
126 LPDDRAWI_DIRECTDRAW_LCL ddlocal = data->lpDD->lpExclusiveOwner;
127 DWORD vram;
128 Display *display = gdi_display;
130 data->ddRVal = DD_OK;
131 if (data->dwModeIndex) {
132 /* enter DGA */
133 XDGADevice *new_dev = NULL;
134 if (dga_dev || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
135 new_dev = TSXDGASetMode(display, DefaultScreen(display), modes[data->dwModeIndex-1].num);
136 if (new_dev) {
137 TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
138 if (dga_dev) {
139 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
140 TSXFree(dga_dev);
141 } else {
142 TSXDGASelectInput(display, DefaultScreen(display),
143 KeyPressMask|KeyReleaseMask|
144 ButtonPressMask|ButtonReleaseMask|
145 PointerMotionMask);
146 X11DRV_EVENT_SetDGAStatus(ddlocal->hWnd, dga_event);
147 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
149 dga_dev = new_dev;
150 vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
151 VirtualAlloc(dga_dev->data, vram, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
152 dga_mem.fpStart = (FLATPTR)dga_dev->data;
153 dga_mem.u1.dwWidth = dga_dev->mode.bytesPerScanline;
154 dga_mem.u2.dwHeight = dga_dev->mode.imageHeight;
155 X11DRV_DDHAL_SwitchMode(data->dwModeIndex, dga_dev->data, &dga_mem);
156 X11DRV_DD_IsDirect = TRUE;
158 else {
159 ERR("failed\n");
160 if (!dga_dev) TSXDGACloseFramebuffer(display, DefaultScreen(display));
161 data->ddRVal = DDERR_GENERIC;
164 else if (dga_dev) {
165 /* exit DGA */
166 X11DRV_DD_IsDirect = FALSE;
167 X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
168 TSXDGASetMode(display, DefaultScreen(display), 0);
169 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
170 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
171 X11DRV_EVENT_SetDGAStatus(0, -1);
172 TSXFree(dga_dev);
173 TSXDGACloseFramebuffer(display, DefaultScreen(display));
174 dga_dev = NULL;
176 return DDHAL_DRIVER_HANDLED;
179 static LPDDHAL_CREATESURFACE X11DRV_XF86DGA2_old_create_surface;
181 static DWORD PASCAL X11DRV_XF86DGA2_CreateSurface(LPDDHAL_CREATESURFACEDATA data)
183 LPDDRAWI_DDRAWSURFACE_LCL lcl = *data->lplpSList;
184 LPDDRAWI_DDRAWSURFACE_GBL gbl = lcl->lpGbl;
185 LPDDSURFACEDESC2 desc = (LPDDSURFACEDESC2)data->lpDDSurfaceDesc;
186 HRESULT hr = DDHAL_DRIVER_NOTHANDLED;
188 if (X11DRV_XF86DGA2_old_create_surface)
189 hr = X11DRV_XF86DGA2_old_create_surface(data);
191 if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) {
192 gbl->fpVidMem = 0; /* tell ddraw to allocate the memory */
193 hr = DDHAL_DRIVER_HANDLED;
195 return hr;
198 static DWORD PASCAL X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data)
200 Display *display = gdi_display;
201 data->lpDDPalette->u1.dwReserved1 = TSXDGACreateColormap(display, DefaultScreen(display), dga_dev, AllocAll);
202 if (data->lpColorTable)
203 X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, 0, 256,
204 data->lpColorTable);
205 data->ddRVal = DD_OK;
206 return DDHAL_DRIVER_HANDLED;
209 static DWORD PASCAL X11DRV_XF86DGA2_Flip(LPDDHAL_FLIPDATA data)
211 Display *display = gdi_display;
212 if (data->lpSurfCurr == X11DRV_DD_Primary) {
213 DWORD ofs = data->lpSurfCurr->lpGbl->fpVidMem - dga_mem.fpStart;
214 TSXDGASetViewport(display, DefaultScreen(display),
215 (ofs % dga_dev->mode.bytesPerScanline)*8/dga_dev->mode.bitsPerPixel,
216 ofs / dga_dev->mode.bytesPerScanline,
217 XDGAFlipImmediate);
219 data->ddRVal = DD_OK;
220 return DDHAL_DRIVER_HANDLED;
223 static DWORD PASCAL X11DRV_XF86DGA2_SetPalette(LPDDHAL_SETPALETTEDATA data)
225 Display *display = gdi_display;
226 if ((data->lpDDSurface == X11DRV_DD_Primary) &&
227 data->lpDDPalette && data->lpDDPalette->u1.dwReserved1) {
228 TSXDGAInstallColormap(display, DefaultScreen(display), data->lpDDPalette->u1.dwReserved1);
230 data->ddRVal = DD_OK;
231 return DDHAL_DRIVER_HANDLED;
234 int X11DRV_XF86DGA2_CreateDriver(LPDDHALINFO info)
236 if (!xf86dga2_mode_count) return 0; /* no DGA */
238 info->dwNumModes = xf86dga2_mode_count;
239 info->lpModeInfo = xf86dga2_modes;
240 info->dwModeIndex = 0;
242 X11DRV_XF86DGA2_old_create_surface = info->lpDDCallbacks->CreateSurface;
243 info->lpDDCallbacks->SetMode = X11DRV_XF86DGA2_SetMode;
244 info->lpDDCallbacks->CreateSurface = X11DRV_XF86DGA2_CreateSurface;
245 info->lpDDCallbacks->CreatePalette = X11DRV_XF86DGA2_CreatePalette;
246 info->lpDDSurfaceCallbacks->Flip = X11DRV_XF86DGA2_Flip;
247 info->lpDDSurfaceCallbacks->SetPalette = X11DRV_XF86DGA2_SetPalette;
248 return TRUE;
251 #endif /* HAVE_LIBXXF86DGA2 */