Removed some unnecessary #includes and dll dependencies.
[wine/multimedia.git] / dlls / ddraw / ddraw / x11.c
blob7344874d85cd314d261f9b36c32d9ed1f2970ca5
1 /* DirectDraw IDirectDraw Xlib interface
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5 */
6 /*
7 * This file contains the Xlib specific interface functions.
8 */
10 #include "config.h"
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <assert.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
19 #include "winerror.h"
20 #include "ddraw.h"
21 #include "d3d.h"
22 #include "win.h"
23 #include "debugtools.h"
24 #include "options.h"
26 DEFAULT_DEBUG_CHANNEL(ddraw);
28 #include "x11_private.h"
30 #define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->d->private)
31 #define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
32 #define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
34 static inline BOOL get_option( const char *name, BOOL def ) {
35 return PROFILE_GetWineIniBool( "x11drv", name, def );
38 int _common_depth_to_pixelformat(DWORD depth,LPDIRECTDRAW ddraw)
40 ICOM_THIS(IDirectDrawImpl,ddraw);
41 XVisualInfo *vi;
42 XPixmapFormatValues *pf;
43 XVisualInfo vt;
44 int nvisuals, npixmap, i;
45 int match = 0;
46 int index = -2;
47 DDPIXELFORMAT *pixelformat = &(This->d->directdraw_pixelformat);
48 DDPIXELFORMAT *screen_pixelformat = &(This->d->screen_pixelformat);
50 This->d->pixel_convert = NULL;
51 This->d->palette_convert = NULL;
53 vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
54 pf = TSXListPixmapFormats(display, &npixmap);
56 for (i = 0; i < npixmap; i++) {
57 if (pf[i].depth == depth) {
58 int j;
60 for (j = 0; j < nvisuals; j++) {
61 if (vi[j].depth == pf[i].depth) {
62 pixelformat->dwSize = sizeof(*pixelformat);
63 if (depth == 8) {
64 pixelformat->dwFlags = DDPF_PALETTEINDEXED8|DDPF_RGB;
65 pixelformat->u1.dwRBitMask = 0;
66 pixelformat->u2.dwGBitMask = 0;
67 pixelformat->u3.dwBBitMask = 0;
68 } else {
69 pixelformat->dwFlags = DDPF_RGB;
70 pixelformat->u1.dwRBitMask = vi[j].red_mask;
71 pixelformat->u2.dwGBitMask = vi[j].green_mask;
72 pixelformat->u3.dwBBitMask = vi[j].blue_mask;
74 pixelformat->dwFourCC = 0;
75 pixelformat->u.dwRGBBitCount = pf[i].bits_per_pixel;
76 pixelformat->u4.dwRGBAlphaBitMask= 0;
77 *screen_pixelformat = *pixelformat;
78 This->d->pixmap_depth = depth;
79 match = 1;
80 index = -1;
81 goto clean_up_and_exit;
84 FIXME("No visual corresponding to pixmap format (depth=%ld)!\n",depth);
88 if (match == 0) {
89 /* We try now to find an emulated mode */
90 int c;
92 for (c = 0; c < sizeof(ModeEmulations) / sizeof(Convert); c++) {
93 if ((ModeEmulations[c].dest.depth == depth) &&
94 (ModeEmulations[c].dest.bpp == depth)
95 ) {
96 /* Found an emulation function, now tries to find a matching visual / pixel format pair */
97 for (i = 0; i < npixmap; i++) {
98 if ((pf[i].depth == ModeEmulations[c].screen.depth) &&
99 (pf[i].bits_per_pixel == ModeEmulations[c].screen.bpp)) {
100 int j;
102 for (j = 0; j < nvisuals; j++) {
103 if (vi[j].depth == pf[i].depth) {
104 screen_pixelformat->dwSize = sizeof(*screen_pixelformat);
105 screen_pixelformat->dwFlags = DDPF_RGB;
106 screen_pixelformat->dwFourCC = 0;
107 screen_pixelformat->u.dwRGBBitCount = pf[i].bits_per_pixel;
108 screen_pixelformat->u1.dwRBitMask = vi[j].red_mask;
109 screen_pixelformat->u2.dwGBitMask = vi[j].green_mask;
110 screen_pixelformat->u3.dwBBitMask = vi[j].blue_mask;
111 screen_pixelformat->u4.dwRGBAlphaBitMask= 0;
113 pixelformat->dwSize = sizeof(*pixelformat);
114 pixelformat->dwFourCC = 0;
115 if (depth == 8) {
116 pixelformat->dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
117 pixelformat->u.dwRGBBitCount = 8;
118 pixelformat->u1.dwRBitMask = 0;
119 pixelformat->u2.dwGBitMask = 0;
120 pixelformat->u3.dwBBitMask = 0;
121 } else {
122 pixelformat->dwFlags = DDPF_RGB;
123 pixelformat->u.dwRGBBitCount = ModeEmulations[c].dest.bpp;
124 pixelformat->u1.dwRBitMask = ModeEmulations[c].dest.rmask;
125 pixelformat->u2.dwGBitMask = ModeEmulations[c].dest.gmask;
126 pixelformat->u3.dwBBitMask = ModeEmulations[c].dest.bmask;
128 pixelformat->u4.dwRGBAlphaBitMask= 0;
129 This->d->pixmap_depth = vi[j].depth;
130 match = 2;
131 index = c;
132 This->d->pixel_convert =ModeEmulations[c].funcs.pixel_convert;
133 This->d->palette_convert=ModeEmulations[c].funcs.palette_convert;
134 goto clean_up_and_exit;
141 ERR("No emulation found for depth %ld!\n",depth);
144 clean_up_and_exit:
145 TSXFree(vi);
146 TSXFree(pf);
148 return index;
151 /*******************************************************************************
152 * IDirectDraw
154 #ifdef HAVE_LIBXXSHM
155 /* Error handlers for Image creation */
156 static int XShmErrorHandler(Display *dpy, XErrorEvent *event) {
157 XShmErrorFlag = 1;
158 return 0;
161 static XImage *create_xshmimage(
162 IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf
164 DSPRIVATE(lpdsf);
165 DDPRIVATE(This);
166 XImage *img;
167 int (*WineXHandler)(Display *, XErrorEvent *);
169 img = TSXShmCreateImage(display,
170 DefaultVisualOfScreen(X11DRV_GetXScreen()),
171 This->d->pixmap_depth,
172 ZPixmap,
173 NULL,
174 &(dspriv->shminfo),
175 lpdsf->s.surface_desc.dwWidth,
176 lpdsf->s.surface_desc.dwHeight
179 if (img == NULL) {
180 FIXME("Couldn't create XShm image (due to X11 remote display or failure).\nReverting to standard X images !\n");
181 ddpriv->xshm_active = 0;
182 return NULL;
185 dspriv->shminfo.shmid = shmget( IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777 );
187 if (dspriv->shminfo.shmid < 0) {
188 FIXME("Couldn't create shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
189 ddpriv->xshm_active = 0;
190 TSXDestroyImage(img);
191 return NULL;
194 dspriv->shminfo.shmaddr=img->data=(char*)shmat(dspriv->shminfo.shmid,0,0);
196 if (img->data == (char *) -1) {
197 FIXME("Couldn't attach shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
198 ddpriv->xshm_active = 0;
199 TSXDestroyImage(img);
200 shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
201 return NULL;
203 dspriv->shminfo.readOnly = False;
205 /* This is where things start to get trickier....
206 * First, we flush the current X connections to be sure to catch all
207 * non-XShm related errors
209 TSXSync(display, False);
210 /* Then we enter in the non-thread safe part of the tests */
211 EnterCriticalSection( &X11DRV_CritSection );
213 /* Reset the error flag, sets our new error handler and try to attach
214 * the surface
216 XShmErrorFlag = 0;
217 WineXHandler = XSetErrorHandler(XShmErrorHandler);
218 XShmAttach(display, &(dspriv->shminfo));
219 XSync(display, False);
221 /* Check the error flag */
222 if (XShmErrorFlag) {
223 /* An error occured */
224 XFlush(display);
225 XShmErrorFlag = 0;
226 XDestroyImage(img);
227 shmdt(dspriv->shminfo.shmaddr);
228 shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
229 XSetErrorHandler(WineXHandler);
231 FIXME("Couldn't attach shared memory segment to X server (due to X11 remote display or failure).\nReverting to standard X images !\n");
232 ddpriv->xshm_active = 0;
234 /* Leave the critical section */
235 LeaveCriticalSection( &X11DRV_CritSection );
236 return NULL;
238 /* Here, to be REALLY sure, I should do a XShmPutImage to check if
239 * this works, but it may be a bit overkill....
241 XSetErrorHandler(WineXHandler);
242 LeaveCriticalSection( &X11DRV_CritSection );
244 shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
246 if (This->d->pixel_convert != NULL) {
247 int bpp = PFGET_BPP(This->d->directdraw_pixelformat);
248 lpdsf->s.surface_desc.u1.lpSurface = VirtualAlloc(
249 NULL,
250 lpdsf->s.surface_desc.dwWidth *
251 lpdsf->s.surface_desc.dwHeight *
252 bpp,
253 MEM_RESERVE | MEM_COMMIT,
254 PAGE_READWRITE
256 } else {
257 lpdsf->s.surface_desc.u1.lpSurface = img->data;
258 VirtualAlloc(img->data, img->bytes_per_line * img->height, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
260 return img;
262 #endif /* HAVE_LIBXXSHM */
264 static XImage *create_ximage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf) {
265 XImage *img = NULL;
266 DDPRIVATE(This);
267 void *img_data;
268 int bpp = PFGET_BPP(This->d->directdraw_pixelformat);
269 int screen_bpp = PFGET_BPP(This->d->screen_pixelformat);
271 #ifdef HAVE_LIBXXSHM
272 if (ddpriv->xshm_active)
273 img = create_xshmimage(This, lpdsf);
275 if (img == NULL) {
276 #endif
277 /* Allocate surface memory */
278 lpdsf->s.surface_desc.u1.lpSurface = VirtualAlloc(
279 NULL,
280 lpdsf->s.surface_desc.dwWidth *
281 lpdsf->s.surface_desc.dwHeight *
282 bpp,
283 MEM_RESERVE | MEM_COMMIT,
284 PAGE_READWRITE
287 if (This->d->pixel_convert != NULL)
288 img_data = VirtualAlloc(
289 NULL,
290 lpdsf->s.surface_desc.dwWidth *
291 lpdsf->s.surface_desc.dwHeight *
292 screen_bpp,
293 MEM_RESERVE | MEM_COMMIT,
294 PAGE_READWRITE
296 else
297 img_data = lpdsf->s.surface_desc.u1.lpSurface;
299 /* In this case, create an XImage */
300 img = TSXCreateImage(display,
301 DefaultVisualOfScreen(X11DRV_GetXScreen()),
302 This->d->pixmap_depth,
303 ZPixmap,
305 img_data,
306 lpdsf->s.surface_desc.dwWidth,
307 lpdsf->s.surface_desc.dwHeight,
309 lpdsf->s.surface_desc.dwWidth*screen_bpp
311 #ifdef HAVE_LIBXXSHM
313 #endif
314 if (This->d->pixel_convert != NULL)
315 lpdsf->s.surface_desc.lPitch = bpp*lpdsf->s.surface_desc.dwWidth;
316 else
317 lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
318 return img;
321 static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
322 LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
323 IUnknown *lpunk
325 ICOM_THIS(IDirectDraw2Impl,iface);
326 IDirectDrawSurfaceImpl* dsurf;
327 x11_ds_private *dspriv;
329 TRACE("(%p)->CreateSurface(%p,%p,%p)\n", This,lpddsd,lpdsf,lpunk);
331 if (TRACE_ON(ddraw)) _dump_surface_desc(lpddsd);
333 *lpdsf = HeapAlloc(
334 GetProcessHeap(),
335 HEAP_ZERO_MEMORY,
336 sizeof(IDirectDrawSurfaceImpl)
338 dsurf = (IDirectDrawSurfaceImpl*)*lpdsf;
339 dsurf->ref = 1;
340 dsurf->private = HeapAlloc(
341 GetProcessHeap(),
342 HEAP_ZERO_MEMORY,
343 sizeof(x11_ds_private)
345 ICOM_VTBL(dsurf) = (ICOM_VTABLE(IDirectDrawSurface)*)&xlib_dds4vt;
346 dspriv = (x11_ds_private*)dsurf->private;
348 dsurf->s.ddraw = This;
349 IDirectDraw2_AddRef(iface);
351 dsurf->s.palette = NULL;
352 dsurf->s.lpClipper = NULL;
353 dspriv->image = NULL; /* This is for off-screen buffers */
355 /* Copy the surface description */
356 dsurf->s.surface_desc = *lpddsd;
358 if (!(lpddsd->dwFlags & DDSD_WIDTH))
359 dsurf->s.surface_desc.dwWidth = This->d->width;
360 if (!(lpddsd->dwFlags & DDSD_HEIGHT))
361 dsurf->s.surface_desc.dwHeight = This->d->height;
362 dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
364 /* Check if this a 'primary surface' or not */
365 if ((lpddsd->dwFlags & DDSD_CAPS) &&
366 (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
368 XImage *img;
370 /* Add flags if there were not present */
371 dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
372 dsurf->s.surface_desc.dwWidth = This->d->width;
373 dsurf->s.surface_desc.dwHeight = This->d->height;
374 dsurf->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
375 dsurf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
377 TRACE("using standard XImage for a primary surface (%p)\n", dsurf);
378 /* Create the XImage */
379 img = create_ximage(This,(IDirectDrawSurface4Impl*)dsurf);
380 if (img == NULL)
381 return DDERR_OUTOFMEMORY;
382 dspriv->image = img;
384 /* Check for backbuffers */
385 if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
386 IDirectDrawSurface4Impl* back;
387 XImage *img;
388 int i;
390 for (i=lpddsd->dwBackBufferCount;i--;) {
391 x11_ds_private *bspriv;
392 back = (IDirectDrawSurface4Impl*)HeapAlloc(
393 GetProcessHeap(),
394 HEAP_ZERO_MEMORY,
395 sizeof(IDirectDrawSurface4Impl)
397 TRACE("allocated back-buffer (%p)\n", back);
399 IDirectDraw2_AddRef(iface);
400 back->s.ddraw = This;
402 back->ref = 1;
403 ICOM_VTBL(back)=(ICOM_VTABLE(IDirectDrawSurface4)*)&xlib_dds4vt;
404 /* Copy the surface description from the front buffer */
405 back->s.surface_desc = dsurf->s.surface_desc;
406 back->s.surface_desc.u1.lpSurface = NULL;
408 back->private = HeapAlloc(
409 GetProcessHeap(),
410 HEAP_ZERO_MEMORY,
411 sizeof(x11_ds_private)
413 bspriv = (x11_ds_private*)back->private;
415 /* Create the XImage. */
416 img = create_ximage(This, back);
417 if (img == NULL)
418 return DDERR_OUTOFMEMORY;
419 TRACE("bspriv = %p\n",bspriv);
420 bspriv->image = img;
422 /* Add relevant info to front and back buffers */
423 /* FIXME: backbuffer/frontbuffer handling broken here, but
424 * will be fixed up in _Flip().
426 SDDSCAPS(dsurf) |= DDSCAPS_FRONTBUFFER;
427 SDDSCAPS(back) |= DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_FLIP;
428 back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
429 SDDSCAPS(back) &= ~(DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE);
430 TRACE("attaching surface %p to %p\n",back,*lpdsf);
431 IDirectDrawSurface4_AddAttachedSurface((LPDIRECTDRAWSURFACE4)(*lpdsf),(LPDIRECTDRAWSURFACE4)back);
434 } else {
435 /* There is no Xlib-specific code here...
436 * Go to the common surface creation function
438 return common_off_screen_CreateSurface(This,dsurf);
440 return DD_OK;
444 * The Xlib Implementation tries to use the passed hwnd as drawing window,
445 * even when the approbiate bitmasks are not specified.
447 static HRESULT WINAPI Xlib_IDirectDraw2Impl_SetCooperativeLevel(
448 LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
450 ICOM_THIS(IDirectDraw2Impl,iface);
451 DDPRIVATE(This);
453 FIXME("(%p)->(%08lx,%08lx)\n",This,(DWORD)hwnd,cooplevel);
454 if (TRACE_ON(ddraw))
455 _dump_cooperativelevel(cooplevel);
456 This->d->mainWindow = hwnd;
458 /* This will be overwritten in the case of Full Screen mode.
459 Windowed games could work with that :-) */
460 if (hwnd) {
461 WND *tmpWnd = WIN_FindWndPtr(hwnd);
462 ddpriv->drawable = X11DRV_WND_GetXWindow(tmpWnd);
463 WIN_ReleaseWndPtr(tmpWnd);
465 if( !ddpriv->drawable ) {
466 ddpriv->drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
467 WIN_ReleaseDesktop();
469 TRACE("Setting drawable to %ld\n", ddpriv->drawable);
471 return DD_OK;
474 static HRESULT WINAPI Xlib_IDirectDrawImpl_SetDisplayMode(
475 LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
477 ICOM_THIS(IDirectDrawImpl,iface);
478 DDPRIVATE(This);
479 char buf[200];
480 WND *tmpWnd;
481 int c;
483 TRACE("(%p)->SetDisplayMode(%ld,%ld,%ld)\n",
484 This, width, height, depth);
486 switch ((c = _common_depth_to_pixelformat(depth,iface))) {
487 case -2:
488 sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
489 MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
490 return DDERR_UNSUPPORTEDMODE;
491 case -1:
492 /* No conversion. Good. */
493 break;
494 default:
495 DPRINTF("DirectDraw warning: running in depth-conversion mode %d. Should run using a %ld depth for optimal performances.\n", c,depth);
498 This->d->width = width;
499 This->d->height = height;
501 _common_IDirectDrawImpl_SetDisplayMode(This);
503 tmpWnd = WIN_FindWndPtr(This->d->window);
504 This->d->paintable = 1;
505 ddpriv->drawable = ((X11DRV_WND_DATA *) tmpWnd->pDriverData)->window;
506 WIN_ReleaseWndPtr(tmpWnd);
508 /* We don't have a context for this window. Host off the desktop */
509 if( !ddpriv->drawable )
511 ddpriv->drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
512 WIN_ReleaseDesktop();
514 TRACE("Setting drawable to %ld\n", ddpriv->drawable);
516 if (get_option( "DXGrab", 0 )) {
517 /* Confine cursor movement (risky, but the user asked for it) */
518 TSXGrabPointer(display, ddpriv->drawable, True, 0, GrabModeAsync, GrabModeAsync, ddpriv->drawable, None, CurrentTime);
521 return DD_OK;
524 static void fill_caps(LPDDCAPS caps) {
525 /* This function tries to fill the capabilities of Wine's DDraw implementation.
526 Need to be fixed, though.. */
527 if (caps == NULL)
528 return;
530 caps->dwSize = sizeof(*caps);
531 caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL | DDCAPS_CANBLTSYSMEM | DDCAPS_COLORKEY | DDCAPS_PALETTE /*| DDCAPS_NOHARDWARE*/;
532 caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
533 caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
534 caps->dwFXCaps = 0;
535 caps->dwFXAlphaCaps = 0;
536 caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
537 caps->dwSVCaps = 0;
538 caps->dwZBufferBitDepths = DDBD_16;
539 /* I put here 8 Mo so that D3D applications will believe they have enough memory
540 to put textures in video memory.
541 BTW, is this only frame buffer memory or also texture memory (for Voodoo boards
542 for example) ? */
543 caps->dwVidMemTotal = 8192 * 1024;
544 caps->dwVidMemFree = 8192 * 1024;
545 /* These are all the supported capabilities of the surfaces */
546 caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
547 DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
548 /*DDSCAPS_OVERLAY |*/ DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
549 DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
550 #ifdef HAVE_OPENGL
551 caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
552 caps->dwCaps2 |= DDCAPS2_NO2DDURING3DSCENE;
553 caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
554 #endif
557 static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetCaps(
558 LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
560 ICOM_THIS(IDirectDraw2Impl,iface);
561 TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
563 /* Put the same caps for the two capabilities */
564 fill_caps(caps1);
565 fill_caps(caps2);
567 return DD_OK;
570 static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreatePalette(
571 LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,
572 LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
574 ICOM_THIS(IDirectDraw2Impl,iface);
575 IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
576 int xsize;
577 HRESULT res;
579 TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
580 res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
581 if (res != 0)
582 return res;
583 (*ilpddpal)->private = HeapAlloc(
584 GetProcessHeap(),
585 HEAP_ZERO_MEMORY,
586 sizeof(x11_dp_private)
588 ICOM_VTBL(*ilpddpal) = &xlib_ddpalvt;
589 return DD_OK;
592 static HRESULT WINAPI Xlib_IDirectDraw2Impl_QueryInterface(
593 LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
595 ICOM_THIS(IDirectDraw2Impl,iface);
597 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
598 if ( IsEqualGUID( &IID_IUnknown, refiid ) ) {
599 *obj = This;
600 IDirectDraw2_AddRef(iface);
602 TRACE(" Creating IUnknown interface (%p)\n", *obj);
604 return S_OK;
606 if ( IsEqualGUID( &IID_IDirectDraw, refiid ) ) {
607 IDirectDrawImpl *dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
608 IDirectDraw2_AddRef(iface);
610 dd->ref = 1;ICOM_VTBL(dd) = &xlib_ddvt;dd->d = This->d;This->d->ref++;
611 *obj = dd;
613 TRACE(" Creating IDirectDraw interface (%p)\n", *obj);
614 return S_OK;
616 if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) ) {
617 IDirectDraw2Impl *dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
618 IDirectDraw2_AddRef(iface);
620 dd->ref = 1;ICOM_VTBL(dd) = &xlib_dd2vt;dd->d = This->d;This->d->ref++;
621 *obj = dd;
623 TRACE(" Creating IDirectDraw2 interface (%p)\n", *obj);
624 return S_OK;
626 if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) ) {
627 IDirectDraw4Impl *dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
628 dd->ref = 1;ICOM_VTBL(dd) = &xlib_dd4vt;dd->d = This->d;This->d->ref++;
629 *obj = dd;
631 IDirectDraw2_AddRef(iface);
632 TRACE(" Creating IDirectDraw4 interface (%p)\n", *obj);
633 return S_OK;
635 #ifdef HAVE_OPENGL
636 if ( IsEqualGUID( &IID_IDirect3D, refiid ) )
637 return create_direct3d(obj,This);
638 if ( IsEqualGUID( &IID_IDirect3D2, refiid ) )
639 return create_direct3d2(obj,This);
640 if ( IsEqualGUID( &IID_IDirect3D3, refiid ) )
641 return create_direct3d3(obj,This);
642 #endif
643 FIXME("(%p):interface for IID %s _NOT_ found!\n",This,debugstr_guid(refiid));
644 return OLE_E_ENUM_NOMORE;
647 static HRESULT WINAPI Xlib_IDirectDraw2Impl_EnumDisplayModes(
648 LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
650 ICOM_THIS(IDirectDraw2Impl,iface);
651 XVisualInfo *vi;
652 XPixmapFormatValues *pf;
653 XVisualInfo vt;
654 int xbpp = 1, nvisuals, npixmap, i, emu;
655 int has_mode[] = { 0, 0, 0, 0 };
656 int has_depth[] = { 8, 15, 16, 24 };
657 DDSURFACEDESC ddsfd;
658 static struct {
659 int w,h;
660 } modes[] = { /* some of the usual modes */
661 {512,384},
662 {640,400},
663 {640,480},
664 {800,600},
665 {1024,768},
666 {1280,1024}
668 DWORD maxWidth, maxHeight;
670 TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
671 ddsfd.dwSize = sizeof(ddsfd);
672 ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS|DDSD_PITCH;
673 if (dwFlags & DDEDM_REFRESHRATES) {
674 ddsfd.dwFlags |= DDSD_REFRESHRATE;
675 ddsfd.u.dwRefreshRate = 60;
677 maxWidth = GetSystemMetrics(SM_CXSCREEN);
678 maxHeight = GetSystemMetrics(SM_CYSCREEN);
680 vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
681 pf = TSXListPixmapFormats(display, &npixmap);
683 i = 0;
684 emu = 0;
685 while ((i < npixmap) || (emu != 4)) {
686 int mode_index = 0;
687 int send_mode = 0;
688 int j;
690 if (i < npixmap) {
691 for (j = 0; j < 4; j++) {
692 if (has_depth[j] == pf[i].depth) {
693 mode_index = j;
694 break;
697 if (j == 4) {
698 i++;
699 continue;
703 if (has_mode[mode_index] == 0) {
704 if (mode_index == 0) {
705 send_mode = 1;
707 ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
708 ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
709 ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
710 ddsfd.ddpfPixelFormat.dwFourCC = 0;
711 ddsfd.ddpfPixelFormat.u.dwRGBBitCount = 8;
712 ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0;
713 ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0;
714 ddsfd.ddpfPixelFormat.u3.dwBBitMask = 0;
715 ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
717 xbpp = 1;
719 has_mode[mode_index] = 1;
720 } else {
721 /* All the 'true color' depths (15, 16 and 24)
722 First, find the corresponding visual to extract the bit masks */
723 for (j = 0; j < nvisuals; j++) {
724 if (vi[j].depth == pf[i].depth) {
725 ddsfd.ddsCaps.dwCaps = 0;
726 ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
727 ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
728 ddsfd.ddpfPixelFormat.dwFourCC = 0;
729 ddsfd.ddpfPixelFormat.u.dwRGBBitCount = pf[i].bits_per_pixel;
730 ddsfd.ddpfPixelFormat.u1.dwRBitMask = vi[j].red_mask;
731 ddsfd.ddpfPixelFormat.u2.dwGBitMask = vi[j].green_mask;
732 ddsfd.ddpfPixelFormat.u3.dwBBitMask = vi[j].blue_mask;
733 ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
735 xbpp = pf[i].bits_per_pixel/8;
737 send_mode = 1;
738 has_mode[mode_index] = 1;
739 break;
742 if (j == nvisuals)
743 WARN("Did not find visual corresponding the the pixmap format !\n");
746 i++;
747 } else {
748 /* Now to emulated modes */
749 if (has_mode[emu] == 0) {
750 int c;
751 int l;
752 int depth = has_depth[emu];
754 for (c = 0; (c < sizeof(ModeEmulations) / sizeof(Convert)) && (send_mode == 0); c++) {
755 if (ModeEmulations[c].dest.depth == depth) {
756 /* Found an emulation function, now tries to find a matching visual / pixel format pair */
757 for (l = 0; (l < npixmap) && (send_mode == 0); l++) {
758 if ((pf[l].depth == ModeEmulations[c].screen.depth) &&
759 (pf[l].bits_per_pixel == ModeEmulations[c].screen.bpp)) {
760 int j;
761 for (j = 0; (j < nvisuals) && (send_mode == 0); j++) {
762 if ((vi[j].depth == pf[l].depth) &&
763 (vi[j].red_mask == ModeEmulations[c].screen.rmask) &&
764 (vi[j].green_mask == ModeEmulations[c].screen.gmask) &&
765 (vi[j].blue_mask == ModeEmulations[c].screen.bmask)) {
766 ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
767 ddsfd.ddpfPixelFormat.dwFourCC = 0;
768 if (depth == 8) {
769 ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
770 ddsfd.ddpfPixelFormat.u.dwRGBBitCount = 8;
771 ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0;
772 ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0;
773 ddsfd.ddpfPixelFormat.u3.dwBBitMask = 0;
774 } else {
775 ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
776 ddsfd.ddpfPixelFormat.u.dwRGBBitCount = ModeEmulations[c].dest.bpp;
777 ddsfd.ddpfPixelFormat.u1.dwRBitMask = ModeEmulations[c].dest.rmask;
778 ddsfd.ddpfPixelFormat.u2.dwGBitMask = ModeEmulations[c].dest.gmask;
779 ddsfd.ddpfPixelFormat.u3.dwBBitMask = ModeEmulations[c].dest.bmask;
781 ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
782 send_mode = 1;
785 if (send_mode == 0)
786 WARN("No visual corresponding to pixmap format !\n");
794 emu++;
797 if (send_mode) {
798 int mode;
800 if (TRACE_ON(ddraw)) {
801 TRACE("Enumerating with pixel format : \n");
802 _dump_pixelformat(&(ddsfd.ddpfPixelFormat));
803 DPRINTF("\n");
806 for (mode = 0; mode < sizeof(modes)/sizeof(modes[0]); mode++) {
807 /* Do not enumerate modes we cannot handle anyway */
808 if ((modes[mode].w > maxWidth) || (modes[mode].h > maxHeight))
809 break;
811 ddsfd.dwWidth = modes[mode].w;
812 ddsfd.dwHeight= modes[mode].h;
813 ddsfd.lPitch = ddsfd.dwWidth * xbpp;
815 /* Now, send the mode description to the application */
816 TRACE(" - mode %4ld - %4ld\n", ddsfd.dwWidth, ddsfd.dwHeight);
817 if (!modescb(&ddsfd, context))
818 goto exit_enum;
821 if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
822 /* modeX is not standard VGA */
823 ddsfd.dwWidth = 320;
824 ddsfd.dwHeight = 200;
825 ddsfd.lPitch = 320 * xbpp;
826 if (!modescb(&ddsfd, context))
827 goto exit_enum;
831 exit_enum:
832 TSXFree(vi);
833 TSXFree(pf);
835 return DD_OK;
838 /* Note: Hack so we can reuse the old functions without compiler warnings */
839 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
840 # define XCAST(fun) (typeof(xlib_ddvt.fn##fun))
841 #else
842 # define XCAST(fun) (void *)
843 #endif
845 ICOM_VTABLE(IDirectDraw) xlib_ddvt = {
846 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
847 XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
848 XCAST(AddRef)IDirectDraw2Impl_AddRef,
849 XCAST(Release)IDirectDraw2Impl_Release,
850 XCAST(Compact)IDirectDraw2Impl_Compact,
851 XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
852 XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
853 XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
854 XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
855 XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
856 XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
857 XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
858 XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
859 XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
860 XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
861 XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
862 XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
863 XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
864 XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
865 XCAST(Initialize)IDirectDraw2Impl_Initialize,
866 XCAST(RestoreDisplayMode)IDirectDraw2Impl_RestoreDisplayMode,
867 XCAST(SetCooperativeLevel)Xlib_IDirectDraw2Impl_SetCooperativeLevel,
868 Xlib_IDirectDrawImpl_SetDisplayMode,
869 XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
872 #undef XCAST
874 /*****************************************************************************
875 * IDirectDraw2
879 static HRESULT WINAPI Xlib_IDirectDraw2Impl_SetDisplayMode(
880 LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD dwRefreshRate,DWORD dwFlags
882 FIXME( "Ignored parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags );
883 return Xlib_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
886 static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetAvailableVidMem(
887 LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
889 ICOM_THIS(IDirectDraw2Impl,iface);
890 TRACE("(%p)->(%p,%p,%p)\n",This,ddscaps,total,free);
891 if (total) *total = 16* 1024 * 1024;
892 if (free) *free = 16* 1024 * 1024;
893 return DD_OK;
896 ICOM_VTABLE(IDirectDraw2) xlib_dd2vt = {
897 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
898 Xlib_IDirectDraw2Impl_QueryInterface,
899 IDirectDraw2Impl_AddRef,
900 IDirectDraw2Impl_Release,
901 IDirectDraw2Impl_Compact,
902 IDirectDraw2Impl_CreateClipper,
903 Xlib_IDirectDraw2Impl_CreatePalette,
904 Xlib_IDirectDraw2Impl_CreateSurface,
905 IDirectDraw2Impl_DuplicateSurface,
906 Xlib_IDirectDraw2Impl_EnumDisplayModes,
907 IDirectDraw2Impl_EnumSurfaces,
908 IDirectDraw2Impl_FlipToGDISurface,
909 Xlib_IDirectDraw2Impl_GetCaps,
910 IDirectDraw2Impl_GetDisplayMode,
911 IDirectDraw2Impl_GetFourCCCodes,
912 IDirectDraw2Impl_GetGDISurface,
913 IDirectDraw2Impl_GetMonitorFrequency,
914 IDirectDraw2Impl_GetScanLine,
915 IDirectDraw2Impl_GetVerticalBlankStatus,
916 IDirectDraw2Impl_Initialize,
917 IDirectDraw2Impl_RestoreDisplayMode,
918 Xlib_IDirectDraw2Impl_SetCooperativeLevel,
919 Xlib_IDirectDraw2Impl_SetDisplayMode,
920 IDirectDraw2Impl_WaitForVerticalBlank,
921 Xlib_IDirectDraw2Impl_GetAvailableVidMem
924 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
925 # define XCAST(fun) (typeof(xlib_dd4vt.fn##fun))
926 #else
927 # define XCAST(fun) (void*)
928 #endif
930 ICOM_VTABLE(IDirectDraw4) xlib_dd4vt = {
931 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
932 XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
933 XCAST(AddRef)IDirectDraw2Impl_AddRef,
934 XCAST(Release)IDirectDraw2Impl_Release,
935 XCAST(Compact)IDirectDraw2Impl_Compact,
936 XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
937 XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
938 XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
939 XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
940 XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
941 XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
942 XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
943 XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
944 XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
945 XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
946 XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
947 XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
948 XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
949 XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
950 XCAST(Initialize)IDirectDraw2Impl_Initialize,
951 XCAST(RestoreDisplayMode)IDirectDraw2Impl_RestoreDisplayMode,
952 XCAST(SetCooperativeLevel)Xlib_IDirectDraw2Impl_SetCooperativeLevel,
953 XCAST(SetDisplayMode)Xlib_IDirectDrawImpl_SetDisplayMode,
954 XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
955 XCAST(GetAvailableVidMem)Xlib_IDirectDraw2Impl_GetAvailableVidMem,
956 IDirectDraw4Impl_GetSurfaceFromDC,
957 IDirectDraw4Impl_RestoreAllSurfaces,
958 IDirectDraw4Impl_TestCooperativeLevel,
959 IDirectDraw4Impl_GetDeviceIdentifier
961 #undef XCAST