Fixed desktop window structure initialization.
[wine] / dlls / x11drv / dga2.c
1 /*
2  * DirectDraw DGA2 interface
3  *
4  * Copyright 2001 TransGaming Technologies, Inc.
5  */
6
7 #include "config.h"
8
9 #ifdef HAVE_LIBXXF86DGA2
10
11 #include "ts_xlib.h"
12 #include "ts_xf86dga2.h"
13 #include "x11drv.h"
14 #include "x11ddraw.h"
15 #include "dga2.h"
16
17 #include "windef.h"
18 #include "wingdi.h"
19 #include "ddrawi.h"
20 #include "debugtools.h"
21
22 DEFAULT_DEBUG_CHANNEL(x11drv);
23
24 extern int usedga;
25
26 LPDDHALMODEINFO xf86dga2_modes;
27 unsigned xf86dga2_mode_count;
28 static XDGAMode* modes;
29 static int dga_event, dga_error;
30
31 static void convert_mode(XDGAMode *mode, LPDDHALMODEINFO info)
32 {
33   info->dwWidth        = mode->viewportWidth;
34   info->dwHeight       = mode->viewportHeight;
35   info->wRefreshRate   = mode->verticalRefresh;
36   info->lPitch         = mode->bytesPerScanline;
37   info->dwBPP          = (mode->depth < 24) ? mode->depth : mode->bitsPerPixel;
38   info->wFlags         = (mode->depth == 8) ? DDMODEINFO_PALETTIZED : 0;
39   info->dwRBitMask     = mode->redMask;
40   info->dwGBitMask     = mode->greenMask;
41   info->dwBBitMask     = mode->blueMask;
42   info->dwAlphaBitMask = 0;
43   TRACE(" width=%ld, height=%ld, bpp=%ld, refresh=%d\n", \
44         info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate); \
45 }
46
47 void X11DRV_XF86DGA2_Init(void)
48 {
49   int nmodes, major, minor, i;
50
51   if (xf86dga2_modes) return; /* already initialized? */
52
53   /* if in desktop mode, don't use DGA */
54   if (root_window != DefaultRootWindow(gdi_display)) return;
55
56   if (!usedga) return;
57
58   if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return;
59
60   if (!TSXDGAQueryVersion(gdi_display, &major, &minor)) return;
61   
62   if (major < 2) return; /* only bother with DGA 2+ */
63
64   /* test that it works */
65   if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) {
66     TRACE("disabling XF86DGA2 (insufficient permissions?)\n");
67     return;
68   }
69   TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display));
70
71   /* retrieve modes */
72   modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes);
73   if (!modes) return;
74
75   TRACE("DGA modes: count=%d\n", nmodes);
76
77   xf86dga2_mode_count = nmodes+1;
78   xf86dga2_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * (nmodes+1));
79
80   /* make dummy mode for exiting DGA */
81   memset(&xf86dga2_modes[0], 0, sizeof(xf86dga2_modes[0]));
82
83   /* convert modes to DDHALMODEINFO format */
84   for (i=0; i<nmodes; i++)
85     convert_mode(&modes[i], &xf86dga2_modes[i+1]);
86
87   TRACE("Enabling DGA\n");
88 }
89
90 void X11DRV_XF86DGA2_Cleanup(void)
91 {
92   if (modes) TSXFree(modes);
93 }
94
95 static XDGADevice *dga_dev;
96
97 static VIDMEM dga_mem = {
98   VIDMEM_ISRECTANGULAR | VIDMEM_ISHEAP
99 };
100
101 static DWORD PASCAL X11DRV_XF86DGA2_SetMode(LPDDHAL_SETMODEDATA data)
102 {
103   LPDDRAWI_DIRECTDRAW_LCL ddlocal = data->lpDD->lpExclusiveOwner;
104   DWORD vram;
105   Display *display = thread_display();
106
107   data->ddRVal = DD_OK;
108   if (data->dwModeIndex) {
109     /* enter DGA */
110     XDGADevice *new_dev = NULL;
111     if (dga_dev || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
112       new_dev = TSXDGASetMode(display, DefaultScreen(display), modes[data->dwModeIndex-1].num);
113     if (new_dev) {
114       TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
115       if (dga_dev) {
116         VirtualFree(dga_dev->data, 0, MEM_RELEASE);
117         TSXFree(dga_dev);
118       } else {
119         TSXDGASelectInput(display, DefaultScreen(display),
120                           KeyPressMask|KeyReleaseMask|
121                           ButtonPressMask|ButtonReleaseMask|
122                           PointerMotionMask);
123         X11DRV_EVENT_SetDGAStatus(ddlocal->hWnd, dga_event);
124         X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
125       }
126       dga_dev = new_dev;
127       vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
128       VirtualAlloc(dga_dev->data, vram, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
129       dga_mem.fpStart = (FLATPTR)dga_dev->data;
130       dga_mem.u1.dwWidth = dga_dev->mode.bytesPerScanline;
131       dga_mem.u2.dwHeight = dga_dev->mode.imageHeight;
132       X11DRV_DDHAL_SwitchMode(data->dwModeIndex, dga_dev->data, &dga_mem);
133       X11DRV_DD_IsDirect = TRUE;
134     }
135     else {
136       ERR("failed\n");
137       if (!dga_dev) TSXDGACloseFramebuffer(display, DefaultScreen(display));
138       data->ddRVal = DDERR_GENERIC;
139     }
140   }
141   else if (dga_dev) {
142     /* exit DGA */
143     X11DRV_DD_IsDirect = FALSE;
144     X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
145     TSXDGASetMode(display, DefaultScreen(display), 0);
146     VirtualFree(dga_dev->data, 0, MEM_RELEASE);
147     X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
148     X11DRV_EVENT_SetDGAStatus(0, -1);
149     TSXFree(dga_dev);
150     TSXDGACloseFramebuffer(display, DefaultScreen(display));
151     dga_dev = NULL;
152   }
153   return DDHAL_DRIVER_HANDLED;
154 }
155
156 static LPDDHAL_CREATESURFACE X11DRV_XF86DGA2_old_create_surface;
157
158 static DWORD PASCAL X11DRV_XF86DGA2_CreateSurface(LPDDHAL_CREATESURFACEDATA data)
159 {
160   LPDDRAWI_DDRAWSURFACE_LCL lcl = *data->lplpSList;
161   LPDDRAWI_DDRAWSURFACE_GBL gbl = lcl->lpGbl;
162   LPDDSURFACEDESC2 desc = (LPDDSURFACEDESC2)data->lpDDSurfaceDesc;
163   HRESULT hr = DDHAL_DRIVER_NOTHANDLED;
164
165   if (X11DRV_XF86DGA2_old_create_surface)
166     hr = X11DRV_XF86DGA2_old_create_surface(data);
167
168   if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) {
169     gbl->fpVidMem = 0; /* tell ddraw to allocate the memory */
170     hr = DDHAL_DRIVER_HANDLED;
171   }
172   return hr;
173 }
174
175 static DWORD PASCAL X11DRV_XF86DGA2_CreatePalette(LPDDHAL_CREATEPALETTEDATA data)
176 {
177   Display *display = thread_display();
178   data->lpDDPalette->u1.dwReserved1 = TSXDGACreateColormap(display, DefaultScreen(display), dga_dev, AllocAll);
179   if (data->lpColorTable)
180     X11DRV_DDHAL_SetPalEntries(data->lpDDPalette->u1.dwReserved1, 0, 256,
181                                data->lpColorTable);
182   data->ddRVal = DD_OK;
183   return DDHAL_DRIVER_HANDLED;
184 }
185
186 static DWORD PASCAL X11DRV_XF86DGA2_Flip(LPDDHAL_FLIPDATA data)
187 {
188   Display *display = thread_display();
189   if (data->lpSurfCurr == X11DRV_DD_Primary) {
190     DWORD ofs = data->lpSurfCurr->lpGbl->fpVidMem - dga_mem.fpStart;
191     TSXDGASetViewport(display, DefaultScreen(display),
192                       (ofs % dga_dev->mode.bytesPerScanline)*8/dga_dev->mode.bitsPerPixel,
193                       ofs / dga_dev->mode.bytesPerScanline,
194                       XDGAFlipImmediate);
195   }
196   data->ddRVal = DD_OK;
197   return DDHAL_DRIVER_HANDLED;
198 }
199
200 static DWORD PASCAL X11DRV_XF86DGA2_SetPalette(LPDDHAL_SETPALETTEDATA data)
201 {
202   Display *display = thread_display();
203   if ((data->lpDDSurface == X11DRV_DD_Primary) &&
204       data->lpDDPalette && data->lpDDPalette->u1.dwReserved1) {
205     TSXDGAInstallColormap(display, DefaultScreen(display), data->lpDDPalette->u1.dwReserved1);
206   }
207   data->ddRVal = DD_OK;
208   return DDHAL_DRIVER_HANDLED;
209 }
210
211 int X11DRV_XF86DGA2_CreateDriver(LPDDHALINFO info)
212 {
213   if (!xf86dga2_mode_count) return 0; /* no DGA */
214
215   info->dwNumModes = xf86dga2_mode_count;
216   info->lpModeInfo = xf86dga2_modes;
217   info->dwModeIndex = 0;
218
219   X11DRV_XF86DGA2_old_create_surface = info->lpDDCallbacks->CreateSurface;
220   info->lpDDCallbacks->SetMode = X11DRV_XF86DGA2_SetMode;
221   info->lpDDCallbacks->CreateSurface = X11DRV_XF86DGA2_CreateSurface;
222   info->lpDDCallbacks->CreatePalette = X11DRV_XF86DGA2_CreatePalette;
223   info->lpDDSurfaceCallbacks->Flip = X11DRV_XF86DGA2_Flip;
224   info->lpDDSurfaceCallbacks->SetPalette = X11DRV_XF86DGA2_SetPalette;
225   return TRUE;
226 }
227
228 #endif /* HAVE_LIBXXF86DGA2 */