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