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