1 /* DirectDraw driver for XF86DGA2 primary surface
3 * Copyright 2000 TransGaming Technologies Inc.
8 #ifdef HAVE_LIBXXF86DGA2
10 #include "debugtools.h"
12 #include "ts_xf86dga2.h"
19 #include "ddraw_private.h"
20 #include "ddraw/main.h"
21 #include "ddraw/user.h"
22 #include "ddraw/dga2.h"
23 #include "dclipper/main.h"
24 #include "dpalette/main.h"
25 #include "dsurface/main.h"
26 #include "dsurface/dib.h"
27 #include "dsurface/user.h"
28 #include "dsurface/dga2.h"
32 DEFAULT_DEBUG_CHANNEL(ddraw);
34 static ICOM_VTABLE(IDirectDraw7) XF86DGA2_DirectDraw_VTable;
36 static const DDDEVICEIDENTIFIER2 xf86dga2_device =
40 { { 0x00010001, 0x00010001 } },
42 /* e2dcb020-dc60-11d1-8407-9714f5d50803 */
43 {0xe2dcb020,0xdc60,0x11d1,{0x84,0x07,0x97,0x14,0xf5,0xd5,0x08,0x03}},
47 HRESULT XF86DGA2_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
48 IUnknown* pUnkOuter, BOOL ex);
49 HRESULT XF86DGA2_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
51 static const ddraw_driver xf86dga2_driver =
54 20, /* XVidMode is 11 */
55 XF86DGA2_DirectDraw_Create,
56 XF86DGA2_DirectDraw_Initialize
59 static XDGAMode* modes;
60 static DWORD num_modes;
61 static int dga_event, dga_error;
63 /* Called from DllInit, which is synchronised so there are no threading
65 static BOOL initialize(void)
70 if (X11DRV_GetXRootWindow() != DefaultRootWindow(display)) return FALSE;
72 /* FIXME: don't use PROFILE calls */
73 if (!PROFILE_GetWineIniBool("x11drv", "UseDGA", 1)) return FALSE;
75 if (!TSXDGAQueryExtension(display, &dga_event, &dga_error)) return FALSE;
77 if (!TSXDGAQueryVersion(display, &major, &minor)) return FALSE;
79 if (major < 2) return FALSE; /* only bother with DGA2 */
81 /* test that it works */
82 if (!TSXDGAOpenFramebuffer(display, DefaultScreen(display))) {
83 TRACE("disabling XF86DGA2 (insufficient permissions?)\n");
86 TSXDGACloseFramebuffer(display, DefaultScreen(display));
88 TRACE("getting XF86DGA2 mode list\n");
89 modes = TSXDGAQueryModes(display, DefaultScreen(display), &nmodes);
90 if (!modes) return FALSE;
93 TRACE("enabling XF86DGA2\n");
98 static void cleanup(void)
103 static XDGAMode* choose_mode(DWORD dwWidth, DWORD dwHeight,
104 DWORD dwRefreshRate, DWORD dwFlags)
106 XDGAMode* best = NULL;
109 /* Choose the smallest mode that is large enough. */
110 for (i=0; i < num_modes; i++)
112 if (modes[i].viewportWidth >= dwWidth && modes[i].viewportHeight >= dwHeight)
114 if (best == NULL) best = &modes[i];
117 if (modes[i].viewportWidth < best->viewportWidth
118 || modes[i].viewportHeight < best->viewportHeight)
124 /* all modes were too small, use the largest */
127 TRACE("all modes too small\n");
129 for (i=1; i < num_modes; i++)
131 if (best == NULL) best = &modes[i];
134 if (modes[i].viewportWidth > best->viewportWidth
135 || modes[i].viewportHeight > best->viewportHeight)
141 TRACE("using %d %d for %lu %lu\n", best->viewportWidth, best->viewportHeight,
147 BOOL DDRAW_XF86DGA2_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
149 if (fdwReason == DLL_PROCESS_ATTACH)
152 DDRAW_register_driver(&xf86dga2_driver);
154 else if (fdwReason == DLL_PROCESS_DETACH)
162 /* Not called from the vtable. */
163 HRESULT XF86DGA2_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
169 hr = User_DirectDraw_Construct(This, ex);
170 if (FAILED(hr)) return hr;
172 This->final_release = XF86DGA2_DirectDraw_final_release;
174 This->create_primary = XF86DGA2_DirectDraw_create_primary;
175 This->create_backbuffer = XF86DGA2_DirectDraw_create_backbuffer;
177 ICOM_INIT_INTERFACE(This, IDirectDraw7, XF86DGA2_DirectDraw_VTable);
182 /* This function is called from DirectDrawCreate(Ex) on the most-derived
183 * class to start construction.
184 * Not called from the vtable. */
185 HRESULT XF86DGA2_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
186 IUnknown* pUnkOuter, BOOL ex)
189 IDirectDrawImpl* This;
193 assert(pUnkOuter == NULL);
195 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
196 sizeof(IDirectDrawImpl)
197 + sizeof(XF86DGA2_DirectDrawImpl));
198 if (This == NULL) return E_OUTOFMEMORY;
200 /* Note that this relation does *not* hold true if the DD object was
201 * CoCreateInstanced then Initialized. */
202 This->private = (XF86DGA2_DirectDrawImpl *)(This+1);
204 hr = XF86DGA2_DirectDraw_Construct(This, ex);
206 HeapFree(GetProcessHeap(), 0, This);
208 *pIface = ICOM_INTERFACE(This, IDirectDraw7);
213 /* This function is called from Uninit_DirectDraw_Initialize on the
214 * most-derived-class to start initialization.
215 * Not called from the vtable. */
216 HRESULT XF86DGA2_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
222 This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
223 sizeof(XF86DGA2_DirectDrawImpl));
224 if (This->private == NULL) return E_OUTOFMEMORY;
226 hr = XF86DGA2_DirectDraw_Construct(This, TRUE); /* XXX ex? */
229 HeapFree(GetProcessHeap(), 0, This->private);
236 /* Called from an internal function pointer. */
237 void XF86DGA2_DirectDraw_final_release(IDirectDrawImpl *This)
239 XF86DGA2_DDRAW_PRIV_VAR(priv, This);
241 if (priv->xf86dga2.current_mode) {
242 TSXDGASetMode(display, DefaultScreen(display), 0);
243 VirtualFree(priv->xf86dga2.current_mode->data, 0, MEM_RELEASE);
244 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
245 X11DRV_EVENT_SetDGAStatus(0, -1);
246 TSXFree(priv->xf86dga2.current_mode);
247 TSXDGACloseFramebuffer(display, DefaultScreen(display));
248 priv->xf86dga2.current_mode = NULL;
251 User_DirectDraw_final_release(This);
254 HRESULT XF86DGA2_DirectDraw_create_primary(IDirectDrawImpl* This,
255 const DDSURFACEDESC2* pDDSD,
256 LPDIRECTDRAWSURFACE7* ppSurf,
259 if (This->cooperative_level & DDSCL_EXCLUSIVE)
260 return XF86DGA2_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
262 return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
265 HRESULT XF86DGA2_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
266 const DDSURFACEDESC2* pDDSD,
267 LPDIRECTDRAWSURFACE7* ppSurf,
269 IDirectDrawSurfaceImpl* primary)
271 if (This->cooperative_level & DDSCL_EXCLUSIVE)
272 return XF86DGA2_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
274 return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
278 XF86DGA2_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
279 LPDDDEVICEIDENTIFIER2 pDDDI,
282 *pDDDI = xf86dga2_device;
287 XF86DGA2_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
289 ICOM_THIS(IDirectDrawImpl, iface);
294 hr = Main_DirectDraw_RestoreDisplayMode(iface);
297 XF86DGA2_DDRAW_PRIV_VAR(priv, This);
299 if (priv->xf86dga2.current_mode)
301 TSXDGASetMode(display, DefaultScreen(display), 0);
302 VirtualFree(priv->xf86dga2.current_mode->data, 0, MEM_RELEASE);
303 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
304 X11DRV_EVENT_SetDGAStatus(0, -1);
305 TSXFree(priv->xf86dga2.current_mode);
306 TSXDGACloseFramebuffer(display, DefaultScreen(display));
307 priv->xf86dga2.current_mode = NULL;
315 XF86DGA2_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
316 DWORD dwHeight, DWORD dwBPP,
317 DWORD dwRefreshRate, DWORD dwFlags)
319 ICOM_THIS(IDirectDrawImpl, iface);
323 TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
324 hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
325 dwRefreshRate, dwFlags);
329 XF86DGA2_DDRAW_PRIV_VAR(priv, This);
330 XDGADevice* old_mode = priv->xf86dga2.current_mode;
332 int old_mode_num = old_mode ? old_mode->mode.num : 0;
334 new_mode = choose_mode(dwWidth, dwHeight, dwRefreshRate, dwFlags);
336 if (new_mode && new_mode->num != old_mode_num)
338 XDGADevice * nm = NULL;
339 if (old_mode || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
340 nm = TSXDGASetMode(display, DefaultScreen(display), new_mode->num);
342 TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
344 VirtualFree(old_mode->data, 0, MEM_RELEASE);
347 TSXDGASelectInput(display, DefaultScreen(display),
348 KeyPressMask|KeyReleaseMask|
349 ButtonPressMask|ButtonReleaseMask|
351 X11DRV_EVENT_SetDGAStatus(This->window, dga_event);
352 X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
354 priv->xf86dga2.current_mode = nm;
355 priv->xf86dga2.next_vofs = 0;
356 TRACE("frame buffer at %p, pitch=%d, width=%d, height=%d\n", nm->data,
357 nm->mode.bytesPerScanline, nm->mode.imageWidth, nm->mode.imageHeight);
358 VirtualAlloc(nm->data, nm->mode.bytesPerScanline * nm->mode.imageHeight,
359 MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
363 /* XXX revert size data to previous mode */
365 TSXDGACloseFramebuffer(display, DefaultScreen(display));
373 static ICOM_VTABLE(IDirectDraw7) XF86DGA2_DirectDraw_VTable =
375 Main_DirectDraw_QueryInterface,
376 Main_DirectDraw_AddRef,
377 Main_DirectDraw_Release,
378 Main_DirectDraw_Compact,
379 Main_DirectDraw_CreateClipper,
380 Main_DirectDraw_CreatePalette,
381 Main_DirectDraw_CreateSurface,
382 Main_DirectDraw_DuplicateSurface,
383 User_DirectDraw_EnumDisplayModes,
384 Main_DirectDraw_EnumSurfaces,
385 Main_DirectDraw_FlipToGDISurface,
386 User_DirectDraw_GetCaps,
387 Main_DirectDraw_GetDisplayMode,
388 Main_DirectDraw_GetFourCCCodes,
389 Main_DirectDraw_GetGDISurface,
390 Main_DirectDraw_GetMonitorFrequency,
391 Main_DirectDraw_GetScanLine,
392 Main_DirectDraw_GetVerticalBlankStatus,
393 Main_DirectDraw_Initialize,
394 XF86DGA2_DirectDraw_RestoreDisplayMode,
395 Main_DirectDraw_SetCooperativeLevel,
396 XF86DGA2_DirectDraw_SetDisplayMode,
397 Main_DirectDraw_WaitForVerticalBlank,
398 Main_DirectDraw_GetAvailableVidMem,
399 Main_DirectDraw_GetSurfaceFromDC,
400 Main_DirectDraw_RestoreAllSurfaces,
401 Main_DirectDraw_TestCooperativeLevel,
402 XF86DGA2_DirectDraw_GetDeviceIdentifier,
403 Main_DirectDraw_StartModeTest,
404 Main_DirectDraw_EvaluateMode
407 #endif /* HAVE_LIBXXF86DGA2 */