Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / x11drv / dga2.c
blobe72b496fcc58edc17278c41399e0a1680b29cfec
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 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include <X11/Xlib.h>
28 #include <X11/extensions/xf86dga.h>
30 #include "x11drv.h"
31 #include "x11ddraw.h"
32 #include "dga2.h"
34 #include "windef.h"
35 #include "wingdi.h"
36 #include "ddrawi.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
41 extern int usedga;
43 LPDDHALMODEINFO xf86dga2_modes;
44 unsigned xf86dga2_mode_count;
45 HWND DGAhwnd = 0;
46 static XDGAMode* modes;
48 static void convert_mode(XDGAMode *mode, LPDDHALMODEINFO info)
50 info->dwWidth = mode->viewportWidth;
51 info->dwHeight = mode->viewportHeight;
52 info->wRefreshRate = mode->verticalRefresh;
53 info->lPitch = mode->bytesPerScanline;
54 info->dwBPP = (mode->depth < 24) ? mode->depth : mode->bitsPerPixel;
55 info->wFlags = (mode->depth == 8) ? DDMODEINFO_PALETTIZED : 0;
56 info->dwRBitMask = mode->redMask;
57 info->dwGBitMask = mode->greenMask;
58 info->dwBBitMask = mode->blueMask;
59 info->dwAlphaBitMask = 0;
60 TRACE(" width=%ld, height=%ld, bpp=%ld, refresh=%d\n",
61 info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate);
64 static int DGA2ErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
66 return 1;
69 static void X11DRV_DGAKeyPressEvent( HWND hwnd, XEvent *xev )
71 /* Fill a XKeyEvent to send to EVENT_Key */
72 XDGAKeyEvent *event = (XDGAKeyEvent *)xev;
73 XEvent ke;
75 ke.xkey.type = KeyPress;
76 ke.xkey.serial = event->serial;
77 ke.xkey.send_event = FALSE;
78 ke.xkey.display = event->display;
79 ke.xkey.window = 0;
80 ke.xkey.root = 0;
81 ke.xkey.subwindow = 0;
82 ke.xkey.time = event->time;
83 ke.xkey.x = -1;
84 ke.xkey.y = -1;
85 ke.xkey.x_root = -1;
86 ke.xkey.y_root = -1;
87 ke.xkey.state = event->state;
88 ke.xkey.keycode = event->keycode;
89 ke.xkey.same_screen = TRUE;
90 X11DRV_KeyEvent( 0, &ke );
93 static void X11DRV_DGAKeyReleaseEvent( HWND hwnd, XEvent *xev )
95 /* Fill a XKeyEvent to send to EVENT_Key */
96 XDGAKeyEvent *event = (XDGAKeyEvent *)xev;
97 XEvent ke;
99 ke.xkey.type = KeyRelease;
100 ke.xkey.serial = event->serial;
101 ke.xkey.send_event = FALSE;
102 ke.xkey.display = event->display;
103 ke.xkey.window = 0;
104 ke.xkey.root = 0;
105 ke.xkey.subwindow = 0;
106 ke.xkey.time = event->time;
107 ke.xkey.x = -1;
108 ke.xkey.y = -1;
109 ke.xkey.x_root = -1;
110 ke.xkey.y_root = -1;
111 ke.xkey.state = event->state;
112 ke.xkey.keycode = event->keycode;
113 ke.xkey.same_screen = TRUE;
114 X11DRV_KeyEvent( 0, &ke );
118 void X11DRV_XF86DGA2_Init(void)
120 int nmodes, major, minor, i, event_base, error_base;
121 Bool ok;
123 TRACE("\n");
125 if (xf86dga2_modes) return; /* already initialized? */
127 /* if in desktop mode, don't use DGA */
128 if (root_window != DefaultRootWindow(gdi_display)) return;
130 if (!usedga) return;
132 wine_tsx11_lock();
133 ok = XDGAQueryExtension(gdi_display, &event_base, &error_base);
134 if (ok)
136 X11DRV_expect_error(gdi_display, DGA2ErrorHandler, NULL);
137 ok = XDGAQueryVersion(gdi_display, &major, &minor);
138 if (X11DRV_check_error()) ok = FALSE;
140 wine_tsx11_unlock();
141 if (!ok) return;
143 if (major < 2) return; /* only bother with DGA 2+ */
145 /* test that it works */
146 wine_tsx11_lock();
147 X11DRV_expect_error(gdi_display, DGA2ErrorHandler, NULL);
148 ok = XDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display));
149 if (X11DRV_check_error()) ok = FALSE;
150 if (ok)
152 XDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));
153 /* retrieve modes */
154 modes = XDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
155 if (!modes) ok = FALSE;
157 else WARN("disabling XF86DGA2 (insufficient permissions?)\n");
158 wine_tsx11_unlock();
159 if (!ok) return;
161 TRACE("DGA modes: count=%d\n", nmodes);
163 xf86dga2_mode_count = nmodes+1;
164 xf86dga2_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * (nmodes+1));
166 /* make dummy mode for exiting DGA */
167 memset(&xf86dga2_modes[0], 0, sizeof(xf86dga2_modes[0]));
169 /* convert modes to DDHALMODEINFO format */
170 for (i=0; i<nmodes; i++)
171 convert_mode(&modes[i], &xf86dga2_modes[i+1]);
173 /* register event handlers */
174 X11DRV_register_event_handler( event_base + MotionNotify, X11DRV_DGAMotionEvent );
175 X11DRV_register_event_handler( event_base + ButtonPress, X11DRV_DGAButtonPressEvent );
176 X11DRV_register_event_handler( event_base + ButtonRelease, X11DRV_DGAButtonReleaseEvent );
177 X11DRV_register_event_handler( event_base + KeyPress, X11DRV_DGAKeyPressEvent );
178 X11DRV_register_event_handler( event_base + KeyRelease, X11DRV_DGAKeyReleaseEvent );
180 TRACE("Enabling XF86DGA2 mode\n");
183 void X11DRV_XF86DGA2_Cleanup(void)
185 wine_tsx11_lock();
186 if (modes) XFree(modes);
187 wine_tsx11_unlock();
190 static XDGADevice *dga_dev;
192 static VIDMEM dga_mem = {
193 VIDMEM_ISRECTANGULAR | VIDMEM_ISHEAP
196 static DWORD PASCAL X11DRV_XF86DGA2_SetMode(LPDDHAL_SETMODEDATA data)
198 LPDDRAWI_DIRECTDRAW_LCL ddlocal = data->lpDD->lpExclusiveOwner;
199 DWORD vram;
200 Display *display = gdi_display;
202 data->ddRVal = DD_OK;
203 wine_tsx11_lock();
204 if (data->dwModeIndex) {
205 /* enter DGA */
206 XDGADevice *new_dev = NULL;
207 if (dga_dev || XDGAOpenFramebuffer(display, DefaultScreen(display)))
208 new_dev = XDGASetMode(display, DefaultScreen(display), modes[data->dwModeIndex-1].num);
209 if (new_dev) {
210 XDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
211 if (dga_dev) {
212 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
213 XFree(dga_dev);
214 } else {
215 XDGASelectInput(display, DefaultScreen(display),
216 KeyPressMask|KeyReleaseMask|
217 ButtonPressMask|ButtonReleaseMask|
218 PointerMotionMask);
219 DGAhwnd = (HWND)ddlocal->hWnd;
221 dga_dev = new_dev;
222 vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
223 VirtualAlloc(dga_dev->data, vram, MEM_SYSTEM, PAGE_READWRITE);
224 dga_mem.fpStart = (FLATPTR)dga_dev->data;
225 dga_mem.u1.dwWidth = dga_dev->mode.bytesPerScanline;
226 dga_mem.u2.dwHeight = dga_dev->mode.imageHeight;
227 X11DRV_DDHAL_SwitchMode(data->dwModeIndex, dga_dev->data, &dga_mem);
228 X11DRV_DD_IsDirect = TRUE;
230 else {
231 ERR("failed\n");
232 if (!dga_dev) XDGACloseFramebuffer(display, DefaultScreen(display));
233 data->ddRVal = DDERR_GENERIC;
236 else if (dga_dev) {
237 /* exit DGA */
238 X11DRV_DD_IsDirect = FALSE;
239 X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
240 XDGASetMode(display, DefaultScreen(display), 0);
241 VirtualFree(dga_dev->data, 0, MEM_RELEASE);
242 DGAhwnd = 0;
243 XFree(dga_dev);
244 XDGACloseFramebuffer(display, DefaultScreen(display));
245 dga_dev = NULL;
247 wine_tsx11_unlock();
248 return DDHAL_DRIVER_HANDLED;
251 static LPDDHAL_CREATESURFACE X11DRV_XF86DGA2_old_create_surface;
253 static DWORD PASCAL X11DRV_XF86DGA2_CreateSurface(LPDDHAL_CREATESURFACEDATA data)
255 LPDDRAWI_DDRAWSURFACE_LCL lcl = *data->lplpSList;
256 LPDDRAWI_DDRAWSURFACE_GBL gbl = lcl->lpGbl;
257 LPDDSURFACEDESC2 desc = (LPDDSURFACEDESC2)data->lpDDSurfaceDesc;
258 HRESULT hr = DDHAL_DRIVER_NOTHANDLED;
260 if (X11DRV_XF86DGA2_old_create_surface)
261 hr = X11DRV_XF86DGA2_old_create_surface(data);
263 if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) {
264 gbl->fpVidMem = 0; /* tell ddraw to allocate the memory */
265 hr = DDHAL_DRIVER_HANDLED;
267 return hr;
270 static DWORD PASCAL X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data)
272 Display *display = gdi_display;
273 wine_tsx11_lock();
274 data->lpDDPalette->u1.dwReserved1 = XDGACreateColormap(display, DefaultScreen(display),
275 dga_dev, AllocAll);
276 wine_tsx11_unlock();
277 if (data->lpColorTable)
278 X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, 0, 256,
279 data->lpColorTable);
280 data->ddRVal = DD_OK;
281 return DDHAL_DRIVER_HANDLED;
284 static DWORD PASCAL X11DRV_XF86DGA2_Flip(LPDDHAL_FLIPDATA data)
286 Display *display = gdi_display;
287 if (data->lpSurfCurr == X11DRV_DD_Primary) {
288 DWORD ofs = data->lpSurfCurr->lpGbl->fpVidMem - dga_mem.fpStart;
289 wine_tsx11_lock();
290 XDGASetViewport(display, DefaultScreen(display),
291 (ofs % dga_dev->mode.bytesPerScanline)*8/dga_dev->mode.bitsPerPixel,
292 ofs / dga_dev->mode.bytesPerScanline,
293 XDGAFlipImmediate);
294 wine_tsx11_unlock();
296 data->ddRVal = DD_OK;
297 return DDHAL_DRIVER_HANDLED;
300 static DWORD PASCAL X11DRV_XF86DGA2_SetPalette(LPDDHAL_SETPALETTEDATA data)
302 Display *display = gdi_display;
303 if ((data->lpDDSurface == X11DRV_DD_Primary) &&
304 data->lpDDPalette && data->lpDDPalette->u1.dwReserved1)
306 wine_tsx11_lock();
307 XDGAInstallColormap(display, DefaultScreen(display), data->lpDDPalette->u1.dwReserved1);
308 wine_tsx11_unlock();
310 data->ddRVal = DD_OK;
311 return DDHAL_DRIVER_HANDLED;
314 int X11DRV_XF86DGA2_CreateDriver(LPDDHALINFO info)
316 if (!xf86dga2_mode_count) return 0; /* no DGA */
318 info->dwNumModes = xf86dga2_mode_count;
319 info->lpModeInfo = xf86dga2_modes;
320 info->dwModeIndex = 0;
322 X11DRV_XF86DGA2_old_create_surface = info->lpDDCallbacks->CreateSurface;
323 info->lpDDCallbacks->SetMode = X11DRV_XF86DGA2_SetMode;
324 info->lpDDCallbacks->CreateSurface = X11DRV_XF86DGA2_CreateSurface;
325 info->lpDDCallbacks->CreatePalette = X11DRV_XF86DGA2_CreatePalette;
326 info->lpDDSurfaceCallbacks->Flip = X11DRV_XF86DGA2_Flip;
327 info->lpDDSurfaceCallbacks->SetPalette = X11DRV_XF86DGA2_SetPalette;
328 return TRUE;
331 #endif /* HAVE_LIBXXF86DGA2 */