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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
28 #include <X11/extensions/xf86dga.h>
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(x11drv
);
43 LPDDHALMODEINFO xf86dga2_modes
;
44 unsigned xf86dga2_mode_count
;
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
)
69 static void X11DRV_DGAKeyPressEvent( HWND hwnd
, XEvent
*xev
)
71 /* Fill a XKeyEvent to send to EVENT_Key */
72 XDGAKeyEvent
*event
= (XDGAKeyEvent
*)xev
;
75 ke
.xkey
.type
= KeyPress
;
76 ke
.xkey
.serial
= event
->serial
;
77 ke
.xkey
.send_event
= FALSE
;
78 ke
.xkey
.display
= event
->display
;
81 ke
.xkey
.subwindow
= 0;
82 ke
.xkey
.time
= event
->time
;
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
;
99 ke
.xkey
.type
= KeyRelease
;
100 ke
.xkey
.serial
= event
->serial
;
101 ke
.xkey
.send_event
= FALSE
;
102 ke
.xkey
.display
= event
->display
;
105 ke
.xkey
.subwindow
= 0;
106 ke
.xkey
.time
= event
->time
;
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
;
125 if (xf86dga2_modes
) return; /* already initialized? */
127 /* if in desktop mode, don't use DGA */
128 if (root_window
!= DefaultRootWindow(gdi_display
)) return;
133 ok
= XDGAQueryExtension(gdi_display
, &event_base
, &error_base
);
136 X11DRV_expect_error(gdi_display
, DGA2ErrorHandler
, NULL
);
137 ok
= XDGAQueryVersion(gdi_display
, &major
, &minor
);
138 if (X11DRV_check_error()) ok
= FALSE
;
143 if (major
< 2) return; /* only bother with DGA 2+ */
145 /* test that it works */
147 X11DRV_expect_error(gdi_display
, DGA2ErrorHandler
, NULL
);
148 ok
= XDGAOpenFramebuffer(gdi_display
, DefaultScreen(gdi_display
));
149 if (X11DRV_check_error()) ok
= FALSE
;
152 XDGACloseFramebuffer(gdi_display
, DefaultScreen(gdi_display
));
154 modes
= XDGAQueryModes(gdi_display
, DefaultScreen(gdi_display
), &nmodes
);
155 if (!modes
) ok
= FALSE
;
157 else WARN("disabling XF86DGA2 (insufficient permissions?)\n");
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)
186 if (modes
) XFree(modes
);
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
;
200 Display
*display
= gdi_display
;
202 data
->ddRVal
= DD_OK
;
204 if (data
->dwModeIndex
) {
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
);
210 XDGASetViewport(display
, DefaultScreen(display
), 0, 0, XDGAFlipImmediate
);
212 VirtualFree(dga_dev
->data
, 0, MEM_RELEASE
);
215 XDGASelectInput(display
, DefaultScreen(display
),
216 KeyPressMask
|KeyReleaseMask
|
217 ButtonPressMask
|ButtonReleaseMask
|
219 DGAhwnd
= (HWND
)ddlocal
->hWnd
;
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
;
232 if (!dga_dev
) XDGACloseFramebuffer(display
, DefaultScreen(display
));
233 data
->ddRVal
= DDERR_GENERIC
;
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
);
244 XDGACloseFramebuffer(display
, DefaultScreen(display
));
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
;
270 static DWORD PASCAL
X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data
)
272 Display
*display
= gdi_display
;
274 data
->lpDDPalette
->u1
.dwReserved1
= XDGACreateColormap(display
, DefaultScreen(display
),
277 if (data
->lpColorTable
)
278 X11DRV_DDHAL_SetPalEntries(data
->lpDDPalette
->u1
.dwReserved1
, 0, 256,
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
;
290 XDGASetViewport(display
, DefaultScreen(display
),
291 (ofs
% dga_dev
->mode
.bytesPerScanline
)*8/dga_dev
->mode
.bitsPerPixel
,
292 ofs
/ dga_dev
->mode
.bytesPerScanline
,
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
)
307 XDGAInstallColormap(display
, DefaultScreen(display
), data
->lpDDPalette
->u1
.dwReserved1
);
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
;
331 #endif /* HAVE_LIBXXF86DGA2 */