- better debug output for surface creation
[wine] / graphics / ddraw.c
1 /*              DirectDraw using DGA or Xlib(XSHM)
2  *
3  * Copyright 1997,1998 Marcus Meissner
4  * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
5  */
6 /* XF86DGA:
7  * When DirectVideo mode is enabled you can no longer use 'normal' X 
8  * applications nor can you switch to a virtual console. Also, enabling
9  * only works, if you have switched to the screen where the application
10  * is running.
11  * Some ways to debug this stuff are:
12  * - A terminal connected to the serial port. Can be bought used for cheap.
13  *   (This is the method I am using.)
14  * - Another machine connected over some kind of network.
15  */
16
17 #include "config.h"
18
19 #ifndef X_DISPLAY_MISSING 
20
21 #include "ts_xlib.h"
22 #include "ts_xutil.h"
23
24 #ifdef HAVE_LIBXXSHM
25 #include <sys/types.h>
26 #include <sys/ipc.h>
27 #include <sys/shm.h>
28 #include "ts_xshm.h"
29 #endif /* defined(HAVE_LIBXXSHM) */
30
31 #ifdef HAVE_LIBXXF86DGA
32 #include "ts_xf86dga.h"
33 #endif /* defined(HAVE_LIBXXF86DGA) */
34
35 #ifdef HAVE_LIBXXF86VM
36 /* X is retarted and insists on declaring INT32, INT16 etc in Xmd.h,
37    this is a crude hack to get around it */
38 #define XMD_H
39 typedef int INT32;
40 #include "ts_xf86vmode.h"
41 #endif /* defined(HAVE_LIBXXF86VM) */
42
43 #include "x11drv.h"
44
45 #include <unistd.h>
46 #include <assert.h>
47 #include <sys/signal.h>
48 #include <fcntl.h>
49 #include <string.h>
50 #include <stdlib.h>
51
52 #include "winerror.h"
53 #include "gdi.h"
54 #include "heap.h"
55 #include "dc.h"
56 #include "win.h"
57 #include "miscemu.h"
58 #include "ddraw.h"
59 #include "d3d.h"
60 #include "debug.h"
61 #include "spy.h"
62 #include "message.h"
63 #include "options.h"
64 #include "monitor.h"
65
66 /* This for all the enumeration and creation of D3D-related objects */
67 #include "ddraw_private.h"
68 #include "d3d_private.h"
69
70 DEFAULT_DEBUG_CHANNEL(ddraw)
71
72 /* define this if you want to play Diablo using XF86DGA. (bug workaround) */
73 #undef DIABLO_HACK
74
75 /* Restore signal handlers overwritten by XF86DGA 
76  */
77 #define RESTORE_SIGNALS
78
79 /* Get the number of bytes per pixel for a given surface */
80 #define GET_BPP(desc) (desc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ? \
81                        1 :                                                                    \
82                        desc.ddpfPixelFormat.x.dwRGBBitCount / 8)
83
84 /* Where do these GUIDs come from?  mkuuid.
85  * They exist solely to distinguish between the targets Wine support,
86  * and should be different than any other GUIDs in existence.
87  */
88 static GUID DGA_DirectDraw_GUID = { /* e2dcb020-dc60-11d1-8407-9714f5d50802 */
89         0xe2dcb020,
90         0xdc60,
91         0x11d1,
92         {0x84, 0x07, 0x97, 0x14, 0xf5, 0xd5, 0x08, 0x02}
93 };
94
95 static GUID XLIB_DirectDraw_GUID = { /* 1574a740-dc61-11d1-8407-f7875a7d1879 */
96     0x1574a740,
97     0xdc61,
98     0x11d1,
99     {0x84, 0x07, 0xf7, 0x87, 0x5a, 0x7d, 0x18, 0x79}
100 };
101
102 static struct ICOM_VTABLE(IDirectDrawSurface4)  dga_dds4vt, xlib_dds4vt;
103 static struct ICOM_VTABLE(IDirectDraw)          dga_ddvt, xlib_ddvt;
104 static struct ICOM_VTABLE(IDirectDraw2)         dga_dd2vt, xlib_dd2vt;
105 static struct ICOM_VTABLE(IDirectDraw4)         dga_dd4vt, xlib_dd4vt;
106 static struct ICOM_VTABLE(IDirectDrawClipper)   ddclipvt;
107 static struct ICOM_VTABLE(IDirectDrawPalette) dga_ddpalvt, xlib_ddpalvt;
108 static struct ICOM_VTABLE(IDirect3D)                    d3dvt;
109 static struct ICOM_VTABLE(IDirect3D2)                   d3d2vt;
110
111 #ifdef HAVE_LIBXXF86VM
112 static XF86VidModeModeInfo *orig_mode = NULL;
113 #endif
114
115 #ifdef HAVE_LIBXXSHM
116 static int XShmErrorFlag = 0;
117 #endif
118
119 BOOL
120 DDRAW_DGA_Available(void)
121 {
122 #ifdef HAVE_LIBXXF86DGA
123         int evbase, evret, fd;
124         
125         if (Options.noDGA)
126           return 0;
127    
128         /* You don't have to be root to use DGA extensions. Simply having access to /dev/mem will do the trick */
129         /* This can be achieved by adding the user to the "kmem" group on Debian 2.x systems, don't know about */
130         /* others. --stephenc */
131         if ((fd = open("/dev/mem", O_RDWR)) != -1)
132           close(fd);
133
134         return (fd != -1) && TSXF86DGAQueryExtension(display,&evbase,&evret);
135 #else /* defined(HAVE_LIBXXF86DGA) */
136         return 0;
137 #endif /* defined(HAVE_LIBXXF86DGA) */
138 }
139
140 /**********************************************************************/
141
142 typedef struct {
143   LPVOID lpCallback;
144   LPVOID lpContext; 
145 } DirectDrawEnumerateProcData;
146
147 /***********************************************************************
148  *              DirectDrawEnumerateExA (DDRAW.*)
149  */
150 HRESULT WINAPI DirectDrawEnumerateExA(
151   LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
152 {
153   TRACE(ddraw, "(%p,%p, %08lx)\n", lpCallback, lpContext, dwFlags);
154   
155   if (TRACE_ON(ddraw)) {
156     DUMP("  Flags : ");
157     if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES)
158       DUMP("DDENUM_ATTACHEDSECONDARYDEVICES ");
159     if (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES)
160       DUMP("DDENUM_DETACHEDSECONDARYDEVICES ");
161     if (dwFlags & DDENUM_NONDISPLAYDEVICES)
162       DUMP("DDENUM_NONDISPLAYDEVICES ");
163     DUMP("\n");
164   }
165
166   if (dwFlags & DDENUM_NONDISPLAYDEVICES) {
167     /* For the moment, Wine does not support any 3D only accelerators */
168     return DD_OK;
169   }
170   
171   if (DDRAW_DGA_Available()) {
172     TRACE(ddraw, "Enumerating DGA interface\n");
173     if (!lpCallback(&DGA_DirectDraw_GUID, "WINE with XFree86 DGA", "display", lpContext, 0))
174       return DD_OK;
175   }
176
177   TRACE(ddraw, "Enumerating Xlib interface\n");
178   if (!lpCallback(&XLIB_DirectDraw_GUID, "WINE with Xlib", "display", lpContext, 0))
179     return DD_OK;
180   
181   TRACE(ddraw, "Enumerating Default interface\n");
182   if (!lpCallback(NULL,"WINE (default)", "display", lpContext, 0))
183     return DD_OK;
184   
185   return DD_OK;
186 }
187
188 /***********************************************************************
189  *              DirectDrawEnumerateExW (DDRAW.*)
190  */
191
192 static BOOL CALLBACK DirectDrawEnumerateExProcW(
193         GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, 
194         LPVOID lpContext, HMONITOR hm)
195 {
196   DirectDrawEnumerateProcData *pEPD =
197     (DirectDrawEnumerateProcData *) lpContext;
198   LPWSTR lpDriverDescriptionW =
199     HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverDescription);
200   LPWSTR lpDriverNameW =
201     HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverName);
202
203   BOOL bResult = (*(LPDDENUMCALLBACKEXW *) pEPD->lpCallback)(
204     lpGUID, lpDriverDescriptionW, lpDriverNameW, pEPD->lpContext, hm);
205
206   HeapFree(GetProcessHeap(), 0, lpDriverDescriptionW);
207   HeapFree(GetProcessHeap(), 0, lpDriverNameW);
208
209   return bResult;
210 }
211
212 /**********************************************************************/
213
214 HRESULT WINAPI DirectDrawEnumerateExW(
215   LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
216 {
217   DirectDrawEnumerateProcData epd;
218   epd.lpCallback = (LPVOID) lpCallback;
219   epd.lpContext = lpContext;
220
221   return DirectDrawEnumerateExA(DirectDrawEnumerateExProcW, 
222                                   (LPVOID) &epd, 0);
223 }
224
225 /***********************************************************************
226  *              DirectDrawEnumerateA (DDRAW.*)
227  */
228
229 static BOOL CALLBACK DirectDrawEnumerateProcA(
230         GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, 
231         LPVOID lpContext, HMONITOR hm)
232 {
233   DirectDrawEnumerateProcData *pEPD = 
234     (DirectDrawEnumerateProcData *) lpContext;
235   
236   return ((LPDDENUMCALLBACKA) pEPD->lpCallback)(
237     lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
238 }
239
240 /**********************************************************************/
241
242 HRESULT WINAPI DirectDrawEnumerateA(
243   LPDDENUMCALLBACKA lpCallback, LPVOID lpContext) 
244 {
245   DirectDrawEnumerateProcData epd;  
246   epd.lpCallback = (LPVOID) lpCallback;
247   epd.lpContext = lpContext;
248
249   return DirectDrawEnumerateExA(DirectDrawEnumerateProcA, 
250                                 (LPVOID) &epd, 0);
251 }
252
253 /***********************************************************************
254  *              DirectDrawEnumerateW (DDRAW.*)
255  */
256
257 static BOOL WINAPI DirectDrawEnumerateProcW(
258   GUID *lpGUID, LPWSTR lpDriverDescription, LPWSTR lpDriverName, 
259   LPVOID lpContext, HMONITOR hm)
260 {
261   DirectDrawEnumerateProcData *pEPD = 
262     (DirectDrawEnumerateProcData *) lpContext;
263   
264   return ((LPDDENUMCALLBACKW) pEPD->lpCallback)(
265     lpGUID, lpDriverDescription, lpDriverName, 
266     pEPD->lpContext);
267 }
268
269 /**********************************************************************/
270
271 HRESULT WINAPI DirectDrawEnumerateW(
272   LPDDENUMCALLBACKW lpCallback, LPVOID lpContext) 
273 {
274   DirectDrawEnumerateProcData epd;  
275   epd.lpCallback = (LPVOID) lpCallback;
276   epd.lpContext = lpContext;
277
278   return DirectDrawEnumerateExW(DirectDrawEnumerateProcW, 
279                                 (LPVOID) &epd, 0);
280 }
281
282 /***********************************************************************
283  *              DSoundHelp (DDRAW.?)
284  */
285
286 /* What is this doing here? */
287 HRESULT WINAPI 
288 DSoundHelp(DWORD x,DWORD y,DWORD z) {
289         FIXME(ddraw,"(0x%08lx,0x%08lx,0x%08lx),stub!\n",x,y,z);
290         return 0;
291 }
292
293 /******************************************************************************
294  *              internal helper functions
295  */
296 static void _dump_DDBLTFX(DWORD flagmask) {
297         int     i;
298         const struct {
299                 DWORD   mask;
300                 char    *name;
301         } flags[] = {
302 #define FE(x) { x, #x},
303                 FE(DDBLTFX_ARITHSTRETCHY)
304                 FE(DDBLTFX_MIRRORLEFTRIGHT)
305                 FE(DDBLTFX_MIRRORUPDOWN)
306                 FE(DDBLTFX_NOTEARING)
307                 FE(DDBLTFX_ROTATE180)
308                 FE(DDBLTFX_ROTATE270)
309                 FE(DDBLTFX_ROTATE90)
310                 FE(DDBLTFX_ZBUFFERRANGE)
311                 FE(DDBLTFX_ZBUFFERBASEDEST)
312 #undef FE
313         };
314         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
315            if (flags[i].mask & flagmask) {
316               DUMP("%s ",flags[i].name);
317               
318            };
319         DUMP("\n");
320         
321 }
322
323 static void _dump_DDBLTFAST(DWORD flagmask) {
324         int     i;
325         const struct {
326                 DWORD   mask;
327                 char    *name;
328         } flags[] = {
329 #define FE(x) { x, #x},
330                 FE(DDBLTFAST_NOCOLORKEY)
331                 FE(DDBLTFAST_SRCCOLORKEY)
332                 FE(DDBLTFAST_DESTCOLORKEY)
333                 FE(DDBLTFAST_WAIT)
334 #undef FE
335         };
336         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
337                 if (flags[i].mask & flagmask)
338                         DUMP("%s ",flags[i].name);
339         DUMP("\n");
340 }
341
342 static void _dump_DDBLT(DWORD flagmask) {
343         int     i;
344         const struct {
345                 DWORD   mask;
346                 char    *name;
347         } flags[] = {
348 #define FE(x) { x, #x},
349                 FE(DDBLT_ALPHADEST)
350                 FE(DDBLT_ALPHADESTCONSTOVERRIDE)
351                 FE(DDBLT_ALPHADESTNEG)
352                 FE(DDBLT_ALPHADESTSURFACEOVERRIDE)
353                 FE(DDBLT_ALPHAEDGEBLEND)
354                 FE(DDBLT_ALPHASRC)
355                 FE(DDBLT_ALPHASRCCONSTOVERRIDE)
356                 FE(DDBLT_ALPHASRCNEG)
357                 FE(DDBLT_ALPHASRCSURFACEOVERRIDE)
358                 FE(DDBLT_ASYNC)
359                 FE(DDBLT_COLORFILL)
360                 FE(DDBLT_DDFX)
361                 FE(DDBLT_DDROPS)
362                 FE(DDBLT_KEYDEST)
363                 FE(DDBLT_KEYDESTOVERRIDE)
364                 FE(DDBLT_KEYSRC)
365                 FE(DDBLT_KEYSRCOVERRIDE)
366                 FE(DDBLT_ROP)
367                 FE(DDBLT_ROTATIONANGLE)
368                 FE(DDBLT_ZBUFFER)
369                 FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE)
370                 FE(DDBLT_ZBUFFERDESTOVERRIDE)
371                 FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE)
372                 FE(DDBLT_ZBUFFERSRCOVERRIDE)
373                 FE(DDBLT_WAIT)
374                 FE(DDBLT_DEPTHFILL)
375 #undef FE
376         };
377         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
378                 if (flags[i].mask & flagmask)
379                         DUMP("%s ",flags[i].name);
380         DUMP("\n");
381 }
382
383 static void _dump_DDSCAPS(void *in) {
384         int     i;
385         const struct {
386                 DWORD   mask;
387                 char    *name;
388         } flags[] = {
389 #define FE(x) { x, #x},
390                 FE(DDSCAPS_RESERVED1)
391                 FE(DDSCAPS_ALPHA)
392                 FE(DDSCAPS_BACKBUFFER)
393                 FE(DDSCAPS_COMPLEX)
394                 FE(DDSCAPS_FLIP)
395                 FE(DDSCAPS_FRONTBUFFER)
396                 FE(DDSCAPS_OFFSCREENPLAIN)
397                 FE(DDSCAPS_OVERLAY)
398                 FE(DDSCAPS_PALETTE)
399                 FE(DDSCAPS_PRIMARYSURFACE)
400                 FE(DDSCAPS_PRIMARYSURFACELEFT)
401                 FE(DDSCAPS_SYSTEMMEMORY)
402                 FE(DDSCAPS_TEXTURE)
403                 FE(DDSCAPS_3DDEVICE)
404                 FE(DDSCAPS_VIDEOMEMORY)
405                 FE(DDSCAPS_VISIBLE)
406                 FE(DDSCAPS_WRITEONLY)
407                 FE(DDSCAPS_ZBUFFER)
408                 FE(DDSCAPS_OWNDC)
409                 FE(DDSCAPS_LIVEVIDEO)
410                 FE(DDSCAPS_HWCODEC)
411                 FE(DDSCAPS_MODEX)
412                 FE(DDSCAPS_MIPMAP)
413                 FE(DDSCAPS_RESERVED2)
414                 FE(DDSCAPS_ALLOCONLOAD)
415                 FE(DDSCAPS_VIDEOPORT)
416                 FE(DDSCAPS_LOCALVIDMEM)
417                 FE(DDSCAPS_NONLOCALVIDMEM)
418                 FE(DDSCAPS_STANDARDVGAMODE)
419                 FE(DDSCAPS_OPTIMIZED)
420 #undef FE
421         };
422         DWORD flagmask = *((DWORD *) in);
423         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
424                 if (flags[i].mask & flagmask)
425                         DUMP("%s ",flags[i].name);
426 }
427
428 static void _dump_pixelformat_flag(DWORD flagmask) {
429         int     i;
430         const struct {
431                 DWORD   mask;
432                 char    *name;
433         } flags[] = {
434 #define FE(x) { x, #x},
435                 FE(DDPF_ALPHAPIXELS)
436                 FE(DDPF_ALPHA)
437                 FE(DDPF_FOURCC)
438                 FE(DDPF_PALETTEINDEXED4)
439                 FE(DDPF_PALETTEINDEXEDTO8)
440                 FE(DDPF_PALETTEINDEXED8)
441                 FE(DDPF_RGB)
442                 FE(DDPF_COMPRESSED)
443                 FE(DDPF_RGBTOYUV)
444                 FE(DDPF_YUV)
445                 FE(DDPF_ZBUFFER)
446                 FE(DDPF_PALETTEINDEXED1)
447                 FE(DDPF_PALETTEINDEXED2)
448                 FE(DDPF_ZPIXELS)
449 #undef FE
450         };
451         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
452                 if (flags[i].mask & flagmask)
453                         DUMP("%s ",flags[i].name);
454 }
455
456 static void _dump_paletteformat(DWORD dwFlags) {
457   int   i;
458   const struct {
459     DWORD       mask;
460     char        *name;
461   } flags[] = {
462 #define FE(x) { x, #x},
463     FE(DDPCAPS_4BIT)
464     FE(DDPCAPS_8BITENTRIES)
465     FE(DDPCAPS_8BIT)
466     FE(DDPCAPS_INITIALIZE)
467     FE(DDPCAPS_PRIMARYSURFACE)
468     FE(DDPCAPS_PRIMARYSURFACELEFT)
469     FE(DDPCAPS_ALLOW256)
470     FE(DDPCAPS_VSYNC)
471     FE(DDPCAPS_1BIT)
472     FE(DDPCAPS_2BIT)
473     FE(DDPCAPS_ALPHA)
474 #undef FE
475   };
476   for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
477     if (flags[i].mask & dwFlags)
478       DUMP("%s ",flags[i].name);
479   DUMP("\n");
480 }
481
482 static void _dump_pixelformat(void *in) {
483   LPDDPIXELFORMAT pf = (LPDDPIXELFORMAT) in;
484   char *cmd;
485   
486   DUMP("( ");
487   _dump_pixelformat_flag(pf->dwFlags);
488   if (pf->dwFlags & DDPF_FOURCC) {
489     DUMP(", dwFourCC : %ld", pf->dwFourCC);
490   }
491   if (pf->dwFlags & DDPF_RGB) {
492     DUMP(", RGB bits: %ld, ", pf->x.dwRGBBitCount);
493     switch (pf->x.dwRGBBitCount) {
494     case 4:
495       cmd = "%1lx";
496       break;
497     case 8:
498       cmd = "%02lx";
499       break;
500     case 16:
501       cmd = "%04lx";
502       break;
503     case 24:
504       cmd = "%06lx";
505       break;
506     case 32:
507       cmd = "%08lx";
508       break;
509     default:
510       ERR(ddraw, "Unexpected bit depth !\n");
511       cmd = "%d";
512     }
513     DUMP(" R "); DUMP(cmd, pf->y.dwRBitMask);
514     DUMP(" G "); DUMP(cmd, pf->z.dwGBitMask);
515     DUMP(" B "); DUMP(cmd, pf->xx.dwBBitMask);
516     if (pf->dwFlags & DDPF_ALPHAPIXELS) {
517       DUMP(" A "); DUMP(cmd, pf->xy.dwRGBAlphaBitMask);
518     }
519     if (pf->dwFlags & DDPF_ZPIXELS) {
520       DUMP(" Z "); DUMP(cmd, pf->xy.dwRGBZBitMask);
521 }
522   }
523   if (pf->dwFlags & DDPF_ZBUFFER) {
524     DUMP(", Z bits : %ld", pf->x.dwZBufferBitDepth);
525   }
526   if (pf->dwFlags & DDPF_ALPHA) {
527     DUMP(", Alpha bits : %ld", pf->x.dwAlphaBitDepth);
528   }
529   DUMP(")");
530 }
531
532 static void _dump_colorkeyflag(DWORD ck) {
533         int     i;
534         const struct {
535                 DWORD   mask;
536                 char    *name;
537         } flags[] = {
538 #define FE(x) { x, #x},
539           FE(DDCKEY_COLORSPACE)
540           FE(DDCKEY_DESTBLT)
541           FE(DDCKEY_DESTOVERLAY)
542           FE(DDCKEY_SRCBLT)
543           FE(DDCKEY_SRCOVERLAY)
544 #undef FE
545         };
546         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
547                 if (flags[i].mask & ck)
548                         DUMP("%s ",flags[i].name);
549 }
550
551 static void _dump_DWORD(void *in) {
552   DUMP("%ld", *((DWORD *) in));
553 }
554 static void _dump_PTR(void *in) {
555   DUMP("%p", *((void **) in));
556 }
557 static void _dump_DDCOLORKEY(void *in) {
558   DDCOLORKEY *ddck = (DDCOLORKEY *) in;
559
560   DUMP(" Low : %ld  - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue);
561 }
562
563 static void _dump_surface_desc(DDSURFACEDESC *lpddsd) {
564   int   i;
565   const struct {
566     DWORD       mask;
567     char        *name;
568     void (*func)(void *);
569     void        *elt;
570   } flags[] = {
571 #define FE(x,func,elt) { x, #x, func, (void *) &(lpddsd->elt)}
572     FE(DDSD_CAPS, _dump_DDSCAPS, ddsCaps),
573     FE(DDSD_HEIGHT, _dump_DWORD, dwHeight),
574     FE(DDSD_WIDTH, _dump_DWORD, dwWidth),
575     FE(DDSD_PITCH, _dump_DWORD, lPitch),
576     FE(DDSD_BACKBUFFERCOUNT, _dump_DWORD, dwBackBufferCount),
577     FE(DDSD_ZBUFFERBITDEPTH, _dump_DWORD, x.dwZBufferBitDepth),
578     FE(DDSD_ALPHABITDEPTH, _dump_DWORD, dwAlphaBitDepth),
579     FE(DDSD_PIXELFORMAT, _dump_pixelformat, ddpfPixelFormat),
580     FE(DDSD_CKDESTOVERLAY, _dump_DDCOLORKEY, ddckCKDestOverlay),
581     FE(DDSD_CKDESTBLT, _dump_DDCOLORKEY, ddckCKDestBlt),
582     FE(DDSD_CKSRCOVERLAY, _dump_DDCOLORKEY, ddckCKSrcOverlay),
583     FE(DDSD_CKSRCBLT, _dump_DDCOLORKEY, ddckCKSrcBlt),
584     FE(DDSD_MIPMAPCOUNT, _dump_DWORD, x.dwMipMapCount),
585     FE(DDSD_REFRESHRATE, _dump_DWORD, x.dwRefreshRate),
586     FE(DDSD_LINEARSIZE, _dump_DWORD, y.dwLinearSize),
587     FE(DDSD_LPSURFACE, _dump_PTR, y.lpSurface)
588 #undef FE
589   };
590   for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
591     if (flags[i].mask & lpddsd->dwFlags) {
592       DUMP(" - %s : ",flags[i].name);
593       flags[i].func(flags[i].elt);
594         DUMP("\n");  
595 }
596 }
597
598
599 /******************************************************************************
600  *              IDirectDrawSurface methods
601  *
602  * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
603  * DDS and DDS2 use those functions. (Function calls did not change (except
604  * using different DirectDrawSurfaceX version), just added flags and functions)
605  */
606 static HRESULT WINAPI IDirectDrawSurface4Impl_Lock(
607     LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
608 ) {
609         ICOM_THIS(IDirectDrawSurface4Impl,iface);
610         TRACE(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
611                 This,lprect,lpddsd,flags,(DWORD)hnd);
612         if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
613             WARN(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
614                          This,lprect,lpddsd,flags,(DWORD)hnd);
615
616         /* First, copy the Surface description */
617         *lpddsd = This->s.surface_desc;
618         TRACE(ddraw,"locked surface: height=%ld, width=%ld, pitch=%ld\n",
619               lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
620
621         /* If asked only for a part, change the surface pointer */
622         if (lprect) {
623                 FIXME(ddraw,"   lprect: %dx%d-%dx%d\n",
624                         lprect->top,lprect->left,lprect->bottom,lprect->right
625                 );
626                 lpddsd->y.lpSurface = (LPVOID) ((char *) This->s.surface_desc.y.lpSurface +
627                         (lprect->top*This->s.surface_desc.lPitch) +
628                                                 (lprect->left*(This->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8)));
629         } else {
630                 assert(This->s.surface_desc.y.lpSurface);
631         }
632         return DD_OK;
633 }
634
635 static HRESULT WINAPI DGA_IDirectDrawSurface4Impl_Unlock(
636         LPDIRECTDRAWSURFACE4 iface,LPVOID surface
637 ) {
638         ICOM_THIS(IDirectDrawSurface4Impl,iface);
639         TRACE(ddraw,"(%p)->Unlock(%p)\n",This,surface);
640         return DD_OK;
641 }
642
643 static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
644   if (This->s.ddraw->d.pixel_convert != NULL)
645     This->s.ddraw->d.pixel_convert(This->s.surface_desc.y.lpSurface,
646                                    This->t.xlib.image->data,
647                                    This->s.surface_desc.dwWidth,
648                                    This->s.surface_desc.dwHeight,
649                                    This->s.surface_desc.lPitch,
650                                    This->s.palette);
651
652 #ifdef HAVE_LIBXXSHM
653     if (This->s.ddraw->e.xlib.xshm_active)
654       TSXShmPutImage(display,
655                      This->s.ddraw->d.drawable,
656                      DefaultGCOfScreen(X11DRV_GetXScreen()),
657                      This->t.xlib.image,
658                      0, 0, 0, 0,
659                      This->t.xlib.image->width,
660                      This->t.xlib.image->height,
661                      False);
662     else
663 #endif
664         TSXPutImage(            display,
665                                 This->s.ddraw->d.drawable,
666                                 DefaultGCOfScreen(X11DRV_GetXScreen()),
667                                 This->t.xlib.image,
668                                 0, 0, 0, 0,
669                                 This->t.xlib.image->width,
670                   This->t.xlib.image->height);
671 }
672
673 static HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
674         LPDIRECTDRAWSURFACE4 iface,LPVOID surface)
675 {
676         ICOM_THIS(IDirectDrawSurface4Impl,iface);
677         TRACE(ddraw,"(%p)->Unlock(%p)\n",This,surface);
678   
679         if (!This->s.ddraw->d.paintable)
680                 return DD_OK;
681
682   /* Only redraw the screen when unlocking the buffer that is on screen */
683         if ((This->t.xlib.image != NULL) &&
684             (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_VISIBLE)) {
685           Xlib_copy_surface_on_screen(This);
686           
687         if (This->s.palette && This->s.palette->cm)
688                 TSXSetWindowColormap(display,This->s.ddraw->d.drawable,This->s.palette->cm);
689         }
690
691         return DD_OK;
692 }
693
694 static HRESULT WINAPI DGA_IDirectDrawSurface4Impl_Flip(
695         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
696 ) {
697         ICOM_THIS(IDirectDrawSurface4Impl,iface);
698         IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
699 #ifdef HAVE_LIBXXF86DGA
700         TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
701         if (!iflipto) {
702                 if (This->s.backbuffer)
703                         iflipto = This->s.backbuffer;
704                 else
705                         iflipto = This;
706         }
707         TSXF86DGASetViewPort(display,DefaultScreen(display),0,iflipto->t.dga.fb_height);
708
709         if (iflipto->s.palette && iflipto->s.palette->cm) {
710                 TSXF86DGAInstallColormap(display,DefaultScreen(display),iflipto->s.palette->cm);
711         }
712         while (!TSXF86DGAViewPortChanged(display,DefaultScreen(display),2)) {
713         }
714         if (iflipto!=This) {
715                 int     tmp;
716                 LPVOID  ptmp;
717
718                 tmp = This->t.dga.fb_height;
719                 This->t.dga.fb_height = iflipto->t.dga.fb_height;
720                 iflipto->t.dga.fb_height = tmp;
721
722                 ptmp = This->s.surface_desc.y.lpSurface;
723                 This->s.surface_desc.y.lpSurface = iflipto->s.surface_desc.y.lpSurface;
724                 iflipto->s.surface_desc.y.lpSurface = ptmp;
725         }
726         return DD_OK;
727 #else /* defined(HAVE_LIBXXF86DGA) */
728         return E_UNEXPECTED;
729 #endif /* defined(HAVE_LIBXXF86DGA) */
730 }
731
732 static HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
733         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
734 ) {
735         ICOM_THIS(IDirectDrawSurface4Impl,iface);
736         IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
737         TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
738
739 #ifdef HAVE_MESAGL
740         if ((This->s.d3d_device != NULL) ||
741             ((This->s.backbuffer != NULL) && (This->s.backbuffer->s.d3d_device != NULL))) {
742           TRACE(ddraw," - OpenGL flip\n");
743           ENTER_GL();
744           glXSwapBuffers(display,
745                          This->s.ddraw->d.drawable);
746           LEAVE_GL();
747
748           return DD_OK;
749         }
750 #endif /* defined(HAVE_MESAGL) */
751         
752         if (!This->s.ddraw->d.paintable)
753                 return DD_OK;
754
755         if (!iflipto) {
756                 if (This->s.backbuffer)
757                         iflipto = This->s.backbuffer;
758                 else
759                         iflipto = This;
760         }
761   
762         Xlib_copy_surface_on_screen(iflipto);
763         
764         if (iflipto->s.palette && iflipto->s.palette->cm) {
765           TSXSetWindowColormap(display,This->s.ddraw->d.drawable,iflipto->s.palette->cm);
766         }
767         if (iflipto!=This) {
768                 XImage *tmp;
769                 LPVOID  *surf;
770                 tmp = This->t.xlib.image;
771                 This->t.xlib.image = iflipto->t.xlib.image;
772                 iflipto->t.xlib.image = tmp;
773                 surf = This->s.surface_desc.y.lpSurface;
774                 This->s.surface_desc.y.lpSurface = iflipto->s.surface_desc.y.lpSurface;
775                 iflipto->s.surface_desc.y.lpSurface = surf;
776         }
777         return DD_OK;
778 }
779
780
781 /* The IDirectDrawSurface4::SetPalette method attaches the specified
782  * DirectDrawPalette object to a surface. The surface uses this palette for all
783  * subsequent operations. The palette change takes place immediately.
784  */
785 static HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_SetPalette(
786         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
787 ) {
788         ICOM_THIS(IDirectDrawSurface4Impl,iface);
789         IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
790         int i;
791         TRACE(ddraw,"(%p)->(%p)\n",This,ipal);
792
793         if (ipal == NULL) {
794           if( This->s.palette != NULL )
795             IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
796           This->s.palette = ipal;
797
798           return DD_OK;
799         }
800         
801         if( !(ipal->cm) && (This->s.ddraw->d.screen_pixelformat.x.dwRGBBitCount<=8)) 
802         {
803                 ipal->cm = TSXCreateColormap(display,This->s.ddraw->d.drawable,
804                                             DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
805
806                 if (!Options.managed)
807                         TSXInstallColormap(display,ipal->cm);
808
809                 for (i=0;i<256;i++) {
810                         XColor xc;
811
812                         xc.red = ipal->palents[i].peRed<<8;
813                         xc.blue = ipal->palents[i].peBlue<<8;
814                         xc.green = ipal->palents[i].peGreen<<8;
815                         xc.flags = DoRed|DoBlue|DoGreen;
816                         xc.pixel = i;
817                         TSXStoreColor(display,ipal->cm,&xc);
818                 }
819                 TSXInstallColormap(display,ipal->cm);
820         }
821
822         /* According to spec, we are only supposed to 
823          * AddRef if this is not the same palette.
824          */
825         if( This->s.palette != ipal )
826         {
827           if( ipal != NULL )
828             IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
829           if( This->s.palette != NULL )
830             IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
831           This->s.palette = ipal; 
832
833           /* I think that we need to attach it to all backbuffers...*/
834           if( This->s.backbuffer ) {
835              if( This->s.backbuffer->s.palette )
836                IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.backbuffer->s.palette );
837              This->s.backbuffer->s.palette = ipal;
838              if( ipal )
839                 IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
840            }
841           /* Perform the refresh */
842           TSXSetWindowColormap(display,This->s.ddraw->d.drawable,This->s.palette->cm);
843         }
844         return DD_OK;
845 }
846
847 static HRESULT WINAPI DGA_IDirectDrawSurface4Impl_SetPalette(
848         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
849 ) {
850         ICOM_THIS(IDirectDrawSurface4Impl,iface);
851         IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
852         TRACE(ddraw,"(%p)->(%p)\n",This,ipal);
853 #ifdef HAVE_LIBXXF86DGA
854         /* According to spec, we are only supposed to 
855          * AddRef if this is not the same palette.
856          */
857         if( This->s.palette != ipal )
858         {
859           if( ipal != NULL ) 
860                 IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
861           if( This->s.palette != NULL )
862             IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
863           This->s.palette = ipal; 
864
865           /* I think that we need to attach it to all backbuffers...*/
866           if( This->s.backbuffer ) {
867              if( This->s.backbuffer->s.palette )
868                IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.backbuffer->s.palette );
869              This->s.backbuffer->s.palette = ipal;
870              if ( ipal )
871                IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
872           }
873           TSXF86DGAInstallColormap(display,DefaultScreen(display),This->s.palette->cm);
874         }
875         return DD_OK;
876 #else /* defined(HAVE_LIBXXF86DGA) */
877         return E_UNEXPECTED;
878 #endif /* defined(HAVE_LIBXXF86DGA) */
879
880
881 }
882
883 static HRESULT _Blt_ColorFill(LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color)
884 {
885         int x, y;
886         LPBYTE first;
887
888         /* Do first row */
889
890 #define COLORFILL_ROW(type) { \
891         type *d = (type *) buf; \
892         for (x = 0; x < width; x++) \
893                 d[x] = (type) color; \
894         break; \
895 }
896
897         switch(bpp) {
898         case 1: COLORFILL_ROW(BYTE)
899         case 2: COLORFILL_ROW(WORD)
900         case 4: COLORFILL_ROW(DWORD)
901         default:
902         FIXME(ddraw, "Stretched blit not implemented for bpp %d!\n", bpp*8);
903         return DDERR_UNSUPPORTED;
904         }
905
906 #undef COLORFILL_ROW
907
908         /* Now copy first row */
909         first = buf;
910         for (y = 1; y < height; y++) {
911                 buf += lPitch;
912                 memcpy(buf, first, width * bpp);
913         }
914
915         return DD_OK;
916 }
917
918 static HRESULT WINAPI IDirectDrawSurface4Impl_Blt(
919         LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
920 ) {
921         ICOM_THIS(IDirectDrawSurface4Impl,iface);
922         RECT    xdst,xsrc;
923         DDSURFACEDESC   ddesc,sdesc;
924         HRESULT                 ret = DD_OK;
925         int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
926         int x, y;
927         LPBYTE dbuf, sbuf;
928
929         TRACE(ddraw,"(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
930
931         if (src) IDirectDrawSurface4_Lock(src, NULL, &sdesc, 0, 0);
932         IDirectDrawSurface4_Lock(iface,NULL,&ddesc,0,0);
933         
934         if (TRACE_ON(ddraw)) {
935           if (rdst) TRACE(ddraw,"       destrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
936           if (rsrc) TRACE(ddraw,"       srcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
937           TRACE(ddraw,"\tflags: ");
938           _dump_DDBLT(dwFlags);
939           if (dwFlags & DDBLT_DDFX) {
940             TRACE(ddraw,"       blitfx: \n");
941                 _dump_DDBLTFX(lpbltfx->dwDDFX);
942           }
943         }
944                 
945         if (rdst) {
946                 memcpy(&xdst,rdst,sizeof(xdst));
947         } else {
948                 xdst.top        = 0;
949                 xdst.bottom     = ddesc.dwHeight;
950                 xdst.left       = 0;
951                 xdst.right      = ddesc.dwWidth;
952         }
953
954         if (rsrc) {
955                 memcpy(&xsrc,rsrc,sizeof(xsrc));
956         } else {
957                 if (src) {
958                 xsrc.top        = 0;
959                 xsrc.bottom     = sdesc.dwHeight;
960                 xsrc.left       = 0;
961                 xsrc.right      = sdesc.dwWidth;
962                 } else {
963                     memset(&xsrc,0,sizeof(xsrc));
964                 }
965         }
966
967         bpp = GET_BPP(ddesc);
968         srcheight = xsrc.bottom - xsrc.top;
969         srcwidth = xsrc.right - xsrc.left;
970         dstheight = xdst.bottom - xdst.top;
971         dstwidth = xdst.right - xdst.left;
972         width = (xdst.right - xdst.left) * bpp;
973         dbuf = (BYTE *) ddesc.y.lpSurface + (xdst.top * ddesc.lPitch) + (xdst.left * bpp);
974
975         dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
976         
977         /* First, all the 'source-less' blits */
978         if (dwFlags & DDBLT_COLORFILL) {
979                 ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
980                                      ddesc.lPitch, lpbltfx->b.dwFillColor);
981                 dwFlags &= ~DDBLT_COLORFILL;
982                 }
983
984         if (dwFlags & DDBLT_DEPTHFILL) {
985 #ifdef HAVE_MESAGL
986           GLboolean ztest;
987           
988           /* Clears the screen */
989           TRACE(ddraw, "        Filling depth buffer with %ld\n", lpbltfx->b.dwFillDepth);
990           glClearDepth(lpbltfx->b.dwFillDepth / 65535.0); /* We suppose a 16 bit Z Buffer */
991           glGetBooleanv(GL_DEPTH_TEST, &ztest);
992           glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
993           glClear(GL_DEPTH_BUFFER_BIT);
994           glDepthMask(ztest);
995           
996           dwFlags &= ~(DDBLT_DEPTHFILL);
997 #endif /* defined(HAVE_MESAGL) */
998         }
999         
1000         if (dwFlags & DDBLT_ROP) {
1001                 /* Catch some degenerate cases here */
1002                 switch(lpbltfx->dwROP) {
1003                         case BLACKNESS:
1004                                 ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, ddesc.lPitch, 0);
1005                                 break;
1006                         case 0xAA0029: /* No-op */
1007                                 break;
1008                         case WHITENESS:
1009                                 ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, ddesc.lPitch, ~0);
1010                                 break;
1011                         default: 
1012                                 FIXME(ddraw, "Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->b.lpDDSPattern);
1013                                 goto error;
1014             }
1015                 dwFlags &= ~DDBLT_ROP;
1016         }
1017
1018     if (dwFlags & DDBLT_DDROPS) {
1019                 FIXME(ddraw, "\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->b.lpDDSPattern);
1020         }
1021
1022         /* Now the 'with source' blits */
1023         if (src) {
1024                 LPBYTE sbase;
1025                 int sx, xinc, sy, yinc;
1026
1027                 sbase = (BYTE *) sdesc.y.lpSurface + (xsrc.top * sdesc.lPitch) + xsrc.left * bpp;
1028                 xinc = (srcwidth << 16) / dstwidth;
1029                 yinc = (srcheight << 16) / dstheight;
1030
1031                 if (!dwFlags) {
1032
1033                         /* No effects, we can cheat here */
1034                         if (dstwidth == srcwidth) {
1035                                 if (dstheight == srcheight) {
1036                                         /* No stretching in either direction.  This needs to be as fast as possible */
1037                                         sbuf = sbase;
1038                                         for (y = 0; y < dstheight; y++) {
1039                                                 memcpy(dbuf, sbuf, width);
1040                                                 sbuf += sdesc.lPitch;
1041                                                 dbuf += ddesc.lPitch;
1042                                         }
1043         } else {
1044                                         /* Stretching in Y direction only */
1045                                         for (y = sy = 0; y < dstheight; y++, sy += yinc) {
1046                                                 sbuf = sbase + (sy >> 16) * sdesc.lPitch;
1047                                                 memcpy(dbuf, sbuf, width);
1048                                                 dbuf += ddesc.lPitch;
1049                   }
1050                 }
1051                         } else {
1052                                 /* Stretching in X direction */
1053                                 int last_sy = -1;
1054                                 for (y = sy = 0; y < dstheight; y++, sy += yinc) {
1055                                         sbuf = sbase + (sy >> 16) * sdesc.lPitch;
1056
1057                                         if ((sy >> 16) == (last_sy >> 16)) {
1058                                                 /* Same as last row - copy already stretched row */
1059                                                 memcpy(dbuf, dbuf - ddesc.lPitch, width);
1060               } else {
1061
1062 #define STRETCH_ROW(type) { \
1063         type *s = (type *) sbuf, *d = (type *) dbuf; \
1064         for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
1065                 d[x] = s[sx >> 16]; \
1066         break; \
1067 }
1068                   
1069                                                 switch(bpp) {
1070                                                         case 1: STRETCH_ROW(BYTE)
1071                                                         case 2: STRETCH_ROW(WORD)
1072                                                         case 4: STRETCH_ROW(DWORD)
1073                                                         default:
1074                                                                 FIXME(ddraw, "Stretched blit not implemented for bpp %d!\n", bpp*8);
1075                                                                 ret = DDERR_UNSUPPORTED;
1076                                                                 goto error;
1077                 }
1078
1079 #undef STRETCH_ROW
1080
1081               }
1082                                         last_sy = sy;
1083                                         dbuf += ddesc.lPitch;
1084               }
1085             }
1086                 } else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
1087                         DWORD keylow, keyhigh;
1088
1089             if (dwFlags & DDBLT_KEYSRC) {
1090                                 keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
1091                                 keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
1092                         } else {
1093                                 /* I'm not sure if this is correct */
1094                                 FIXME(ddraw, "DDBLT_KEYDEST not fully supported yet.\n");
1095                                 keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
1096                                 keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
1097                         }
1098
1099 #define COPYROW_COLORKEY(type) { \
1100         type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
1101         for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
1102                 tmp = s[sx >> 16]; \
1103                 if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
1104         } \
1105         break; \
1106                 }
1107                 
1108                         for (y = sy = 0; y < dstheight; y++, sy += yinc) {
1109                                 sbuf = sbase + (sy >> 16) * sdesc.lPitch;
1110
1111                                 switch (bpp) {
1112                                         case 1: COPYROW_COLORKEY(BYTE)
1113                                         case 2: COPYROW_COLORKEY(WORD)
1114                                         case 4: COPYROW_COLORKEY(DWORD)
1115               default:
1116                                                 FIXME(ddraw, "%s color-keyed blit not implemented for bpp %d!\n",
1117                                                         (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
1118                                                 ret = DDERR_UNSUPPORTED;
1119                                                 goto error;
1120               }
1121                                 dbuf += ddesc.lPitch;
1122           }
1123
1124 #undef COPYROW_COLORKEY
1125                         
1126                         dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
1127
1128         }
1129         }
1130         
1131 error:
1132         
1133         if (dwFlags && FIXME_ON(ddraw)) {
1134           FIXME(ddraw,"\tUnsupported flags: ");
1135           _dump_DDBLT(dwFlags);
1136         }
1137
1138         IDirectDrawSurface4_Unlock(iface,ddesc.y.lpSurface);
1139         if (src) IDirectDrawSurface4_Unlock(src,sdesc.y.lpSurface);
1140
1141         return DD_OK;
1142 }
1143
1144 static HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(
1145         LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD trans
1146 ) {
1147         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1148         int                             bpp, w, h, x, y;
1149         DDSURFACEDESC   ddesc,sdesc;
1150         HRESULT                 ret = DD_OK;
1151         LPBYTE                  sbuf, dbuf;
1152
1153
1154         if (TRACE_ON(ddraw)) {
1155             FIXME(ddraw,"(%p)->(%ld,%ld,%p,%p,%08lx)\n",
1156                     This,dstx,dsty,src,rsrc,trans
1157             );
1158             FIXME(ddraw,"       trans:");
1159             if (FIXME_ON(ddraw))
1160               _dump_DDBLTFAST(trans);
1161             FIXME(ddraw,"       srcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
1162         }
1163         /* We need to lock the surfaces, or we won't get refreshes when done. */
1164         IDirectDrawSurface4_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
1165         IDirectDrawSurface4_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
1166
1167         bpp = GET_BPP(This->s.surface_desc);
1168         sbuf = (BYTE *) sdesc.y.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp;
1169         dbuf = (BYTE *) ddesc.y.lpSurface + (dsty      * ddesc.lPitch) + dstx       * bpp;
1170
1171
1172         h=rsrc->bottom-rsrc->top;
1173         if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
1174         if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
1175         if (h<0) h=0;
1176
1177         w=rsrc->right-rsrc->left;
1178         if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
1179         if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
1180         if (w<0) w=0;
1181
1182         if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
1183                 DWORD keylow, keyhigh;
1184                 if (trans & DDBLTFAST_SRCCOLORKEY) {
1185                         keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
1186                         keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
1187                 } else {
1188                         /* I'm not sure if this is correct */
1189                         FIXME(ddraw, "DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
1190                         keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
1191                         keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
1192                 }
1193
1194 #define COPYBOX_COLORKEY(type) { \
1195         type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
1196         s = (type *) ((BYTE *) sdesc.y.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp); \
1197         d = (type *) ((BYTE *) ddesc.y.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp); \
1198         for (y = 0; y < h; y++) { \
1199                 for (x = 0; x < w; x++) { \
1200                         tmp = s[x]; \
1201                         if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
1202                 } \
1203                 (LPBYTE)s += sdesc.lPitch; \
1204                 (LPBYTE)d += ddesc.lPitch; \
1205         } \
1206         break; \
1207 }
1208
1209                 switch (bpp) {
1210                         case 1: COPYBOX_COLORKEY(BYTE)
1211                         case 2: COPYBOX_COLORKEY(WORD)
1212                         case 4: COPYBOX_COLORKEY(DWORD)
1213                         default:
1214                                 FIXME(ddraw, "Source color key blitting not supported for bpp %d\n", bpp*8);
1215                                 ret = DDERR_UNSUPPORTED;
1216                                 goto error;
1217         }
1218
1219 #undef COPYBOX_COLORKEY
1220
1221         } else {
1222                 int width = w * bpp;
1223
1224                 for (y = 0; y < h; y++) {
1225                         memcpy(dbuf, sbuf, width);
1226                         sbuf += sdesc.lPitch;
1227                         dbuf += ddesc.lPitch;
1228                 }
1229         }
1230
1231 error:
1232
1233         IDirectDrawSurface4_Unlock(iface,ddesc.y.lpSurface);
1234         IDirectDrawSurface4_Unlock(src,sdesc.y.lpSurface);
1235         return ret;
1236 }
1237
1238 static HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(
1239         LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
1240 ) {
1241         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1242         FIXME(ddraw,"(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",
1243                 This,ddbltbatch,x,y
1244         );
1245         return DD_OK;
1246 }
1247
1248 static HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(
1249         LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps
1250 ) {
1251         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1252         TRACE(ddraw,"(%p)->GetCaps(%p)\n",This,caps);
1253         caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
1254         return DD_OK;
1255 }
1256
1257 static HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(
1258         LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd
1259 ) { 
1260         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1261                 TRACE(ddraw, "(%p)->GetSurfaceDesc(%p)\n",
1262                              This,ddsd);
1263   
1264   /* Simply copy the surface description stored in the object */
1265   *ddsd = This->s.surface_desc;
1266   
1267   if (TRACE_ON(ddraw)) {
1268     _dump_surface_desc(ddsd);
1269         }
1270
1271         return DD_OK;
1272 }
1273
1274 static ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface) {
1275         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1276         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
1277
1278         return ++(This->ref);
1279 }
1280
1281 static ULONG WINAPI DGA_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
1282         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1283         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
1284
1285 #ifdef HAVE_LIBXXF86DGA
1286         if (!--(This->ref)) {
1287                 IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
1288                 /* clear out of surface list */
1289                 if (This->t.dga.fb_height == -1) {
1290                         HeapFree(GetProcessHeap(),0,This->s.surface_desc.y.lpSurface);
1291                 } else {
1292                         This->s.ddraw->e.dga.vpmask &= ~(1<<(This->t.dga.fb_height/This->s.ddraw->e.dga.fb_height));
1293                 }
1294
1295                 /* Free the backbuffer */
1296                 if (This->s.backbuffer)
1297                         IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->s.backbuffer);
1298
1299                 /* Free the DIBSection (if any) */
1300                 if (This->s.hdc != 0) {
1301                   SelectObject(This->s.hdc, This->s.holdbitmap);
1302                   DeleteDC(This->s.hdc);
1303                   DeleteObject(This->s.DIBsection);
1304                 }
1305                 
1306                 HeapFree(GetProcessHeap(),0,This);
1307                 return 0;
1308         }
1309 #endif /* defined(HAVE_LIBXXF86DGA) */
1310         return This->ref;
1311 }
1312
1313 static ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
1314         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1315         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
1316
1317         if (!--(This->ref)) {
1318                 IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
1319
1320                 if( This->s.backbuffer )
1321                   IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->s.backbuffer);
1322
1323     if (This->t.xlib.image != NULL) {
1324       if (This->s.ddraw->d.pixel_convert != NULL) {
1325         /* In pixel conversion mode, there are two buffers to release... */
1326         HeapFree(GetProcessHeap(),0,This->s.surface_desc.y.lpSurface);
1327         
1328 #ifdef HAVE_LIBXXSHM
1329         if (This->s.ddraw->e.xlib.xshm_active) {
1330           TSXShmDetach(display, &(This->t.xlib.shminfo));
1331           TSXDestroyImage(This->t.xlib.image);
1332           shmdt(This->t.xlib.shminfo.shmaddr);
1333         } else {
1334 #endif
1335           HeapFree(GetProcessHeap(),0,This->t.xlib.image->data);
1336           This->t.xlib.image->data = NULL;
1337           TSXDestroyImage(This->t.xlib.image);
1338 #ifdef HAVE_LIBXXSHM
1339         }
1340 #endif
1341         
1342       } else {
1343                 This->t.xlib.image->data = NULL;
1344       
1345 #ifdef HAVE_LIBXXSHM
1346       if (This->s.ddraw->e.xlib.xshm_active) {
1347         TSXShmDetach(display, &(This->t.xlib.shminfo));
1348                 TSXDestroyImage(This->t.xlib.image);
1349         shmdt(This->t.xlib.shminfo.shmaddr);
1350       } else {
1351 #endif
1352               HeapFree(GetProcessHeap(),0,This->s.surface_desc.y.lpSurface);
1353         TSXDestroyImage(This->t.xlib.image);
1354 #ifdef HAVE_LIBXXSHM    
1355       }
1356 #endif
1357       }
1358       
1359                 This->t.xlib.image = 0;
1360     } else {
1361             HeapFree(GetProcessHeap(),0,This->s.surface_desc.y.lpSurface);
1362     }
1363
1364                 if (This->s.palette)
1365                         IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
1366
1367                 /* Free the DIBSection (if any) */
1368                 if (This->s.hdc != 0) {
1369                   SelectObject(This->s.hdc, This->s.holdbitmap);
1370                   DeleteDC(This->s.hdc);
1371                   DeleteObject(This->s.DIBsection);
1372                 }
1373
1374                 HeapFree(GetProcessHeap(),0,This);
1375                 return 0;
1376         }
1377   
1378         return This->ref;
1379 }
1380
1381 static HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(
1382         LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
1383 ) {
1384         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1385         TRACE(ddraw, "(%p)->GetAttachedSurface(%p,%p)\n",
1386                      This, lpddsd, lpdsf);
1387
1388         if (TRACE_ON(ddraw)) {
1389                 TRACE(ddraw,"   caps ");
1390                 _dump_DDSCAPS((void *) &(lpddsd->dwCaps));
1391                 DUMP("\n");
1392         }
1393
1394         if (!(lpddsd->dwCaps & DDSCAPS_BACKBUFFER)) {
1395                 FIXME(ddraw,"whoops, can only handle backbuffers for now\n");
1396                 return E_FAIL;
1397         }
1398
1399         /* FIXME: should handle more than one backbuffer */
1400         *lpdsf = (LPDIRECTDRAWSURFACE4)This->s.backbuffer;
1401  
1402         if( This->s.backbuffer )
1403           IDirectDrawSurface4_AddRef( (IDirectDrawSurface4*)This->s.backbuffer );
1404
1405         return DD_OK;
1406 }
1407
1408 static HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(
1409         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
1410 ) {
1411         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1412         TRACE(ddraw,"(%p)->(%p, %p)\n",This,ddraw,lpdsfd);
1413
1414         return DDERR_ALREADYINITIALIZED;
1415 }
1416
1417 static HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(
1418         LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf
1419 ) {
1420         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1421         TRACE(ddraw,"(%p)->(%p)\n",This,pf);
1422
1423         *pf = This->s.surface_desc.ddpfPixelFormat;
1424         
1425         if (TRACE_ON(ddraw)) {
1426         _dump_pixelformat(pf);
1427           DUMP("\n");
1428         }
1429         
1430         return DD_OK;
1431 }
1432
1433 static HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags) {
1434         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1435         FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",This,dwFlags);
1436         return DD_OK;
1437 }
1438
1439 static HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(
1440         LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2
1441 ) {
1442         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1443         FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,x1,x2);
1444         return DD_OK;
1445 }
1446
1447 static HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(
1448         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER clipper
1449 ) {
1450         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1451         FIXME(ddraw,"(%p)->(%p),stub!\n",This,clipper);
1452         return DD_OK;
1453 }
1454
1455 static HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(
1456         LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf
1457 ) {
1458         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1459         FIXME(ddraw,"(%p)->(%p),stub!\n",This,surf);
1460
1461         IDirectDrawSurface4_AddRef(iface);
1462         
1463         /* This hack will be enough for the moment */
1464         if (This->s.backbuffer == NULL)
1465           This->s.backbuffer = (IDirectDrawSurface4Impl*)surf;
1466         return DD_OK;
1467 }
1468
1469 static HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
1470         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1471   DDSURFACEDESC desc;
1472   BITMAPINFO *b_info;
1473   UINT usage;
1474   
1475         FIXME(ddraw,"(%p)->GetDC(%p)\n",This,lphdc);
1476
1477   /* Creates a DIB Section of the same size / format as the surface */
1478   IDirectDrawSurface4_Lock(iface,NULL,&desc,0,0);
1479
1480   if (This->s.hdc == 0) {
1481     switch (desc.ddpfPixelFormat.x.dwRGBBitCount) {
1482     case 16:
1483     case 32:
1484 #if 0 /* This should be filled if Wine's DIBSection did understand BI_BITFIELDS */
1485       b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
1486       break;
1487 #endif
1488       
1489     case 24:
1490       b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
1491       break;
1492       
1493     default:
1494       b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1495                                         sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (2 << desc.ddpfPixelFormat.x.dwRGBBitCount));
1496       break;
1497     }
1498     
1499     b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1500     b_info->bmiHeader.biWidth = desc.dwWidth;
1501     b_info->bmiHeader.biHeight = desc.dwHeight;
1502     b_info->bmiHeader.biPlanes = 1;
1503     b_info->bmiHeader.biBitCount = desc.ddpfPixelFormat.x.dwRGBBitCount;
1504 #if 0
1505     if ((desc.ddpfPixelFormat.x.dwRGBBitCount != 16) &&
1506         (desc.ddpfPixelFormat.x.dwRGBBitCount != 32))
1507 #endif
1508       b_info->bmiHeader.biCompression = BI_RGB;
1509 #if 0
1510     else
1511       b_info->bmiHeader.biCompression = BI_BITFIELDS;
1512 #endif
1513     b_info->bmiHeader.biSizeImage = (desc.ddpfPixelFormat.x.dwRGBBitCount / 8) * desc.dwWidth * desc.dwHeight;
1514     b_info->bmiHeader.biXPelsPerMeter = 0;
1515     b_info->bmiHeader.biYPelsPerMeter = 0;
1516     b_info->bmiHeader.biClrUsed = 0;
1517     b_info->bmiHeader.biClrImportant = 0;
1518     
1519     switch (desc.ddpfPixelFormat.x.dwRGBBitCount) {
1520     case 16:
1521     case 32:
1522 #if 0
1523       {
1524         DWORD *masks = (DWORD *) &(b_info->bmiColors);
1525         
1526         usage = 0;
1527         masks[0] = desc.ddpfPixelFormat.y.dwRBitMask;
1528         masks[1] = desc.ddpfPixelFormat.z.dwGBitMask;
1529         masks[2] = desc.ddpfPixelFormat.xx.dwBBitMask;
1530       } break;
1531 #endif
1532       
1533     case 24:
1534       /* Nothing to do */
1535       usage = DIB_RGB_COLORS;
1536       break;
1537       
1538     default: {
1539       int i;
1540       
1541       /* Fill the palette */
1542       usage = DIB_RGB_COLORS;
1543
1544       if (This->s.palette == NULL) {
1545         ERR(ddraw, "Bad palette !!!\n");
1546       } else {
1547         RGBQUAD *rgb = (RGBQUAD *) &(b_info->bmiColors);
1548         PALETTEENTRY *pent = (PALETTEENTRY *) &(This->s.palette->palents);
1549         
1550         for (i = 0; i < (2 << desc.ddpfPixelFormat.x.dwRGBBitCount); i++) {
1551           rgb[i].rgbBlue = pent[i].peBlue;
1552           rgb[i].rgbRed = pent[i].peRed;
1553           rgb[i].rgbGreen = pent[i].peGreen; 
1554         }
1555       }
1556     } break;
1557     }  
1558     
1559     This->s.DIBsection = CreateDIBSection(BeginPaint(This->s.ddraw->d.mainWindow,&This->s.ddraw->d.ps),
1560                                           b_info,
1561                                           usage,
1562                                           &(This->s.bitmap_data),
1563                                           NULL,
1564                                           0);
1565     EndPaint(This->s.ddraw->d.mainWindow,&This->s.ddraw->d.ps);
1566     TRACE(ddraw, "DIBSection at : %p\n", This->s.bitmap_data);
1567     
1568     /* b_info is not useful anymore */
1569     HeapFree(GetProcessHeap(), 0, b_info);
1570       
1571     /* Create the DC */
1572     This->s.hdc = CreateCompatibleDC(0);
1573     This->s.holdbitmap = SelectObject(This->s.hdc, This->s.DIBsection);
1574   }
1575   
1576   /* Copy our surface in the DIB section */
1577   if ((GET_BPP(desc) * desc.dwWidth) == desc.lPitch) {
1578     memcpy(This->s.bitmap_data, desc.y.lpSurface, desc.lPitch * desc.dwHeight);
1579   } else {
1580     /* TODO */
1581     FIXME(ddraw, "This case has to be done :/\n");
1582   }
1583
1584   TRACE(ddraw, "HDC : %08lx\n", (DWORD) This->s.hdc);
1585   *lphdc = This->s.hdc;
1586   
1587         return DD_OK;
1588 }
1589
1590 static HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc) {
1591         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1592         
1593         FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",This,(long)hdc);
1594
1595   TRACE(ddraw, "Copying DIBSection at : %p\n", This->s.bitmap_data);
1596   
1597   /* Copy the DIB section to our surface */
1598   if ((GET_BPP(This->s.surface_desc) * This->s.surface_desc.dwWidth) == This->s.surface_desc.lPitch) {
1599     memcpy(This->s.surface_desc.y.lpSurface, This->s.bitmap_data, This->s.surface_desc.lPitch * This->s.surface_desc.dwHeight);
1600   } else {
1601     /* TODO */
1602     FIXME(ddraw, "This case has to be done :/\n");
1603         }
1604
1605   /* Unlock the surface */
1606   IDirectDrawSurface4_Unlock(iface,This->s.surface_desc.y.lpSurface);
1607         
1608         return DD_OK;
1609
1610 }
1611
1612 static HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj) {
1613         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1614         char    xrefiid[50];
1615
1616         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1617         TRACE(ddraw,"(%p)->(%s,%p)\n",This,xrefiid,obj);
1618         
1619         /* All DirectDrawSurface versions (1, 2, 3 and 4) use
1620          * the same interface. And IUnknown does that too of course.
1621          */
1622         if (    !memcmp(&IID_IDirectDrawSurface4,refiid,sizeof(IID))    ||
1623                 !memcmp(&IID_IDirectDrawSurface3,refiid,sizeof(IID))    ||
1624                 !memcmp(&IID_IDirectDrawSurface2,refiid,sizeof(IID))    ||
1625                 !memcmp(&IID_IDirectDrawSurface,refiid,sizeof(IID))     ||
1626                 !memcmp(&IID_IUnknown,refiid,sizeof(IID))
1627         ) {
1628                 *obj = This;
1629                 IDirectDrawSurface4_AddRef(iface);
1630
1631                 TRACE(ddraw, "  Creating IDirectDrawSurface interface (%p)\n", *obj);
1632                 
1633                 return S_OK;
1634         }
1635         else if (!memcmp(&IID_IDirect3DTexture2,refiid,sizeof(IID)))
1636           {
1637             /* Texture interface */
1638             *obj = d3dtexture2_create(This);
1639             IDirectDrawSurface4_AddRef(iface);
1640             
1641             TRACE(ddraw, "  Creating IDirect3DTexture2 interface (%p)\n", *obj);
1642             
1643             return S_OK;
1644           }
1645         else if (!memcmp(&IID_IDirect3DTexture,refiid,sizeof(IID)))
1646           {
1647             /* Texture interface */
1648             *obj = d3dtexture_create(This);
1649             IDirectDrawSurface4_AddRef(iface);
1650             
1651             TRACE(ddraw, "  Creating IDirect3DTexture interface (%p)\n", *obj);
1652             
1653             return S_OK;
1654           }
1655         else if (is_OpenGL_dx3(refiid, (IDirectDrawSurfaceImpl*)This, (IDirect3DDeviceImpl**) obj))
1656           {
1657             /* It is the OpenGL Direct3D Device */
1658             IDirectDrawSurface4_AddRef(iface);
1659
1660             TRACE(ddraw, "  Creating IDirect3DDevice interface (%p)\n", *obj);
1661                         
1662                 return S_OK;
1663         }
1664         
1665         FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",This,xrefiid);
1666         return OLE_E_ENUM_NOMORE;
1667 }
1668
1669 static HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface) {
1670         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1671         TRACE(ddraw,"(%p)->(), stub!\n",This);
1672         return DD_OK; /* hmm */
1673 }
1674
1675 static HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb) {
1676         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1677         FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,context,esfcb);
1678
1679         /* For the moment, only enumerating the back buffer */
1680         if (This->s.backbuffer != NULL) {
1681           TRACE(ddraw, "Enumerating back-buffer (%p)\n", This->s.backbuffer);
1682           if (esfcb((LPDIRECTDRAWSURFACE) This->s.backbuffer, &(This->s.backbuffer->s.surface_desc), context) == DDENUMRET_CANCEL)
1683             return DD_OK;
1684         }
1685         
1686         return DD_OK;
1687 }
1688
1689 static HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface) {
1690         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1691         FIXME(ddraw,"(%p)->(),stub!\n",This);
1692         return DD_OK;
1693 }
1694
1695 static HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(
1696         LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey ) 
1697 {
1698         ICOM_THIS(IDirectDrawSurface4Impl,iface);
1699         TRACE(ddraw,"(%p)->(0x%08lx,%p)\n",This,dwFlags,ckey);
1700         if (TRACE_ON(ddraw)) {
1701           _dump_colorkeyflag(dwFlags);
1702           DUMP(" : ");
1703           _dump_DDCOLORKEY((void *) ckey);
1704           DUMP("\n");
1705         }
1706
1707         /* If this surface was loaded as a texture, call also the texture
1708            SetColorKey callback */
1709         if (This->s.texture) {
1710           This->s.SetColorKey_cb(This->s.texture, dwFlags, ckey);
1711         }
1712
1713         if( dwFlags & DDCKEY_SRCBLT )
1714         {
1715            dwFlags &= ~DDCKEY_SRCBLT;
1716            This->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
1717            memcpy( &(This->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
1718         }
1719
1720         if( dwFlags & DDCKEY_DESTBLT )
1721         {
1722            dwFlags &= ~DDCKEY_DESTBLT;
1723            This->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
1724            memcpy( &(This->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
1725         }
1726
1727         if( dwFlags & DDCKEY_SRCOVERLAY )
1728         {
1729            dwFlags &= ~DDCKEY_SRCOVERLAY;
1730            This->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1731            memcpy( &(This->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );      
1732         }
1733         
1734         if( dwFlags & DDCKEY_DESTOVERLAY )
1735         {
1736            dwFlags &= ~DDCKEY_DESTOVERLAY;
1737            This->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1738            memcpy( &(This->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );     
1739         }
1740
1741         if( dwFlags )
1742         {
1743           FIXME( ddraw, "unhandled dwFlags: 0x%08lx\n", dwFlags );
1744         }
1745
1746         return DD_OK;
1747
1748 }
1749
1750 static HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(
1751         LPDIRECTDRAWSURFACE4 iface, 
1752         LPRECT lpRect )
1753 {
1754   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1755   FIXME(ddraw,"(%p)->(%p),stub!\n",This,lpRect); 
1756
1757   return DD_OK;
1758 }
1759
1760 static HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(
1761         LPDIRECTDRAWSURFACE4 iface, 
1762         DWORD dwFlags,
1763         LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface )
1764 {
1765   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1766   FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n",This,dwFlags,lpDDSAttachedSurface);
1767
1768   return DD_OK;
1769 }
1770
1771 static HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(
1772         LPDIRECTDRAWSURFACE4 iface,
1773         DWORD dwFlags,
1774         LPVOID lpContext,
1775         LPDDENUMSURFACESCALLBACK lpfnCallback )
1776 {
1777   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1778   FIXME(ddraw,"(%p)->(0x%08lx,%p,%p),stub!\n", This,dwFlags,
1779           lpContext, lpfnCallback );
1780
1781   return DD_OK;
1782 }
1783
1784 static HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(
1785         LPDIRECTDRAWSURFACE4 iface,
1786         LPDIRECTDRAWCLIPPER* lplpDDClipper )
1787 {
1788   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1789   FIXME(ddraw,"(%p)->(%p),stub!\n", This, lplpDDClipper);
1790
1791   return DD_OK;
1792 }
1793
1794 static HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(
1795         LPDIRECTDRAWSURFACE4 iface,
1796         DWORD dwFlags,
1797         LPDDCOLORKEY lpDDColorKey )
1798 {
1799   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1800   TRACE(ddraw,"(%p)->(0x%08lx,%p)\n", This, dwFlags, lpDDColorKey);
1801
1802   if( dwFlags & DDCKEY_SRCBLT )  {
1803      dwFlags &= ~DDCKEY_SRCBLT;
1804      memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
1805   }
1806
1807   if( dwFlags & DDCKEY_DESTBLT )
1808   {
1809     dwFlags &= ~DDCKEY_DESTBLT;
1810     memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
1811   }
1812
1813   if( dwFlags & DDCKEY_SRCOVERLAY )
1814   {
1815     dwFlags &= ~DDCKEY_SRCOVERLAY;
1816     memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
1817   }
1818
1819   if( dwFlags & DDCKEY_DESTOVERLAY )
1820   {
1821     dwFlags &= ~DDCKEY_DESTOVERLAY;
1822     memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
1823   }
1824
1825   if( dwFlags )
1826   {
1827     FIXME( ddraw, "unhandled dwFlags: 0x%08lx\n", dwFlags );
1828   }
1829
1830   return DD_OK;
1831 }
1832
1833 static HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(
1834         LPDIRECTDRAWSURFACE4 iface,
1835         DWORD dwFlags ) 
1836 {
1837   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1838   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
1839
1840   return DD_OK;
1841 }
1842
1843 static HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(
1844         LPDIRECTDRAWSURFACE4 iface,
1845         LPDIRECTDRAWPALETTE* lplpDDPalette )
1846 {
1847   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1848   FIXME(ddraw,"(%p)->(%p),stub!\n", This, lplpDDPalette);
1849
1850   return DD_OK;
1851 }
1852
1853 static HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(
1854         LPDIRECTDRAWSURFACE4 iface,
1855         LONG lX,
1856         LONG lY)
1857 {
1858   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1859   FIXME(ddraw,"(%p)->(%ld,%ld),stub!\n", This, lX, lY);
1860
1861   return DD_OK;
1862 }
1863
1864 static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(
1865         LPDIRECTDRAWSURFACE4 iface,
1866         LPRECT lpSrcRect,
1867         LPDIRECTDRAWSURFACE4 lpDDDestSurface,
1868         LPRECT lpDestRect,
1869         DWORD dwFlags,
1870         LPDDOVERLAYFX lpDDOverlayFx )
1871 {
1872   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1873   FIXME(ddraw,"(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", This,
1874          lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
1875
1876   return DD_OK;
1877 }
1878  
1879 static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(
1880         LPDIRECTDRAWSURFACE4 iface,
1881         DWORD dwFlags )
1882 {
1883   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1884   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags); 
1885
1886   return DD_OK;
1887 }
1888
1889 static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(
1890         LPDIRECTDRAWSURFACE4 iface,
1891         DWORD dwFlags,
1892         LPDIRECTDRAWSURFACE4 lpDDSReference )
1893 {
1894   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1895   FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n", This, dwFlags, lpDDSReference);
1896
1897   return DD_OK;
1898 }
1899
1900 static HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(
1901         LPDIRECTDRAWSURFACE4 iface,
1902         LPVOID* lplpDD )
1903 {
1904   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1905   FIXME(ddraw,"(%p)->(%p),stub!\n", This, lplpDD);
1906
1907   /* Not sure about that... */
1908   *lplpDD = (void *) This->s.ddraw;
1909   
1910   return DD_OK;
1911 }
1912
1913 static HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(
1914         LPDIRECTDRAWSURFACE4 iface,
1915         DWORD dwFlags )
1916 {
1917   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1918   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
1919
1920   return DD_OK;
1921 }
1922
1923 static HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(
1924         LPDIRECTDRAWSURFACE4 iface,
1925         DWORD dwFlags )
1926 {
1927   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1928   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
1929
1930   return DD_OK;
1931 }
1932
1933 static HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(
1934         LPDIRECTDRAWSURFACE4 iface,
1935         LPDDSURFACEDESC lpDDSD,
1936         DWORD dwFlags )
1937 {
1938   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1939   FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n", This, lpDDSD, dwFlags);
1940
1941   return DD_OK;
1942 }
1943
1944 static HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(LPDIRECTDRAWSURFACE4 iface,
1945                                                          REFGUID guidTag,
1946                                                          LPVOID lpData,
1947                                                          DWORD cbSize,
1948                                                          DWORD dwFlags) {
1949   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1950   FIXME(ddraw, "(%p)->(%p,%p,%ld,%08lx\n", This, guidTag, lpData, cbSize, dwFlags);
1951   
1952   return DD_OK;
1953 }
1954
1955 static HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(LPDIRECTDRAWSURFACE4 iface,
1956                                                          REFGUID guidTag,
1957                                                          LPVOID lpBuffer,
1958                                                          LPDWORD lpcbBufferSize) {
1959   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1960   FIXME(ddraw, "(%p)->(%p,%p,%p)\n", This, guidTag, lpBuffer, lpcbBufferSize);
1961   
1962   return DD_OK;
1963 }
1964
1965 static HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(LPDIRECTDRAWSURFACE4 iface,
1966                                                           REFGUID guidTag)  {
1967   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1968   FIXME(ddraw, "(%p)->(%p)\n", This, guidTag);
1969   
1970   return DD_OK;
1971 }
1972
1973 static HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(LPDIRECTDRAWSURFACE4 iface,
1974                                                              LPDWORD lpValue)  {
1975   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1976   FIXME(ddraw, "(%p)->(%p)\n", This, lpValue);
1977   
1978   return DD_OK;
1979 }
1980
1981 static HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(LPDIRECTDRAWSURFACE4 iface) {
1982   ICOM_THIS(IDirectDrawSurface4Impl,iface);
1983   FIXME(ddraw, "(%p)\n", This);
1984   
1985   return DD_OK;
1986 }
1987
1988 static ICOM_VTABLE(IDirectDrawSurface4) dga_dds4vt = 
1989 {
1990         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1991         IDirectDrawSurface4Impl_QueryInterface,
1992         IDirectDrawSurface4Impl_AddRef,
1993         DGA_IDirectDrawSurface4Impl_Release,
1994         IDirectDrawSurface4Impl_AddAttachedSurface,
1995         IDirectDrawSurface4Impl_AddOverlayDirtyRect,
1996         IDirectDrawSurface4Impl_Blt,
1997         IDirectDrawSurface4Impl_BltBatch,
1998         IDirectDrawSurface4Impl_BltFast,
1999         IDirectDrawSurface4Impl_DeleteAttachedSurface,
2000         IDirectDrawSurface4Impl_EnumAttachedSurfaces,
2001         IDirectDrawSurface4Impl_EnumOverlayZOrders,
2002         DGA_IDirectDrawSurface4Impl_Flip,
2003         IDirectDrawSurface4Impl_GetAttachedSurface,
2004         IDirectDrawSurface4Impl_GetBltStatus,
2005         IDirectDrawSurface4Impl_GetCaps,
2006         IDirectDrawSurface4Impl_GetClipper,
2007         IDirectDrawSurface4Impl_GetColorKey,
2008         IDirectDrawSurface4Impl_GetDC,
2009         IDirectDrawSurface4Impl_GetFlipStatus,
2010         IDirectDrawSurface4Impl_GetOverlayPosition,
2011         IDirectDrawSurface4Impl_GetPalette,
2012         IDirectDrawSurface4Impl_GetPixelFormat,
2013         IDirectDrawSurface4Impl_GetSurfaceDesc,
2014         IDirectDrawSurface4Impl_Initialize,
2015         IDirectDrawSurface4Impl_IsLost,
2016         IDirectDrawSurface4Impl_Lock,
2017         IDirectDrawSurface4Impl_ReleaseDC,
2018         IDirectDrawSurface4Impl_Restore,
2019         IDirectDrawSurface4Impl_SetClipper,
2020         IDirectDrawSurface4Impl_SetColorKey,
2021         IDirectDrawSurface4Impl_SetOverlayPosition,
2022         DGA_IDirectDrawSurface4Impl_SetPalette,
2023         DGA_IDirectDrawSurface4Impl_Unlock,
2024         IDirectDrawSurface4Impl_UpdateOverlay,
2025         IDirectDrawSurface4Impl_UpdateOverlayDisplay,
2026         IDirectDrawSurface4Impl_UpdateOverlayZOrder,
2027         IDirectDrawSurface4Impl_GetDDInterface,
2028         IDirectDrawSurface4Impl_PageLock,
2029         IDirectDrawSurface4Impl_PageUnlock,
2030         IDirectDrawSurface4Impl_SetSurfaceDesc,
2031         IDirectDrawSurface4Impl_SetPrivateData,
2032         IDirectDrawSurface4Impl_GetPrivateData,
2033         IDirectDrawSurface4Impl_FreePrivateData,
2034         IDirectDrawSurface4Impl_GetUniquenessValue,
2035         IDirectDrawSurface4Impl_ChangeUniquenessValue
2036 };
2037
2038 static ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt = 
2039 {
2040         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2041         IDirectDrawSurface4Impl_QueryInterface,
2042         IDirectDrawSurface4Impl_AddRef,
2043         Xlib_IDirectDrawSurface4Impl_Release,
2044         IDirectDrawSurface4Impl_AddAttachedSurface,
2045         IDirectDrawSurface4Impl_AddOverlayDirtyRect,
2046         IDirectDrawSurface4Impl_Blt,
2047         IDirectDrawSurface4Impl_BltBatch,
2048         IDirectDrawSurface4Impl_BltFast,
2049         IDirectDrawSurface4Impl_DeleteAttachedSurface,
2050         IDirectDrawSurface4Impl_EnumAttachedSurfaces,
2051         IDirectDrawSurface4Impl_EnumOverlayZOrders,
2052         Xlib_IDirectDrawSurface4Impl_Flip,
2053         IDirectDrawSurface4Impl_GetAttachedSurface,
2054         IDirectDrawSurface4Impl_GetBltStatus,
2055         IDirectDrawSurface4Impl_GetCaps,
2056         IDirectDrawSurface4Impl_GetClipper,
2057         IDirectDrawSurface4Impl_GetColorKey,
2058         IDirectDrawSurface4Impl_GetDC,
2059         IDirectDrawSurface4Impl_GetFlipStatus,
2060         IDirectDrawSurface4Impl_GetOverlayPosition,
2061         IDirectDrawSurface4Impl_GetPalette,
2062         IDirectDrawSurface4Impl_GetPixelFormat,
2063         IDirectDrawSurface4Impl_GetSurfaceDesc,
2064         IDirectDrawSurface4Impl_Initialize,
2065         IDirectDrawSurface4Impl_IsLost,
2066         IDirectDrawSurface4Impl_Lock,
2067         IDirectDrawSurface4Impl_ReleaseDC,
2068         IDirectDrawSurface4Impl_Restore,
2069         IDirectDrawSurface4Impl_SetClipper,
2070         IDirectDrawSurface4Impl_SetColorKey,
2071         IDirectDrawSurface4Impl_SetOverlayPosition,
2072         Xlib_IDirectDrawSurface4Impl_SetPalette,
2073         Xlib_IDirectDrawSurface4Impl_Unlock,
2074         IDirectDrawSurface4Impl_UpdateOverlay,
2075         IDirectDrawSurface4Impl_UpdateOverlayDisplay,
2076         IDirectDrawSurface4Impl_UpdateOverlayZOrder,
2077         IDirectDrawSurface4Impl_GetDDInterface,
2078         IDirectDrawSurface4Impl_PageLock,
2079         IDirectDrawSurface4Impl_PageUnlock,
2080         IDirectDrawSurface4Impl_SetSurfaceDesc,
2081         IDirectDrawSurface4Impl_SetPrivateData,
2082         IDirectDrawSurface4Impl_GetPrivateData,
2083         IDirectDrawSurface4Impl_FreePrivateData,
2084         IDirectDrawSurface4Impl_GetUniquenessValue,
2085         IDirectDrawSurface4Impl_ChangeUniquenessValue
2086 };
2087
2088 /******************************************************************************
2089  *                      DirectDrawCreateClipper (DDRAW.7)
2090  */
2091 HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags,
2092                                         LPDIRECTDRAWCLIPPER *lplpDDClipper,
2093                                         LPUNKNOWN pUnkOuter)
2094 {
2095   IDirectDrawClipperImpl** ilplpDDClipper=(IDirectDrawClipperImpl**)lplpDDClipper;
2096   TRACE(ddraw, "(%08lx,%p,%p)\n", dwFlags, ilplpDDClipper, pUnkOuter);
2097
2098   *ilplpDDClipper = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
2099   (*ilplpDDClipper)->lpvtbl = &ddclipvt;
2100   (*ilplpDDClipper)->ref = 1;
2101
2102   return DD_OK;
2103 }
2104
2105 /******************************************************************************
2106  *                      IDirectDrawClipper
2107  */
2108 static HRESULT WINAPI IDirectDrawClipperImpl_SetHwnd(
2109         LPDIRECTDRAWCLIPPER iface,DWORD x,HWND hwnd
2110 ) {
2111         ICOM_THIS(IDirectDrawClipperImpl,iface);
2112         FIXME(ddraw,"(%p)->SetHwnd(0x%08lx,0x%08lx),stub!\n",This,x,(DWORD)hwnd);
2113         return DD_OK;
2114 }
2115
2116 static ULONG WINAPI IDirectDrawClipperImpl_Release(LPDIRECTDRAWCLIPPER iface) {
2117         ICOM_THIS(IDirectDrawClipperImpl,iface);
2118         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
2119
2120         This->ref--;
2121         if (This->ref)
2122                 return This->ref;
2123         HeapFree(GetProcessHeap(),0,This);
2124         return 0;
2125 }
2126
2127 static HRESULT WINAPI IDirectDrawClipperImpl_GetClipList(
2128         LPDIRECTDRAWCLIPPER iface,LPRECT rects,LPRGNDATA lprgn,LPDWORD hmm
2129 ) {
2130         ICOM_THIS(IDirectDrawClipperImpl,iface);
2131         FIXME(ddraw,"(%p,%p,%p,%p),stub!\n",This,rects,lprgn,hmm);
2132         if (hmm) *hmm=0;
2133         return DD_OK;
2134 }
2135
2136 static HRESULT WINAPI IDirectDrawClipperImpl_SetClipList(
2137         LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD hmm
2138 ) {
2139         ICOM_THIS(IDirectDrawClipperImpl,iface);
2140         FIXME(ddraw,"(%p,%p,%ld),stub!\n",This,lprgn,hmm);
2141         return DD_OK;
2142 }
2143
2144 static HRESULT WINAPI IDirectDrawClipperImpl_QueryInterface(
2145          LPDIRECTDRAWCLIPPER iface,
2146          REFIID riid,
2147          LPVOID* ppvObj )
2148 {
2149    ICOM_THIS(IDirectDrawClipperImpl,iface);
2150    FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,riid,ppvObj);
2151    return OLE_E_ENUM_NOMORE;
2152 }
2153
2154 static ULONG WINAPI IDirectDrawClipperImpl_AddRef( LPDIRECTDRAWCLIPPER iface )
2155 {
2156   ICOM_THIS(IDirectDrawClipperImpl,iface);
2157   TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
2158   return ++(This->ref);
2159 }
2160
2161 static HRESULT WINAPI IDirectDrawClipperImpl_GetHWnd(
2162          LPDIRECTDRAWCLIPPER iface,
2163          HWND* HWndPtr )
2164 {
2165    ICOM_THIS(IDirectDrawClipperImpl,iface);
2166    FIXME(ddraw,"(%p)->(%p),stub!\n",This,HWndPtr);
2167    return DD_OK;
2168 }
2169
2170 static HRESULT WINAPI IDirectDrawClipperImpl_Initialize(
2171          LPDIRECTDRAWCLIPPER iface,
2172          LPDIRECTDRAW lpDD,
2173          DWORD dwFlags )
2174 {
2175    ICOM_THIS(IDirectDrawClipperImpl,iface);
2176    FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n",This,lpDD,dwFlags);
2177    return DD_OK;
2178 }
2179
2180 static HRESULT WINAPI IDirectDrawClipperImpl_IsClipListChanged(
2181          LPDIRECTDRAWCLIPPER iface,
2182          BOOL* lpbChanged )
2183 {
2184    ICOM_THIS(IDirectDrawClipperImpl,iface);
2185    FIXME(ddraw,"(%p)->(%p),stub!\n",This,lpbChanged);
2186    return DD_OK;
2187 }
2188
2189 static ICOM_VTABLE(IDirectDrawClipper) ddclipvt = 
2190 {
2191         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2192         IDirectDrawClipperImpl_QueryInterface,
2193         IDirectDrawClipperImpl_AddRef,
2194         IDirectDrawClipperImpl_Release,
2195         IDirectDrawClipperImpl_GetClipList,
2196         IDirectDrawClipperImpl_GetHWnd,
2197         IDirectDrawClipperImpl_Initialize,
2198         IDirectDrawClipperImpl_IsClipListChanged,
2199         IDirectDrawClipperImpl_SetClipList,
2200         IDirectDrawClipperImpl_SetHwnd
2201 };
2202
2203
2204 /******************************************************************************
2205  *                      IDirectDrawPalette
2206  */
2207 static HRESULT WINAPI IDirectDrawPaletteImpl_GetEntries(
2208         LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
2209 ) {
2210         ICOM_THIS(IDirectDrawPaletteImpl,iface);
2211         int     i;
2212
2213         TRACE(ddraw,"(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",
2214               This,x,start,count,palent);
2215
2216         /* No palette created and not in depth-convertion mode -> BUG ! */
2217         if ((This->cm == None) &&
2218             (This->ddraw->d.palette_convert == NULL))
2219         {
2220                 FIXME(ddraw,"app tried to read colormap for non-palettized mode\n");
2221                 return DDERR_GENERIC;
2222         }
2223         for (i=0;i<count;i++) {
2224                 palent[i].peRed   = This->palents[start+i].peRed;
2225                 palent[i].peBlue  = This->palents[start+i].peBlue;
2226                 palent[i].peGreen = This->palents[start+i].peGreen;
2227                 palent[i].peFlags = This->palents[start+i].peFlags;
2228
2229         }
2230         return DD_OK;
2231 }
2232
2233 static HRESULT WINAPI Xlib_IDirectDrawPaletteImpl_SetEntries(
2234         LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
2235 ) {
2236         ICOM_THIS(IDirectDrawPaletteImpl,iface);
2237         XColor          xc;
2238         int             i;
2239
2240         TRACE(ddraw,"(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
2241                 This,x,start,count,palent
2242         );
2243         for (i=0;i<count;i++) {
2244                 xc.red = palent[i].peRed<<8;
2245                 xc.blue = palent[i].peBlue<<8;
2246                 xc.green = palent[i].peGreen<<8;
2247                 xc.flags = DoRed|DoBlue|DoGreen;
2248                 xc.pixel = start+i;
2249
2250                 if (This->cm)
2251                     TSXStoreColor(display,This->cm,&xc);
2252
2253                 This->palents[start+i].peRed = palent[i].peRed;
2254                 This->palents[start+i].peBlue = palent[i].peBlue;
2255                 This->palents[start+i].peGreen = palent[i].peGreen;
2256                 This->palents[start+i].peFlags = palent[i].peFlags;
2257         }
2258
2259         /* Now, if we are in 'depth conversion mode', update the screen palette */
2260         if (This->ddraw->d.palette_convert != NULL)
2261           This->ddraw->d.palette_convert(palent, This->screen_palents, start, count);
2262           
2263         return DD_OK;
2264 }
2265
2266 static HRESULT WINAPI DGA_IDirectDrawPaletteImpl_SetEntries(
2267         LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
2268 ) {
2269 #ifdef HAVE_LIBXXF86DGA
2270         ICOM_THIS(IDirectDrawPaletteImpl,iface);
2271         XColor          xc;
2272         Colormap        cm;
2273         int             i;
2274
2275         TRACE(ddraw,"(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
2276                 This,x,start,count,palent
2277         );
2278         if (!This->cm) /* should not happen */ {
2279                 FIXME(ddraw,"app tried to set colormap in non-palettized mode\n");
2280                 return DDERR_GENERIC;
2281         }
2282         /* FIXME: free colorcells instead of freeing whole map */
2283         cm = This->cm;
2284         This->cm = TSXCopyColormapAndFree(display,This->cm);
2285         TSXFreeColormap(display,cm);
2286
2287         for (i=0;i<count;i++) {
2288                 xc.red = palent[i].peRed<<8;
2289                 xc.blue = palent[i].peBlue<<8;
2290                 xc.green = palent[i].peGreen<<8;
2291                 xc.flags = DoRed|DoBlue|DoGreen;
2292                 xc.pixel = i+start;
2293
2294                 TSXStoreColor(display,This->cm,&xc);
2295
2296                 This->palents[start+i].peRed = palent[i].peRed;
2297                 This->palents[start+i].peBlue = palent[i].peBlue;
2298                 This->palents[start+i].peGreen = palent[i].peGreen;
2299                 This->palents[start+i].peFlags = palent[i].peFlags;
2300         }
2301         TSXF86DGAInstallColormap(display,DefaultScreen(display),This->cm);
2302         return DD_OK;
2303 #else /* defined(HAVE_LIBXXF86DGA) */
2304         return E_UNEXPECTED;
2305 #endif /* defined(HAVE_LIBXXF86DGA) */
2306 }
2307
2308 static ULONG WINAPI IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE iface) {
2309         ICOM_THIS(IDirectDrawPaletteImpl,iface);
2310         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
2311         if (!--(This->ref)) {
2312                 if (This->cm) {
2313                         TSXFreeColormap(display,This->cm);
2314                         This->cm = 0;
2315                 }
2316                 HeapFree(GetProcessHeap(),0,This);
2317                 return 0;
2318         }
2319         return This->ref;
2320 }
2321
2322 static ULONG WINAPI IDirectDrawPaletteImpl_AddRef(LPDIRECTDRAWPALETTE iface) {
2323         ICOM_THIS(IDirectDrawPaletteImpl,iface);
2324
2325         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
2326         return ++(This->ref);
2327 }
2328
2329 static HRESULT WINAPI IDirectDrawPaletteImpl_Initialize(
2330         LPDIRECTDRAWPALETTE iface,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
2331 ) {
2332         ICOM_THIS(IDirectDrawPaletteImpl,iface);
2333         TRACE(ddraw,"(%p)->(%p,%ld,%p)\n", This, ddraw, x, palent);
2334
2335         return DDERR_ALREADYINITIALIZED;
2336 }
2337
2338 static HRESULT WINAPI IDirectDrawPaletteImpl_GetCaps(
2339          LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps )
2340 {
2341    ICOM_THIS(IDirectDrawPaletteImpl,iface);
2342    FIXME( ddraw, "(%p)->(%p) stub.\n", This, lpdwCaps );
2343    return DD_OK;
2344
2345
2346 static HRESULT WINAPI IDirectDrawPaletteImpl_QueryInterface(
2347         LPDIRECTDRAWPALETTE iface,REFIID refiid,LPVOID *obj ) 
2348 {
2349   ICOM_THIS(IDirectDrawPaletteImpl,iface);
2350   char    xrefiid[50];
2351
2352   WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
2353   FIXME(ddraw,"(%p)->(%s,%p) stub.\n",This,xrefiid,obj);
2354
2355   return S_OK;
2356 }
2357
2358 static ICOM_VTABLE(IDirectDrawPalette) dga_ddpalvt = 
2359 {
2360         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2361         IDirectDrawPaletteImpl_QueryInterface,
2362         IDirectDrawPaletteImpl_AddRef,
2363         IDirectDrawPaletteImpl_Release,
2364         IDirectDrawPaletteImpl_GetCaps,
2365         IDirectDrawPaletteImpl_GetEntries,
2366         IDirectDrawPaletteImpl_Initialize,
2367         DGA_IDirectDrawPaletteImpl_SetEntries
2368 };
2369
2370 static ICOM_VTABLE(IDirectDrawPalette) xlib_ddpalvt = 
2371 {
2372         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2373         IDirectDrawPaletteImpl_QueryInterface,
2374         IDirectDrawPaletteImpl_AddRef,
2375         IDirectDrawPaletteImpl_Release,
2376         IDirectDrawPaletteImpl_GetCaps,
2377         IDirectDrawPaletteImpl_GetEntries,
2378         IDirectDrawPaletteImpl_Initialize,
2379         Xlib_IDirectDrawPaletteImpl_SetEntries
2380 };
2381
2382 /*******************************************************************************
2383  *                              IDirect3D
2384  */
2385 static HRESULT WINAPI IDirect3DImpl_QueryInterface(
2386         LPDIRECT3D iface,REFIID refiid,LPVOID *obj
2387 ) {
2388         ICOM_THIS(IDirect3DImpl,iface);
2389         /* FIXME: Not sure if this is correct */
2390         char    xrefiid[50];
2391
2392         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
2393         TRACE(ddraw,"(%p)->(%s,%p)\n",This,xrefiid,obj);
2394         if ((!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) ||
2395             (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) ||
2396             (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4)))) {
2397                 *obj = This->ddraw;
2398                 IDirect3D_AddRef(iface);
2399
2400                 TRACE(ddraw, "  Creating IDirectDrawX interface (%p)\n", *obj);
2401                 
2402                 return S_OK;
2403         }
2404         if ((!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) ||
2405             (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)))) {
2406                 *obj = This;
2407                 IDirect3D_AddRef(iface);
2408
2409                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
2410
2411                 return S_OK;
2412         }
2413         if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) {
2414                 IDirect3D2Impl*  d3d;
2415
2416                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
2417                 d3d->ref = 1;
2418                 d3d->ddraw = This->ddraw;
2419                 IDirect3D_AddRef(iface);
2420                 d3d->lpvtbl = &d3d2vt;
2421                 *obj = d3d;
2422
2423                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
2424
2425                 return S_OK;
2426         }
2427         FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",This,xrefiid);
2428         return OLE_E_ENUM_NOMORE;
2429 }
2430
2431 static ULONG WINAPI IDirect3DImpl_AddRef(LPDIRECT3D iface) {
2432         ICOM_THIS(IDirect3DImpl,iface);
2433         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
2434
2435         return ++(This->ref);
2436 }
2437
2438 static ULONG WINAPI IDirect3DImpl_Release(LPDIRECT3D iface)
2439 {
2440         ICOM_THIS(IDirect3DImpl,iface);
2441         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
2442
2443         if (!--(This->ref)) {
2444                 IDirectDraw2_Release((IDirectDraw2*)This->ddraw);
2445                 HeapFree(GetProcessHeap(),0,This);
2446                 return 0;
2447         }
2448         return This->ref;
2449 }
2450
2451 static HRESULT WINAPI IDirect3DImpl_Initialize(
2452          LPDIRECT3D iface, REFIID refiid )
2453 {
2454   ICOM_THIS(IDirect3DImpl,iface);
2455   /* FIXME: Not sure if this is correct */
2456   char    xrefiid[50];
2457
2458   WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
2459   FIXME(ddraw,"(%p)->(%s):stub.\n",This,xrefiid);
2460   
2461   return DDERR_ALREADYINITIALIZED;
2462 }
2463
2464 static HRESULT WINAPI IDirect3DImpl_EnumDevices(LPDIRECT3D iface,
2465                                             LPD3DENUMDEVICESCALLBACK cb,
2466                                             LPVOID context) {
2467   ICOM_THIS(IDirect3DImpl,iface);
2468   FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,cb,context);
2469
2470   /* Call functions defined in d3ddevices.c */
2471   if (!d3d_OpenGL_dx3(cb, context))
2472     return DD_OK;
2473
2474   return DD_OK;
2475 }
2476
2477 static HRESULT WINAPI IDirect3DImpl_CreateLight(LPDIRECT3D iface,
2478                                             LPDIRECT3DLIGHT *lplight,
2479                                             IUnknown *lpunk)
2480 {
2481   ICOM_THIS(IDirect3DImpl,iface);
2482   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lplight, lpunk);
2483   
2484   /* Call the creation function that is located in d3dlight.c */
2485   *lplight = d3dlight_create_dx3(This);
2486   
2487   return DD_OK;
2488 }
2489
2490 static HRESULT WINAPI IDirect3DImpl_CreateMaterial(LPDIRECT3D iface,
2491                                                LPDIRECT3DMATERIAL *lpmaterial,
2492                                                IUnknown *lpunk)
2493 {
2494   ICOM_THIS(IDirect3DImpl,iface);
2495   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpmaterial, lpunk);
2496
2497   /* Call the creation function that is located in d3dviewport.c */
2498   *lpmaterial = d3dmaterial_create(This);
2499   
2500   return DD_OK;
2501 }
2502
2503 static HRESULT WINAPI IDirect3DImpl_CreateViewport(LPDIRECT3D iface,
2504                                                LPDIRECT3DVIEWPORT *lpviewport,
2505                                                IUnknown *lpunk)
2506 {
2507   ICOM_THIS(IDirect3DImpl,iface);
2508   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpviewport, lpunk);
2509   
2510   /* Call the creation function that is located in d3dviewport.c */
2511   *lpviewport = d3dviewport_create(This);
2512   
2513   return DD_OK;
2514 }
2515
2516 static HRESULT WINAPI IDirect3DImpl_FindDevice(LPDIRECT3D iface,
2517                                            LPD3DFINDDEVICESEARCH lpfinddevsrc,
2518                                            LPD3DFINDDEVICERESULT lpfinddevrst)
2519 {
2520   ICOM_THIS(IDirect3DImpl,iface);
2521   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpfinddevsrc, lpfinddevrst);
2522   
2523   return DD_OK;
2524 }
2525
2526 static ICOM_VTABLE(IDirect3D) d3dvt = 
2527 {
2528         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2529         IDirect3DImpl_QueryInterface,
2530         IDirect3DImpl_AddRef,
2531         IDirect3DImpl_Release,
2532         IDirect3DImpl_Initialize,
2533         IDirect3DImpl_EnumDevices,
2534         IDirect3DImpl_CreateLight,
2535         IDirect3DImpl_CreateMaterial,
2536         IDirect3DImpl_CreateViewport,
2537         IDirect3DImpl_FindDevice
2538 };
2539
2540 /*******************************************************************************
2541  *                              IDirect3D2
2542  */
2543 static HRESULT WINAPI IDirect3D2Impl_QueryInterface(
2544         LPDIRECT3D2 iface,REFIID refiid,LPVOID *obj) {  
2545         ICOM_THIS(IDirect3D2Impl,iface);
2546
2547         /* FIXME: Not sure if this is correct */
2548         char    xrefiid[50];
2549
2550         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
2551         TRACE(ddraw,"(%p)->(%s,%p)\n",This,xrefiid,obj);
2552         if ((!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) ||
2553             (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) ||
2554             (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4)))) {
2555                 *obj = This->ddraw;
2556                 IDirect3D2_AddRef(iface);
2557
2558                 TRACE(ddraw, "  Creating IDirectDrawX interface (%p)\n", *obj);
2559                 
2560                 return S_OK;
2561         }
2562         if ((!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) ||
2563             (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)))) {
2564                 *obj = This;
2565                 IDirect3D2_AddRef(iface);
2566
2567                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
2568
2569                 return S_OK;
2570         }
2571         if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
2572                 IDirect3DImpl*  d3d;
2573
2574                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
2575                 d3d->ref = 1;
2576                 d3d->ddraw = This->ddraw;
2577                 IDirect3D2_AddRef(iface);
2578                 d3d->lpvtbl = &d3dvt;
2579                 *obj = d3d;
2580
2581                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
2582
2583                 return S_OK;
2584         }
2585         FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",This,xrefiid);
2586         return OLE_E_ENUM_NOMORE;
2587 }
2588
2589 static ULONG WINAPI IDirect3D2Impl_AddRef(LPDIRECT3D2 iface) {
2590         ICOM_THIS(IDirect3D2Impl,iface);
2591         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
2592
2593         return ++(This->ref);
2594 }
2595
2596 static ULONG WINAPI IDirect3D2Impl_Release(LPDIRECT3D2 iface) {
2597         ICOM_THIS(IDirect3D2Impl,iface);
2598         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
2599
2600         if (!--(This->ref)) {
2601                 IDirectDraw2_Release((IDirectDraw2*)This->ddraw);
2602                 HeapFree(GetProcessHeap(),0,This);
2603                 return 0;
2604         }
2605         return This->ref;
2606 }
2607
2608 static HRESULT WINAPI IDirect3D2Impl_EnumDevices(
2609         LPDIRECT3D2 iface,LPD3DENUMDEVICESCALLBACK cb, LPVOID context
2610 ) {
2611         ICOM_THIS(IDirect3D2Impl,iface);
2612         FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,cb,context);
2613
2614         /* Call functions defined in d3ddevices.c */
2615         if (!d3d_OpenGL(cb, context))
2616           return DD_OK;
2617
2618         return DD_OK;
2619 }
2620
2621 static HRESULT WINAPI IDirect3D2Impl_CreateLight(LPDIRECT3D2 iface,
2622                                              LPDIRECT3DLIGHT *lplight,
2623                                              IUnknown *lpunk)
2624 {
2625   ICOM_THIS(IDirect3D2Impl,iface);
2626   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lplight, lpunk);
2627
2628   /* Call the creation function that is located in d3dlight.c */
2629   *lplight = d3dlight_create(This);
2630   
2631         return DD_OK;
2632 }
2633
2634 static HRESULT WINAPI IDirect3D2Impl_CreateMaterial(LPDIRECT3D2 iface,
2635                                                 LPDIRECT3DMATERIAL2 *lpmaterial,
2636                                                 IUnknown *lpunk)
2637 {
2638   ICOM_THIS(IDirect3D2Impl,iface);
2639   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpmaterial, lpunk);
2640
2641   /* Call the creation function that is located in d3dviewport.c */
2642   *lpmaterial = d3dmaterial2_create(This);
2643
2644   return DD_OK;
2645 }
2646
2647 static HRESULT WINAPI IDirect3D2Impl_CreateViewport(LPDIRECT3D2 iface,
2648                                                 LPDIRECT3DVIEWPORT2 *lpviewport,
2649                                                 IUnknown *lpunk)
2650 {
2651   ICOM_THIS(IDirect3D2Impl,iface);
2652   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpviewport, lpunk);
2653   
2654   /* Call the creation function that is located in d3dviewport.c */
2655   *lpviewport = d3dviewport2_create(This);
2656   
2657   return DD_OK;
2658 }
2659
2660 static HRESULT WINAPI IDirect3D2Impl_FindDevice(LPDIRECT3D2 iface,
2661                                             LPD3DFINDDEVICESEARCH lpfinddevsrc,
2662                                             LPD3DFINDDEVICERESULT lpfinddevrst)
2663 {
2664   ICOM_THIS(IDirect3D2Impl,iface);
2665   TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpfinddevsrc, lpfinddevrst);
2666
2667   return DD_OK;
2668 }
2669
2670 static HRESULT WINAPI IDirect3D2Impl_CreateDevice(LPDIRECT3D2 iface,
2671                                               REFCLSID rguid,
2672                                               LPDIRECTDRAWSURFACE surface,
2673                                               LPDIRECT3DDEVICE2 *device)
2674 {
2675   ICOM_THIS(IDirect3D2Impl,iface);
2676   char  xbuf[50];
2677   
2678   WINE_StringFromCLSID(rguid,xbuf);
2679   FIXME(ddraw,"(%p)->(%s,%p,%p): stub\n",This,xbuf,surface,device);
2680
2681   if (is_OpenGL(rguid, (IDirectDrawSurfaceImpl*)surface, (IDirect3DDevice2Impl**)device, This)) {
2682     IDirect3D2_AddRef(iface);
2683     return DD_OK;
2684 }
2685
2686   return DDERR_INVALIDPARAMS;
2687 }
2688
2689 static ICOM_VTABLE(IDirect3D2) d3d2vt = 
2690 {
2691         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2692         IDirect3D2Impl_QueryInterface,
2693         IDirect3D2Impl_AddRef,
2694         IDirect3D2Impl_Release,
2695         IDirect3D2Impl_EnumDevices,
2696         IDirect3D2Impl_CreateLight,
2697         IDirect3D2Impl_CreateMaterial,
2698         IDirect3D2Impl_CreateViewport,
2699         IDirect3D2Impl_FindDevice,
2700         IDirect3D2Impl_CreateDevice
2701 };
2702
2703 /*******************************************************************************
2704  *                              IDirectDraw
2705  */
2706
2707 /* Used in conjunction with cbWndExtra for storage of the this ptr for the window.
2708  * Please adjust allocation in Xlib_DirectDrawCreate if you store more data here.
2709  */
2710 static INT ddrawXlibThisOffset = 0;
2711
2712 static HRESULT common_off_screen_CreateSurface(IDirectDraw2Impl* This,
2713                                                IDirectDrawSurfaceImpl* lpdsf)
2714 {
2715   int bpp;
2716   
2717   /* The surface was already allocated when entering in this function */
2718   TRACE(ddraw,"using system memory for a surface (%p)\n", lpdsf);
2719
2720   if (lpdsf->s.surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH) {
2721     /* This is a Z Buffer */
2722     TRACE(ddraw, "Creating Z-Buffer of %ld bit depth\n", lpdsf->s.surface_desc.x.dwZBufferBitDepth);
2723     bpp = lpdsf->s.surface_desc.x.dwZBufferBitDepth / 8;
2724   } else {
2725     /* This is a standard image */
2726     if (!(lpdsf->s.surface_desc.dwFlags & DDSD_PIXELFORMAT)) {
2727     /* No pixel format => use DirectDraw's format */
2728       lpdsf->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
2729       lpdsf->s.surface_desc.dwFlags |= DDSD_PIXELFORMAT;
2730   }
2731
2732     bpp = GET_BPP(lpdsf->s.surface_desc);
2733   }
2734
2735   if (lpdsf->s.surface_desc.dwFlags & DDSD_LPSURFACE) {
2736     /* The surface was preallocated : seems that we have nothing to do :-) */
2737     WARN(ddraw, "Creates a surface that is already allocated : assuming this is an application bug !\n");
2738   }
2739   
2740   lpdsf->s.surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE;
2741   lpdsf->s.surface_desc.y.lpSurface =
2742     (LPBYTE)HeapAlloc(GetProcessHeap(),0,lpdsf->s.surface_desc.dwWidth * lpdsf->s.surface_desc.dwHeight * bpp);
2743   lpdsf->s.surface_desc.lPitch = lpdsf->s.surface_desc.dwWidth * bpp;
2744   
2745   return DD_OK;
2746 }
2747
2748 static HRESULT WINAPI DGA_IDirectDraw2Impl_CreateSurface(
2749         LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
2750 ) {
2751 #ifdef HAVE_LIBXXF86DGA
2752         ICOM_THIS(IDirectDraw2Impl,iface);
2753         IDirectDrawSurfaceImpl** ilpdsf=(IDirectDrawSurfaceImpl**)lpdsf;
2754         int     i;
2755
2756         TRACE(ddraw, "(%p)->(%p,%p,%p)\n",This,lpddsd,ilpdsf,lpunk);
2757         if (TRACE_ON(ddraw)) {
2758           _dump_surface_desc(lpddsd);
2759         }
2760
2761         *ilpdsf = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurfaceImpl));
2762         IDirectDraw2_AddRef(iface);
2763         
2764         (*ilpdsf)->ref = 1;
2765         (*ilpdsf)->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface)*)&dga_dds4vt;
2766         (*ilpdsf)->s.ddraw = This;
2767         (*ilpdsf)->s.palette = NULL;
2768         (*ilpdsf)->t.dga.fb_height = -1; /* This is to have non-on screen surfaces freed */
2769
2770         /* Copy the surface description */
2771         (*ilpdsf)->s.surface_desc = *lpddsd;
2772         
2773         if (!(lpddsd->dwFlags & DDSD_WIDTH))
2774           (*ilpdsf)->s.surface_desc.dwWidth  = This->d.width;
2775         if (!(lpddsd->dwFlags & DDSD_HEIGHT))
2776           (*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
2777         (*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
2778         
2779         /* Check if this a 'primary surface' or not */
2780         if ((lpddsd->dwFlags & DDSD_CAPS) &&
2781             (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
2782
2783           /* This is THE primary surface => there is DGA-specific code */
2784           /* First, store the surface description */
2785           (*ilpdsf)->s.surface_desc = *lpddsd;
2786           
2787           /* Find a viewport */
2788                 for (i=0;i<32;i++)
2789                         if (!(This->e.dga.vpmask & (1<<i)))
2790                                 break;
2791                 TRACE(ddraw,"using viewport %d for a primary surface\n",i);
2792                 /* if i == 32 or maximum ... return error */
2793                 This->e.dga.vpmask|=(1<<i);
2794           (*ilpdsf)->s.surface_desc.y.lpSurface =
2795             This->e.dga.fb_addr+((i*This->e.dga.fb_height)*This->e.dga.fb_width*This->d.directdraw_pixelformat.x.dwRGBBitCount/8);
2796                 (*ilpdsf)->t.dga.fb_height = i*This->e.dga.fb_height;
2797           (*ilpdsf)->s.surface_desc.lPitch = This->e.dga.fb_width*This->d.directdraw_pixelformat.x.dwRGBBitCount/8;
2798           lpddsd->lPitch = (*ilpdsf)->s.surface_desc.lPitch;
2799
2800           /* Add flags if there were not present */
2801           (*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
2802           (*ilpdsf)->s.surface_desc.dwWidth = This->d.width;
2803           (*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
2804           TRACE(ddraw,"primary surface: dwWidth=%ld, dwHeight=%ld, lPitch=%ld\n",This->d.width,This->d.height,lpddsd->lPitch);
2805           /* We put our surface always in video memory */
2806           (*ilpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
2807           (*ilpdsf)->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
2808         (*ilpdsf)->s.backbuffer = NULL;
2809           
2810         if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
2811                 IDirectDrawSurface4Impl*        back;
2812
2813                 if (lpddsd->dwBackBufferCount>1)
2814                         FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
2815
2816             (*ilpdsf)->s.backbuffer = back =
2817               (IDirectDrawSurface4Impl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface4Impl));
2818                 IDirectDraw2_AddRef(iface);
2819                 back->ref = 1;
2820                 back->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface4)*)&dga_dds4vt;
2821                 for (i=0;i<32;i++)
2822                         if (!(This->e.dga.vpmask & (1<<i)))
2823                                 break;
2824                 TRACE(ddraw,"using viewport %d for backbuffer\n",i);
2825                 /* if i == 32 or maximum ... return error */
2826                 This->e.dga.vpmask|=(1<<i);
2827                 back->t.dga.fb_height = i*This->e.dga.fb_height;
2828
2829             /* Copy the surface description from the front buffer */
2830             back->s.surface_desc = (*ilpdsf)->s.surface_desc;
2831             /* Change the parameters that are not the same */
2832             back->s.surface_desc.y.lpSurface = This->e.dga.fb_addr+
2833               ((i*This->e.dga.fb_height)*This->e.dga.fb_width*This->d.directdraw_pixelformat.x.dwRGBBitCount/8);
2834                 back->s.ddraw = This;
2835                 back->s.backbuffer = NULL; /* does not have a backbuffer, it is
2836                                             * one! */
2837
2838             /* Add relevant info to front and back buffers */
2839             (*ilpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
2840             back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
2841             back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
2842             back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
2843             back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
2844           }
2845         } else {
2846           /* There is no DGA-specific code here...
2847              Go to the common surface creation function */
2848           return common_off_screen_CreateSurface(This, *ilpdsf);
2849         }
2850         
2851         return DD_OK;
2852 #else /* defined(HAVE_LIBXXF86DGA) */
2853         return E_UNEXPECTED;
2854 #endif /* defined(HAVE_LIBXXF86DGA) */
2855 }
2856
2857 #ifdef HAVE_LIBXXSHM
2858 /* Error handlers for Image creation */
2859 static int XShmErrorHandler(Display *dpy, XErrorEvent *event) {
2860   XShmErrorFlag = 1;
2861   return 0;
2862 }
2863
2864 static XImage *create_xshmimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf) {
2865   XImage *img;
2866   int (*WineXHandler)(Display *, XErrorEvent *);
2867
2868     img = TSXShmCreateImage(display,
2869                             DefaultVisualOfScreen(X11DRV_GetXScreen()),
2870                             This->d.pixmap_depth,
2871                             ZPixmap,
2872                             NULL,
2873                             &(lpdsf->t.xlib.shminfo),
2874                             lpdsf->s.surface_desc.dwWidth,
2875                             lpdsf->s.surface_desc.dwHeight);
2876     
2877   if (img == NULL) {
2878     MSG("Couldn't create XShm image (due to X11 remote display or failure).\nReverting to standard X images !\n");
2879     This->e.xlib.xshm_active = 0;
2880       return NULL;
2881   }
2882
2883     lpdsf->t.xlib.shminfo.shmid = shmget( IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777 );
2884     if (lpdsf->t.xlib.shminfo.shmid < 0) {
2885     MSG("Couldn't create shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
2886     This->e.xlib.xshm_active = 0;
2887       TSXDestroyImage(img);
2888       return NULL;
2889     }
2890
2891     lpdsf->t.xlib.shminfo.shmaddr = img->data = (char*)shmat(lpdsf->t.xlib.shminfo.shmid, 0, 0);
2892       
2893     if (img->data == (char *) -1) {
2894     MSG("Couldn't attach shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
2895     This->e.xlib.xshm_active = 0;
2896       TSXDestroyImage(img);
2897       shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
2898       return NULL;
2899     }
2900     lpdsf->t.xlib.shminfo.readOnly = False;
2901       
2902   /* This is where things start to get trickier....
2903      First, we flush the current X connections to be sure to catch all non-XShm related
2904      errors */
2905     TSXSync(display, False);
2906   /* Then we enter in the non-thread safe part of the tests */
2907   EnterCriticalSection( &X11DRV_CritSection );
2908   
2909   /* Reset the error flag, sets our new error handler and try to attach the surface */
2910   XShmErrorFlag = 0;
2911   WineXHandler = XSetErrorHandler(XShmErrorHandler);
2912   XShmAttach(display, &(lpdsf->t.xlib.shminfo));
2913   XSync(display, False);
2914
2915   /* Check the error flag */
2916   if (XShmErrorFlag) {
2917     /* An error occured */
2918     XFlush(display);
2919     XShmErrorFlag = 0;
2920     XDestroyImage(img);
2921     shmdt(lpdsf->t.xlib.shminfo.shmaddr);
2922     shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
2923     XSetErrorHandler(WineXHandler);
2924
2925     MSG("Couldn't attach shared memory segment to X server (due to X11 remote display or failure).\nReverting to standard X images !\n");
2926     This->e.xlib.xshm_active = 0;
2927     
2928     /* Leave the critical section */
2929     LeaveCriticalSection( &X11DRV_CritSection );
2930
2931     return NULL;
2932   }
2933
2934   /* Here, to be REALLY sure, I should do a XShmPutImage to check if this works,
2935      but it may be a bit overkill.... */
2936   XSetErrorHandler(WineXHandler);
2937   LeaveCriticalSection( &X11DRV_CritSection );
2938   
2939     shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
2940
2941     if (This->d.pixel_convert != NULL) {
2942       lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
2943                                                     lpdsf->s.surface_desc.dwWidth *
2944                                                     lpdsf->s.surface_desc.dwHeight *
2945                                                     (This->d.directdraw_pixelformat.x.dwRGBBitCount));
2946     } else {
2947     lpdsf->s.surface_desc.y.lpSurface = img->data;
2948     }
2949
2950   return img;
2951 }
2952 #endif /* HAVE_LIBXXSHM */
2953
2954 static XImage *create_ximage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf) {
2955   XImage *img = NULL;
2956   void *img_data;
2957
2958 #ifdef HAVE_LIBXXSHM
2959   if (This->e.xlib.xshm_active) {
2960     img = create_xshmimage(This, lpdsf);
2961   }
2962     
2963   if (img == NULL) {
2964 #endif
2965     /* Allocate surface memory */
2966     lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
2967                                                   lpdsf->s.surface_desc.dwWidth *
2968                                                   lpdsf->s.surface_desc.dwHeight *
2969                                                   (This->d.directdraw_pixelformat.x.dwRGBBitCount / 8));
2970     
2971     if (This->d.pixel_convert != NULL) {
2972       img_data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
2973                            lpdsf->s.surface_desc.dwWidth *
2974                            lpdsf->s.surface_desc.dwHeight *
2975                            (This->d.screen_pixelformat.x.dwRGBBitCount / 8));
2976     } else {
2977       img_data = lpdsf->s.surface_desc.y.lpSurface;
2978     }
2979       
2980     /* In this case, create an XImage */
2981     img =
2982       TSXCreateImage(display,
2983                      DefaultVisualOfScreen(X11DRV_GetXScreen()),
2984                      This->d.pixmap_depth,
2985                      ZPixmap,
2986                      0,
2987                      img_data,
2988                      lpdsf->s.surface_desc.dwWidth,
2989                      lpdsf->s.surface_desc.dwHeight,
2990                      32,
2991                      lpdsf->s.surface_desc.dwWidth * (This->d.screen_pixelformat.x.dwRGBBitCount / 8)
2992                      );
2993     
2994 #ifdef HAVE_LIBXXSHM
2995   }
2996 #endif
2997   if (This->d.pixel_convert != NULL) {
2998     lpdsf->s.surface_desc.lPitch = (This->d.directdraw_pixelformat.x.dwRGBBitCount / 8) * lpdsf->s.surface_desc.dwWidth;
2999   } else {
3000   lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
3001   }
3002   
3003   return img;
3004 }
3005
3006 static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
3007         LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
3008 ) {
3009         ICOM_THIS(IDirectDraw2Impl,iface);
3010         IDirectDrawSurfaceImpl** ilpdsf=(IDirectDrawSurfaceImpl**)lpdsf;
3011         TRACE(ddraw, "(%p)->CreateSurface(%p,%p,%p)\n",
3012                      This,lpddsd,ilpdsf,lpunk);
3013
3014         if (TRACE_ON(ddraw)) {
3015           _dump_surface_desc(lpddsd);
3016         }
3017
3018         *ilpdsf = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurfaceImpl));
3019
3020         IDirectDraw2_AddRef(iface);
3021         (*ilpdsf)->s.ddraw             = This;
3022         (*ilpdsf)->ref                 = 1;
3023         (*ilpdsf)->lpvtbl              = (ICOM_VTABLE(IDirectDrawSurface)*)&xlib_dds4vt;
3024         (*ilpdsf)->s.palette = NULL;
3025         (*ilpdsf)->t.xlib.image = NULL; /* This is for off-screen buffers */
3026
3027         /* Copy the surface description */
3028         (*ilpdsf)->s.surface_desc = *lpddsd;
3029         
3030         if (!(lpddsd->dwFlags & DDSD_WIDTH))
3031           (*ilpdsf)->s.surface_desc.dwWidth  = This->d.width;
3032         if (!(lpddsd->dwFlags & DDSD_HEIGHT))
3033           (*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
3034         (*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
3035
3036         /* Check if this a 'primary surface' or not */
3037   if ((lpddsd->dwFlags & DDSD_CAPS) && 
3038             (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
3039     XImage *img;
3040       
3041     TRACE(ddraw,"using standard XImage for a primary surface (%p)\n", *ilpdsf);
3042
3043     /* Create the XImage */
3044     img = create_ximage(This, (IDirectDrawSurface4Impl*) *ilpdsf);
3045     if (img == NULL)
3046       return DDERR_OUTOFMEMORY;
3047     (*ilpdsf)->t.xlib.image = img;
3048
3049           /* Add flags if there were not present */
3050           (*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
3051           (*ilpdsf)->s.surface_desc.dwWidth = This->d.width;
3052           (*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
3053           (*ilpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
3054           (*ilpdsf)->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
3055           (*ilpdsf)->s.backbuffer = NULL;
3056     
3057     /* Check for backbuffers */
3058         if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
3059                 IDirectDrawSurface4Impl*        back;
3060       XImage *img;
3061
3062                 if (lpddsd->dwBackBufferCount>1)
3063                         FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
3064
3065       (*ilpdsf)->s.backbuffer = back =
3066         (IDirectDrawSurface4Impl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface4Impl));
3067
3068       TRACE(ddraw,"allocated back-buffer (%p)\n", back);
3069       
3070                 IDirectDraw2_AddRef(iface);
3071                 back->s.ddraw = This;
3072
3073                 back->ref = 1;
3074                 back->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface4)*)&xlib_dds4vt;
3075             /* Copy the surface description from the front buffer */
3076             back->s.surface_desc = (*ilpdsf)->s.surface_desc;
3077
3078       /* Create the XImage */
3079       img = create_ximage(This, back);
3080       if (img == NULL)
3081         return DDERR_OUTOFMEMORY;
3082       back->t.xlib.image = img;
3083       
3084                 back->s.backbuffer = NULL; /* does not have a backbuffer, it is
3085                                             * one! */
3086
3087             /* Add relevant info to front and back buffers */
3088             (*ilpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
3089             back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
3090             back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
3091             back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
3092             back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
3093         }
3094         } else {
3095           /* There is no Xlib-specific code here...
3096              Go to the common surface creation function */
3097           return common_off_screen_CreateSurface(This, *ilpdsf);
3098   }
3099   
3100         return DD_OK;
3101 }
3102
3103 static HRESULT WINAPI IDirectDraw2Impl_DuplicateSurface(
3104         LPDIRECTDRAW2 iface,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
3105 ) {
3106         ICOM_THIS(IDirectDraw2Impl,iface);
3107         FIXME(ddraw,"(%p)->(%p,%p) simply copies\n",This,src,dst);
3108         *dst = src; /* FIXME */
3109         return DD_OK;
3110 }
3111
3112 /* 
3113  * The Xlib Implementation tries to use the passed hwnd as drawing window,
3114  * even when the approbiate bitmasks are not specified.
3115  */
3116 static HRESULT WINAPI IDirectDraw2Impl_SetCooperativeLevel(
3117         LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
3118 ) {
3119         ICOM_THIS(IDirectDraw2Impl,iface);
3120         int     i;
3121         const struct {
3122                 int     mask;
3123                 char    *name;
3124         } flagmap[] = {
3125 #define FE(x) { x, #x},
3126                 FE(DDSCL_FULLSCREEN)
3127                 FE(DDSCL_ALLOWREBOOT)
3128                 FE(DDSCL_NOWINDOWCHANGES)
3129                 FE(DDSCL_NORMAL)
3130                 FE(DDSCL_ALLOWMODEX)
3131                 FE(DDSCL_EXCLUSIVE)
3132                 FE(DDSCL_SETFOCUSWINDOW)
3133                 FE(DDSCL_SETDEVICEWINDOW)
3134                 FE(DDSCL_CREATEDEVICEWINDOW)
3135 #undef FE
3136         };
3137
3138         FIXME(ddraw,"(%p)->(%08lx,%08lx)\n",This,(DWORD)hwnd,cooplevel);
3139         if(TRACE_ON(ddraw)){
3140           dbg_decl_str(ddraw, 512);
3141           for (i=0;i<sizeof(flagmap)/sizeof(flagmap[0]);i++)
3142             if (flagmap[i].mask & cooplevel)
3143               dsprintf(ddraw, "%s ", flagmap[i].name);
3144           TRACE(ddraw," cooperative level %s\n", dbg_str(ddraw));
3145         }
3146         This->d.mainWindow = hwnd;
3147
3148         /* This will be overwritten in the case of Full Screen mode.
3149            Windowed games could work with that :-) */
3150         if (hwnd)
3151         {
3152             WND *tmpWnd = WIN_FindWndPtr(hwnd);
3153             This->d.drawable  = X11DRV_WND_GetXWindow(tmpWnd);
3154             WIN_ReleaseWndPtr(tmpWnd);
3155
3156             if( !This->d.drawable ) {
3157               This->d.drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
3158               WIN_ReleaseDesktop();
3159         }
3160             TRACE(ddraw, "Setting drawable to %ld\n", This->d.drawable);
3161         }
3162
3163         return DD_OK;
3164 }
3165
3166 /* Small helper to either use the cooperative window or create a new 
3167  * one (for mouse and keyboard input) and drawing in the Xlib implementation.
3168  */
3169 static void _common_IDirectDrawImpl_SetDisplayMode(IDirectDrawImpl* This) {
3170         RECT    rect;
3171
3172         /* Do not destroy the application supplied cooperative window */
3173         if (This->d.window && This->d.window != This->d.mainWindow) {
3174                 DestroyWindow(This->d.window);
3175                 This->d.window = 0;
3176         }
3177         /* Sanity check cooperative window before assigning it to drawing. */
3178         if (    IsWindow(This->d.mainWindow) &&
3179                 IsWindowVisible(This->d.mainWindow)
3180         ) {
3181                 GetWindowRect(This->d.mainWindow,&rect);
3182                 if (((rect.right-rect.left) >= This->d.width)   &&
3183                     ((rect.bottom-rect.top) >= This->d.height)
3184                 )
3185                         This->d.window = This->d.mainWindow;
3186         }
3187         /* ... failed, create new one. */
3188         if (!This->d.window) {
3189             This->d.window = CreateWindowExA(
3190                     0,
3191                     "WINE_DirectDraw",
3192                     "WINE_DirectDraw",
3193                     WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME,
3194                     0,0,
3195                     This->d.width,
3196                     This->d.height,
3197                     0,
3198                     0,
3199                     0,
3200                     NULL
3201             );
3202             /*Store THIS with the window. We'll use it in the window procedure*/
3203             SetWindowLongA(This->d.window,ddrawXlibThisOffset,(LONG)This);
3204             ShowWindow(This->d.window,TRUE);
3205             UpdateWindow(This->d.window);
3206         }
3207         SetFocus(This->d.window);
3208 }
3209
3210 static int _common_depth_to_pixelformat(DWORD depth, DDPIXELFORMAT *pixelformat, DDPIXELFORMAT *screen_pixelformat, int *pix_depth) {
3211   XVisualInfo *vi;
3212   XPixmapFormatValues *pf;
3213   XVisualInfo vt;
3214   int nvisuals, npixmap, i;
3215   int match = 0;
3216
3217   vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
3218   pf = XListPixmapFormats(display, &npixmap);
3219   
3220   for (i = 0; i < npixmap; i++) {
3221     if (pf[i].bits_per_pixel == depth) {
3222       int j;
3223       
3224       for (j = 0; j < nvisuals; j++) {
3225         if (vi[j].depth == pf[i].depth) {
3226           pixelformat->dwSize = sizeof(*pixelformat);
3227           if (depth == 8) {
3228             pixelformat->dwFlags = DDPF_PALETTEINDEXED8;
3229             pixelformat->y.dwRBitMask = 0;
3230             pixelformat->z.dwGBitMask = 0;
3231             pixelformat->xx.dwBBitMask = 0;
3232           } else {
3233             pixelformat->dwFlags = DDPF_RGB;
3234             pixelformat->y.dwRBitMask = vi[j].red_mask;
3235             pixelformat->z.dwGBitMask = vi[j].green_mask;
3236             pixelformat->xx.dwBBitMask = vi[j].blue_mask;
3237           }
3238           pixelformat->dwFourCC = 0;
3239           pixelformat->x.dwRGBBitCount = pf[i].bits_per_pixel;
3240           pixelformat->xy.dwRGBAlphaBitMask= 0;
3241
3242           *screen_pixelformat = *pixelformat;
3243           
3244           if (pix_depth != NULL)
3245             *pix_depth = vi[j].depth;
3246           
3247           match = 1;
3248           
3249           break;
3250         }
3251       }
3252
3253       if (j == nvisuals)
3254         ERR(ddraw, "No visual corresponding to pixmap format !\n");
3255     }
3256   }
3257
3258   if ((match == 0) && (depth == 8)) {
3259     pixelformat->dwSize = sizeof(*pixelformat);
3260     pixelformat->dwFlags = DDPF_PALETTEINDEXED8;
3261     pixelformat->dwFourCC = 0;
3262     pixelformat->x.dwRGBBitCount = 8;
3263     pixelformat->y.dwRBitMask = 0;
3264     pixelformat->z.dwGBitMask = 0;
3265     pixelformat->xx.dwBBitMask = 0;
3266     pixelformat->xy.dwRGBAlphaBitMask= 0;    
3267     
3268     /* In that case, find a visual to emulate the 8 bpp format */
3269     for (i = 0; i < npixmap; i++) {
3270       if (pf[i].bits_per_pixel >= depth) {
3271         int j;
3272         
3273         for (j = 0; j < nvisuals; j++) {
3274           if (vi[j].depth == pf[i].depth) {
3275             screen_pixelformat->dwSize = sizeof(*screen_pixelformat);
3276             screen_pixelformat->dwFlags = DDPF_RGB;
3277             screen_pixelformat->dwFourCC = 0;
3278             screen_pixelformat->x.dwRGBBitCount = pf[i].bits_per_pixel;
3279             screen_pixelformat->y.dwRBitMask = vi[j].red_mask;
3280             screen_pixelformat->z.dwGBitMask = vi[j].green_mask;
3281             screen_pixelformat->xx.dwBBitMask = vi[j].blue_mask;
3282             screen_pixelformat->xy.dwRGBAlphaBitMask= 0;
3283
3284             if (pix_depth != NULL)
3285               *pix_depth = vi[j].depth;
3286             
3287             match = 2;
3288             
3289             break;
3290           }
3291         }
3292         
3293         if (j == nvisuals)
3294           ERR(ddraw, "No visual corresponding to pixmap format !\n");
3295       }
3296     }
3297   }
3298   
3299   TSXFree(vi);
3300   TSXFree(pf);
3301
3302   return match;
3303 }
3304
3305 static HRESULT WINAPI DGA_IDirectDrawImpl_SetDisplayMode(
3306         LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
3307 ) {
3308 #ifdef HAVE_LIBXXF86DGA
3309         ICOM_THIS(IDirectDrawImpl,iface);
3310         int     i,mode_count;
3311
3312         TRACE(ddraw, "(%p)->(%ld,%ld,%ld)\n", This, width, height, depth);
3313
3314         /* We hope getting the asked for depth */
3315         if (_common_depth_to_pixelformat(depth, &(This->d.directdraw_pixelformat), &(This->d.screen_pixelformat), NULL) != 1) {
3316           /* I.e. no visual found or emulated */
3317                 ERR(ddraw,"(w=%ld,h=%ld,d=%ld), unsupported depth!\n",width,height,depth);
3318                 return DDERR_UNSUPPORTEDMODE;
3319         }
3320         
3321         if (This->d.width < width) {
3322                 ERR(ddraw,"SetDisplayMode(w=%ld,h=%ld,d=%ld), width %ld exceeds framebuffer width %ld\n",width,height,depth,width,This->d.width);
3323                 return DDERR_UNSUPPORTEDMODE;
3324         }
3325         This->d.width   = width;
3326         This->d.height  = height;
3327
3328         /* adjust fb_height, so we don't overlap */
3329         if (This->e.dga.fb_height < height)
3330                 This->e.dga.fb_height = height;
3331         _common_IDirectDrawImpl_SetDisplayMode(This);
3332
3333 #ifdef HAVE_LIBXXF86VM
3334         {
3335             XF86VidModeModeInfo **all_modes, *vidmode = NULL;
3336             XF86VidModeModeLine mod_tmp;
3337             /* int dotclock_tmp; */
3338
3339             /* save original video mode and set fullscreen if available*/
3340             orig_mode = (XF86VidModeModeInfo *) malloc (sizeof(XF86VidModeModeInfo));  
3341             TSXF86VidModeGetModeLine(display, DefaultScreen(display), &orig_mode->dotclock, &mod_tmp);
3342             orig_mode->hdisplay = mod_tmp.hdisplay; 
3343             orig_mode->hsyncstart = mod_tmp.hsyncstart;
3344             orig_mode->hsyncend = mod_tmp.hsyncend; 
3345             orig_mode->htotal = mod_tmp.htotal;
3346             orig_mode->vdisplay = mod_tmp.vdisplay; 
3347             orig_mode->vsyncstart = mod_tmp.vsyncstart;
3348             orig_mode->vsyncend = mod_tmp.vsyncend; 
3349             orig_mode->vtotal = mod_tmp.vtotal;
3350             orig_mode->flags = mod_tmp.flags; 
3351             orig_mode->private = mod_tmp.private;
3352             
3353             TSXF86VidModeGetAllModeLines(display,DefaultScreen(display),&mode_count,&all_modes);
3354             for (i=0;i<mode_count;i++)
3355             {
3356                 if (all_modes[i]->hdisplay == width && all_modes[i]->vdisplay == height)
3357                 {
3358                     vidmode = (XF86VidModeModeInfo *)malloc(sizeof(XF86VidModeModeInfo));
3359                     *vidmode = *(all_modes[i]);
3360                     break;
3361                 } else
3362                     TSXFree(all_modes[i]->private);
3363             }
3364             for (i++;i<mode_count;i++) TSXFree(all_modes[i]->private);
3365             TSXFree(all_modes);
3366
3367             if (!vidmode)
3368                 WARN(ddraw, "Fullscreen mode not available!\n");
3369
3370             if (vidmode)
3371               {
3372                 TRACE(ddraw,"SwitchToMode(%dx%d)\n",vidmode->hdisplay,vidmode->vdisplay);
3373                 TSXF86VidModeSwitchToMode(display, DefaultScreen(display), vidmode);
3374 #if 0 /* This messes up my screen (XF86_Mach64, 3.3.2.3a) for some reason, and should now be unnecessary */
3375                 TSXF86VidModeSetViewPort(display, DefaultScreen(display), 0, 0);
3376 #endif
3377               }
3378         }
3379 #endif
3380
3381         /* FIXME: this function OVERWRITES several signal handlers. 
3382          * can we save them? and restore them later? In a way that
3383          * it works for the library too?
3384          */
3385         TSXF86DGADirectVideo(display,DefaultScreen(display),XF86DGADirectGraphics);
3386 #ifdef DIABLO_HACK
3387         TSXF86DGASetViewPort(display,DefaultScreen(display),0,This->e.dga.fb_height);
3388 #else
3389         TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
3390 #endif
3391
3392 #ifdef RESTORE_SIGNALS
3393         SIGNAL_InitHandlers();
3394 #endif
3395         return DD_OK;
3396 #else /* defined(HAVE_LIBXXF86DGA) */
3397         return E_UNEXPECTED;
3398 #endif /* defined(HAVE_LIBXXF86DGA) */
3399 }
3400
3401 /* *************************************
3402       16 / 15 bpp to palettized 8 bpp
3403    ************************************* */
3404 static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
3405   unsigned char  *c_src = (unsigned char  *) src;
3406   unsigned short *c_dst = (unsigned short *) dst;
3407   int x, y;
3408
3409   if (palette != NULL) {
3410     unsigned short *pal = (unsigned short *) palette->screen_palents;
3411
3412     for (y = 0; y < height; y++) {
3413       for (x = 0; x < width; x++) {
3414         c_dst[x + y * width] = pal[c_src[x + y * pitch]];
3415       }
3416     }
3417   } else {
3418     WARN(ddraw, "No palette set...\n");
3419     memset(dst, 0, width * height * 2);
3420   }
3421 }
3422 static void palette_convert_16_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
3423   int i;
3424   unsigned short *pal = (unsigned short *) screen_palette;
3425   
3426   for (i = 0; i < count; i++)
3427     pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
3428                       ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
3429                       ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
3430 }
3431 static void palette_convert_15_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
3432   int i;
3433   unsigned short *pal = (unsigned short *) screen_palette;
3434   
3435   for (i = 0; i < count; i++)
3436     pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) |
3437                       ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
3438                       ((((unsigned short) palent[i].peGreen) & 0xF8) << 2));
3439 }
3440
3441 /* *************************************
3442       24 / 32 bpp to palettized 8 bpp
3443    ************************************* */
3444 static void pixel_convert_32_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
3445   unsigned char  *c_src = (unsigned char  *) src;
3446   unsigned int *c_dst = (unsigned int *) dst;
3447   int x, y;
3448
3449   if (palette != NULL) {
3450     unsigned int *pal = (unsigned int *) palette->screen_palents;
3451     
3452     for (y = 0; y < height; y++) {
3453       for (x = 0; x < width; x++) {
3454         c_dst[x + y * width] = pal[c_src[x + y * pitch]];
3455       }
3456     }
3457   } else {
3458     WARN(ddraw, "No palette set...\n");
3459     memset(dst, 0, width * height * 4);
3460   }
3461 }
3462 static void palette_convert_24_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
3463   int i;
3464   unsigned int *pal = (unsigned int *) screen_palette;
3465   
3466   for (i = 0; i < count; i++)
3467     pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) |
3468                       (((unsigned int) palent[i].peGreen) << 8) |
3469                       ((unsigned int) palent[i].peBlue));
3470 }
3471
3472 static HRESULT WINAPI Xlib_IDirectDrawImpl_SetDisplayMode(
3473         LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
3474 ) {
3475         ICOM_THIS(IDirectDrawImpl,iface);
3476         char    buf[200];
3477         WND *tmpWnd;
3478
3479         TRACE(ddraw, "(%p)->SetDisplayMode(%ld,%ld,%ld)\n",
3480                       This, width, height, depth);
3481
3482         switch (_common_depth_to_pixelformat(depth,
3483                                              &(This->d.directdraw_pixelformat),
3484                                              &(This->d.screen_pixelformat),
3485                                              &(This->d.pixmap_depth))) {
3486         case 0:
3487           sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
3488           MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
3489           return DDERR_UNSUPPORTEDMODE;
3490
3491         case 1:
3492           /* No convertion */
3493           This->d.pixel_convert = NULL;
3494           This->d.palette_convert = NULL;
3495           break;
3496
3497         case 2: {
3498           int found = 0;
3499
3500           WARN(ddraw, "Warning : running in depth-convertion mode. Should run using a %ld depth for optimal performances.\n", depth);
3501           
3502           /* Set the depth convertion routines */
3503           switch (This->d.screen_pixelformat.x.dwRGBBitCount) {
3504           case 16:
3505             if ((This->d.screen_pixelformat.y.dwRBitMask == 0xF800) &&
3506                 (This->d.screen_pixelformat.z.dwGBitMask == 0x07E0) &&
3507                 (This->d.screen_pixelformat.xx.dwBBitMask == 0x001F)) {
3508               /* 16 bpp */
3509               found = 1;
3510               
3511               This->d.pixel_convert = pixel_convert_16_to_8;
3512               This->d.palette_convert = palette_convert_16_to_8;
3513             } else if ((This->d.screen_pixelformat.y.dwRBitMask == 0x7C00) &&
3514                        (This->d.screen_pixelformat.z.dwGBitMask == 0x03E0) &&
3515                        (This->d.screen_pixelformat.xx.dwBBitMask == 0x001F)) {
3516               /* 15 bpp */
3517               found = 1;
3518
3519               This->d.pixel_convert = pixel_convert_16_to_8;
3520               This->d.palette_convert = palette_convert_15_to_8;
3521             }
3522             break;
3523             
3524           case 24:
3525             /* Not handled yet :/ */
3526             found = 0;
3527                         break;
3528             
3529           case 32:
3530             if ((This->d.screen_pixelformat.y.dwRBitMask ==  0xFF0000) &&
3531                 (This->d.screen_pixelformat.z.dwGBitMask ==  0x00FF00) &&
3532                 (This->d.screen_pixelformat.xx.dwBBitMask == 0x0000FF)) {
3533               /* 24 bpp */
3534               found = 1;
3535
3536               This->d.pixel_convert = pixel_convert_32_to_8;
3537               This->d.palette_convert = palette_convert_24_to_8;
3538             }
3539               break;
3540           }
3541
3542           if (!found) {
3543                 sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
3544                 MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
3545                 return DDERR_UNSUPPORTEDMODE;
3546           }
3547         } break;
3548         }
3549
3550         This->d.width   = width;
3551         This->d.height  = height;
3552
3553         _common_IDirectDrawImpl_SetDisplayMode(This);
3554
3555         tmpWnd = WIN_FindWndPtr(This->d.window);
3556         This->d.paintable = 1;
3557         This->d.drawable  = ((X11DRV_WND_DATA *) tmpWnd->pDriverData)->window;
3558         WIN_ReleaseWndPtr(tmpWnd);
3559
3560         /* We don't have a context for this window. Host off the desktop */
3561         if( !This->d.drawable )
3562         {
3563            This->d.drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
3564             WIN_ReleaseDesktop();
3565         }
3566         TRACE(ddraw, "Setting drawable to %ld\n", This->d.drawable);
3567
3568         return DD_OK;
3569 }
3570
3571 static HRESULT WINAPI DGA_IDirectDraw2Impl_GetCaps(
3572         LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
3573 ) {
3574 #ifdef HAVE_LIBXXF86DGA
3575         ICOM_THIS(IDirectDraw2Impl,iface);
3576         TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
3577         caps1->dwVidMemTotal = This->e.dga.fb_memsize;
3578         caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);              /* we can do anything */
3579         caps1->ddsCaps.dwCaps = 0xffffffff;     /* we can do anything */
3580         if (caps2) {
3581                 caps2->dwVidMemTotal = This->e.dga.fb_memsize;
3582                 caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);              /* we can do anything */
3583                 caps2->ddsCaps.dwCaps = 0xffffffff;     /* we can do anything */
3584         }
3585         return DD_OK;
3586 #else /* defined(HAVE_LIBXXF86DGA) */
3587         return E_UNEXPECTED;
3588 #endif /* defined(HAVE_LIBXXF86DGA) */
3589 }
3590
3591 static void fill_caps(LPDDCAPS caps) {
3592   /* This function tries to fill the capabilities of Wine's DDraw implementation.
3593      Need to be fixed, though.. */
3594   if (caps == NULL)
3595     return;
3596
3597   caps->dwSize = sizeof(*caps);
3598   caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL |
3599     DDCAPS_CANBLTSYSMEM |  DDCAPS_COLORKEY | DDCAPS_PALETTE;
3600   caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
3601   caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
3602   caps->dwFXCaps = 0;
3603   caps->dwFXAlphaCaps = 0;
3604   caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
3605   caps->dwSVCaps = 0;
3606   caps->dwZBufferBitDepths = DDBD_16;
3607   /* I put here 8 Mo so that D3D applications will believe they have enough memory
3608      to put textures in video memory.
3609      BTW, is this only frame buffer memory or also texture memory (for Voodoo boards
3610      for example) ? */
3611   caps->dwVidMemTotal = 8192 * 1024;
3612   caps->dwVidMemFree = 8192 * 1024;
3613   /* These are all the supported capabilities of the surfaces */
3614   caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
3615     DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
3616       DDSCAPS_OVERLAY | DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
3617         DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
3618 #ifdef HAVE_MESAGL
3619   caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
3620   caps->dwCaps2 |=  DDCAPS2_NO2DDURING3DSCENE;
3621   caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
3622 #endif
3623 }
3624
3625 static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetCaps(
3626         LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
3627 )  {
3628         ICOM_THIS(IDirectDraw2Impl,iface);
3629         TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
3630
3631         /* Put the same caps for the two capabilities */
3632         fill_caps(caps1);
3633         fill_caps(caps2);
3634
3635         return DD_OK;
3636 }
3637
3638 static HRESULT WINAPI IDirectDraw2Impl_CreateClipper(
3639         LPDIRECTDRAW2 iface,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
3640 ) {
3641         ICOM_THIS(IDirectDraw2Impl,iface);
3642         IDirectDrawClipperImpl** ilpddclip=(IDirectDrawClipperImpl**)lpddclip;
3643         FIXME(ddraw,"(%p)->(%08lx,%p,%p),stub!\n",
3644                 This,x,ilpddclip,lpunk
3645         );
3646         *ilpddclip = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
3647         (*ilpddclip)->ref = 1;
3648         (*ilpddclip)->lpvtbl = &ddclipvt;
3649         return DD_OK;
3650 }
3651
3652 static HRESULT WINAPI common_IDirectDraw2Impl_CreatePalette(
3653         IDirectDraw2Impl* This,DWORD dwFlags,LPPALETTEENTRY palent,IDirectDrawPaletteImpl **lpddpal,LPUNKNOWN lpunk,int *psize
3654 ) {
3655         int size = 0;
3656           
3657         if (TRACE_ON(ddraw))
3658           _dump_paletteformat(dwFlags);
3659         
3660         *lpddpal = (IDirectDrawPaletteImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPaletteImpl));
3661         if (*lpddpal == NULL) return E_OUTOFMEMORY;
3662         (*lpddpal)->ref = 1;
3663         (*lpddpal)->ddraw = (IDirectDrawImpl*)This;
3664         (*lpddpal)->installed = 0;
3665
3666           if (dwFlags & DDPCAPS_1BIT)
3667             size = 2;
3668           else if (dwFlags & DDPCAPS_2BIT)
3669             size = 4;
3670           else if (dwFlags & DDPCAPS_4BIT)
3671             size = 16;
3672           else if (dwFlags & DDPCAPS_8BIT)
3673             size = 256;
3674           else
3675             ERR(ddraw, "unhandled palette format\n");
3676         *psize = size;
3677         
3678         if (palent)
3679         {
3680           /* Now, if we are in 'depth conversion mode', create the screen palette */
3681           if (This->d.palette_convert != NULL)      
3682             This->d.palette_convert(palent, (*lpddpal)->screen_palents, 0, size);
3683
3684           memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
3685         } else if (This->d.palette_convert != NULL) {
3686           /* In that case, put all 0xFF */
3687           memset((*lpddpal)->screen_palents, 0xFF, 256 * sizeof(int));
3688         }
3689         
3690         return DD_OK;
3691 }
3692
3693 static HRESULT WINAPI DGA_IDirectDraw2Impl_CreatePalette(
3694         LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
3695 ) {
3696         ICOM_THIS(IDirectDraw2Impl,iface);
3697         IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
3698         HRESULT res;
3699         int xsize = 0,i;
3700
3701         TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
3702         res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
3703         if (res != 0) return res;
3704         (*ilpddpal)->lpvtbl = &dga_ddpalvt;
3705         if (This->d.directdraw_pixelformat.x.dwRGBBitCount<=8) {
3706                 (*ilpddpal)->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
3707         } else {
3708                 FIXME(ddraw,"why are we doing CreatePalette in hi/truecolor?\n");
3709                 (*ilpddpal)->cm = 0;
3710         }
3711         if (((*ilpddpal)->cm)&&xsize) {
3712           for (i=0;i<xsize;i++) {
3713                   XColor xc;
3714
3715                   xc.red = (*ilpddpal)->palents[i].peRed<<8;
3716                   xc.blue = (*ilpddpal)->palents[i].peBlue<<8;
3717                   xc.green = (*ilpddpal)->palents[i].peGreen<<8;
3718                   xc.flags = DoRed|DoBlue|DoGreen;
3719                   xc.pixel = i;
3720                   TSXStoreColor(display,(*ilpddpal)->cm,&xc);
3721           }
3722         }
3723         return DD_OK;
3724 }
3725
3726 static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreatePalette(
3727         LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
3728 ) {
3729         ICOM_THIS(IDirectDraw2Impl,iface);
3730         IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
3731         int xsize;
3732         HRESULT res;
3733
3734         TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
3735         res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
3736         if (res != 0) return res;
3737         (*ilpddpal)->lpvtbl = &xlib_ddpalvt;
3738         return DD_OK;
3739 }
3740
3741 static HRESULT WINAPI DGA_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
3742 #ifdef HAVE_LIBXXF86DGA
3743         ICOM_THIS(IDirectDraw2Impl,iface);
3744         TRACE(ddraw, "(%p)->()\n",This);
3745         Sleep(1000);
3746         TSXF86DGADirectVideo(display,DefaultScreen(display),0);
3747 #ifdef RESTORE_SIGNALS
3748         SIGNAL_InitHandlers();
3749 #endif
3750         return DD_OK;
3751 #else /* defined(HAVE_LIBXXF86DGA) */
3752         return E_UNEXPECTED;
3753 #endif
3754 }
3755
3756 static HRESULT WINAPI Xlib_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
3757         ICOM_THIS(IDirectDraw2Impl,iface);
3758         TRACE(ddraw, "(%p)->RestoreDisplayMode()\n", This);
3759         Sleep(1000);
3760         return DD_OK;
3761 }
3762
3763 static HRESULT WINAPI IDirectDraw2Impl_WaitForVerticalBlank(
3764         LPDIRECTDRAW2 iface,DWORD x,HANDLE h
3765 ) {
3766         ICOM_THIS(IDirectDraw2Impl,iface);
3767         TRACE(ddraw,"(%p)->(0x%08lx,0x%08x)\n",This,x,h);
3768         return DD_OK;
3769 }
3770
3771 static ULONG WINAPI IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 iface) {
3772         ICOM_THIS(IDirectDraw2Impl,iface);
3773         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
3774
3775         return ++(This->ref);
3776 }
3777
3778 static ULONG WINAPI DGA_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
3779         ICOM_THIS(IDirectDraw2Impl,iface);
3780         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
3781
3782 #ifdef HAVE_LIBXXF86DGA
3783         if (!--(This->ref)) {
3784                 TSXF86DGADirectVideo(display,DefaultScreen(display),0);
3785                 if (This->d.window && (This->d.mainWindow != This->d.window))
3786                         DestroyWindow(This->d.window);
3787 #ifdef HAVE_LIBXXF86VM
3788                 if (orig_mode) {
3789                         TSXF86VidModeSwitchToMode(
3790                                 display,
3791                                 DefaultScreen(display),
3792                                 orig_mode);
3793                         if (orig_mode->privsize)
3794                                 TSXFree(orig_mode->private);            
3795                         free(orig_mode);
3796                         orig_mode = NULL;
3797                 }
3798 #endif
3799                 
3800 #ifdef RESTORE_SIGNALS
3801                 SIGNAL_InitHandlers();
3802 #endif
3803                 HeapFree(GetProcessHeap(),0,This);
3804                 return 0;
3805         }
3806 #endif /* defined(HAVE_LIBXXF86DGA) */
3807         return This->ref;
3808 }
3809
3810 static ULONG WINAPI Xlib_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
3811         ICOM_THIS(IDirectDraw2Impl,iface);
3812         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
3813
3814         if (!--(This->ref)) {
3815                 if (This->d.window && (This->d.mainWindow != This->d.window))
3816                         DestroyWindow(This->d.window);
3817                 HeapFree(GetProcessHeap(),0,This);
3818                 return 0;
3819         }
3820         /* FIXME: destroy window ... */
3821         return This->ref;
3822 }
3823
3824 static HRESULT WINAPI DGA_IDirectDraw2Impl_QueryInterface(
3825         LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
3826 ) {
3827         ICOM_THIS(IDirectDraw2Impl,iface);
3828         char    xrefiid[50];
3829
3830         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
3831         TRACE(ddraw,"(%p)->(%s,%p)\n",This,xrefiid,obj);
3832         if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
3833                 *obj = This;
3834                 IDirectDraw2_AddRef(iface);
3835
3836                 TRACE(ddraw, "  Creating IUnknown interface (%p)\n", *obj);
3837                 
3838                 return S_OK;
3839         }
3840         if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
3841                 This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&dga_ddvt;
3842                 IDirectDraw2_AddRef(iface);
3843                 *obj = This;
3844
3845                 TRACE(ddraw, "  Creating IDirectDraw interface (%p)\n", *obj);
3846                 
3847                 return S_OK;
3848         }
3849         if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
3850                 This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&dga_dd2vt;
3851                 IDirectDraw2_AddRef(iface);
3852                 *obj = This;
3853
3854                 TRACE(ddraw, "  Creating IDirectDraw2 interface (%p)\n", *obj);
3855
3856                 return S_OK;
3857         }
3858         if (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4))) {
3859                 This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&dga_dd4vt;
3860                 IDirectDraw2_AddRef(iface);
3861                 *obj = This;
3862
3863                 TRACE(ddraw, "  Creating IDirectDraw4 interface (%p)\n", *obj);
3864
3865                 return S_OK;
3866         }
3867         if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
3868                 IDirect3DImpl* d3d;
3869
3870                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
3871                 d3d->ref = 1;
3872                 d3d->ddraw = (IDirectDrawImpl*)This;
3873                 IDirectDraw2_AddRef(iface);
3874                 d3d->lpvtbl = &d3dvt;
3875                 *obj = d3d;
3876
3877                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
3878                 
3879                 return S_OK;
3880         }
3881         if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) {
3882                 IDirect3D2Impl* d3d;
3883
3884                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
3885                 d3d->ref = 1;
3886                 d3d->ddraw = (IDirectDrawImpl*)This;
3887                 IDirectDraw2_AddRef(iface);
3888                 d3d->lpvtbl = &d3d2vt;
3889                 *obj = d3d;
3890
3891                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
3892                 
3893                 return S_OK;
3894         }
3895         WARN(ddraw,"(%p):interface for IID %s _NOT_ found!\n",This,xrefiid);
3896         return OLE_E_ENUM_NOMORE;
3897 }
3898
3899 static HRESULT WINAPI Xlib_IDirectDraw2Impl_QueryInterface(
3900         LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
3901 ) {
3902         ICOM_THIS(IDirectDraw2Impl,iface);
3903         char    xrefiid[50];
3904
3905         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
3906         TRACE(ddraw,"(%p)->(%s,%p)\n",This,xrefiid,obj);
3907         if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
3908                 *obj = This;
3909                 IDirectDraw2_AddRef(iface);
3910
3911                 TRACE(ddraw, "  Creating IUnknown interface (%p)\n", *obj);
3912                 
3913                 return S_OK;
3914         }
3915         if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
3916                 This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&xlib_ddvt;
3917                 IDirectDraw2_AddRef(iface);
3918                 *obj = This;
3919
3920                 TRACE(ddraw, "  Creating IDirectDraw interface (%p)\n", *obj);
3921                 
3922                 return S_OK;
3923         }
3924         if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
3925                 This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&xlib_dd2vt;
3926                 IDirectDraw2_AddRef(iface);
3927                 *obj = This;
3928
3929                 TRACE(ddraw, "  Creating IDirectDraw2 interface (%p)\n", *obj);
3930                 
3931                 return S_OK;
3932         }
3933         if (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4))) {
3934                 This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&xlib_dd4vt;
3935                 IDirectDraw2_AddRef(iface);
3936                 *obj = This;
3937
3938                 TRACE(ddraw, "  Creating IDirectDraw4 interface (%p)\n", *obj);
3939
3940                 return S_OK;
3941         }
3942         if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
3943                 IDirect3DImpl* d3d;
3944
3945                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
3946                 d3d->ref = 1;
3947                 d3d->ddraw = (IDirectDrawImpl*)This;
3948                 IDirectDraw2_AddRef(iface);
3949                 d3d->lpvtbl = &d3dvt;
3950                 *obj = d3d;
3951
3952                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
3953
3954                 return S_OK;
3955         }
3956         if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D))) {
3957                 IDirect3D2Impl* d3d;
3958
3959                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
3960                 d3d->ref = 1;
3961                 d3d->ddraw = (IDirectDrawImpl*)This;
3962                 IDirectDraw2_AddRef(iface);
3963                 d3d->lpvtbl = &d3d2vt;
3964                 *obj = d3d;
3965
3966                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
3967
3968                 return S_OK;
3969         }
3970         WARN(ddraw,"(%p):interface for IID %s _NOT_ found!\n",This,xrefiid);
3971         return OLE_E_ENUM_NOMORE;
3972 }
3973
3974 static HRESULT WINAPI IDirectDraw2Impl_GetVerticalBlankStatus(
3975         LPDIRECTDRAW2 iface,BOOL *status
3976 ) {
3977         ICOM_THIS(IDirectDraw2Impl,iface);
3978         TRACE(ddraw,"(%p)->(%p)\n",This,status);
3979         *status = TRUE;
3980         return DD_OK;
3981 }
3982
3983 static HRESULT WINAPI DGA_IDirectDraw2Impl_EnumDisplayModes(
3984         LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
3985 ) {
3986         ICOM_THIS(IDirectDraw2Impl,iface);
3987         DDSURFACEDESC   ddsfd;
3988         static struct {
3989                 int w,h;
3990         } modes[5] = { /* some of the usual modes */
3991                 {512,384},
3992                 {640,400},
3993                 {640,480},
3994                 {800,600},
3995                 {1024,768},
3996         };
3997         static int depths[4] = {8,16,24,32};
3998         int     i,j;
3999
4000         TRACE(ddraw,"(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
4001         ddsfd.dwSize = sizeof(ddsfd);
4002         ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
4003         if (dwFlags & DDEDM_REFRESHRATES) {
4004                 ddsfd.dwFlags |= DDSD_REFRESHRATE;
4005                 ddsfd.x.dwRefreshRate = 60;
4006         }
4007
4008         for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
4009                 ddsfd.dwBackBufferCount = 1;
4010                 ddsfd.ddpfPixelFormat.dwFourCC  = 0;
4011                 ddsfd.ddpfPixelFormat.dwFlags   = DDPF_RGB;
4012                 ddsfd.ddpfPixelFormat.x.dwRGBBitCount   = depths[i];
4013                 /* FIXME: those masks would have to be set in depth > 8 */
4014                 if (depths[i]==8) {
4015                 ddsfd.ddpfPixelFormat.y.dwRBitMask      = 0;
4016                 ddsfd.ddpfPixelFormat.z.dwGBitMask      = 0;
4017                 ddsfd.ddpfPixelFormat.xx.dwBBitMask     = 0;
4018                 ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
4019                         ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
4020                         ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
4021                 } else {
4022                   ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
4023                   
4024                   /* FIXME: We should query those from X itself */
4025                   switch (depths[i]) {
4026                   case 16:
4027                     ddsfd.ddpfPixelFormat.y.dwRBitMask = 0xF800;
4028                     ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x07E0;
4029                     ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x001F;
4030                     break;
4031                   case 24:
4032                     ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x00FF0000;
4033                     ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x0000FF00;
4034                     ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x000000FF;
4035                     break;
4036                   case 32:
4037                     ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x00FF0000;
4038                     ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x0000FF00;
4039                     ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x000000FF;
4040                     break;
4041                   }
4042                 }
4043
4044                 ddsfd.dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
4045                 ddsfd.dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
4046                 TRACE(ddraw," enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
4047                 if (!modescb(&ddsfd,context)) return DD_OK;
4048
4049                 for (j=0;j<sizeof(modes)/sizeof(modes[0]);j++) {
4050                         ddsfd.dwWidth   = modes[j].w;
4051                         ddsfd.dwHeight  = modes[j].h;
4052                         TRACE(ddraw," enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
4053                         if (!modescb(&ddsfd,context)) return DD_OK;
4054                 }
4055
4056                 if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
4057                         /* modeX is not standard VGA */
4058
4059                         ddsfd.dwHeight = 200;
4060                         ddsfd.dwWidth = 320;
4061                         TRACE(ddraw," enumerating (320x200x%d)\n",depths[i]);
4062                         if (!modescb(&ddsfd,context)) return DD_OK;
4063                 }
4064         }
4065         return DD_OK;
4066 }
4067
4068 static HRESULT WINAPI Xlib_IDirectDraw2Impl_EnumDisplayModes(
4069         LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
4070 ) {
4071   ICOM_THIS(IDirectDraw2Impl,iface);
4072   XVisualInfo *vi;
4073   XPixmapFormatValues *pf;
4074   XVisualInfo vt;
4075   int nvisuals, npixmap, i;
4076   int send_mode;
4077   int has_8bpp = 0;
4078   DDSURFACEDESC ddsfd;
4079   static struct {
4080     int w,h;
4081   } modes[] = { /* some of the usual modes */
4082     {512,384},
4083     {640,400},
4084     {640,480},
4085     {800,600},
4086     {1024,768},
4087     {1280,1024}
4088   };
4089   DWORD maxWidth, maxHeight;
4090
4091   TRACE(ddraw,"(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
4092   ddsfd.dwSize = sizeof(ddsfd);
4093   ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS;
4094   if (dwFlags & DDEDM_REFRESHRATES) {
4095     ddsfd.dwFlags |= DDSD_REFRESHRATE;
4096     ddsfd.x.dwRefreshRate = 60;
4097   }
4098   maxWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
4099   maxHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
4100   
4101   vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
4102   pf = XListPixmapFormats(display, &npixmap);
4103
4104   i = 0;
4105   send_mode = 0;
4106   while (i < npixmap) {
4107     if ((has_8bpp == 0) && (pf[i].depth == 8)) {
4108       /* Special case of a 8bpp depth */
4109       has_8bpp = 1;
4110       send_mode = 1;
4111
4112       ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
4113       ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
4114       ddsfd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8;
4115       ddsfd.ddpfPixelFormat.dwFourCC = 0;
4116       ddsfd.ddpfPixelFormat.x.dwRGBBitCount = 8;
4117       ddsfd.ddpfPixelFormat.y.dwRBitMask = 0;
4118       ddsfd.ddpfPixelFormat.z.dwGBitMask = 0;
4119       ddsfd.ddpfPixelFormat.xx.dwBBitMask = 0;
4120       ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
4121     } else if (pf[i].depth > 8) {
4122       int j;
4123       
4124       /* All the 'true color' depths (15, 16 and 24)
4125          First, find the corresponding visual to extract the bit masks */
4126       for (j = 0; j < nvisuals; j++) {
4127         if (vi[j].depth == pf[i].depth) {
4128           ddsfd.ddsCaps.dwCaps = 0;
4129           ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
4130           ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4131           ddsfd.ddpfPixelFormat.dwFourCC = 0;
4132           ddsfd.ddpfPixelFormat.x.dwRGBBitCount = pf[i].bits_per_pixel;
4133           ddsfd.ddpfPixelFormat.y.dwRBitMask = vi[j].red_mask;
4134           ddsfd.ddpfPixelFormat.z.dwGBitMask = vi[j].green_mask;
4135           ddsfd.ddpfPixelFormat.xx.dwBBitMask = vi[j].blue_mask;
4136           ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
4137
4138           send_mode = 1;
4139           break;
4140         }
4141       }
4142       
4143       if (j == nvisuals)
4144         ERR(ddraw, "Did not find visual corresponding the the pixmap format !\n");
4145     } else {
4146       send_mode = 0;
4147     }
4148
4149     if (send_mode) {
4150       int mode;
4151
4152       if (TRACE_ON(ddraw)) {
4153         TRACE(ddraw, "Enumerating with pixel format : \n");
4154         _dump_pixelformat(&(ddsfd.ddpfPixelFormat));
4155         DUMP("\n");
4156       }
4157       
4158       for (mode = 0; mode < sizeof(modes)/sizeof(modes[0]); mode++) {
4159         /* Do not enumerate modes we cannot handle anyway */
4160         if ((modes[mode].w > maxWidth) || (modes[mode].h > maxHeight))
4161           break;
4162
4163         ddsfd.dwWidth = modes[mode].w;
4164         ddsfd.dwHeight = modes[mode].h;
4165         
4166         /* Now, send the mode description to the application */
4167         TRACE(ddraw, " - mode %4ld - %4ld\n", ddsfd.dwWidth, ddsfd.dwHeight);
4168         if (!modescb(&ddsfd, context))
4169           goto exit_enum;
4170       }
4171
4172       if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
4173         /* modeX is not standard VGA */
4174         ddsfd.dwWidth = 320;
4175         ddsfd.dwHeight = 200;
4176         if (!modescb(&ddsfd, context))
4177           goto exit_enum;
4178       }
4179     }
4180
4181     /* Hack to always enumerate a 8bpp depth */
4182     i++;
4183     if ((i == npixmap) && (has_8bpp == 0)) {
4184       i--;
4185       pf[i].depth = 8;
4186     }
4187   }
4188   
4189  exit_enum:
4190   TSXFree(vi);
4191   TSXFree(pf);
4192
4193   return DD_OK;
4194 }
4195
4196 static HRESULT WINAPI DGA_IDirectDraw2Impl_GetDisplayMode(
4197         LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
4198 ) {
4199 #ifdef HAVE_LIBXXF86DGA
4200         ICOM_THIS(IDirectDraw2Impl,iface);
4201         TRACE(ddraw,"(%p)->(%p)\n",This,lpddsfd);
4202         lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
4203         lpddsfd->dwHeight = This->d.height;
4204         lpddsfd->dwWidth = This->d.width;
4205         lpddsfd->lPitch = This->e.dga.fb_width*This->d.directdraw_pixelformat.x.dwRGBBitCount/8;
4206         lpddsfd->dwBackBufferCount = 1;
4207         lpddsfd->x.dwRefreshRate = 60;
4208         lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
4209         lpddsfd->ddpfPixelFormat = This->d.directdraw_pixelformat;
4210         return DD_OK;
4211 #else /* defined(HAVE_LIBXXF86DGA) */
4212         return E_UNEXPECTED;
4213 #endif /* defined(HAVE_LIBXXF86DGA) */
4214 }
4215
4216 static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetDisplayMode(
4217         LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
4218 ) {
4219         ICOM_THIS(IDirectDraw2Impl,iface);
4220         TRACE(ddraw,"(%p)->GetDisplayMode(%p)\n",This,lpddsfd);
4221         lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
4222         lpddsfd->dwHeight = This->d.height;
4223         lpddsfd->dwWidth = This->d.width;
4224         lpddsfd->lPitch = lpddsfd->dwWidth * This->d.directdraw_pixelformat.x.dwRGBBitCount/8;
4225         lpddsfd->dwBackBufferCount = 1;
4226         lpddsfd->x.dwRefreshRate = 60;
4227         lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
4228         lpddsfd->ddpfPixelFormat = This->d.directdraw_pixelformat;
4229         return DD_OK;
4230 }
4231
4232 static HRESULT WINAPI IDirectDraw2Impl_FlipToGDISurface(LPDIRECTDRAW2 iface) {
4233         ICOM_THIS(IDirectDraw2Impl,iface);
4234         TRACE(ddraw,"(%p)->()\n",This);
4235         return DD_OK;
4236 }
4237
4238 static HRESULT WINAPI IDirectDraw2Impl_GetMonitorFrequency(
4239         LPDIRECTDRAW2 iface,LPDWORD freq
4240 ) {
4241         ICOM_THIS(IDirectDraw2Impl,iface);
4242         FIXME(ddraw,"(%p)->(%p) returns 60 Hz always\n",This,freq);
4243         *freq = 60*100; /* 60 Hz */
4244         return DD_OK;
4245 }
4246
4247 /* what can we directly decompress? */
4248 static HRESULT WINAPI IDirectDraw2Impl_GetFourCCCodes(
4249         LPDIRECTDRAW2 iface,LPDWORD x,LPDWORD y
4250 ) {
4251         ICOM_THIS(IDirectDraw2Impl,iface);
4252         FIXME(ddraw,"(%p,%p,%p), stub\n",This,x,y);
4253         return DD_OK;
4254 }
4255
4256 static HRESULT WINAPI IDirectDraw2Impl_EnumSurfaces(
4257         LPDIRECTDRAW2 iface,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,LPDDENUMSURFACESCALLBACK ddsfcb
4258 ) {
4259   ICOM_THIS(IDirectDraw2Impl,iface);
4260   FIXME(ddraw,"(%p)->(0x%08lx,%p,%p,%p),stub!\n",This,x,ddsfd,context,ddsfcb);
4261   return DD_OK;
4262 }
4263
4264 static HRESULT WINAPI IDirectDraw2Impl_Compact(
4265           LPDIRECTDRAW2 iface )
4266 {
4267   ICOM_THIS(IDirectDraw2Impl,iface);
4268   FIXME(ddraw,"(%p)->()\n", This );
4269  
4270   return DD_OK;
4271 }
4272
4273 static HRESULT WINAPI IDirectDraw2Impl_GetGDISurface(LPDIRECTDRAW2 iface,
4274                                                  LPDIRECTDRAWSURFACE *lplpGDIDDSSurface) {
4275   ICOM_THIS(IDirectDraw2Impl,iface);
4276   FIXME(ddraw,"(%p)->(%p)\n", This, lplpGDIDDSSurface);
4277
4278   return DD_OK;
4279 }
4280
4281 static HRESULT WINAPI IDirectDraw2Impl_GetScanLine(LPDIRECTDRAW2 iface,
4282                                                LPDWORD lpdwScanLine) {
4283   ICOM_THIS(IDirectDraw2Impl,iface);
4284   FIXME(ddraw,"(%p)->(%p)\n", This, lpdwScanLine);
4285
4286   return DD_OK;
4287 }
4288
4289 static HRESULT WINAPI IDirectDraw2Impl_Initialize(LPDIRECTDRAW2 iface,
4290                                               GUID *lpGUID) {
4291   ICOM_THIS(IDirectDraw2Impl,iface);
4292   FIXME(ddraw,"(%p)->(%p)\n", This, lpGUID);
4293   
4294   return DD_OK;
4295 }
4296
4297 /* Note: Hack so we can reuse the old functions without compiler warnings */
4298 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4299 # define XCAST(fun)     (typeof(dga_ddvt.fn##fun))
4300 #else
4301 # define XCAST(fun)     (void *)
4302 #endif
4303
4304 static ICOM_VTABLE(IDirectDraw) dga_ddvt = 
4305 {
4306         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4307         XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
4308         XCAST(AddRef)IDirectDraw2Impl_AddRef,
4309         XCAST(Release)DGA_IDirectDraw2Impl_Release,
4310         XCAST(Compact)IDirectDraw2Impl_Compact,
4311         XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
4312         XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
4313         XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
4314         XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
4315         XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
4316         XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
4317         XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
4318         XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
4319         XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
4320         XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
4321         XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
4322         XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
4323         XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
4324         XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
4325         XCAST(Initialize)IDirectDraw2Impl_Initialize,
4326         XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
4327         XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
4328         DGA_IDirectDrawImpl_SetDisplayMode,
4329         XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
4330 };
4331
4332 static ICOM_VTABLE(IDirectDraw) xlib_ddvt = 
4333 {
4334         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4335         XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
4336         XCAST(AddRef)IDirectDraw2Impl_AddRef,
4337         XCAST(Release)Xlib_IDirectDraw2Impl_Release,
4338         XCAST(Compact)IDirectDraw2Impl_Compact,
4339         XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
4340         XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
4341         XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
4342         XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
4343         XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
4344         XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
4345         XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
4346         XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
4347         XCAST(GetDisplayMode)Xlib_IDirectDraw2Impl_GetDisplayMode,
4348         XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
4349         XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
4350         XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
4351         XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
4352         XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
4353         XCAST(Initialize)IDirectDraw2Impl_Initialize,
4354         XCAST(RestoreDisplayMode)Xlib_IDirectDraw2Impl_RestoreDisplayMode,
4355         XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
4356         Xlib_IDirectDrawImpl_SetDisplayMode,
4357         XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
4358 };
4359
4360 #undef XCAST
4361
4362 /*****************************************************************************
4363  *      IDirectDraw2
4364  *
4365  */
4366
4367
4368 static HRESULT WINAPI DGA_IDirectDraw2Impl_SetDisplayMode(
4369         LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
4370 ) {
4371         return DGA_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
4372 }
4373
4374 static HRESULT WINAPI Xlib_IDirectDraw2Impl_SetDisplayMode(
4375         LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
4376 ) {
4377         return Xlib_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
4378 }
4379
4380 static HRESULT WINAPI DGA_IDirectDraw2Impl_GetAvailableVidMem(
4381         LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
4382 ) {
4383         ICOM_THIS(IDirectDraw2Impl,iface);
4384         TRACE(ddraw,"(%p)->(%p,%p,%p)\n",
4385                 This,ddscaps,total,free
4386         );
4387         if (total) *total = This->e.dga.fb_memsize * 1024;
4388         if (free) *free = This->e.dga.fb_memsize * 1024;
4389         return DD_OK;
4390 }
4391
4392 static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetAvailableVidMem(
4393         LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
4394 ) {
4395         ICOM_THIS(IDirectDraw2Impl,iface);
4396         TRACE(ddraw,"(%p)->(%p,%p,%p)\n",
4397                 This,ddscaps,total,free
4398         );
4399         if (total) *total = 2048 * 1024;
4400         if (free) *free = 2048 * 1024;
4401         return DD_OK;
4402 }
4403
4404 static ICOM_VTABLE(IDirectDraw2) dga_dd2vt = 
4405 {
4406         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4407         DGA_IDirectDraw2Impl_QueryInterface,
4408         IDirectDraw2Impl_AddRef,
4409         DGA_IDirectDraw2Impl_Release,
4410         IDirectDraw2Impl_Compact,
4411         IDirectDraw2Impl_CreateClipper,
4412         DGA_IDirectDraw2Impl_CreatePalette,
4413         DGA_IDirectDraw2Impl_CreateSurface,
4414         IDirectDraw2Impl_DuplicateSurface,
4415         DGA_IDirectDraw2Impl_EnumDisplayModes,
4416         IDirectDraw2Impl_EnumSurfaces,
4417         IDirectDraw2Impl_FlipToGDISurface,
4418         DGA_IDirectDraw2Impl_GetCaps,
4419         DGA_IDirectDraw2Impl_GetDisplayMode,
4420         IDirectDraw2Impl_GetFourCCCodes,
4421         IDirectDraw2Impl_GetGDISurface,
4422         IDirectDraw2Impl_GetMonitorFrequency,
4423         IDirectDraw2Impl_GetScanLine,
4424         IDirectDraw2Impl_GetVerticalBlankStatus,
4425         IDirectDraw2Impl_Initialize,
4426         DGA_IDirectDraw2Impl_RestoreDisplayMode,
4427         IDirectDraw2Impl_SetCooperativeLevel,
4428         DGA_IDirectDraw2Impl_SetDisplayMode,
4429         IDirectDraw2Impl_WaitForVerticalBlank,
4430         DGA_IDirectDraw2Impl_GetAvailableVidMem
4431 };
4432
4433 static ICOM_VTABLE(IDirectDraw2) xlib_dd2vt = 
4434 {
4435         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4436         Xlib_IDirectDraw2Impl_QueryInterface,
4437         IDirectDraw2Impl_AddRef,
4438         Xlib_IDirectDraw2Impl_Release,
4439         IDirectDraw2Impl_Compact,
4440         IDirectDraw2Impl_CreateClipper,
4441         Xlib_IDirectDraw2Impl_CreatePalette,
4442         Xlib_IDirectDraw2Impl_CreateSurface,
4443         IDirectDraw2Impl_DuplicateSurface,
4444         Xlib_IDirectDraw2Impl_EnumDisplayModes,
4445         IDirectDraw2Impl_EnumSurfaces,
4446         IDirectDraw2Impl_FlipToGDISurface,
4447         Xlib_IDirectDraw2Impl_GetCaps,
4448         Xlib_IDirectDraw2Impl_GetDisplayMode,
4449         IDirectDraw2Impl_GetFourCCCodes,
4450         IDirectDraw2Impl_GetGDISurface,
4451         IDirectDraw2Impl_GetMonitorFrequency,
4452         IDirectDraw2Impl_GetScanLine,
4453         IDirectDraw2Impl_GetVerticalBlankStatus,
4454         IDirectDraw2Impl_Initialize,
4455         Xlib_IDirectDraw2Impl_RestoreDisplayMode,
4456         IDirectDraw2Impl_SetCooperativeLevel,
4457         Xlib_IDirectDraw2Impl_SetDisplayMode,
4458         IDirectDraw2Impl_WaitForVerticalBlank,
4459         Xlib_IDirectDraw2Impl_GetAvailableVidMem        
4460 };
4461
4462 /*****************************************************************************
4463  *      IDirectDraw4
4464  *
4465  */
4466
4467 static HRESULT WINAPI IDirectDraw4Impl_GetSurfaceFromDC(LPDIRECTDRAW4 iface,
4468                                                     HDC hdc,
4469                                                     LPDIRECTDRAWSURFACE *lpDDS) {
4470   ICOM_THIS(IDirectDraw4Impl,iface);
4471   FIXME(ddraw, "(%p)->(%08ld,%p)\n", This, (DWORD) hdc, lpDDS);
4472
4473   return DD_OK;
4474 }
4475
4476 static HRESULT WINAPI IDirectDraw4Impl_RestoreAllSurfaces(LPDIRECTDRAW4 iface) {
4477   ICOM_THIS(IDirectDraw4Impl,iface);
4478   FIXME(ddraw, "(%p)->()\n", This);
4479
4480   return DD_OK;
4481 }
4482
4483 static HRESULT WINAPI IDirectDraw4Impl_TestCooperativeLevel(LPDIRECTDRAW4 iface) {
4484   ICOM_THIS(IDirectDraw4Impl,iface);
4485   FIXME(ddraw, "(%p)->()\n", This);
4486
4487   return DD_OK;
4488 }
4489
4490 static HRESULT WINAPI IDirectDraw4Impl_GetDeviceIdentifier(LPDIRECTDRAW4 iface,
4491                                                        LPDDDEVICEIDENTIFIER lpdddi,
4492                                                        DWORD dwFlags) {
4493   ICOM_THIS(IDirectDraw4Impl,iface);
4494   FIXME(ddraw, "(%p)->(%p,%08lx)\n", This, lpdddi, dwFlags);
4495   
4496   return DD_OK;
4497 }
4498
4499 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4500 # define XCAST(fun)     (typeof(dga_dd4vt.fn##fun))
4501 #else
4502 # define XCAST(fun)     (void*)
4503 #endif
4504
4505
4506 static ICOM_VTABLE(IDirectDraw4) dga_dd4vt = 
4507 {
4508         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4509         XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
4510         XCAST(AddRef)IDirectDraw2Impl_AddRef,
4511         XCAST(Release)DGA_IDirectDraw2Impl_Release,
4512         XCAST(Compact)IDirectDraw2Impl_Compact,
4513         XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
4514         XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
4515         XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
4516         XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
4517         XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
4518         XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
4519         XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
4520         XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
4521         XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
4522         XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
4523         XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
4524         XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
4525         XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
4526         XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
4527         XCAST(Initialize)IDirectDraw2Impl_Initialize,
4528         XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
4529         XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
4530         XCAST(SetDisplayMode)DGA_IDirectDrawImpl_SetDisplayMode,
4531         XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
4532         XCAST(GetAvailableVidMem)DGA_IDirectDraw2Impl_GetAvailableVidMem,
4533         IDirectDraw4Impl_GetSurfaceFromDC,
4534         IDirectDraw4Impl_RestoreAllSurfaces,
4535         IDirectDraw4Impl_TestCooperativeLevel,
4536         IDirectDraw4Impl_GetDeviceIdentifier
4537 };
4538
4539 static ICOM_VTABLE(IDirectDraw4) xlib_dd4vt = 
4540 {
4541         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4542         XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
4543         XCAST(AddRef)IDirectDraw2Impl_AddRef,
4544         XCAST(Release)Xlib_IDirectDraw2Impl_Release,
4545         XCAST(Compact)IDirectDraw2Impl_Compact,
4546         XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
4547         XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
4548         XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
4549         XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
4550         XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
4551         XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
4552         XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
4553         XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
4554         XCAST(GetDisplayMode)Xlib_IDirectDraw2Impl_GetDisplayMode,
4555         XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
4556         XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
4557         XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
4558         XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
4559         XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
4560         XCAST(Initialize)IDirectDraw2Impl_Initialize,
4561         XCAST(RestoreDisplayMode)Xlib_IDirectDraw2Impl_RestoreDisplayMode,
4562         XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
4563         XCAST(SetDisplayMode)Xlib_IDirectDrawImpl_SetDisplayMode,
4564         XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
4565         XCAST(GetAvailableVidMem)Xlib_IDirectDraw2Impl_GetAvailableVidMem,
4566         IDirectDraw4Impl_GetSurfaceFromDC,
4567         IDirectDraw4Impl_RestoreAllSurfaces,
4568         IDirectDraw4Impl_TestCooperativeLevel,
4569         IDirectDraw4Impl_GetDeviceIdentifier
4570 };
4571
4572 #undef XCAST
4573
4574 /******************************************************************************
4575  *                              DirectDrawCreate
4576  */
4577
4578 LRESULT WINAPI Xlib_DDWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
4579 {
4580    LRESULT ret;
4581    IDirectDrawImpl* ddraw = NULL;
4582    DWORD lastError;
4583
4584    /* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
4585
4586    SetLastError( ERROR_SUCCESS );
4587    ddraw  = (IDirectDrawImpl*)GetWindowLongA( hwnd, ddrawXlibThisOffset );
4588    if( (!ddraw)  &&
4589        ( ( lastError = GetLastError() ) != ERROR_SUCCESS )
4590      ) 
4591    {
4592      ERR( ddraw, "Unable to retrieve this ptr from window. Error %08lx\n", lastError );
4593    }
4594
4595    if( ddraw )
4596    {
4597       /* Perform any special direct draw functions */
4598       if (msg==WM_PAINT)
4599         ddraw->d.paintable = 1;
4600
4601       /* Now let the application deal with the rest of this */
4602       if( ddraw->d.mainWindow )
4603       {
4604     
4605         /* Don't think that we actually need to call this but... 
4606            might as well be on the safe side of things... */
4607
4608         /* I changed hwnd to ddraw->d.mainWindow as I did not see why
4609            it should be the procedures of our fake window that gets called
4610            instead of those of the window provided by the application.
4611            And with this patch, mouse clicks work with Monkey Island III
4612              - Lionel */
4613         ret = DefWindowProcA( ddraw->d.mainWindow, msg, wParam, lParam );
4614
4615         if( !ret )
4616         {
4617           WND *tmpWnd =WIN_FindWndPtr(ddraw->d.mainWindow);
4618           /* We didn't handle the message - give it to the application */
4619           if (ddraw && ddraw->d.mainWindow && tmpWnd)
4620           {
4621                 ret = CallWindowProcA(tmpWnd->winproc,
4622                                    ddraw->d.mainWindow, msg, wParam, lParam );
4623           }
4624           WIN_ReleaseWndPtr(tmpWnd);
4625
4626         }
4627         
4628       } else {
4629         ret = DefWindowProcA(hwnd, msg, wParam, lParam );
4630       } 
4631
4632     }
4633     else
4634     {
4635         ret = DefWindowProcA(hwnd,msg,wParam,lParam);
4636     }
4637
4638     return ret;
4639 }
4640
4641 HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
4642 #ifdef HAVE_LIBXXF86DGA
4643         IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
4644         int     memsize,banksize,width,major,minor,flags,height;
4645         char    *addr;
4646         int     fd;                     
4647         int     depth;
4648
4649         /* Must be able to access /dev/mem for DGA extensions to work, root is not neccessary. --stephenc */
4650         if ((fd = open("/dev/mem", O_RDWR)) != -1)
4651           close(fd);
4652         
4653         if (fd  == -1) {
4654           MSG("Must be able to access /dev/mem to use XF86DGA!\n");
4655           MessageBoxA(0,"Using the XF86DGA extension requires access to /dev/mem.","WINE DirectDraw",MB_OK|MB_ICONSTOP);
4656           return E_UNEXPECTED;
4657         }
4658         if (!DDRAW_DGA_Available()) {
4659                 TRACE(ddraw,"No XF86DGA detected.\n");
4660                 return DDERR_GENERIC;
4661         }
4662         *ilplpDD = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
4663         (*ilplpDD)->lpvtbl = &dga_ddvt;
4664         (*ilplpDD)->ref = 1;
4665         TSXF86DGAQueryVersion(display,&major,&minor);
4666         TRACE(ddraw,"XF86DGA is version %d.%d\n",major,minor);
4667         TSXF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
4668         if (!(flags & XF86DGADirectPresent))
4669                 MSG("direct video is NOT PRESENT.\n");
4670         TSXF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
4671         (*ilplpDD)->e.dga.fb_width = width;
4672         TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
4673         TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
4674         (*ilplpDD)->e.dga.fb_height = height;
4675         TRACE(ddraw,"video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
4676                 addr,width,banksize,memsize
4677         );
4678         TRACE(ddraw,"viewport height: %d\n",height);
4679
4680         /* Get the screen dimensions as seen by Wine.
4681            In that case, it may be better to ignore the -desktop mode and return the
4682            real screen size => print a warning */
4683         (*ilplpDD)->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
4684         (*ilplpDD)->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
4685         if (((*ilplpDD)->d.height != height) ||
4686             ((*ilplpDD)->d.width != width))
4687           WARN(ddraw, "You seem to be runnin in -desktop mode. This may prove dangerous in DGA mode...\n");
4688         (*ilplpDD)->e.dga.fb_addr = addr;
4689         (*ilplpDD)->e.dga.fb_memsize = memsize;
4690         (*ilplpDD)->e.dga.fb_banksize = banksize;
4691
4692 #ifdef DIABLO_HACK
4693         (*ilplpDD)->e.dga.vpmask = 1;
4694 #else
4695         (*ilplpDD)->e.dga.vpmask = 0;
4696 #endif
4697
4698         /* just assume the default depth is the DGA depth too */
4699         depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
4700         _common_depth_to_pixelformat(depth, &((*ilplpDD)->d.directdraw_pixelformat), &((*ilplpDD)->d.screen_pixelformat), NULL);
4701 #ifdef RESTORE_SIGNALS
4702         SIGNAL_InitHandlers();
4703 #endif
4704
4705         return DD_OK;
4706 #else /* defined(HAVE_LIBXXF86DGA) */
4707         return DDERR_INVALIDDIRECTDRAWGUID;
4708 #endif /* defined(HAVE_LIBXXF86DGA) */
4709 }
4710
4711 BOOL
4712 DDRAW_XSHM_Available(void)
4713    {
4714 #ifdef HAVE_LIBXXSHM
4715   if (TSXShmQueryExtension(display))
4716       {
4717       int major, minor;
4718       Bool shpix;
4719
4720       if (TSXShmQueryVersion(display, &major, &minor, &shpix))
4721         return 1;
4722       else
4723         return 0;
4724     }
4725     else
4726     return 0;
4727 #else
4728   return 0;
4729 #endif
4730 }
4731
4732 HRESULT WINAPI Xlib_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
4733         IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
4734         int depth;
4735
4736         *ilplpDD = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
4737         (*ilplpDD)->lpvtbl = &xlib_ddvt;
4738         (*ilplpDD)->ref = 1;
4739         (*ilplpDD)->d.drawable = 0; /* in SetDisplayMode */
4740
4741         /* At DirectDraw creation, the depth is the default depth */
4742         depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
4743         _common_depth_to_pixelformat(depth,
4744                                      &((*ilplpDD)->d.directdraw_pixelformat),
4745                                      &((*ilplpDD)->d.screen_pixelformat),
4746                                      &((*ilplpDD)->d.pixmap_depth));
4747         (*ilplpDD)->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
4748         (*ilplpDD)->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
4749
4750 #ifdef HAVE_LIBXXSHM
4751         /* Test if XShm is available. */
4752         if (((*ilplpDD)->e.xlib.xshm_active = DDRAW_XSHM_Available()))
4753           TRACE(ddraw, "Using XShm extension.\n");
4754 #endif
4755         
4756         return DD_OK;
4757 }
4758
4759 HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter ) {
4760         IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
4761         char    xclsid[50];
4762         WNDCLASSA       wc;
4763         /* WND*            pParentWindow; */
4764         HRESULT ret;
4765
4766         if (HIWORD(lpGUID))
4767                 WINE_StringFromCLSID(lpGUID,xclsid);
4768         else {
4769                 sprintf(xclsid,"<guid-0x%08x>",(int)lpGUID);
4770                 lpGUID = NULL;
4771         }
4772
4773         TRACE(ddraw,"(%s,%p,%p)\n",xclsid,ilplpDD,pUnkOuter);
4774
4775         if ((!lpGUID) ||
4776             (!memcmp(lpGUID,&IID_IDirectDraw ,sizeof(IID_IDirectDraw ))) ||
4777             (!memcmp(lpGUID,&IID_IDirectDraw2,sizeof(IID_IDirectDraw2))) ||
4778             (!memcmp(lpGUID,&IID_IDirectDraw4,sizeof(IID_IDirectDraw4)))) {
4779                 /* if they didn't request a particular interface, use the best
4780                  * supported one */
4781                 if (DDRAW_DGA_Available())
4782                         lpGUID = &DGA_DirectDraw_GUID;
4783                 else
4784                         lpGUID = &XLIB_DirectDraw_GUID;
4785         }
4786
4787         wc.style        = CS_GLOBALCLASS;
4788         wc.lpfnWndProc  = Xlib_DDWndProc;
4789         wc.cbClsExtra   = 0;
4790         wc.cbWndExtra   = /* Defines extra mem for window. This is used for storing this */
4791                           sizeof( LPDIRECTDRAW ); /*  ddrawXlibThisOffset */
4792
4793         /* We can be a child of the desktop since we're really important */
4794         /*
4795          This code is not useful since hInstance is forced to 0 afterward
4796         pParentWindow   = WIN_GetDesktop();
4797         wc.hInstance    = pParentWindow ? pParentWindow->hwndSelf : 0;
4798         */
4799         wc.hInstance    = 0; 
4800
4801         
4802         wc.hIcon        = 0;
4803         wc.hCursor      = (HCURSOR)IDC_ARROWA;
4804         wc.hbrBackground= NULL_BRUSH;
4805         wc.lpszMenuName = 0;
4806         wc.lpszClassName= "WINE_DirectDraw";
4807         RegisterClassA(&wc);
4808
4809         if (!memcmp(lpGUID, &DGA_DirectDraw_GUID, sizeof(GUID)))
4810                 ret = DGA_DirectDrawCreate(lplpDD, pUnkOuter);
4811         else if (!memcmp(lpGUID, &XLIB_DirectDraw_GUID, sizeof(GUID)))
4812                 ret = Xlib_DirectDrawCreate(lplpDD, pUnkOuter);
4813         else
4814           goto err;
4815
4816
4817         (*ilplpDD)->d.winclass = RegisterClassA(&wc);
4818         return ret;
4819
4820       err:
4821         ERR(ddraw, "DirectDrawCreate(%s,%p,%p): did not recognize requested GUID\n",xclsid,lplpDD,pUnkOuter);
4822         return DDERR_INVALIDDIRECTDRAWGUID;
4823 }
4824
4825
4826 #else /* !defined(X_DISPLAY_MISSING) */
4827
4828 #include "windef.h"
4829
4830 #define DD_OK 0
4831
4832 typedef void *LPGUID;
4833 typedef void *LPUNKNOWN;
4834 typedef void *LPDIRECTDRAW;
4835 typedef void *LPDIRECTDRAWCLIPPER;
4836 typedef void *LPDDENUMCALLBACKA;
4837 typedef void *LPDDENUMCALLBACKEXA;
4838 typedef void *LPDDENUMCALLBACKEXW;
4839 typedef void *LPDDENUMCALLBACKW;
4840
4841 HRESULT WINAPI DSoundHelp(DWORD x, DWORD y, DWORD z) 
4842 {
4843   return DD_OK;
4844 }
4845
4846 HRESULT WINAPI DirectDrawCreate(
4847   LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) 
4848 {
4849   return DD_OK;
4850 }
4851
4852 HRESULT WINAPI DirectDrawCreateClipper(
4853   DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, LPUNKNOWN pUnkOuter)
4854 {
4855   return DD_OK;
4856 }
4857
4858 HRESULT WINAPI DirectDrawEnumerateA(
4859   LPDDENUMCALLBACKA lpCallback, LPVOID lpContext) 
4860 {
4861   return DD_OK;
4862 }
4863
4864 HRESULT WINAPI DirectDrawEnumerateExA(
4865   LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
4866 {
4867   return DD_OK;
4868 }
4869
4870 HRESULT WINAPI DirectDrawEnumerateExW(
4871   LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
4872 {
4873   return DD_OK;
4874 }
4875
4876 HRESULT WINAPI DirectDrawEnumerateW(
4877   LPDDENUMCALLBACKW lpCallback, LPVOID lpContext) 
4878 {
4879   return DD_OK;
4880 }
4881
4882 #endif /* !defined(X_DISPLAY_MISSING) */
4883
4884
4885 /*******************************************************************************
4886  * DirectDraw ClassFactory
4887  *
4888  *  Heavily inspired (well, can you say completely copied :-) ) from DirectSound
4889  *
4890  */
4891 typedef struct
4892 {
4893     /* IUnknown fields */
4894     ICOM_VTABLE(IClassFactory)* lpvtbl;
4895     DWORD                       ref;
4896 } IClassFactoryImpl;
4897
4898 static HRESULT WINAPI 
4899 DDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
4900         ICOM_THIS(IClassFactoryImpl,iface);
4901         char buf[80];
4902
4903         if (HIWORD(riid))
4904             WINE_StringFromCLSID(riid,buf);
4905         else
4906             sprintf(buf,"<guid-0x%04x>",LOWORD(riid));
4907         FIXME(ddraw,"(%p)->(%s,%p),stub!\n",This,buf,ppobj);
4908         return E_NOINTERFACE;
4909 }
4910
4911 static ULONG WINAPI
4912 DDCF_AddRef(LPCLASSFACTORY iface) {
4913         ICOM_THIS(IClassFactoryImpl,iface);
4914         return ++(This->ref);
4915 }
4916
4917 static ULONG WINAPI DDCF_Release(LPCLASSFACTORY iface) {
4918         ICOM_THIS(IClassFactoryImpl,iface);
4919         /* static class, won't be  freed */
4920         return --(This->ref);
4921 }
4922
4923 static HRESULT WINAPI DDCF_CreateInstance(
4924         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
4925 ) {
4926         ICOM_THIS(IClassFactoryImpl,iface);
4927         char buf[80];
4928
4929         WINE_StringFromCLSID(riid,buf);
4930         TRACE(ddraw,"(%p)->(%p,%s,%p)\n",This,pOuter,buf,ppobj);
4931         if ((!memcmp(riid,&IID_IDirectDraw ,sizeof(IID_IDirectDraw ))) ||
4932             (!memcmp(riid,&IID_IDirectDraw2,sizeof(IID_IDirectDraw2))) ||
4933             (!memcmp(riid,&IID_IDirectDraw4,sizeof(IID_IDirectDraw4)))) {
4934                 /* FIXME: reuse already created DirectDraw if present? */
4935                 return DirectDrawCreate((LPGUID) riid,(LPDIRECTDRAW*)ppobj,pOuter);
4936         }
4937         return E_NOINTERFACE;
4938 }
4939
4940 static HRESULT WINAPI DDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
4941         ICOM_THIS(IClassFactoryImpl,iface);
4942         FIXME(ddraw,"(%p)->(%d),stub!\n",This,dolock);
4943         return S_OK;
4944 }
4945
4946 static ICOM_VTABLE(IClassFactory) DDCF_Vtbl = 
4947 {
4948         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4949         DDCF_QueryInterface,
4950         DDCF_AddRef,
4951         DDCF_Release,
4952         DDCF_CreateInstance,
4953         DDCF_LockServer
4954 };
4955 static IClassFactoryImpl DDRAW_CF = {&DDCF_Vtbl, 1 };
4956
4957 /*******************************************************************************
4958  * DllGetClassObject [DDRAW.13]
4959  * Retrieves class object from a DLL object
4960  *
4961  * NOTES
4962  *    Docs say returns STDAPI
4963  *
4964  * PARAMS
4965  *    rclsid [I] CLSID for the class object
4966  *    riid   [I] Reference to identifier of interface for class object
4967  *    ppv    [O] Address of variable to receive interface pointer for riid
4968  *
4969  * RETURNS
4970  *    Success: S_OK
4971  *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
4972  *             E_UNEXPECTED
4973  */
4974 DWORD WINAPI DDRAW_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
4975 {
4976     char buf[80],xbuf[80];
4977
4978     if (HIWORD(rclsid))
4979         WINE_StringFromCLSID(rclsid,xbuf);
4980     else
4981         sprintf(xbuf,"<guid-0x%04x>",LOWORD(rclsid));
4982     if (HIWORD(riid))
4983         WINE_StringFromCLSID(riid,buf);
4984     else
4985         sprintf(buf,"<guid-0x%04x>",LOWORD(riid));
4986     WINE_StringFromCLSID(riid,xbuf);
4987     TRACE(ddraw, "(%p,%p,%p)\n", xbuf, buf, ppv);
4988     if (!memcmp(riid,&IID_IClassFactory,sizeof(IID_IClassFactory))) {
4989         *ppv = (LPVOID)&DDRAW_CF;
4990         IClassFactory_AddRef((IClassFactory*)*ppv);
4991     return S_OK;
4992     }
4993     FIXME(ddraw, "(%p,%p,%p): no interface found.\n", xbuf, buf, ppv);
4994     return E_NOINTERFACE;
4995 }
4996
4997
4998 /*******************************************************************************
4999  * DllCanUnloadNow [DDRAW.12]  Determines whether the DLL is in use.
5000  *
5001  * RETURNS
5002  *    Success: S_OK
5003  *    Failure: S_FALSE
5004  */
5005 DWORD WINAPI DDRAW_DllCanUnloadNow(void)
5006 {
5007     FIXME(ddraw, "(void): stub\n");
5008     return S_FALSE;
5009 }