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