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