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