Group commit for recovery after disk crash.
[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 #include <unistd.h>
19 #include <assert.h>
20 #include "ts_xlib.h"
21 #include "ts_xutil.h"
22 #include <sys/signal.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include "windows.h"
27
28 #ifdef HAVE_LIBXXF86VM
29 /* X is retarted and insists on declaring INT32, INT16 etc in Xmd.h,
30    this is a crude hack to get around it */
31 #define XMD_H
32 #include "ts_xf86vmode.h"
33 #endif
34
35 #include "winerror.h"
36 #include "gdi.h"
37 #include "heap.h"
38 #include "ldt.h"
39 #include "dc.h"
40 #include "win.h"
41 #include "miscemu.h"
42 #include "ddraw.h"
43 #include "d3d.h"
44 #include "debug.h"
45 #include "spy.h"
46 #include "message.h"
47 #include "x11drv.h"
48 #include "options.h"
49 #include "objbase.h"
50
51 #ifdef HAVE_LIBXXF86DGA
52 #include "ts_xf86dga.h"
53 #endif
54
55 #ifdef HAVE_LIBXXSHM
56 #include <sys/types.h>
57 #include <sys/ipc.h>
58 #include <sys/shm.h>
59 #include "ts_xshm.h"
60 #endif
61
62 /* This for all the enumeration and creation of D3D-related objects */
63 #include "d3d_private.h"
64
65 /* define this if you want to play Diablo using XF86DGA. (bug workaround) */
66 #undef DIABLO_HACK
67
68 /* Restore signal handlers overwritten by XF86DGA 
69  * this is a define, for it will only work in emulator mode
70  */
71 #undef RESTORE_SIGNALS
72
73 /* Where do these GUIDs come from?  mkuuid.
74  * They exist solely to distinguish between the targets Wine support,
75  * and should be different than any other GUIDs in existence.
76  */
77 static GUID DGA_DirectDraw_GUID = { /* e2dcb020-dc60-11d1-8407-9714f5d50802 */
78         0xe2dcb020,
79         0xdc60,
80         0x11d1,
81         {0x84, 0x07, 0x97, 0x14, 0xf5, 0xd5, 0x08, 0x02}
82 };
83
84 static GUID XLIB_DirectDraw_GUID = { /* 1574a740-dc61-11d1-8407-f7875a7d1879 */
85     0x1574a740,
86     0xdc61,
87     0x11d1,
88     {0x84, 0x07, 0xf7, 0x87, 0x5a, 0x7d, 0x18, 0x79}
89 };
90
91 static struct IDirectDrawSurface3_VTable        dga_dds3vt, xlib_dds3vt;
92 static struct IDirectDraw_VTable                dga_ddvt, xlib_ddvt;
93 static struct IDirectDraw2_VTable               dga_dd2vt, xlib_dd2vt;
94 static struct IDirectDrawClipper_VTable ddclipvt;
95 static struct IDirectDrawPalette_VTable dga_ddpalvt, xlib_ddpalvt;
96 static struct IDirect3D_VTable                  d3dvt;
97 static struct IDirect3D2_VTable                 d3d2vt;
98
99 #ifdef HAVE_LIBXXF86VM
100 static XF86VidModeModeInfo *orig_mode = NULL;
101 #endif
102
103 BOOL32
104 DDRAW_DGA_Available(void)
105 {
106 #ifdef HAVE_LIBXXF86DGA
107         int evbase, evret, fd;
108         
109         if (Options.noDGA)
110           return 0;
111    
112         /* You don't have to be root to use DGA extensions. Simply having access to /dev/mem will do the trick */
113         /* This can be achieved by adding the user to the "kmem" group on Debian 2.x systems, don't know about */
114         /* others. --stephenc */
115         if ((fd = open("/dev/mem", O_RDWR)) != -1)
116           close(fd);
117
118         return (fd != -1) && TSXF86DGAQueryExtension(display,&evbase,&evret);
119 #else /* defined(HAVE_LIBXXF86DGA) */
120         return 0;
121 #endif /* defined(HAVE_LIBXXF86DGA) */
122 }
123
124 HRESULT WINAPI
125 DirectDrawEnumerate32A(LPDDENUMCALLBACK32A ddenumproc,LPVOID data) {
126         if (DDRAW_DGA_Available()) {
127           TRACE(ddraw, "Enumerating DGA interface\n");
128                 ddenumproc(&DGA_DirectDraw_GUID,"WINE with XFree86 DGA","display",data);
129         }
130         TRACE(ddraw, "Enumerating Xlib interface\n");
131         ddenumproc(&XLIB_DirectDraw_GUID,"WINE with Xlib","display",data);
132         TRACE(ddraw, "Enumerating Default interface\n");
133         ddenumproc(NULL,"WINE (default)","display",data);
134         return DD_OK;
135 }
136
137 /* What is this doing here? */
138 HRESULT WINAPI 
139 DSoundHelp(DWORD x,DWORD y,DWORD z) {
140         FIXME(ddraw,"(0x%08lx,0x%08lx,0x%08lx),stub!\n",x,y,z);
141         return 0;
142 }
143
144
145 /******************************************************************************
146  *              internal helper functions
147  */
148 static void _dump_DDBLTFX(DWORD flagmask) {
149         int     i;
150         const struct {
151                 DWORD   mask;
152                 char    *name;
153         } flags[] = {
154 #define FE(x) { x, #x},
155                 FE(DDBLTFX_ARITHSTRETCHY)
156                 FE(DDBLTFX_MIRRORLEFTRIGHT)
157                 FE(DDBLTFX_MIRRORUPDOWN)
158                 FE(DDBLTFX_NOTEARING)
159                 FE(DDBLTFX_ROTATE180)
160                 FE(DDBLTFX_ROTATE270)
161                 FE(DDBLTFX_ROTATE90)
162                 FE(DDBLTFX_ZBUFFERRANGE)
163                 FE(DDBLTFX_ZBUFFERBASEDEST)
164         };
165         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
166            if (flags[i].mask & flagmask) {
167               DUMP("%s ",flags[i].name);
168               
169            };
170         DUMP("\n");
171         
172 }
173
174 static void _dump_DDBLTFAST(DWORD flagmask) {
175         int     i;
176         const struct {
177                 DWORD   mask;
178                 char    *name;
179         } flags[] = {
180 #define FE(x) { x, #x},
181                 FE(DDBLTFAST_NOCOLORKEY)
182                 FE(DDBLTFAST_SRCCOLORKEY)
183                 FE(DDBLTFAST_DESTCOLORKEY)
184                 FE(DDBLTFAST_WAIT)
185         };
186         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
187                 if (flags[i].mask & flagmask)
188                         DUMP("%s ",flags[i].name);
189         DUMP("\n");
190 }
191
192 static void _dump_DDBLT(DWORD flagmask) {
193         int     i;
194         const struct {
195                 DWORD   mask;
196                 char    *name;
197         } flags[] = {
198 #define FE(x) { x, #x},
199                 FE(DDBLT_ALPHADEST)
200                 FE(DDBLT_ALPHADESTCONSTOVERRIDE)
201                 FE(DDBLT_ALPHADESTNEG)
202                 FE(DDBLT_ALPHADESTSURFACEOVERRIDE)
203                 FE(DDBLT_ALPHAEDGEBLEND)
204                 FE(DDBLT_ALPHASRC)
205                 FE(DDBLT_ALPHASRCCONSTOVERRIDE)
206                 FE(DDBLT_ALPHASRCNEG)
207                 FE(DDBLT_ALPHASRCSURFACEOVERRIDE)
208                 FE(DDBLT_ASYNC)
209                 FE(DDBLT_COLORFILL)
210                 FE(DDBLT_DDFX)
211                 FE(DDBLT_DDROPS)
212                 FE(DDBLT_KEYDEST)
213                 FE(DDBLT_KEYDESTOVERRIDE)
214                 FE(DDBLT_KEYSRC)
215                 FE(DDBLT_KEYSRCOVERRIDE)
216                 FE(DDBLT_ROP)
217                 FE(DDBLT_ROTATIONANGLE)
218                 FE(DDBLT_ZBUFFER)
219                 FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE)
220                 FE(DDBLT_ZBUFFERDESTOVERRIDE)
221                 FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE)
222                 FE(DDBLT_ZBUFFERSRCOVERRIDE)
223                 FE(DDBLT_WAIT)
224                 FE(DDBLT_DEPTHFILL)
225         };
226         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
227                 if (flags[i].mask & flagmask)
228                         DUMP("%s ",flags[i].name);
229 }
230
231 static void _dump_DDSCAPS(DWORD flagmask) {
232         int     i;
233         const struct {
234                 DWORD   mask;
235                 char    *name;
236         } flags[] = {
237 #define FE(x) { x, #x},
238                 FE(DDSCAPS_RESERVED1)
239                 FE(DDSCAPS_ALPHA)
240                 FE(DDSCAPS_BACKBUFFER)
241                 FE(DDSCAPS_COMPLEX)
242                 FE(DDSCAPS_FLIP)
243                 FE(DDSCAPS_FRONTBUFFER)
244                 FE(DDSCAPS_OFFSCREENPLAIN)
245                 FE(DDSCAPS_OVERLAY)
246                 FE(DDSCAPS_PALETTE)
247                 FE(DDSCAPS_PRIMARYSURFACE)
248                 FE(DDSCAPS_PRIMARYSURFACELEFT)
249                 FE(DDSCAPS_SYSTEMMEMORY)
250                 FE(DDSCAPS_TEXTURE)
251                 FE(DDSCAPS_3DDEVICE)
252                 FE(DDSCAPS_VIDEOMEMORY)
253                 FE(DDSCAPS_VISIBLE)
254                 FE(DDSCAPS_WRITEONLY)
255                 FE(DDSCAPS_ZBUFFER)
256                 FE(DDSCAPS_OWNDC)
257                 FE(DDSCAPS_LIVEVIDEO)
258                 FE(DDSCAPS_HWCODEC)
259                 FE(DDSCAPS_MODEX)
260                 FE(DDSCAPS_MIPMAP)
261                 FE(DDSCAPS_RESERVED2)
262                 FE(DDSCAPS_ALLOCONLOAD)
263                 FE(DDSCAPS_VIDEOPORT)
264                 FE(DDSCAPS_LOCALVIDMEM)
265                 FE(DDSCAPS_NONLOCALVIDMEM)
266                 FE(DDSCAPS_STANDARDVGAMODE)
267                 FE(DDSCAPS_OPTIMIZED)
268         };
269         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
270                 if (flags[i].mask & flagmask)
271                         DUMP("%s ",flags[i].name);
272         DUMP("\n");
273 }
274
275 static void _dump_DDSD(DWORD flagmask) {
276         int     i;
277         const struct {
278                 DWORD   mask;
279                 char    *name;
280         } flags[] = {
281                 FE(DDSD_CAPS)
282                 FE(DDSD_HEIGHT)
283                 FE(DDSD_WIDTH)
284                 FE(DDSD_PITCH)
285                 FE(DDSD_BACKBUFFERCOUNT)
286                 FE(DDSD_ZBUFFERBITDEPTH)
287                 FE(DDSD_ALPHABITDEPTH)
288                 FE(DDSD_PIXELFORMAT)
289                 FE(DDSD_CKDESTOVERLAY)
290                 FE(DDSD_CKDESTBLT)
291                 FE(DDSD_CKSRCOVERLAY)
292                 FE(DDSD_CKSRCBLT)
293                 FE(DDSD_MIPMAPCOUNT)
294                 FE(DDSD_REFRESHRATE)
295                 FE(DDSD_LINEARSIZE)
296                 FE(DDSD_LPSURFACE)
297         };
298         for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
299                 if (flags[i].mask & flagmask)
300                         DUMP("%s ",flags[i].name);
301         DUMP("\n");
302 }
303
304 static void _dump_DDCOLORKEY(DWORD flagmask) {
305         int     i;
306         const struct {
307                 DWORD   mask;
308                 char    *name;
309         } flags[] = {
310 #define FE(x) { x, #x},
311                 FE(DDPF_ALPHAPIXELS)
312                 FE(DDPF_ALPHA)
313                 FE(DDPF_FOURCC)
314                 FE(DDPF_PALETTEINDEXED4)
315                 FE(DDPF_PALETTEINDEXEDTO8)
316                 FE(DDPF_PALETTEINDEXED8)
317                 FE(DDPF_RGB)
318                 FE(DDPF_COMPRESSED)
319                 FE(DDPF_RGBTOYUV)
320                 FE(DDPF_YUV)
321                 FE(DDPF_ZBUFFER)
322                 FE(DDPF_PALETTEINDEXED1)
323                 FE(DDPF_PALETTEINDEXED2)
324                 FE(DDPF_ZPIXELS)
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_pixelformat(LPDDPIXELFORMAT pf) {
333   DUMP("Size : %ld\n", pf->dwSize);
334   if (pf->dwFlags)
335   _dump_DDCOLORKEY(pf->dwFlags);
336   DUMP("dwFourCC : %ld\n", pf->dwFourCC);
337   DUMP("RGB bit count : %ld\n", pf->x.dwRGBBitCount);
338   DUMP("Masks : R %08lx  G %08lx  B %08lx  A %08lx\n",
339        pf->y.dwRBitMask, pf->z.dwGBitMask, pf->xx.dwBBitMask, pf->xy.dwRGBAlphaBitMask);
340 }
341
342 static int _getpixelformat(LPDIRECTDRAW2 ddraw,LPDDPIXELFORMAT pf) {
343         static XVisualInfo      *vi;
344         XVisualInfo             vt;
345         int                     nitems;
346
347         if (!vi)
348                 vi = TSXGetVisualInfo(display,VisualNoMask,&vt,&nitems);
349
350         pf->dwFourCC = 0;
351         pf->dwSize = sizeof(DDPIXELFORMAT);
352         if (ddraw->d.depth==8) {
353                 pf->dwFlags             = DDPF_RGB|DDPF_PALETTEINDEXED8;
354                 pf->x.dwRGBBitCount     = 8;
355                 pf->y.dwRBitMask        = 0;
356                 pf->z.dwGBitMask        = 0;
357                 pf->xx.dwBBitMask       = 0;
358                 pf->xy.dwRGBAlphaBitMask= 0;
359                 return 0;
360         }
361         if (ddraw->d.depth==16) {
362                 pf->dwFlags             = DDPF_RGB;
363                 pf->x.dwRGBBitCount     = 16;
364                 pf->y.dwRBitMask        = vi[0].red_mask;
365                 pf->z.dwGBitMask        = vi[0].green_mask;
366                 pf->xx.dwBBitMask       = vi[0].blue_mask;
367                 pf->xy.dwRGBAlphaBitMask= 0;
368                 return 0;
369         }
370         FIXME(ddraw,"_getpixelformat:unknown depth %ld?\n",ddraw->d.depth);
371         return DDERR_GENERIC;
372 }
373
374 /******************************************************************************
375  *              IDirectDrawSurface,IDirectDrawSurface2,IDirectDrawSurface3
376  *
377  * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
378  * DDS and DDS2 use those functions. (Function calls did not change (except
379  * using different DirectDrawSurfaceX version), just added flags and functions)
380  */
381 static HRESULT WINAPI IDirectDrawSurface3_Lock(
382     LPDIRECTDRAWSURFACE3 this,LPRECT32 lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE32 hnd
383 ) {
384         TRACE(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
385                 this,lprect,lpddsd,flags,(DWORD)hnd);
386         if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
387             WARN(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
388                          this,lprect,lpddsd,flags,(DWORD)hnd);
389
390         /* First, copy the Surface description */
391         *lpddsd = this->s.surface_desc;
392
393         /* If asked only for a part, change the surface pointer */
394         if (lprect) {
395                 FIXME(ddraw,"   lprect: %dx%d-%dx%d\n",
396                         lprect->top,lprect->left,lprect->bottom,lprect->right
397                 );
398                 lpddsd->y.lpSurface = this->s.surface_desc.y.lpSurface +
399                         (lprect->top*this->s.surface_desc.lPitch) +
400                         (lprect->left*(this->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8));
401         } else {
402                 assert(this->s.surface_desc.y.lpSurface);
403         }
404         return DD_OK;
405 }
406
407 static HRESULT WINAPI DGA_IDirectDrawSurface3_Unlock(
408         LPDIRECTDRAWSURFACE3 this,LPVOID surface
409 ) {
410         TRACE(ddraw,"(%p)->Unlock(%p)\n",this,surface);
411         return DD_OK;
412 }
413
414 static HRESULT WINAPI Xlib_IDirectDrawSurface3_Unlock(
415         LPDIRECTDRAWSURFACE3 this,LPVOID surface)
416 {
417         TRACE(ddraw,"(%p)->Unlock(%p)\n",this,surface);
418
419         if (!this->s.ddraw->d.paintable)
420                 return DD_OK;
421
422   /* Only redraw the screen when unlocking the buffer that is on screen */
423         if ((this->t.xlib.image != NULL) &&
424             (this->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_VISIBLE)) {
425 #ifdef HAVE_LIBXXSHM
426     if (this->s.ddraw->e.xlib.xshm_active)
427       TSXShmPutImage(display,
428                      this->s.ddraw->d.drawable,
429                      DefaultGCOfScreen(screen),
430                      this->t.xlib.image,
431                      0, 0, 0, 0,
432                      this->t.xlib.image->width,
433                      this->t.xlib.image->height,
434                      False);
435     else
436 #endif
437         TSXPutImage(            display,
438                                 this->s.ddraw->d.drawable,
439                                 DefaultGCOfScreen(screen),
440                                 this->t.xlib.image,
441                                 0, 0, 0, 0,
442                                 this->t.xlib.image->width,
443                   this->t.xlib.image->height);
444   
445         if (this->s.palette && this->s.palette->cm)
446                 TSXSetWindowColormap(display,this->s.ddraw->d.drawable,this->s.palette->cm);
447         }
448
449         return DD_OK;
450 }
451
452 static HRESULT WINAPI DGA_IDirectDrawSurface3_Flip(
453         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWSURFACE3 flipto,DWORD dwFlags
454 ) {
455 #ifdef HAVE_LIBXXF86DGA
456         TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",this,flipto,dwFlags);
457         if (!flipto) {
458                 if (this->s.backbuffer)
459                         flipto = this->s.backbuffer;
460                 else
461                         flipto = this;
462         }
463         TSXF86DGASetViewPort(display,DefaultScreen(display),0,flipto->t.dga.fb_height);
464
465         if (flipto->s.palette && flipto->s.palette->cm) {
466                 TSXF86DGAInstallColormap(display,DefaultScreen(display),flipto->s.palette->cm);
467         }
468         while (!TSXF86DGAViewPortChanged(display,DefaultScreen(display),2)) {
469         }
470         if (flipto!=this) {
471                 int     tmp;
472                 LPVOID  ptmp;
473
474                 tmp = this->t.dga.fb_height;
475                 this->t.dga.fb_height = flipto->t.dga.fb_height;
476                 flipto->t.dga.fb_height = tmp;
477
478                 ptmp = this->s.surface_desc.y.lpSurface;
479                 this->s.surface_desc.y.lpSurface = flipto->s.surface_desc.y.lpSurface;
480                 flipto->s.surface_desc.y.lpSurface = ptmp;
481         }
482         return DD_OK;
483 #else /* defined(HAVE_LIBXXF86DGA) */
484         return E_UNEXPECTED;
485 #endif /* defined(HAVE_LIBXXF86DGA) */
486 }
487
488 static HRESULT WINAPI Xlib_IDirectDrawSurface3_Flip(
489         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWSURFACE3 flipto,DWORD dwFlags
490 ) {
491         TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",this,flipto,dwFlags);
492         if (!this->s.ddraw->d.paintable)
493                 return DD_OK;
494
495         if (!flipto) {
496                 if (this->s.backbuffer)
497                         flipto = this->s.backbuffer;
498                 else
499                         flipto = this;
500         }
501   
502 #ifdef HAVE_LIBXXSHM
503         if (this->s.ddraw->e.xlib.xshm_active) {
504           TSXShmPutImage(display,
505                          this->s.ddraw->d.drawable,
506                          DefaultGCOfScreen(screen),
507                          flipto->t.xlib.image,
508                          0, 0, 0, 0,
509                          flipto->t.xlib.image->width,
510                          flipto->t.xlib.image->height,
511                          False);
512         } else
513 #endif
514         TSXPutImage(display,
515                                 this->s.ddraw->d.drawable,
516                                 DefaultGCOfScreen(screen),
517                                 flipto->t.xlib.image,
518                                 0, 0, 0, 0,
519                                 flipto->t.xlib.image->width,
520                                 flipto->t.xlib.image->height);
521         
522         if (flipto->s.palette && flipto->s.palette->cm) {
523           TSXSetWindowColormap(display,this->s.ddraw->d.drawable,flipto->s.palette->cm);
524         }
525         if (flipto!=this) {
526                 XImage *tmp;
527                 LPVOID  *surf;
528                 tmp = this->t.xlib.image;
529                 this->t.xlib.image = flipto->t.xlib.image;
530                 flipto->t.xlib.image = tmp;
531                 surf = this->s.surface_desc.y.lpSurface;
532                 this->s.surface_desc.y.lpSurface = flipto->s.surface_desc.y.lpSurface;
533                 flipto->s.surface_desc.y.lpSurface = surf;
534         }
535         return DD_OK;
536 }
537
538
539 /* The IDirectDrawSurface3::SetPalette method attaches the specified
540  * DirectDrawPalette object to a surface. The surface uses this palette for all
541  * subsequent operations. The palette change takes place immediately.
542  */
543 static HRESULT WINAPI Xlib_IDirectDrawSurface3_SetPalette(
544         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWPALETTE pal
545 ) {
546         int i;
547         TRACE(ddraw,"(%p)->(%p)\n",this,pal);
548
549         if (pal == NULL) {
550           if( this->s.palette != NULL )
551             this->s.palette->lpvtbl->fnRelease( this->s.palette );
552           this->s.palette = pal;
553
554           return DD_OK;
555         }
556         
557         if( !(pal->cm) && (this->s.ddraw->d.depth<=8)) 
558         {
559                 pal->cm = TSXCreateColormap(display,this->s.ddraw->d.drawable,DefaultVisualOfScreen(screen),AllocAll);
560
561                 if (!Options.managed)
562                         TSXInstallColormap(display,pal->cm);
563
564                 for (i=0;i<256;i++) {
565                         XColor xc;
566
567                         xc.red = pal->palents[i].peRed<<8;
568                         xc.blue = pal->palents[i].peBlue<<8;
569                         xc.green = pal->palents[i].peGreen<<8;
570                         xc.flags = DoRed|DoBlue|DoGreen;
571                         xc.pixel = i;
572                         TSXStoreColor(display,pal->cm,&xc);
573                 }
574                 TSXInstallColormap(display,pal->cm);
575         }
576
577         /* According to spec, we are only supposed to 
578          * AddRef if this is not the same palette.
579          */
580         if( this->s.palette != pal )
581         {
582           if( pal != NULL )
583             pal->lpvtbl->fnAddRef( pal );
584           if( this->s.palette != NULL )
585             this->s.palette->lpvtbl->fnRelease( this->s.palette );
586           this->s.palette = pal; 
587
588           /* I think that we need to attach it to all backbuffers...*/
589           if( this->s.backbuffer ) {
590              if( this->s.backbuffer->s.palette )
591                this->s.backbuffer->s.palette->lpvtbl->fnRelease(
592                  this->s.backbuffer->s.palette );
593              this->s.backbuffer->s.palette = pal;
594              if( pal )
595                 pal->lpvtbl->fnAddRef( pal );
596            }
597           /* Perform the refresh */
598           TSXSetWindowColormap(display,this->s.ddraw->d.drawable,this->s.palette->cm);
599         }
600         return DD_OK;
601 }
602
603 static HRESULT WINAPI DGA_IDirectDrawSurface3_SetPalette(
604         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWPALETTE pal
605 ) {
606         TRACE(ddraw,"(%p)->(%p)\n",this,pal);
607 #ifdef HAVE_LIBXXF86DGA
608         /* According to spec, we are only supposed to 
609          * AddRef if this is not the same palette.
610          */
611         if( this->s.palette != pal )
612         {
613           if( pal != NULL ) 
614                 pal->lpvtbl->fnAddRef( pal );
615           if( this->s.palette != NULL )
616             this->s.palette->lpvtbl->fnRelease( this->s.palette );
617           this->s.palette = pal; 
618
619           /* I think that we need to attach it to all backbuffers...*/
620           if( this->s.backbuffer ) {
621              if( this->s.backbuffer->s.palette )
622                this->s.backbuffer->s.palette->lpvtbl->fnRelease(this->s.backbuffer->s.palette );
623              this->s.backbuffer->s.palette = pal;
624              if( pal ) pal->lpvtbl->fnAddRef( pal );
625           }
626           TSXF86DGAInstallColormap(display,DefaultScreen(display),this->s.palette->cm);
627         }
628         return DD_OK;
629 #else /* defined(HAVE_LIBXXF86DGA) */
630         return E_UNEXPECTED;
631 #endif /* defined(HAVE_LIBXXF86DGA) */
632
633
634 }
635
636 static HRESULT WINAPI IDirectDrawSurface3_Blt(
637         LPDIRECTDRAWSURFACE3 this,LPRECT32 rdst,LPDIRECTDRAWSURFACE3 src,LPRECT32 rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
638 ) {
639         RECT32  xdst,xsrc;
640         DDSURFACEDESC   ddesc,sdesc;
641         int     i,j;
642
643           TRACE(ddraw,"(%p)->(%p,%p,%p,%08lx,%p)\n",
644                 this,rdst,src,rsrc,dwFlags,lpbltfx);
645
646         if (src != NULL)
647           src ->lpvtbl->fnLock(src, NULL,&sdesc,0,0);
648         this->lpvtbl->fnLock(this,NULL,&ddesc,0,0);
649         
650         if (TRACE_ON(ddraw)) {
651           if (rdst) TRACE(ddraw,"       destrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
652           if (rsrc) TRACE(ddraw,"       srcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
653           TRACE(ddraw,"\tflags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n");
654           if (dwFlags & DDBLT_DDFX) {
655             TRACE(ddraw,"       blitfx: \n");_dump_DDBLTFX(lpbltfx->dwDDFX);
656           }
657         }
658                 
659         if (rdst) {
660                 memcpy(&xdst,rdst,sizeof(xdst));
661         } else {
662                 xdst.top        = 0;
663                 xdst.bottom     = ddesc.dwHeight;
664                 xdst.left       = 0;
665                 xdst.right      = ddesc.dwWidth;
666         }
667
668         if (rsrc) {
669                 memcpy(&xsrc,rsrc,sizeof(xsrc));
670         } else {
671                 if (src) {
672                 xsrc.top        = 0;
673                 xsrc.bottom     = sdesc.dwHeight;
674                 xsrc.left       = 0;
675                 xsrc.right      = sdesc.dwWidth;
676                 } else {
677                     memset(&xsrc,0,sizeof(xsrc));
678                 }
679         }
680
681         dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
682         
683         if (dwFlags & DDBLT_COLORFILL) {
684                 int     bpp = ddesc.ddpfPixelFormat.x.dwRGBBitCount / 8;
685                 LPBYTE  xline,xpixel;
686
687                 xline = (LPBYTE) ddesc.y.lpSurface + xdst.top * ddesc.lPitch;
688                 for (i=xdst.top;i<xdst.bottom;i++) {
689                         xpixel = xline+bpp*xdst.left;
690
691                         for (j=xdst.left;j<xdst.right;j++) {
692                                 /* FIXME: this only works on little endian
693                                  * architectures, where DWORD starts with low
694                                  * byte first!
695                                  */
696                                 memcpy(xpixel,&(lpbltfx->b.dwFillColor),bpp);
697                                 xpixel += bpp;
698                         }
699                         xline += ddesc.lPitch;
700                 }
701                 dwFlags &= ~(DDBLT_COLORFILL);
702         }
703
704         if (!src) {
705             if (dwFlags) {
706               TRACE(ddraw,"\t(src=NULL):Unsupported flags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n");
707             }
708             this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
709             return DD_OK;
710         }
711
712         if (    (xsrc.top ==0) && (xsrc.bottom ==ddesc.dwHeight) &&
713                 (xsrc.left==0) && (xsrc.right  ==ddesc.dwWidth) &&
714                 (xdst.top ==0) && (xdst.bottom ==ddesc.dwHeight) &&
715                 (xdst.left==0) && (xdst.right  ==ddesc.dwWidth)  &&
716                 !dwFlags
717         ) {
718                 memcpy(ddesc.y.lpSurface,
719                        sdesc.y.lpSurface,
720                        ddesc.dwHeight * ddesc.lPitch);
721         } else {
722           int bpp = ddesc.ddpfPixelFormat.x.dwRGBBitCount / 8;
723           int srcheight = xsrc.bottom - xsrc.top;
724           int srcwidth = xsrc.right - xsrc.left;
725           int dstheight = xdst.bottom - xdst.top;
726           int dstwidth = xdst.right - xdst.left;
727           int width = (xsrc.right - xsrc.left) * bpp;
728           int h;
729
730           /* Sanity check for rectangle sizes */
731           if ((srcheight != dstheight) || (srcwidth  != dstwidth)) {
732             int x, y;
733             
734             /* I think we should do a Blit with 'stretching' here....
735                Tomb Raider II uses this to display the background during the menu selection
736                when the screen resolution is != than 40x480 */
737             TRACE(ddraw, "Blt with stretching\n");
738
739             /* This is a basic stretch implementation. It is painfully slow and quite ugly. */
740             if (bpp == 1) {
741               /* In this case, we cannot do any anti-aliasing */
742               for (y = xdst.top; y < xdst.bottom; y++) {
743                 for (x = xdst.left; x < xdst.right; x++) {
744                   double sx, sy;
745                   unsigned char *dbuf = (unsigned char *) ddesc.y.lpSurface;
746                   unsigned char *sbuf = (unsigned char *) sdesc.y.lpSurface;
747
748                   sx = (((double) (x - xdst.left) / dstwidth) * srcwidth) + xsrc.left;
749                   sy = (((double) (y - xdst.top) / dstheight) * srcheight) + xsrc.top;
750                   
751                   dbuf[(y * ddesc.lPitch) + x] = sbuf[(((int) sy) * sdesc.lPitch) + ((int) sx)];
752                 }
753               }
754             } else {
755               FIXME(ddraw, "Not done yet for depth != 8\n");
756             }
757           } else {
758             /* Same size => fast blit */
759             for (h = 0; h < srcheight; h++) {
760             memcpy(ddesc.y.lpSurface + ((h + xdst.top) * ddesc.lPitch) + xdst.left * bpp,
761                    sdesc.y.lpSurface + ((h + xsrc.top) * sdesc.lPitch) + xsrc.left * bpp,
762                    width);
763           }
764         }
765         }
766         
767         if (dwFlags && FIXME_ON(ddraw)) {
768           FIXME(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags);
769         }
770
771         this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
772         src ->lpvtbl->fnUnlock(src,sdesc.y.lpSurface);
773
774         return DD_OK;
775 }
776
777 static HRESULT WINAPI IDirectDrawSurface3_BltFast(
778         LPDIRECTDRAWSURFACE3 this,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE3 src,LPRECT32 rsrc,DWORD trans
779 ) {
780         int             i,bpp,w,h;
781         DDSURFACEDESC   ddesc,sdesc;
782
783         if (1  || TRACE_ON(ddraw)) {
784             FIXME(ddraw,"(%p)->(%ld,%ld,%p,%p,%08lx)\n",
785                     this,dstx,dsty,src,rsrc,trans
786             );
787             FIXME(ddraw,"       trans:");_dump_DDBLTFAST(trans);fprintf(stderr,"\n");
788             FIXME(ddraw,"       srcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
789         }
790         /* We need to lock the surfaces, or we won't get refreshes when done. */
791         src ->lpvtbl->fnLock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
792         this->lpvtbl->fnLock(this,NULL,&ddesc,DDLOCK_WRITEONLY,0);
793         bpp = this->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8;
794         h=rsrc->bottom-rsrc->top;
795         if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
796         if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
797         if (h<0) h=0;
798         w=rsrc->right-rsrc->left;
799         if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
800         if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
801         if (w<0) w=0;
802
803         for (i=0;i<h;i++) {
804                 memcpy( ddesc.y.lpSurface+(dsty     +i)*ddesc.lPitch+dstx*bpp,
805                         sdesc.y.lpSurface+(rsrc->top+i)*sdesc.lPitch+rsrc->left*bpp,
806                         w*bpp
807                 );
808         }
809         this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
810         src ->lpvtbl->fnUnlock(src,sdesc.y.lpSurface);
811         return DD_OK;
812 }
813
814 static HRESULT WINAPI IDirectDrawSurface3_BltBatch(
815         LPDIRECTDRAWSURFACE3 this,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
816 ) {
817         FIXME(ddraw,"(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",
818                 this,ddbltbatch,x,y
819         );
820         return DD_OK;
821 }
822
823 static HRESULT WINAPI IDirectDrawSurface3_GetCaps(
824         LPDIRECTDRAWSURFACE3 this,LPDDSCAPS caps
825 ) {
826         TRACE(ddraw,"(%p)->GetCaps(%p)\n",this,caps);
827         caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
828         return DD_OK;
829 }
830
831 static HRESULT WINAPI IDirectDrawSurface3_GetSurfaceDesc(
832         LPDIRECTDRAWSURFACE3 this,LPDDSURFACEDESC ddsd
833 ) { 
834                 TRACE(ddraw, "(%p)->GetSurfaceDesc(%p)\n",
835                              this,ddsd);
836   
837   /* Simply copy the surface description stored in the object */
838   *ddsd = this->s.surface_desc;
839   
840   if (TRACE_ON(ddraw)) {
841                 fprintf(stderr,"        flags: ");
842                 _dump_DDSD(ddsd->dwFlags);
843     if (ddsd->dwFlags & DDSD_CAPS) {
844       fprintf(stderr, "  caps:  ");
845       _dump_DDSCAPS(ddsd->ddsCaps.dwCaps);
846     }
847                 fprintf(stderr,"\n");
848         }
849
850         return DD_OK;
851 }
852
853 static ULONG WINAPI IDirectDrawSurface3_AddRef(LPDIRECTDRAWSURFACE3 this) {
854         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
855
856         return ++(this->ref);
857 }
858
859 static ULONG WINAPI DGA_IDirectDrawSurface3_Release(LPDIRECTDRAWSURFACE3 this) {
860         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
861
862 #ifdef HAVE_LIBXXF86DGA
863         if (!--(this->ref)) {
864                 this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw);
865                 /* clear out of surface list */
866                 if (this->t.dga.fb_height == -1) {
867                         HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
868                 } else {
869                         this->s.ddraw->e.dga.vpmask &= ~(1<<(this->t.dga.fb_height/this->s.ddraw->e.dga.fb_height));
870                 }
871
872                 /* Free the backbuffer */
873                 if (this->s.backbuffer)
874                         this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer);
875
876                 HeapFree(GetProcessHeap(),0,this);
877                 return 0;
878         }
879 #endif /* defined(HAVE_LIBXXF86DGA) */
880         return this->ref;
881 }
882
883 static ULONG WINAPI Xlib_IDirectDrawSurface3_Release(LPDIRECTDRAWSURFACE3 this) {
884         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
885
886         if (!--(this->ref)) {
887                 this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw);
888
889                 if( this->s.backbuffer )
890                   this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer);
891
892     if (this->t.xlib.image != NULL) {
893                 this->t.xlib.image->data = NULL;
894       
895 #ifdef HAVE_LIBXXSHM
896       if (this->s.ddraw->e.xlib.xshm_active) {
897         TSXShmDetach(display, &(this->t.xlib.shminfo));
898                 TSXDestroyImage(this->t.xlib.image);
899         shmdt(this->t.xlib.shminfo.shmaddr);
900       } else {
901 #endif
902               HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
903         TSXDestroyImage(this->t.xlib.image);
904 #ifdef HAVE_LIBXXSHM    
905       }
906 #endif
907       
908                 this->t.xlib.image = 0;
909     } else {
910             HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
911     }
912
913                 if (this->s.palette)
914                         this->s.palette->lpvtbl->fnRelease(this->s.palette);
915
916                 HeapFree(GetProcessHeap(),0,this);
917                 return 0;
918         }
919   
920         return this->ref;
921 }
922
923 static HRESULT WINAPI IDirectDrawSurface3_GetAttachedSurface(
924         LPDIRECTDRAWSURFACE3 this,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE3 *lpdsf
925 ) {
926         TRACE(ddraw, "(%p)->GetAttachedSurface(%p,%p)\n",
927                      this, lpddsd, lpdsf);
928
929         if (TRACE_ON(ddraw)) {
930                 TRACE(ddraw,"   caps ");
931                 _dump_DDSCAPS(lpddsd->dwCaps);
932         }
933
934         if (!(lpddsd->dwCaps & DDSCAPS_BACKBUFFER)) {
935                 FIXME(ddraw,"whoops, can only handle backbuffers for now\n");
936                 return E_FAIL;
937         }
938
939         /* FIXME: should handle more than one backbuffer */
940         *lpdsf = this->s.backbuffer;
941  
942         if( this->s.backbuffer )
943           this->s.backbuffer->lpvtbl->fnAddRef( this->s.backbuffer );
944
945         return DD_OK;
946 }
947
948 static HRESULT WINAPI IDirectDrawSurface3_Initialize(
949         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
950 ) {
951         TRACE(ddraw,"(%p)->(%p, %p)\n",this,ddraw,lpdsfd);
952
953         return DDERR_ALREADYINITIALIZED;
954 }
955
956 static HRESULT WINAPI IDirectDrawSurface3_GetPixelFormat(
957         LPDIRECTDRAWSURFACE3 this,LPDDPIXELFORMAT pf
958 ) {
959         TRACE(ddraw,"(%p)->(%p)\n",this,pf);
960
961         *pf = this->s.surface_desc.ddpfPixelFormat;
962         
963         return DD_OK;
964 }
965
966 static HRESULT WINAPI IDirectDrawSurface3_GetBltStatus(LPDIRECTDRAWSURFACE3 this,DWORD dwFlags) {
967         FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",this,dwFlags);
968         return DD_OK;
969 }
970
971 static HRESULT WINAPI IDirectDrawSurface3_GetOverlayPosition(
972         LPDIRECTDRAWSURFACE3 this,LPLONG x1,LPLONG x2
973 ) {
974         FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,x1,x2);
975         return DD_OK;
976 }
977
978 static HRESULT WINAPI IDirectDrawSurface3_SetClipper(
979         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWCLIPPER clipper
980 ) {
981         FIXME(ddraw,"(%p)->(%p),stub!\n",this,clipper);
982         return DD_OK;
983 }
984
985 static HRESULT WINAPI IDirectDrawSurface3_AddAttachedSurface(
986         LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWSURFACE3 surf
987 ) {
988         FIXME(ddraw,"(%p)->(%p),stub!\n",this,surf);
989
990         /* This hack will be enough for the moment */
991         if (this->s.backbuffer == NULL)
992         this->s.backbuffer = surf;
993         return DD_OK;
994 }
995
996 static HRESULT WINAPI IDirectDrawSurface3_GetDC(LPDIRECTDRAWSURFACE3 this,HDC32* lphdc) {
997         FIXME(ddraw,"(%p)->GetDC(%p)\n",this,lphdc);
998         *lphdc = BeginPaint32(this->s.ddraw->d.window,&this->s.ddraw->d.ps);
999         return DD_OK;
1000 }
1001
1002 static HRESULT WINAPI IDirectDrawSurface3_ReleaseDC(LPDIRECTDRAWSURFACE3 this,HDC32 hdc) {
1003         FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",this,(long)hdc);
1004         EndPaint32(this->s.ddraw->d.window,&this->s.ddraw->d.ps);
1005         return DD_OK;
1006 }
1007
1008
1009 static HRESULT WINAPI IDirectDrawSurface3_QueryInterface(LPDIRECTDRAWSURFACE3 this,REFIID refiid,LPVOID *obj) {
1010         char    xrefiid[50];
1011
1012         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1013         TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
1014         
1015         /* DirectDrawSurface,DirectDrawSurface2 and DirectDrawSurface3 use
1016          * the same interface. And IUnknown does that too of course.
1017          */
1018         if (    !memcmp(&IID_IDirectDrawSurface3,refiid,sizeof(IID))    ||
1019                 !memcmp(&IID_IDirectDrawSurface2,refiid,sizeof(IID))    ||
1020                 !memcmp(&IID_IDirectDrawSurface,refiid,sizeof(IID))     ||
1021                 !memcmp(&IID_IUnknown,refiid,sizeof(IID))
1022         ) {
1023                 *obj = this;
1024                 this->lpvtbl->fnAddRef(this);
1025
1026                 TRACE(ddraw, "  Creating IDirect3DSurfaceX interface (%p)\n", *obj);
1027                 
1028                 return S_OK;
1029         }
1030         else if (!memcmp(&IID_IDirect3DTexture2,refiid,sizeof(IID)))
1031           {
1032             /* Texture interface */
1033             *obj = d3dtexture2_create(this);
1034             this->lpvtbl->fnAddRef(this);
1035             
1036             TRACE(ddraw, "  Creating IDirect3DTexture2 interface (%p)\n", *obj);
1037             
1038             return S_OK;
1039           }
1040         else if (!memcmp(&IID_IDirect3DTexture,refiid,sizeof(IID)))
1041           {
1042             /* Texture interface */
1043             *obj = d3dtexture_create(this);
1044             this->lpvtbl->fnAddRef(this);
1045             
1046             TRACE(ddraw, "  Creating IDirect3DTexture interface (%p)\n", *obj);
1047             
1048             return S_OK;
1049           }
1050         else if (is_OpenGL_dx3(refiid, (LPDIRECTDRAWSURFACE) this, (LPDIRECT3DDEVICE *) obj))
1051           {
1052             /* It is the OpenGL Direct3D Device */
1053             this->lpvtbl->fnAddRef(this);
1054
1055             TRACE(ddraw, "  Creating IDirect3DDevice interface (%p)\n", *obj);
1056                         
1057                 return S_OK;
1058         }
1059         
1060         FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",this,xrefiid);
1061         return OLE_E_ENUM_NOMORE;
1062 }
1063
1064 static HRESULT WINAPI IDirectDrawSurface3_IsLost(LPDIRECTDRAWSURFACE3 this) {
1065         TRACE(ddraw,"(%p)->(), stub!\n",this);
1066         return DD_OK; /* hmm */
1067 }
1068
1069 static HRESULT WINAPI IDirectDrawSurface3_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE3 this,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb) {
1070         FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,context,esfcb);
1071         return DD_OK;
1072 }
1073
1074 static HRESULT WINAPI IDirectDrawSurface3_Restore(LPDIRECTDRAWSURFACE3 this) {
1075         FIXME(ddraw,"(%p)->(),stub!\n",this);
1076         return DD_OK;
1077 }
1078
1079 static HRESULT WINAPI IDirectDrawSurface3_SetColorKey(
1080         LPDIRECTDRAWSURFACE3 this, DWORD dwFlags, LPDDCOLORKEY ckey ) 
1081 {
1082         TRACE(ddraw,"(%p)->(0x%08lx,%p)\n",this,dwFlags,ckey);
1083
1084         if( dwFlags & DDCKEY_SRCBLT )
1085         {
1086            dwFlags &= ~DDCKEY_SRCBLT;
1087            this->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
1088            memcpy( &(this->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
1089         }
1090
1091         if( dwFlags & DDCKEY_DESTBLT )
1092         {
1093            dwFlags &= ~DDCKEY_DESTBLT;
1094            this->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
1095            memcpy( &(this->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
1096         }
1097
1098         if( dwFlags & DDCKEY_SRCOVERLAY )
1099         {
1100            dwFlags &= ~DDCKEY_SRCOVERLAY;
1101            this->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1102            memcpy( &(this->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );      
1103         }
1104         
1105         if( dwFlags & DDCKEY_DESTOVERLAY )
1106         {
1107            dwFlags &= ~DDCKEY_DESTOVERLAY;
1108            this->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1109            memcpy( &(this->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );     
1110         }
1111
1112         if( dwFlags )
1113         {
1114           FIXME( ddraw, "unhandled dwFlags: 0x%08lx\n", dwFlags );
1115         }
1116
1117         return DD_OK;
1118
1119 }
1120
1121 static HRESULT WINAPI IDirectDrawSurface3_AddOverlayDirtyRect(
1122         LPDIRECTDRAWSURFACE3 this, 
1123         LPRECT32 lpRect )
1124 {
1125   FIXME(ddraw,"(%p)->(%p),stub!\n",this,lpRect); 
1126
1127   return DD_OK;
1128 }
1129
1130 static HRESULT WINAPI IDirectDrawSurface3_DeleteAttachedSurface(
1131         LPDIRECTDRAWSURFACE3 this, 
1132         DWORD dwFlags,
1133         LPDIRECTDRAWSURFACE3 lpDDSAttachedSurface )
1134 {
1135   FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n",this,dwFlags,lpDDSAttachedSurface);
1136
1137   return DD_OK;
1138 }
1139
1140 static HRESULT WINAPI IDirectDrawSurface3_EnumOverlayZOrders(
1141         LPDIRECTDRAWSURFACE3 this,
1142         DWORD dwFlags,
1143         LPVOID lpContext,
1144         LPDDENUMSURFACESCALLBACK lpfnCallback )
1145 {
1146   FIXME(ddraw,"(%p)->(0x%08lx,%p,%p),stub!\n", this,dwFlags,
1147           lpContext, lpfnCallback );
1148
1149   return DD_OK;
1150 }
1151
1152 static HRESULT WINAPI IDirectDrawSurface3_GetClipper(
1153         LPDIRECTDRAWSURFACE3 this,
1154         LPDIRECTDRAWCLIPPER* lplpDDClipper )
1155 {
1156   FIXME(ddraw,"(%p)->(%p),stub!\n", this, lplpDDClipper);
1157
1158   return DD_OK;
1159 }
1160
1161 static HRESULT WINAPI IDirectDrawSurface3_GetColorKey(
1162         LPDIRECTDRAWSURFACE3 this,
1163         DWORD dwFlags,
1164         LPDDCOLORKEY lpDDColorKey )
1165 {
1166   TRACE(ddraw,"(%p)->(0x%08lx,%p)\n", this, dwFlags, lpDDColorKey);
1167
1168   if( dwFlags & DDCKEY_SRCBLT )  {
1169      dwFlags &= ~DDCKEY_SRCBLT;
1170      memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
1171   }
1172
1173   if( dwFlags & DDCKEY_DESTBLT )
1174   {
1175     dwFlags &= ~DDCKEY_DESTBLT;
1176     memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
1177   }
1178
1179   if( dwFlags & DDCKEY_SRCOVERLAY )
1180   {
1181     dwFlags &= ~DDCKEY_SRCOVERLAY;
1182     memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
1183   }
1184
1185   if( dwFlags & DDCKEY_DESTOVERLAY )
1186   {
1187     dwFlags &= ~DDCKEY_DESTOVERLAY;
1188     memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
1189   }
1190
1191   if( dwFlags )
1192   {
1193     FIXME( ddraw, "unhandled dwFlags: 0x%08lx\n", dwFlags );
1194   }
1195
1196   return DD_OK;
1197 }
1198
1199 static HRESULT WINAPI IDirectDrawSurface3_GetFlipStatus(
1200         LPDIRECTDRAWSURFACE3 this,
1201         DWORD dwFlags ) 
1202 {
1203   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
1204
1205   return DD_OK;
1206 }
1207
1208 static HRESULT WINAPI IDirectDrawSurface3_GetPalette(
1209         LPDIRECTDRAWSURFACE3 this,
1210         LPDIRECTDRAWPALETTE* lplpDDPalette )
1211 {
1212   FIXME(ddraw,"(%p)->(%p),stub!\n", this, lplpDDPalette);
1213
1214   return DD_OK;
1215 }
1216
1217 static HRESULT WINAPI IDirectDrawSurface3_SetOverlayPosition(
1218         LPDIRECTDRAWSURFACE3 this,
1219         LONG lX,
1220         LONG lY)
1221 {
1222   FIXME(ddraw,"(%p)->(%ld,%ld),stub!\n", this, lX, lY);
1223
1224   return DD_OK;
1225 }
1226
1227 static HRESULT WINAPI IDirectDrawSurface3_UpdateOverlay(
1228         LPDIRECTDRAWSURFACE3 this,
1229         LPRECT32 lpSrcRect,
1230         LPDIRECTDRAWSURFACE3 lpDDDestSurface,
1231         LPRECT32 lpDestRect,
1232         DWORD dwFlags,
1233         LPDDOVERLAYFX lpDDOverlayFx )
1234 {
1235   FIXME(ddraw,"(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", this,
1236          lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
1237
1238   return DD_OK;
1239 }
1240  
1241 static HRESULT WINAPI IDirectDrawSurface3_UpdateOverlayDisplay(
1242         LPDIRECTDRAWSURFACE3 this,
1243         DWORD dwFlags )
1244 {
1245   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags); 
1246
1247   return DD_OK;
1248 }
1249
1250 static HRESULT WINAPI IDirectDrawSurface3_UpdateOverlayZOrder(
1251         LPDIRECTDRAWSURFACE3 this,
1252         DWORD dwFlags,
1253         LPDIRECTDRAWSURFACE3 lpDDSReference )
1254 {
1255   FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n", this, dwFlags, lpDDSReference);
1256
1257   return DD_OK;
1258 }
1259
1260 static HRESULT WINAPI IDirectDrawSurface3_GetDDInterface(
1261         LPDIRECTDRAWSURFACE3 this,
1262         LPVOID* lplpDD )
1263 {
1264   FIXME(ddraw,"(%p)->(%p),stub!\n", this, lplpDD);
1265
1266   /* Not sure about that... */
1267   *lplpDD = (void *) this->s.ddraw;
1268   
1269   return DD_OK;
1270 }
1271
1272 static HRESULT WINAPI IDirectDrawSurface3_PageLock(
1273         LPDIRECTDRAWSURFACE3 this,
1274         DWORD dwFlags )
1275 {
1276   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
1277
1278   return DD_OK;
1279 }
1280
1281 static HRESULT WINAPI IDirectDrawSurface3_PageUnlock(
1282         LPDIRECTDRAWSURFACE3 this,
1283         DWORD dwFlags )
1284 {
1285   FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
1286
1287   return DD_OK;
1288 }
1289
1290 static HRESULT WINAPI IDirectDrawSurface3_SetSurfaceDesc(
1291         LPDIRECTDRAWSURFACE3 this,
1292         LPDDSURFACEDESC lpDDSD,
1293         DWORD dwFlags )
1294 {
1295   FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n", this, lpDDSD, dwFlags);
1296
1297   return DD_OK;
1298 }
1299
1300 static struct IDirectDrawSurface3_VTable dga_dds3vt = {
1301         IDirectDrawSurface3_QueryInterface,
1302         IDirectDrawSurface3_AddRef,
1303         DGA_IDirectDrawSurface3_Release,
1304         IDirectDrawSurface3_AddAttachedSurface,
1305         IDirectDrawSurface3_AddOverlayDirtyRect,
1306         IDirectDrawSurface3_Blt,
1307         IDirectDrawSurface3_BltBatch,
1308         IDirectDrawSurface3_BltFast,
1309         IDirectDrawSurface3_DeleteAttachedSurface,
1310         IDirectDrawSurface3_EnumAttachedSurfaces,
1311         IDirectDrawSurface3_EnumOverlayZOrders,
1312         DGA_IDirectDrawSurface3_Flip,
1313         IDirectDrawSurface3_GetAttachedSurface,
1314         IDirectDrawSurface3_GetBltStatus,
1315         IDirectDrawSurface3_GetCaps,
1316         IDirectDrawSurface3_GetClipper,
1317         IDirectDrawSurface3_GetColorKey,
1318         IDirectDrawSurface3_GetDC,
1319         IDirectDrawSurface3_GetFlipStatus,
1320         IDirectDrawSurface3_GetOverlayPosition,
1321         IDirectDrawSurface3_GetPalette,
1322         IDirectDrawSurface3_GetPixelFormat,
1323         IDirectDrawSurface3_GetSurfaceDesc,
1324         IDirectDrawSurface3_Initialize,
1325         IDirectDrawSurface3_IsLost,
1326         IDirectDrawSurface3_Lock,
1327         IDirectDrawSurface3_ReleaseDC,
1328         IDirectDrawSurface3_Restore,
1329         IDirectDrawSurface3_SetClipper,
1330         IDirectDrawSurface3_SetColorKey,
1331         IDirectDrawSurface3_SetOverlayPosition,
1332         DGA_IDirectDrawSurface3_SetPalette,
1333         DGA_IDirectDrawSurface3_Unlock,
1334         IDirectDrawSurface3_UpdateOverlay,
1335         IDirectDrawSurface3_UpdateOverlayDisplay,
1336         IDirectDrawSurface3_UpdateOverlayZOrder,
1337         IDirectDrawSurface3_GetDDInterface,
1338         IDirectDrawSurface3_PageLock,
1339         IDirectDrawSurface3_PageUnlock,
1340         IDirectDrawSurface3_SetSurfaceDesc,
1341 };
1342
1343 static struct IDirectDrawSurface3_VTable xlib_dds3vt = {
1344         IDirectDrawSurface3_QueryInterface,
1345         IDirectDrawSurface3_AddRef,
1346         Xlib_IDirectDrawSurface3_Release,
1347         IDirectDrawSurface3_AddAttachedSurface,
1348         IDirectDrawSurface3_AddOverlayDirtyRect,
1349         IDirectDrawSurface3_Blt,
1350         IDirectDrawSurface3_BltBatch,
1351         IDirectDrawSurface3_BltFast,
1352         IDirectDrawSurface3_DeleteAttachedSurface,
1353         IDirectDrawSurface3_EnumAttachedSurfaces,
1354         IDirectDrawSurface3_EnumOverlayZOrders,
1355         Xlib_IDirectDrawSurface3_Flip,
1356         IDirectDrawSurface3_GetAttachedSurface,
1357         IDirectDrawSurface3_GetBltStatus,
1358         IDirectDrawSurface3_GetCaps,
1359         IDirectDrawSurface3_GetClipper,
1360         IDirectDrawSurface3_GetColorKey,
1361         IDirectDrawSurface3_GetDC,
1362         IDirectDrawSurface3_GetFlipStatus,
1363         IDirectDrawSurface3_GetOverlayPosition,
1364         IDirectDrawSurface3_GetPalette,
1365         IDirectDrawSurface3_GetPixelFormat,
1366         IDirectDrawSurface3_GetSurfaceDesc,
1367         IDirectDrawSurface3_Initialize,
1368         IDirectDrawSurface3_IsLost,
1369         IDirectDrawSurface3_Lock,
1370         IDirectDrawSurface3_ReleaseDC,
1371         IDirectDrawSurface3_Restore,
1372         IDirectDrawSurface3_SetClipper,
1373         IDirectDrawSurface3_SetColorKey,
1374         IDirectDrawSurface3_SetOverlayPosition,
1375         Xlib_IDirectDrawSurface3_SetPalette,
1376         Xlib_IDirectDrawSurface3_Unlock,
1377         IDirectDrawSurface3_UpdateOverlay,
1378         IDirectDrawSurface3_UpdateOverlayDisplay,
1379         IDirectDrawSurface3_UpdateOverlayZOrder,
1380         IDirectDrawSurface3_GetDDInterface,
1381         IDirectDrawSurface3_PageLock,
1382         IDirectDrawSurface3_PageUnlock,
1383         IDirectDrawSurface3_SetSurfaceDesc,
1384 };
1385
1386 /******************************************************************************
1387  *                      DirectDrawCreateClipper (DDRAW.7)
1388  */
1389 HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags,
1390                                         LPDIRECTDRAWCLIPPER *lplpDDClipper,
1391                                         LPUNKNOWN pUnkOuter)
1392 {
1393   TRACE(ddraw, "(%08lx,%p,%p)\n", dwFlags, lplpDDClipper, pUnkOuter);
1394
1395   *lplpDDClipper = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipper));
1396   (*lplpDDClipper)->lpvtbl = &ddclipvt;
1397   (*lplpDDClipper)->ref = 1;
1398
1399   return DD_OK;
1400 }
1401
1402 /******************************************************************************
1403  *                      IDirectDrawClipper
1404  */
1405 static HRESULT WINAPI IDirectDrawClipper_SetHwnd(
1406         LPDIRECTDRAWCLIPPER this,DWORD x,HWND32 hwnd
1407 ) {
1408         FIXME(ddraw,"(%p)->SetHwnd(0x%08lx,0x%08lx),stub!\n",this,x,(DWORD)hwnd);
1409         return DD_OK;
1410 }
1411
1412 static ULONG WINAPI IDirectDrawClipper_Release(LPDIRECTDRAWCLIPPER this) {
1413         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
1414
1415         this->ref--;
1416         if (this->ref)
1417                 return this->ref;
1418         HeapFree(GetProcessHeap(),0,this);
1419         return 0;
1420 }
1421
1422 static HRESULT WINAPI IDirectDrawClipper_GetClipList(
1423         LPDIRECTDRAWCLIPPER this,LPRECT32 rects,LPRGNDATA lprgn,LPDWORD hmm
1424 ) {
1425         FIXME(ddraw,"(%p,%p,%p,%p),stub!\n",this,rects,lprgn,hmm);
1426         if (hmm) *hmm=0;
1427         return DD_OK;
1428 }
1429
1430 static HRESULT WINAPI IDirectDrawClipper_SetClipList(
1431         LPDIRECTDRAWCLIPPER this,LPRGNDATA lprgn,DWORD hmm
1432 ) {
1433         FIXME(ddraw,"(%p,%p,%ld),stub!\n",this,lprgn,hmm);
1434         return DD_OK;
1435 }
1436
1437 static HRESULT WINAPI IDirectDrawClipper_QueryInterface(
1438          LPDIRECTDRAWCLIPPER this,
1439          REFIID riid,
1440          LPVOID* ppvObj )
1441 {
1442    FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,riid,ppvObj);
1443    return OLE_E_ENUM_NOMORE;
1444 }
1445
1446 static ULONG WINAPI IDirectDrawClipper_AddRef( LPDIRECTDRAWCLIPPER this )
1447 {
1448   TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
1449   return ++(this->ref);
1450 }
1451
1452 static HRESULT WINAPI IDirectDrawClipper_GetHWnd(
1453          LPDIRECTDRAWCLIPPER this,
1454          HWND32* HWndPtr )
1455 {
1456    FIXME(ddraw,"(%p)->(%p),stub!\n",this,HWndPtr);
1457    return DD_OK;
1458 }
1459
1460 static HRESULT WINAPI IDirectDrawClipper_Initialize(
1461          LPDIRECTDRAWCLIPPER this,
1462          LPDIRECTDRAW lpDD,
1463          DWORD dwFlags )
1464 {
1465    FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n",this,lpDD,dwFlags);
1466    return DD_OK;
1467 }
1468
1469 static HRESULT WINAPI IDirectDrawClipper_IsClipListChanged(
1470          LPDIRECTDRAWCLIPPER this,
1471          BOOL32* lpbChanged )
1472 {
1473    FIXME(ddraw,"(%p)->(%p),stub!\n",this,lpbChanged);
1474    return DD_OK;
1475 }
1476
1477 static struct IDirectDrawClipper_VTable ddclipvt = {
1478         IDirectDrawClipper_QueryInterface,
1479         IDirectDrawClipper_AddRef,
1480         IDirectDrawClipper_Release,
1481         IDirectDrawClipper_GetClipList,
1482         IDirectDrawClipper_GetHWnd,
1483         IDirectDrawClipper_Initialize,
1484         IDirectDrawClipper_IsClipListChanged,
1485         IDirectDrawClipper_SetClipList,
1486         IDirectDrawClipper_SetHwnd
1487 };
1488
1489
1490 /******************************************************************************
1491  *                      IDirectDrawPalette
1492  */
1493 static HRESULT WINAPI IDirectDrawPalette_GetEntries(
1494         LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
1495 ) {
1496         int     i;
1497
1498         TRACE(ddraw,"(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",
1499               this,x,start,count,palent);
1500
1501         if (!this->cm) /* should not happen */ {
1502                 FIXME(ddraw,"app tried to read colormap for non-palettized mode\n");
1503                 return DDERR_GENERIC;
1504         }
1505         for (i=0;i<count;i++) {
1506                 palent[i].peRed   = this->palents[start+i].peRed;
1507                 palent[i].peBlue  = this->palents[start+i].peBlue;
1508                 palent[i].peGreen = this->palents[start+i].peGreen;
1509                 palent[i].peFlags = this->palents[start+i].peFlags;
1510
1511         }
1512         return DD_OK;
1513 }
1514
1515 static HRESULT WINAPI Xlib_IDirectDrawPalette_SetEntries(
1516         LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
1517 ) {
1518         XColor          xc;
1519         int             i;
1520
1521         TRACE(ddraw,"(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
1522                 this,x,start,count,palent
1523         );
1524         for (i=0;i<count;i++) {
1525                 xc.red = palent[i].peRed<<8;
1526                 xc.blue = palent[i].peBlue<<8;
1527                 xc.green = palent[i].peGreen<<8;
1528                 xc.flags = DoRed|DoBlue|DoGreen;
1529                 xc.pixel = start+i;
1530
1531                 if (this->cm)
1532                     TSXStoreColor(display,this->cm,&xc);
1533
1534                 this->palents[start+i].peRed = palent[i].peRed;
1535                 this->palents[start+i].peBlue = palent[i].peBlue;
1536                 this->palents[start+i].peGreen = palent[i].peGreen;
1537                 this->palents[start+i].peFlags = palent[i].peFlags;
1538         }
1539         if (!this->cm) /* should not happen */ {
1540         }
1541         return DD_OK;
1542 }
1543
1544 static HRESULT WINAPI DGA_IDirectDrawPalette_SetEntries(
1545         LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
1546 ) {
1547 #ifdef HAVE_LIBXXF86DGA
1548         XColor          xc;
1549         Colormap        cm;
1550         int             i;
1551
1552         TRACE(ddraw,"(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
1553                 this,x,start,count,palent
1554         );
1555         if (!this->cm) /* should not happen */ {
1556                 FIXME(ddraw,"app tried to set colormap in non-palettized mode\n");
1557                 return DDERR_GENERIC;
1558         }
1559         /* FIXME: free colorcells instead of freeing whole map */
1560         cm = this->cm;
1561         this->cm = TSXCopyColormapAndFree(display,this->cm);
1562         TSXFreeColormap(display,cm);
1563
1564         for (i=0;i<count;i++) {
1565                 xc.red = palent[i].peRed<<8;
1566                 xc.blue = palent[i].peBlue<<8;
1567                 xc.green = palent[i].peGreen<<8;
1568                 xc.flags = DoRed|DoBlue|DoGreen;
1569                 xc.pixel = i+start;
1570
1571                 TSXStoreColor(display,this->cm,&xc);
1572
1573                 this->palents[start+i].peRed = palent[i].peRed;
1574                 this->palents[start+i].peBlue = palent[i].peBlue;
1575                 this->palents[start+i].peGreen = palent[i].peGreen;
1576                 this->palents[start+i].peFlags = palent[i].peFlags;
1577         }
1578         TSXF86DGAInstallColormap(display,DefaultScreen(display),this->cm);
1579         return DD_OK;
1580 #else /* defined(HAVE_LIBXXF86DGA) */
1581         return E_UNEXPECTED;
1582 #endif /* defined(HAVE_LIBXXF86DGA) */
1583 }
1584
1585 static ULONG WINAPI IDirectDrawPalette_Release(LPDIRECTDRAWPALETTE this) {
1586         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
1587         if (!--(this->ref)) {
1588                 if (this->cm) {
1589                         TSXFreeColormap(display,this->cm);
1590                         this->cm = 0;
1591                 }
1592                 HeapFree(GetProcessHeap(),0,this);
1593                 return 0;
1594         }
1595         return this->ref;
1596 }
1597
1598 static ULONG WINAPI IDirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE this) {
1599
1600         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
1601         return ++(this->ref);
1602 }
1603
1604 static HRESULT WINAPI IDirectDrawPalette_Initialize(
1605         LPDIRECTDRAWPALETTE this,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
1606 ) {
1607         TRACE(ddraw,"(%p)->(%p,%ld,%p)\n", this, ddraw, x, palent);
1608
1609         return DDERR_ALREADYINITIALIZED;
1610 }
1611
1612 static HRESULT WINAPI IDirectDrawPalette_GetCaps(
1613          LPDIRECTDRAWPALETTE this, LPDWORD lpdwCaps )
1614 {
1615    FIXME( ddraw, "(%p)->(%p) stub.\n", this, lpdwCaps );
1616    return DD_OK;
1617
1618
1619 static HRESULT WINAPI IDirectDrawPalette_QueryInterface(
1620         LPDIRECTDRAWPALETTE this,REFIID refiid,LPVOID *obj ) 
1621 {
1622   char    xrefiid[50];
1623
1624   WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1625   FIXME(ddraw,"(%p)->(%s,%p) stub.\n",this,xrefiid,obj);
1626
1627   return S_OK;
1628 }
1629
1630 static struct IDirectDrawPalette_VTable dga_ddpalvt = {
1631         IDirectDrawPalette_QueryInterface,
1632         IDirectDrawPalette_AddRef,
1633         IDirectDrawPalette_Release,
1634         IDirectDrawPalette_GetCaps,
1635         IDirectDrawPalette_GetEntries,
1636         IDirectDrawPalette_Initialize,
1637         DGA_IDirectDrawPalette_SetEntries
1638 };
1639
1640 static struct IDirectDrawPalette_VTable xlib_ddpalvt = {
1641         IDirectDrawPalette_QueryInterface,
1642         IDirectDrawPalette_AddRef,
1643         IDirectDrawPalette_Release,
1644         IDirectDrawPalette_GetCaps,
1645         IDirectDrawPalette_GetEntries,
1646         IDirectDrawPalette_Initialize,
1647         Xlib_IDirectDrawPalette_SetEntries
1648 };
1649
1650 /*******************************************************************************
1651  *                              IDirect3D
1652  */
1653 static HRESULT WINAPI IDirect3D_QueryInterface(
1654         LPDIRECT3D this,REFIID refiid,LPVOID *obj
1655 ) {
1656         /* FIXME: Not sure if this is correct */
1657         char    xrefiid[50];
1658
1659         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1660         TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
1661         if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
1662                 *obj = this;
1663                 this->lpvtbl->fnAddRef(this);
1664
1665                 TRACE(ddraw, "  Creating IUnknown interface (%p)\n", *obj);
1666                 
1667                 return S_OK;
1668         }
1669         if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
1670                 LPDIRECT3D      d3d;
1671
1672                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
1673                 d3d->ref = 1;
1674                 d3d->ddraw = (LPDIRECTDRAW)this;
1675                 this->lpvtbl->fnAddRef(this);
1676                 d3d->lpvtbl = &d3dvt;
1677                 *obj = d3d;
1678
1679                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
1680
1681                 return S_OK;
1682         }
1683         if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D))) {
1684                 LPDIRECT3D2     d3d;
1685
1686                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
1687                 d3d->ref = 1;
1688                 d3d->ddraw = (LPDIRECTDRAW)this;
1689                 this->lpvtbl->fnAddRef(this);
1690                 d3d->lpvtbl = &d3d2vt;
1691                 *obj = d3d;
1692
1693                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
1694
1695                 return S_OK;
1696         }
1697         FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",this,xrefiid);
1698         return OLE_E_ENUM_NOMORE;
1699 }
1700
1701 static ULONG WINAPI IDirect3D_AddRef(LPDIRECT3D this) {
1702         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
1703
1704         return ++(this->ref);
1705 }
1706
1707 static ULONG WINAPI IDirect3D_Release(LPDIRECT3D this)
1708 {
1709         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
1710
1711         if (!--(this->ref)) {
1712                 this->ddraw->lpvtbl->fnRelease(this->ddraw);
1713                 HeapFree(GetProcessHeap(),0,this);
1714                 return 0;
1715         }
1716         return this->ref;
1717 }
1718
1719 static HRESULT WINAPI IDirect3D_Initialize(
1720          LPDIRECT3D this, REFIID refiid )
1721 {
1722   /* FIXME: Not sure if this is correct */
1723   char    xrefiid[50];
1724
1725   WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1726   FIXME(ddraw,"(%p)->(%s):stub.\n",this,xrefiid);
1727   
1728   return DDERR_ALREADYINITIALIZED;
1729 }
1730
1731 static HRESULT WINAPI IDirect3D_EnumDevices(LPDIRECT3D this,
1732                                             LPD3DENUMDEVICESCALLBACK cb,
1733                                             LPVOID context) {
1734   FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,cb,context);
1735
1736   /* Call functions defined in d3ddevices.c */
1737   if (d3d_OpenGL_dx3(cb, context))
1738     return DD_OK;
1739
1740   return DD_OK;
1741 }
1742
1743 static HRESULT WINAPI IDirect3D_CreateLight(LPDIRECT3D this,
1744                                             LPDIRECT3DLIGHT *lplight,
1745                                             IUnknown *lpunk)
1746 {
1747   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lplight, lpunk);
1748   
1749   /* Call the creation function that is located in d3dlight.c */
1750   *lplight = d3dlight_create_dx3(this);
1751   
1752   return DD_OK;
1753 }
1754
1755 static HRESULT WINAPI IDirect3D_CreateMaterial(LPDIRECT3D this,
1756                                                LPDIRECT3DMATERIAL *lpmaterial,
1757                                                IUnknown *lpunk)
1758 {
1759   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpmaterial, lpunk);
1760
1761   /* Call the creation function that is located in d3dviewport.c */
1762   *lpmaterial = d3dmaterial_create(this);
1763   
1764   return DD_OK;
1765 }
1766
1767 static HRESULT WINAPI IDirect3D_CreateViewport(LPDIRECT3D this,
1768                                                LPDIRECT3DVIEWPORT *lpviewport,
1769                                                IUnknown *lpunk)
1770 {
1771   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpviewport, lpunk);
1772   
1773   /* Call the creation function that is located in d3dviewport.c */
1774   *lpviewport = d3dviewport_create(this);
1775   
1776   return DD_OK;
1777 }
1778
1779 static HRESULT WINAPI IDirect3D_FindDevice(LPDIRECT3D this,
1780                                            LPD3DFINDDEVICESEARCH lpfinddevsrc,
1781                                            LPD3DFINDDEVICERESULT lpfinddevrst)
1782 {
1783   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpfinddevsrc, lpfinddevrst);
1784   
1785   return DD_OK;
1786 }
1787
1788 static struct IDirect3D_VTable d3dvt = {
1789         IDirect3D_QueryInterface,
1790         IDirect3D_AddRef,
1791         IDirect3D_Release,
1792         IDirect3D_Initialize,
1793         IDirect3D_EnumDevices,
1794         IDirect3D_CreateLight,
1795         IDirect3D_CreateMaterial,
1796         IDirect3D_CreateViewport,
1797         IDirect3D_FindDevice
1798 };
1799
1800 /*******************************************************************************
1801  *                              IDirect3D2
1802  */
1803 static HRESULT WINAPI IDirect3D2_QueryInterface(
1804         LPDIRECT3D2 this,REFIID refiid,LPVOID *obj) {
1805   /* For the moment, we use the same function as in IDirect3D */
1806   TRACE(ddraw, "Calling IDirect3D enumerating function.\n");
1807   
1808   return IDirect3D_QueryInterface((LPDIRECT3D) this, refiid, obj);
1809 }
1810
1811 static ULONG WINAPI IDirect3D2_AddRef(LPDIRECT3D2 this) {
1812         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
1813
1814         return ++(this->ref);
1815 }
1816
1817 static ULONG WINAPI IDirect3D2_Release(LPDIRECT3D2 this) {
1818         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
1819
1820         if (!--(this->ref)) {
1821                 this->ddraw->lpvtbl->fnRelease(this->ddraw);
1822                 HeapFree(GetProcessHeap(),0,this);
1823                 return 0;
1824         }
1825         return this->ref;
1826 }
1827
1828 static HRESULT WINAPI IDirect3D2_EnumDevices(
1829         LPDIRECT3D2 this,LPD3DENUMDEVICESCALLBACK cb, LPVOID context
1830 ) {
1831         FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,cb,context);
1832
1833         /* Call functions defined in d3ddevices.c */
1834         if (d3d_OpenGL(cb, context))
1835           return DD_OK;
1836
1837         return DD_OK;
1838 }
1839
1840 static HRESULT WINAPI IDirect3D2_CreateLight(LPDIRECT3D2 this,
1841                                              LPDIRECT3DLIGHT *lplight,
1842                                              IUnknown *lpunk)
1843 {
1844   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lplight, lpunk);
1845
1846   /* Call the creation function that is located in d3dlight.c */
1847   *lplight = d3dlight_create(this);
1848   
1849         return DD_OK;
1850 }
1851
1852 static HRESULT WINAPI IDirect3D2_CreateMaterial(LPDIRECT3D2 this,
1853                                                 LPDIRECT3DMATERIAL2 *lpmaterial,
1854                                                 IUnknown *lpunk)
1855 {
1856   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpmaterial, lpunk);
1857
1858   /* Call the creation function that is located in d3dviewport.c */
1859   *lpmaterial = d3dmaterial2_create(this);
1860
1861   return DD_OK;
1862 }
1863
1864 static HRESULT WINAPI IDirect3D2_CreateViewport(LPDIRECT3D2 this,
1865                                                 LPDIRECT3DVIEWPORT2 *lpviewport,
1866                                                 IUnknown *lpunk)
1867 {
1868   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpviewport, lpunk);
1869   
1870   /* Call the creation function that is located in d3dviewport.c */
1871   *lpviewport = d3dviewport2_create(this);
1872   
1873   return DD_OK;
1874 }
1875
1876 static HRESULT WINAPI IDirect3D2_FindDevice(LPDIRECT3D2 this,
1877                                             LPD3DFINDDEVICESEARCH lpfinddevsrc,
1878                                             LPD3DFINDDEVICERESULT lpfinddevrst)
1879 {
1880   TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpfinddevsrc, lpfinddevrst);
1881
1882   return DD_OK;
1883 }
1884
1885 static HRESULT WINAPI IDirect3D2_CreateDevice(LPDIRECT3D2 this,
1886                                               REFCLSID rguid,
1887                                               LPDIRECTDRAWSURFACE surface,
1888                                               LPDIRECT3DDEVICE2 *device)
1889 {
1890   char  xbuf[50];
1891   
1892   WINE_StringFromCLSID(rguid,xbuf);
1893   FIXME(ddraw,"(%p)->(%s,%p,%p): stub\n",this,xbuf,surface,device);
1894
1895   if (is_OpenGL(rguid, surface, device, this)) {
1896     this->lpvtbl->fnAddRef(this);
1897     return DD_OK;
1898 }
1899
1900   return DDERR_INVALIDPARAMS;
1901 }
1902
1903 static struct IDirect3D2_VTable d3d2vt = {
1904         IDirect3D2_QueryInterface,
1905         IDirect3D2_AddRef,
1906         IDirect3D2_Release,
1907         IDirect3D2_EnumDevices,
1908         IDirect3D2_CreateLight,
1909         IDirect3D2_CreateMaterial,
1910         IDirect3D2_CreateViewport,
1911         IDirect3D2_FindDevice,
1912         IDirect3D2_CreateDevice
1913 };
1914
1915 /*******************************************************************************
1916  *                              IDirectDraw
1917  */
1918
1919 /* Used in conjunction with cbWndExtra for storage of the this ptr for the window.
1920  * Please adjust allocation in Xlib_DirectDrawCreate if you store more data here.
1921  */
1922 static INT32 ddrawXlibThisOffset = 0;
1923
1924 static HRESULT common_off_screen_CreateSurface(LPDIRECTDRAW2 this,
1925                                                LPDDSURFACEDESC lpddsd,
1926                                                LPDIRECTDRAWSURFACE lpdsf)
1927 {
1928   int bpp;
1929   
1930   /* The surface was already allocated when entering in this function */
1931   TRACE(ddraw,"using system memory for a surface (%p)\n", lpdsf);
1932
1933   if (lpddsd->dwFlags & DDSD_ZBUFFERBITDEPTH) {
1934     /* This is a Z Buffer */
1935     bpp = lpddsd->x.dwZBufferBitDepth;
1936   } else {
1937     /* This is a standard image */
1938   if (!(lpddsd->dwFlags & DDSD_PIXELFORMAT)) {
1939     /* No pixel format => use DirectDraw's format */
1940     _getpixelformat(this,&(lpddsd->ddpfPixelFormat));
1941     lpddsd->dwFlags |= DDSD_PIXELFORMAT;
1942   }  else {
1943     /* To check what the program wants */
1944     if (TRACE_ON(ddraw)) {
1945       _dump_pixelformat(&(lpddsd->ddpfPixelFormat));
1946     }
1947   }
1948   }
1949
1950   if (lpddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
1951     bpp = 1;
1952   } else {
1953   bpp = lpddsd->ddpfPixelFormat.x.dwRGBBitCount / 8;
1954   }
1955
1956   /* Copy the surface description */
1957   lpdsf->s.surface_desc = *lpddsd;
1958   
1959   lpdsf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
1960   lpdsf->s.surface_desc.y.lpSurface = (LPBYTE)HeapAlloc(GetProcessHeap(),0,lpddsd->dwWidth * lpddsd->dwHeight * bpp);
1961   lpdsf->s.surface_desc.lPitch = lpddsd->dwWidth * bpp;
1962   
1963   return DD_OK;
1964 }
1965
1966 static HRESULT WINAPI DGA_IDirectDraw2_CreateSurface(
1967         LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
1968 ) {
1969 #ifdef HAVE_LIBXXF86DGA
1970         int     i;
1971
1972         TRACE(ddraw, "(%p)->(%p,%p,%p)\n",this,lpddsd,lpdsf,lpunk);
1973         if (TRACE_ON(ddraw)) {
1974                 DUMP("[w=%ld,h=%ld,flags ",lpddsd->dwWidth,lpddsd->dwHeight);
1975                 _dump_DDSD(lpddsd->dwFlags);
1976                 fprintf(stderr,"caps ");
1977                 _dump_DDSCAPS(lpddsd->ddsCaps.dwCaps);
1978                 fprintf(stderr,"]\n");
1979         }
1980
1981         *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
1982         this->lpvtbl->fnAddRef(this);
1983         
1984         (*lpdsf)->ref = 1;
1985         (*lpdsf)->lpvtbl = (LPDIRECTDRAWSURFACE_VTABLE)&dga_dds3vt;
1986         (*lpdsf)->s.ddraw = this;
1987         (*lpdsf)->s.palette = NULL;
1988         (*lpdsf)->t.dga.fb_height = -1; /* This is to have non-on screen surfaces freed */
1989
1990         if (!(lpddsd->dwFlags & DDSD_WIDTH))
1991           lpddsd->dwWidth  = this->d.width;
1992         if (!(lpddsd->dwFlags & DDSD_HEIGHT))
1993           lpddsd->dwHeight = this->d.height;
1994         
1995         /* Check if this a 'primary surface' or not */
1996         if ((lpddsd->dwFlags & DDSD_CAPS) &&
1997             (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
1998
1999           /* This is THE primary surface => there is DGA-specific code */
2000           /* First, store the surface description */
2001           (*lpdsf)->s.surface_desc = *lpddsd;
2002           
2003           /* Find a viewport */
2004                 for (i=0;i<32;i++)
2005                         if (!(this->e.dga.vpmask & (1<<i)))
2006                                 break;
2007                 TRACE(ddraw,"using viewport %d for a primary surface\n",i);
2008                 /* if i == 32 or maximum ... return error */
2009                 this->e.dga.vpmask|=(1<<i);
2010           (*lpdsf)->s.surface_desc.y.lpSurface =
2011             this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
2012                 (*lpdsf)->t.dga.fb_height = i*this->e.dga.fb_height;
2013           (*lpdsf)->s.surface_desc.lPitch = this->e.dga.fb_width*this->d.depth/8;
2014           lpddsd->lPitch = (*lpdsf)->s.surface_desc.lPitch;
2015
2016           /* Add flags if there were not present */
2017           (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
2018           (*lpdsf)->s.surface_desc.dwWidth = this->d.width;
2019           (*lpdsf)->s.surface_desc.dwHeight = this->d.height;
2020           (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
2021           _getpixelformat(this,&((*lpdsf)->s.surface_desc.ddpfPixelFormat));
2022         (*lpdsf)->s.backbuffer = NULL;
2023           
2024         if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
2025                 LPDIRECTDRAWSURFACE3    back;
2026
2027                 if (lpddsd->dwBackBufferCount>1)
2028                         FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
2029
2030             (*lpdsf)->s.backbuffer = back =
2031               (LPDIRECTDRAWSURFACE3)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface3));
2032                 this->lpvtbl->fnAddRef(this);
2033                 back->ref = 1;
2034                 back->lpvtbl = (LPDIRECTDRAWSURFACE3_VTABLE)&dga_dds3vt;
2035                 for (i=0;i<32;i++)
2036                         if (!(this->e.dga.vpmask & (1<<i)))
2037                                 break;
2038                 TRACE(ddraw,"using viewport %d for backbuffer\n",i);
2039                 /* if i == 32 or maximum ... return error */
2040                 this->e.dga.vpmask|=(1<<i);
2041                 back->t.dga.fb_height = i*this->e.dga.fb_height;
2042
2043             /* Copy the surface description from the front buffer */
2044             back->s.surface_desc = (*lpdsf)->s.surface_desc;
2045             /* Change the parameters that are not the same */
2046             back->s.surface_desc.y.lpSurface = this->e.dga.fb_addr+
2047               ((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
2048                 back->s.ddraw = this;
2049                 back->s.backbuffer = NULL; /* does not have a backbuffer, it is
2050                                             * one! */
2051
2052             /* Add relevant info to front and back buffers */
2053             (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
2054             back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
2055             back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
2056             back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
2057           }
2058         } else {
2059           /* There is no DGA-specific code here...
2060              Go to the common surface creation function */
2061           return common_off_screen_CreateSurface(this, lpddsd, *lpdsf);
2062         }
2063         
2064         return DD_OK;
2065 #else /* defined(HAVE_LIBXXF86DGA) */
2066         return E_UNEXPECTED;
2067 #endif /* defined(HAVE_LIBXXF86DGA) */
2068 }
2069
2070 static XImage *create_ximage(LPDIRECTDRAW2 this, LPDIRECTDRAWSURFACE3 lpdsf) {
2071   XImage *img;
2072
2073 #ifdef HAVE_LIBXXSHM
2074   if (this->e.xlib.xshm_active) {
2075     img = TSXShmCreateImage(display,
2076                             DefaultVisualOfScreen(screen),
2077                             this->d.depth,
2078                             ZPixmap,
2079                             NULL,
2080                             &(lpdsf->t.xlib.shminfo),
2081                             lpdsf->s.surface_desc.dwWidth,
2082                             lpdsf->s.surface_desc.dwHeight);
2083     
2084     if (img == NULL)
2085       return NULL;
2086
2087     lpdsf->t.xlib.shminfo.shmid = shmget( IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777 );
2088     if (lpdsf->t.xlib.shminfo.shmid < 0) {
2089       TSXDestroyImage(img);
2090       return NULL;
2091     }
2092
2093     lpdsf->t.xlib.shminfo.shmaddr = img->data = (char*)shmat(lpdsf->t.xlib.shminfo.shmid, 0, 0);
2094       
2095     if (img->data == (char *) -1) {
2096       TSXDestroyImage(img);
2097       shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
2098       return NULL;
2099     }
2100     lpdsf->t.xlib.shminfo.readOnly = False;
2101       
2102     TSXShmAttach(display, &(lpdsf->t.xlib.shminfo));
2103     TSXSync(display, False);
2104
2105     shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
2106
2107     lpdsf->s.surface_desc.y.lpSurface = img->data;
2108   } else {
2109 #endif
2110     /* Allocate surface memory */
2111     lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
2112                                                   lpdsf->s.surface_desc.dwWidth *
2113                                                   lpdsf->s.surface_desc.dwHeight *
2114                                                   (this->d.depth / 8));
2115     
2116     /* In this case, create an XImage */
2117     img =
2118       TSXCreateImage(display,
2119                      DefaultVisualOfScreen(screen),
2120                      this->d.depth,
2121                      ZPixmap,
2122                      0,
2123                      lpdsf->s.surface_desc.y.lpSurface,
2124                      lpdsf->s.surface_desc.dwWidth,
2125                      lpdsf->s.surface_desc.dwHeight,
2126                      32,
2127                      lpdsf->s.surface_desc.dwWidth * (this->d.depth / 8)
2128                      );
2129     
2130 #ifdef HAVE_LIBXXSHM
2131   }
2132 #endif
2133   lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
2134   
2135   return img;
2136 }
2137
2138 static HRESULT WINAPI Xlib_IDirectDraw2_CreateSurface(
2139         LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
2140 ) {
2141         TRACE(ddraw, "(%p)->CreateSurface(%p,%p,%p)\n",
2142                      this,lpddsd,lpdsf,lpunk);
2143
2144         if (TRACE_ON(ddraw)) {
2145                 fprintf(stderr,"[w=%ld,h=%ld,flags ",lpddsd->dwWidth,lpddsd->dwHeight);
2146                 _dump_DDSD(lpddsd->dwFlags);
2147                 fprintf(stderr,"caps ");
2148                 _dump_DDSCAPS(lpddsd->ddsCaps.dwCaps);
2149                 fprintf(stderr,"]\n");
2150         }
2151
2152         *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
2153
2154         this->lpvtbl->fnAddRef(this);
2155         (*lpdsf)->s.ddraw             = this;
2156         (*lpdsf)->ref                 = 1;
2157         (*lpdsf)->lpvtbl              = (LPDIRECTDRAWSURFACE_VTABLE)&xlib_dds3vt;
2158         (*lpdsf)->s.palette = NULL;
2159         (*lpdsf)->t.xlib.image = NULL; /* This is for off-screen buffers */
2160
2161         if (!(lpddsd->dwFlags & DDSD_WIDTH))
2162                 lpddsd->dwWidth  = this->d.width;
2163         if (!(lpddsd->dwFlags & DDSD_HEIGHT))
2164                 lpddsd->dwHeight = this->d.height;
2165
2166         /* Check if this a 'primary surface' or not */
2167   if ((lpddsd->dwFlags & DDSD_CAPS) && 
2168             (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
2169     XImage *img;
2170       
2171     TRACE(ddraw,"using standard XImage for a primary surface (%p)\n", *lpdsf);
2172
2173           /* First, store the surface description */
2174           (*lpdsf)->s.surface_desc = *lpddsd;
2175           
2176     /* Create the XImage */
2177     img = create_ximage(this, (LPDIRECTDRAWSURFACE3) *lpdsf);
2178     if (img == NULL)
2179       return DDERR_OUTOFMEMORY;
2180     (*lpdsf)->t.xlib.image = img;
2181
2182           /* Add flags if there were not present */
2183           (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
2184           (*lpdsf)->s.surface_desc.dwWidth = this->d.width;
2185           (*lpdsf)->s.surface_desc.dwHeight = this->d.height;
2186           (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
2187           _getpixelformat(this,&((*lpdsf)->s.surface_desc.ddpfPixelFormat));
2188           (*lpdsf)->s.backbuffer = NULL;
2189     
2190     /* Check for backbuffers */
2191         if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
2192                 LPDIRECTDRAWSURFACE3    back;
2193       XImage *img;
2194
2195                 if (lpddsd->dwBackBufferCount>1)
2196                         FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
2197
2198       (*lpdsf)->s.backbuffer = back =
2199         (LPDIRECTDRAWSURFACE3)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface3));
2200
2201       TRACE(ddraw,"allocated back-buffer (%p)\n", back);
2202       
2203                 this->lpvtbl->fnAddRef(this);
2204                 back->s.ddraw = this;
2205
2206                 back->ref = 1;
2207                 back->lpvtbl = (LPDIRECTDRAWSURFACE3_VTABLE)&xlib_dds3vt;
2208             /* Copy the surface description from the front buffer */
2209             back->s.surface_desc = (*lpdsf)->s.surface_desc;
2210
2211       /* Create the XImage */
2212       img = create_ximage(this, back);
2213       if (img == NULL)
2214         return DDERR_OUTOFMEMORY;
2215       back->t.xlib.image = img;
2216       
2217                 back->s.backbuffer = NULL; /* does not have a backbuffer, it is
2218                                             * one! */
2219
2220             /* Add relevant info to front and back buffers */
2221             (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
2222             back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
2223             back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
2224             back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
2225         }
2226         } else {
2227           /* There is no Xlib-specific code here...
2228              Go to the common surface creation function */
2229           return common_off_screen_CreateSurface(this, lpddsd, *lpdsf);
2230   }
2231   
2232         return DD_OK;
2233 }
2234
2235 static HRESULT WINAPI IDirectDraw2_DuplicateSurface(
2236         LPDIRECTDRAW2 this,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
2237 ) {
2238         FIXME(ddraw,"(%p)->(%p,%p) simply copies\n",this,src,dst);
2239         *dst = src; /* FIXME */
2240         return DD_OK;
2241 }
2242
2243 /* 
2244  * The Xlib Implementation tries to use the passed hwnd as drawing window,
2245  * even when the approbiate bitmasks are not specified.
2246  */
2247 static HRESULT WINAPI IDirectDraw2_SetCooperativeLevel(
2248         LPDIRECTDRAW2 this,HWND32 hwnd,DWORD cooplevel
2249 ) {
2250         int     i;
2251         const struct {
2252                 int     mask;
2253                 char    *name;
2254         } flagmap[] = {
2255                 FE(DDSCL_FULLSCREEN)
2256                 FE(DDSCL_ALLOWREBOOT)
2257                 FE(DDSCL_NOWINDOWCHANGES)
2258                 FE(DDSCL_NORMAL)
2259                 FE(DDSCL_ALLOWMODEX)
2260                 FE(DDSCL_EXCLUSIVE)
2261                 FE(DDSCL_SETFOCUSWINDOW)
2262                 FE(DDSCL_SETDEVICEWINDOW)
2263                 FE(DDSCL_CREATEDEVICEWINDOW)
2264         };
2265
2266         FIXME(ddraw,"(%p)->(%08lx,%08lx)\n",this,(DWORD)hwnd,cooplevel);
2267         if(TRACE_ON(ddraw)){
2268           dbg_decl_str(ddraw, 512);
2269           for (i=0;i<sizeof(flagmap)/sizeof(flagmap[0]);i++)
2270             if (flagmap[i].mask & cooplevel)
2271               dsprintf(ddraw, "%s ", flagmap[i].name);
2272           TRACE(ddraw," cooperative level %s\n", dbg_str(ddraw));
2273         }
2274         this->d.mainWindow = hwnd;
2275
2276         /* This will be overwritten in the case of Full Screen mode.
2277            Windowed games could work with that :-) */
2278         if (hwnd)
2279         this->d.drawable  = ((X11DRV_WND_DATA *) WIN_FindWndPtr(hwnd)->pDriverData)->window;
2280
2281         return DD_OK;
2282 }
2283
2284 /* Small helper to either use the cooperative window or create a new 
2285  * one (for mouse and keyboard input) and drawing in the Xlib implementation.
2286  */
2287 static void _common_IDirectDraw_SetDisplayMode(LPDIRECTDRAW this) {
2288         RECT32  rect;
2289
2290         /* Do not destroy the application supplied cooperative window */
2291         if (this->d.window && this->d.window != this->d.mainWindow) {
2292                 DestroyWindow32(this->d.window);
2293                 this->d.window = 0;
2294         }
2295         /* Sanity check cooperative window before assigning it to drawing. */
2296         if (    IsWindow32(this->d.mainWindow) &&
2297                 IsWindowVisible32(this->d.mainWindow)
2298         ) {
2299                 GetWindowRect32(this->d.mainWindow,&rect);
2300                 if (((rect.right-rect.left) >= this->d.width)   &&
2301                     ((rect.bottom-rect.top) >= this->d.height)
2302                 )
2303                         this->d.window = this->d.mainWindow;
2304         }
2305         /* ... failed, create new one. */
2306         if (!this->d.window) {
2307             this->d.window = CreateWindowEx32A(
2308                     0,
2309                     "WINE_DirectDraw",
2310                     "WINE_DirectDraw",
2311                     WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME,
2312                     0,0,
2313                     this->d.width,
2314                     this->d.height,
2315                     0,
2316                     0,
2317                     0,
2318                     NULL
2319             );
2320             /*Store THIS with the window. We'll use it in the window procedure*/
2321             SetWindowLong32A(this->d.window,ddrawXlibThisOffset,(LONG)this);
2322             ShowWindow32(this->d.window,TRUE);
2323             UpdateWindow32(this->d.window);
2324         }
2325         SetFocus32(this->d.window);
2326 }
2327
2328 static HRESULT WINAPI DGA_IDirectDraw_SetDisplayMode(
2329         LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
2330 ) {
2331 #ifdef HAVE_LIBXXF86DGA
2332         int     i,*depths,depcount,mode_count;
2333
2334         TRACE(ddraw, "(%p)->(%ld,%ld,%ld)\n", this, width, height, depth);
2335
2336         depths = TSXListDepths(display,DefaultScreen(display),&depcount);
2337         for (i=0;i<depcount;i++)
2338                 if (depths[i]==depth)
2339                         break;
2340         TSXFree(depths);
2341         if (i==depcount) {/* not found */
2342                 ERR(ddraw,"(w=%ld,h=%ld,d=%ld), unsupported depth!\n",width,height,depth);
2343                 return DDERR_UNSUPPORTEDMODE;
2344         }
2345         if (this->d.width < width) {
2346                 ERR(ddraw,"SetDisplayMode(w=%ld,h=%ld,d=%ld), width %ld exceeds framebuffer width %ld\n",width,height,depth,width,this->d.width);
2347                 return DDERR_UNSUPPORTEDMODE;
2348         }
2349         this->d.width   = width;
2350         this->d.height  = height;
2351         this->d.depth   = depth;
2352
2353         /* adjust fb_height, so we don't overlap */
2354         if (this->e.dga.fb_height < height)
2355                 this->e.dga.fb_height = height;
2356         _common_IDirectDraw_SetDisplayMode(this);
2357
2358 #ifdef HAVE_LIBXXF86VM
2359         {
2360             XF86VidModeModeInfo **all_modes, *vidmode = NULL;
2361             XF86VidModeModeLine mod_tmp;
2362             int dotclock_tmp;
2363
2364             /* save original video mode and set fullscreen if available*/
2365             orig_mode = (XF86VidModeModeInfo *) malloc (sizeof(XF86VidModeModeInfo));  
2366             TSXF86VidModeGetModeLine(display, DefaultScreen(display), &orig_mode->dotclock, &mod_tmp);
2367             orig_mode->hdisplay = mod_tmp.hdisplay; 
2368             orig_mode->hsyncstart = mod_tmp.hsyncstart;
2369             orig_mode->hsyncend = mod_tmp.hsyncend; 
2370             orig_mode->htotal = mod_tmp.htotal;
2371             orig_mode->vdisplay = mod_tmp.vdisplay; 
2372             orig_mode->vsyncstart = mod_tmp.vsyncstart;
2373             orig_mode->vsyncend = mod_tmp.vsyncend; 
2374             orig_mode->vtotal = mod_tmp.vtotal;
2375             orig_mode->flags = mod_tmp.flags; 
2376             orig_mode->private = mod_tmp.private;
2377             
2378             TSXF86VidModeGetAllModeLines(display,DefaultScreen(display),&mode_count,&all_modes);
2379             for (i=0;i<mode_count;i++)
2380             {
2381                 if (all_modes[i]->hdisplay == width && all_modes[i]->vdisplay == height)
2382                 {
2383                     vidmode = (XF86VidModeModeInfo *)malloc(sizeof(XF86VidModeModeInfo));
2384                     *vidmode = *(all_modes[i]);
2385                     break;
2386                 } else
2387                     TSXFree(all_modes[i]->private);
2388             }
2389             TSXFree(all_modes);
2390
2391             if (!vidmode)
2392                 WARN(ddraw, "Fullscreen mode not available!\n");
2393
2394             if (vidmode)
2395               {
2396                 TSXF86VidModeSwitchToMode(display, DefaultScreen(display), vidmode);
2397                 TSXF86VidModeSetViewPort(display, DefaultScreen(display), 0, 0);
2398               }
2399         }
2400 #endif
2401
2402         /* FIXME: this function OVERWRITES several signal handlers. 
2403          * can we save them? and restore them later? In a way that
2404          * it works for the library too?
2405          */
2406         TSXF86DGADirectVideo(display,DefaultScreen(display),XF86DGADirectGraphics);
2407 #ifdef DIABLO_HACK
2408         TSXF86DGASetViewPort(display,DefaultScreen(display),0,this->e.dga.fb_height);
2409 #endif
2410
2411 #ifdef RESTORE_SIGNALS
2412         SIGNAL_InitEmulator();
2413 #endif
2414         return DD_OK;
2415 #else /* defined(HAVE_LIBXXF86DGA) */
2416         return E_UNEXPECTED;
2417 #endif /* defined(HAVE_LIBXXF86DGA) */
2418 }
2419
2420 static HRESULT WINAPI Xlib_IDirectDraw_SetDisplayMode(
2421         LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
2422 ) {
2423         int     i,*depths,depcount;
2424         char    buf[200];
2425
2426         TRACE(ddraw, "(%p)->SetDisplayMode(%ld,%ld,%ld)\n",
2427                       this, width, height, depth);
2428
2429         depths = TSXListDepths(display,DefaultScreen(display),&depcount);
2430         for (i=0;i<depcount;i++)
2431                 if (depths[i]==depth)
2432                         break;
2433         TSXFree(depths);
2434         if (i==depcount) {/* not found */
2435                 sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
2436                 MessageBox32A(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
2437                 return DDERR_UNSUPPORTEDMODE;
2438         }
2439         this->d.width   = width;
2440         this->d.height  = height;
2441         this->d.depth   = depth;
2442
2443         _common_IDirectDraw_SetDisplayMode(this);
2444
2445         this->d.paintable = 1;
2446         this->d.drawable  = ((X11DRV_WND_DATA *) WIN_FindWndPtr(this->d.window)->pDriverData)->window;  
2447         /* We don't have a context for this window. Host off the desktop */
2448         if( !this->d.drawable )
2449            this->d.drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
2450         return DD_OK;
2451 }
2452
2453 static HRESULT WINAPI DGA_IDirectDraw2_GetCaps(
2454         LPDIRECTDRAW2 this,LPDDCAPS caps1,LPDDCAPS caps2
2455 ) {
2456 #ifdef HAVE_LIBXXF86DGA
2457         TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",this,caps1,caps2);
2458         caps1->dwVidMemTotal = this->e.dga.fb_memsize;
2459         caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);              /* we can do anything */
2460         caps1->ddsCaps.dwCaps = 0xffffffff;     /* we can do anything */
2461         if (caps2) {
2462                 caps2->dwVidMemTotal = this->e.dga.fb_memsize;
2463                 caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);              /* we can do anything */
2464                 caps2->ddsCaps.dwCaps = 0xffffffff;     /* we can do anything */
2465         }
2466         return DD_OK;
2467 #else /* defined(HAVE_LIBXXF86DGA) */
2468         return E_UNEXPECTED;
2469 #endif /* defined(HAVE_LIBXXF86DGA) */
2470 }
2471
2472 static void fill_caps(LPDDCAPS caps) {
2473   /* This function tries to fill the capabilities of Wine's DDraw implementation.
2474      Need to be fixed, though.. */
2475   if (caps == NULL)
2476     return;
2477
2478   caps->dwSize = sizeof(*caps);
2479   caps->dwCaps = DDCAPS_3D | DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL |
2480     DDCAPS_CANBLTSYSMEM | DDCAPS_PALETTE | DDCAPS_ZBLTS;
2481   caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NO2DDURING3DSCENE | DDCAPS2_NOPAGELOCKREQUIRED |
2482     DDCAPS2_WIDESURFACES;
2483   caps->dwCKeyCaps = 0;
2484   caps->dwFXCaps = 0;
2485   caps->dwFXAlphaCaps = 0;
2486   caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
2487   caps->dwSVCaps = 0;
2488   caps->dwZBufferBitDepths = DDBD_16;
2489   /* I put here 8 Mo so that D3D applications will believe they have enough memory
2490      to put textures in video memory.
2491      BTW, is this only frame buffer memory or also texture memory (for Voodoo boards
2492      for example) ? */
2493   caps->dwVidMemTotal = 8192 * 1024;
2494   caps->dwVidMemFree = 8192 * 1024;
2495   /* These are all the supported capabilities of the surfaces */
2496   caps->ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
2497     DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_MIPMAP | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
2498       DDSCAPS_OVERLAY | DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE |
2499         DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE | DDSCAPS_ZBUFFER;
2500 }
2501
2502 static HRESULT WINAPI Xlib_IDirectDraw2_GetCaps(
2503         LPDIRECTDRAW2 this,LPDDCAPS caps1,LPDDCAPS caps2
2504 )  {
2505         TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",this,caps1,caps2);
2506
2507         /* Put the same caps for the two capabilities */
2508         fill_caps(caps1);
2509         fill_caps(caps2);
2510
2511         return DD_OK;
2512 }
2513
2514 static HRESULT WINAPI IDirectDraw2_CreateClipper(
2515         LPDIRECTDRAW2 this,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
2516 ) {
2517         FIXME(ddraw,"(%p)->(%08lx,%p,%p),stub!\n",
2518                 this,x,lpddclip,lpunk
2519         );
2520         *lpddclip = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipper));
2521         (*lpddclip)->ref = 1;
2522         (*lpddclip)->lpvtbl = &ddclipvt;
2523         return DD_OK;
2524 }
2525
2526 static HRESULT WINAPI common_IDirectDraw2_CreatePalette(
2527         LPDIRECTDRAW2 this,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
2528 ) {
2529         *lpddpal = (LPDIRECTDRAWPALETTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPalette));
2530         if (*lpddpal == NULL) return E_OUTOFMEMORY;
2531         (*lpddpal)->ref = 1;
2532         (*lpddpal)->ddraw = (LPDIRECTDRAW)this;
2533         (*lpddpal)->installed = 0;
2534         if (this->d.depth<=8) {
2535                 (*lpddpal)->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(screen),AllocAll);
2536         } else {
2537                 /* we don't want palettes in hicolor or truecolor */
2538                 (*lpddpal)->cm = 0;
2539         }
2540
2541         if (palent)
2542         {
2543           int size = 0;
2544           
2545           if (dwFlags & DDPCAPS_1BIT)
2546             size = 2;
2547           else if (dwFlags & DDPCAPS_2BIT)
2548             size = 4;
2549           else if (dwFlags & DDPCAPS_4BIT)
2550             size = 16;
2551           else if (dwFlags & DDPCAPS_8BIT)
2552             size = 256;
2553           else
2554             ERR(ddraw, "unhandled palette format\n");
2555           
2556           memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
2557         }
2558         return DD_OK;
2559 }
2560
2561 static HRESULT WINAPI DGA_IDirectDraw2_CreatePalette(
2562         LPDIRECTDRAW2 this,DWORD x,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
2563 ) {
2564         HRESULT res;
2565         TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",this,x,palent,lpddpal,lpunk);
2566         res = common_IDirectDraw2_CreatePalette(this,x,palent,lpddpal,lpunk);
2567         if (res != 0) return res;
2568         (*lpddpal)->lpvtbl = &dga_ddpalvt;
2569         return DD_OK;
2570 }
2571
2572 static HRESULT WINAPI Xlib_IDirectDraw2_CreatePalette(
2573         LPDIRECTDRAW2 this,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
2574 ) {
2575         TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",this,dwFlags,palent,lpddpal,lpunk);
2576         *lpddpal = (LPDIRECTDRAWPALETTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPalette));
2577
2578         TRACE(ddraw, "Palette created : %p\n", *lpddpal);
2579         
2580         if (*lpddpal == NULL) 
2581                 return E_OUTOFMEMORY;
2582
2583         (*lpddpal)->ref = 1;
2584         (*lpddpal)->installed = 0;
2585         (*lpddpal)->lpvtbl = &xlib_ddpalvt;
2586
2587         (*lpddpal)->ddraw = (LPDIRECTDRAW)this;
2588         this->lpvtbl->fnAddRef(this);
2589
2590         if (palent) {
2591           int size = 0;
2592
2593           if (dwFlags & DDPCAPS_1BIT)
2594             size = 2;
2595           else if (dwFlags & DDPCAPS_2BIT)
2596             size = 4;
2597           else if (dwFlags & DDPCAPS_4BIT)
2598             size = 16;
2599           else if (dwFlags & DDPCAPS_8BIT)
2600             size = 256;
2601           else
2602             ERR(ddraw, "unhandled palette format\n");
2603           
2604           memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
2605         }
2606
2607         return DD_OK;
2608 }
2609
2610 static HRESULT WINAPI DGA_IDirectDraw2_RestoreDisplayMode(LPDIRECTDRAW2 this) {
2611 #ifdef HAVE_LIBXXF86DGA
2612         TRACE(ddraw, "(%p)->()\n",this);
2613         Sleep(1000);
2614         TSXF86DGADirectVideo(display,DefaultScreen(display),0);
2615 #ifdef RESTORE_SIGNALS
2616         SIGNAL_InitEmulator();
2617 #endif
2618         return DD_OK;
2619 #else /* defined(HAVE_LIBXXF86DGA) */
2620         return E_UNEXPECTED;
2621 #endif
2622 }
2623
2624 static HRESULT WINAPI Xlib_IDirectDraw2_RestoreDisplayMode(LPDIRECTDRAW2 this) {
2625         TRACE(ddraw, "(%p)->RestoreDisplayMode()\n", this);
2626         Sleep(1000);
2627         return DD_OK;
2628 }
2629
2630 static HRESULT WINAPI IDirectDraw2_WaitForVerticalBlank(
2631         LPDIRECTDRAW2 this,DWORD x,HANDLE32 h
2632 ) {
2633         TRACE(ddraw,"(%p)->(0x%08lx,0x%08x)\n",this,x,h);
2634         return DD_OK;
2635 }
2636
2637 static ULONG WINAPI IDirectDraw2_AddRef(LPDIRECTDRAW2 this) {
2638         TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
2639
2640         return ++(this->ref);
2641 }
2642
2643 static ULONG WINAPI DGA_IDirectDraw2_Release(LPDIRECTDRAW2 this) {
2644         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
2645
2646 #ifdef HAVE_LIBXXF86DGA
2647         if (!--(this->ref)) {
2648                 TSXF86DGADirectVideo(display,DefaultScreen(display),0);
2649
2650 #ifdef HAVE_LIBXXF86VM
2651                 if (orig_mode) {
2652                         TSXF86VidModeSwitchToMode(
2653                                 display,
2654                                 DefaultScreen(display),
2655                                 orig_mode);
2656                         if (orig_mode->privsize)
2657                                 TSXFree(orig_mode->private);            
2658                         free(orig_mode);
2659                         orig_mode = NULL;
2660                 }
2661 #endif
2662                 
2663 #ifdef RESTORE_SIGNALS
2664                 SIGNAL_InitEmulator();
2665 #endif
2666                 HeapFree(GetProcessHeap(),0,this);
2667                 return 0;
2668         }
2669 #endif /* defined(HAVE_LIBXXF86DGA) */
2670         return this->ref;
2671 }
2672
2673 static ULONG WINAPI Xlib_IDirectDraw2_Release(LPDIRECTDRAW2 this) {
2674         TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
2675
2676         if (!--(this->ref)) {
2677                 HeapFree(GetProcessHeap(),0,this);
2678                 return 0;
2679         }
2680         /* FIXME: destroy window ... */
2681         return this->ref;
2682 }
2683
2684 static HRESULT WINAPI DGA_IDirectDraw2_QueryInterface(
2685         LPDIRECTDRAW2 this,REFIID refiid,LPVOID *obj
2686 ) {
2687         char    xrefiid[50];
2688
2689         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
2690         TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
2691         if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
2692                 *obj = this;
2693                 this->lpvtbl->fnAddRef(this);
2694
2695                 TRACE(ddraw, "  Creating IUnknown interface (%p)\n", *obj);
2696                 
2697                 return S_OK;
2698         }
2699         if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
2700                 this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&dga_ddvt;
2701                 this->lpvtbl->fnAddRef(this);
2702                 *obj = this;
2703
2704                 TRACE(ddraw, "  Creating IDirectDraw interface (%p)\n", *obj);
2705                 
2706                 return S_OK;
2707         }
2708         if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
2709                 this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&dga_dd2vt;
2710                 this->lpvtbl->fnAddRef(this);
2711                 *obj = this;
2712
2713                 TRACE(ddraw, "  Creating IDirectDraw2 interface (%p)\n", *obj);
2714
2715                 return S_OK;
2716         }
2717         if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
2718                 LPDIRECT3D      d3d;
2719
2720                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
2721                 d3d->ref = 1;
2722                 d3d->ddraw = (LPDIRECTDRAW)this;
2723                 this->lpvtbl->fnAddRef(this);
2724                 d3d->lpvtbl = &d3dvt;
2725                 *obj = d3d;
2726
2727                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
2728                 
2729                 return S_OK;
2730         }
2731         if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D))) {
2732                 LPDIRECT3D2     d3d;
2733
2734                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
2735                 d3d->ref = 1;
2736                 d3d->ddraw = (LPDIRECTDRAW)this;
2737                 this->lpvtbl->fnAddRef(this);
2738                 d3d->lpvtbl = &d3d2vt;
2739                 *obj = d3d;
2740
2741                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
2742                 
2743                 return S_OK;
2744         }
2745         WARN(ddraw,"(%p):interface for IID %s _NOT_ found!\n",this,xrefiid);
2746         return OLE_E_ENUM_NOMORE;
2747 }
2748
2749 static HRESULT WINAPI Xlib_IDirectDraw2_QueryInterface(
2750         LPDIRECTDRAW2 this,REFIID refiid,LPVOID *obj
2751 ) {
2752         char    xrefiid[50];
2753
2754         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
2755         TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
2756         if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
2757                 *obj = this;
2758                 this->lpvtbl->fnAddRef(this);
2759
2760                 TRACE(ddraw, "  Creating IUnknown interface (%p)\n", *obj);
2761                 
2762                 return S_OK;
2763         }
2764         if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
2765                 this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&xlib_ddvt;
2766                 this->lpvtbl->fnAddRef(this);
2767                 *obj = this;
2768
2769                 TRACE(ddraw, "  Creating IDirectDraw interface (%p)\n", *obj);
2770                 
2771                 return S_OK;
2772         }
2773         if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
2774                 this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&xlib_dd2vt;
2775                 this->lpvtbl->fnAddRef(this);
2776                 *obj = this;
2777
2778                 TRACE(ddraw, "  Creating IDirectDraw2 interface (%p)\n", *obj);
2779                 
2780                 return S_OK;
2781         }
2782         if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
2783                 LPDIRECT3D      d3d;
2784
2785                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
2786                 d3d->ref = 1;
2787                 d3d->ddraw = (LPDIRECTDRAW)this;
2788                 this->lpvtbl->fnAddRef(this);
2789                 d3d->lpvtbl = &d3dvt;
2790                 *obj = d3d;
2791
2792                 TRACE(ddraw, "  Creating IDirect3D interface (%p)\n", *obj);
2793
2794                 return S_OK;
2795         }
2796         if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D))) {
2797                 LPDIRECT3D2     d3d;
2798
2799                 d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
2800                 d3d->ref = 1;
2801                 d3d->ddraw = (LPDIRECTDRAW)this;
2802                 this->lpvtbl->fnAddRef(this);
2803                 d3d->lpvtbl = &d3d2vt;
2804                 *obj = d3d;
2805
2806                 TRACE(ddraw, "  Creating IDirect3D2 interface (%p)\n", *obj);
2807
2808                 return S_OK;
2809         }
2810         WARN(ddraw,"(%p):interface for IID %s _NOT_ found!\n",this,xrefiid);
2811         return OLE_E_ENUM_NOMORE;
2812 }
2813
2814 static HRESULT WINAPI IDirectDraw2_GetVerticalBlankStatus(
2815         LPDIRECTDRAW2 this,BOOL32 *status
2816 ) {
2817         TRACE(ddraw,"(%p)->(%p)\n",this,status);
2818         *status = TRUE;
2819         return DD_OK;
2820 }
2821
2822 static HRESULT WINAPI IDirectDraw2_EnumDisplayModes(
2823         LPDIRECTDRAW2 this,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
2824 ) {
2825         DDSURFACEDESC   ddsfd;
2826         static struct {
2827                 int w,h;
2828         } modes[5] = { /* some of the usual modes */
2829                 {512,384},
2830                 {640,400},
2831                 {640,480},
2832                 {800,600},
2833                 {1024,768},
2834         };
2835         static int depths[4] = {8,16,24,32};
2836         int     i,j;
2837
2838         TRACE(ddraw,"(%p)->(0x%08lx,%p,%p,%p)\n",this,dwFlags,lpddsfd,context,modescb);
2839         ddsfd.dwSize = sizeof(ddsfd);
2840         ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
2841         if (dwFlags & DDEDM_REFRESHRATES) {
2842                 ddsfd.dwFlags |= DDSD_REFRESHRATE;
2843                 ddsfd.x.dwRefreshRate = 60;
2844         }
2845
2846         for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
2847                 ddsfd.dwBackBufferCount = 1;
2848                 ddsfd.ddpfPixelFormat.dwFourCC  = 0;
2849                 ddsfd.ddpfPixelFormat.dwFlags   = DDPF_RGB;
2850                 ddsfd.ddpfPixelFormat.x.dwRGBBitCount   = depths[i];
2851                 /* FIXME: those masks would have to be set in depth > 8 */
2852                 if (depths[i]==8) {
2853                 ddsfd.ddpfPixelFormat.y.dwRBitMask      = 0;
2854                 ddsfd.ddpfPixelFormat.z.dwGBitMask      = 0;
2855                 ddsfd.ddpfPixelFormat.xx.dwBBitMask     = 0;
2856                 ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
2857                         ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
2858                         ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
2859                 } else {
2860                   ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
2861                   
2862                   /* FIXME: We should query those from X itself */
2863                   switch (depths[i]) {
2864                   case 16:
2865                     ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x000f;
2866                     ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x00f0;
2867                     ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x0f00;
2868                     break;
2869                   case 24:
2870                     ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x000000ff;
2871                     ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x0000ff00;
2872                     ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x00ff0000;
2873                     break;
2874                   case 32:
2875                     ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x000000ff;
2876                     ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x0000ff00;
2877                     ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x00ff0000;
2878                     break;
2879                   }
2880                 }
2881
2882                 ddsfd.dwWidth = screenWidth;
2883                 ddsfd.dwHeight = screenHeight;
2884                 TRACE(ddraw," enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
2885                 if (!modescb(&ddsfd,context)) return DD_OK;
2886
2887                 for (j=0;j<sizeof(modes)/sizeof(modes[0]);j++) {
2888                         ddsfd.dwWidth   = modes[j].w;
2889                         ddsfd.dwHeight  = modes[j].h;
2890                         TRACE(ddraw," enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
2891                         if (!modescb(&ddsfd,context)) return DD_OK;
2892                 }
2893
2894                 if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
2895                         /* modeX is not standard VGA */
2896
2897                         ddsfd.dwHeight = 200;
2898                         ddsfd.dwWidth = 320;
2899                         TRACE(ddraw," enumerating (320x200x%d)\n",depths[i]);
2900                         if (!modescb(&ddsfd,context)) return DD_OK;
2901                 }
2902         }
2903         return DD_OK;
2904 }
2905
2906 static HRESULT WINAPI DGA_IDirectDraw2_GetDisplayMode(
2907         LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsfd
2908 ) {
2909 #ifdef HAVE_LIBXXF86DGA
2910         TRACE(ddraw,"(%p)->(%p)\n",this,lpddsfd);
2911         lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
2912         lpddsfd->dwHeight = screenHeight;
2913         lpddsfd->dwWidth = screenWidth;
2914         lpddsfd->lPitch = this->e.dga.fb_width*this->d.depth/8;
2915         lpddsfd->dwBackBufferCount = 1;
2916         lpddsfd->x.dwRefreshRate = 60;
2917         lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
2918         _getpixelformat(this,&(lpddsfd->ddpfPixelFormat));
2919         return DD_OK;
2920 #else /* defined(HAVE_LIBXXF86DGA) */
2921         return E_UNEXPECTED;
2922 #endif /* defined(HAVE_LIBXXF86DGA) */
2923 }
2924
2925 static HRESULT WINAPI Xlib_IDirectDraw2_GetDisplayMode(
2926         LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsfd
2927 ) {
2928         TRACE(ddraw,"(%p)->GetDisplayMode(%p)\n",this,lpddsfd);
2929         lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
2930         lpddsfd->dwHeight = screenHeight;
2931         lpddsfd->dwWidth = screenWidth;
2932         /* POOLE FIXME: Xlib */
2933         lpddsfd->lPitch = this->e.dga.fb_width*this->d.depth/8;
2934         /* END FIXME: Xlib */
2935         lpddsfd->dwBackBufferCount = 1;
2936         lpddsfd->x.dwRefreshRate = 60;
2937         lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
2938         _getpixelformat(this,&(lpddsfd->ddpfPixelFormat));
2939         return DD_OK;
2940 }
2941
2942 static HRESULT WINAPI IDirectDraw2_FlipToGDISurface(LPDIRECTDRAW2 this) {
2943         TRACE(ddraw,"(%p)->()\n",this);
2944         return DD_OK;
2945 }
2946
2947 static HRESULT WINAPI IDirectDraw2_GetMonitorFrequency(
2948         LPDIRECTDRAW2 this,LPDWORD freq
2949 ) {
2950         FIXME(ddraw,"(%p)->(%p) returns 60 Hz always\n",this,freq);
2951         *freq = 60*100; /* 60 Hz */
2952         return DD_OK;
2953 }
2954
2955 /* what can we directly decompress? */
2956 static HRESULT WINAPI IDirectDraw2_GetFourCCCodes(
2957         LPDIRECTDRAW2 this,LPDWORD x,LPDWORD y
2958 ) {
2959         FIXME(ddraw,"(%p,%p,%p), stub\n",this,x,y);
2960         return DD_OK;
2961 }
2962
2963 static HRESULT WINAPI IDirectDraw2_EnumSurfaces(
2964         LPDIRECTDRAW2 this,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,LPDDENUMSURFACESCALLBACK ddsfcb
2965 ) {
2966   FIXME(ddraw,"(%p)->(0x%08lx,%p,%p,%p),stub!\n",this,x,ddsfd,context,ddsfcb);
2967   return DD_OK;
2968 }
2969
2970 static HRESULT WINAPI IDirectDraw2_Compact(
2971           LPDIRECTDRAW2 this )
2972 {
2973   FIXME(ddraw,"(%p)->()\n", this );
2974  
2975   return DD_OK;
2976 }
2977
2978
2979 /* Note: Hack so we can reuse the old functions without compiler warnings */
2980 #ifdef __GNUC__
2981 # define XCAST(fun)     (typeof(dga_ddvt.fn##fun))
2982 #else
2983 # define XCAST(fun)     (void*)
2984 #endif
2985
2986 static struct IDirectDraw_VTable dga_ddvt = {
2987         XCAST(QueryInterface)DGA_IDirectDraw2_QueryInterface,
2988         XCAST(AddRef)IDirectDraw2_AddRef,
2989         XCAST(Release)DGA_IDirectDraw2_Release,
2990         XCAST(Compact)IDirectDraw2_Compact,
2991         XCAST(CreateClipper)IDirectDraw2_CreateClipper,
2992         XCAST(CreatePalette)DGA_IDirectDraw2_CreatePalette,
2993         XCAST(CreateSurface)DGA_IDirectDraw2_CreateSurface,
2994         XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
2995         XCAST(EnumDisplayModes)IDirectDraw2_EnumDisplayModes,
2996         XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
2997         XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
2998         XCAST(GetCaps)DGA_IDirectDraw2_GetCaps,
2999         XCAST(GetDisplayMode)DGA_IDirectDraw2_GetDisplayMode,
3000         XCAST(GetFourCCCodes)IDirectDraw2_GetFourCCCodes,
3001         XCAST(GetGDISurface)15,
3002         XCAST(GetMonitorFrequency)IDirectDraw2_GetMonitorFrequency,
3003         XCAST(GetScanLine)17,
3004         XCAST(GetVerticalBlankStatus)IDirectDraw2_GetVerticalBlankStatus,
3005         XCAST(Initialize)19,
3006         XCAST(RestoreDisplayMode)DGA_IDirectDraw2_RestoreDisplayMode,
3007         XCAST(SetCooperativeLevel)IDirectDraw2_SetCooperativeLevel,
3008         DGA_IDirectDraw_SetDisplayMode,
3009         XCAST(WaitForVerticalBlank)IDirectDraw2_WaitForVerticalBlank,
3010 };
3011
3012 static struct IDirectDraw_VTable xlib_ddvt = {
3013         XCAST(QueryInterface)Xlib_IDirectDraw2_QueryInterface,
3014         XCAST(AddRef)IDirectDraw2_AddRef,
3015         XCAST(Release)Xlib_IDirectDraw2_Release,
3016         XCAST(Compact)IDirectDraw2_Compact,
3017         XCAST(CreateClipper)IDirectDraw2_CreateClipper,
3018         XCAST(CreatePalette)Xlib_IDirectDraw2_CreatePalette,
3019         XCAST(CreateSurface)Xlib_IDirectDraw2_CreateSurface,
3020         XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
3021         XCAST(EnumDisplayModes)IDirectDraw2_EnumDisplayModes,
3022         XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
3023         XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
3024         XCAST(GetCaps)Xlib_IDirectDraw2_GetCaps,
3025         XCAST(GetDisplayMode)Xlib_IDirectDraw2_GetDisplayMode,
3026         XCAST(GetFourCCCodes)IDirectDraw2_GetFourCCCodes,
3027         XCAST(GetGDISurface)15,
3028         XCAST(GetMonitorFrequency)IDirectDraw2_GetMonitorFrequency,
3029         XCAST(GetScanLine)17,
3030         XCAST(GetVerticalBlankStatus)IDirectDraw2_GetVerticalBlankStatus,
3031         XCAST(Initialize)19,
3032         XCAST(RestoreDisplayMode)Xlib_IDirectDraw2_RestoreDisplayMode,
3033         XCAST(SetCooperativeLevel)IDirectDraw2_SetCooperativeLevel,
3034         Xlib_IDirectDraw_SetDisplayMode,
3035         XCAST(WaitForVerticalBlank)IDirectDraw2_WaitForVerticalBlank,
3036 };
3037
3038 /*****************************************************************************
3039  *      IDirectDraw2
3040  *
3041  */
3042
3043
3044 static HRESULT WINAPI DGA_IDirectDraw2_SetDisplayMode(
3045         LPDIRECTDRAW2 this,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
3046 ) {
3047         return DGA_IDirectDraw_SetDisplayMode((LPDIRECTDRAW)this,width,height,depth);
3048 }
3049
3050 static HRESULT WINAPI Xlib_IDirectDraw2_SetDisplayMode(
3051         LPDIRECTDRAW2 this,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
3052 ) {
3053         return Xlib_IDirectDraw_SetDisplayMode((LPDIRECTDRAW)this,width,height,depth);
3054 }
3055
3056 static HRESULT WINAPI DGA_IDirectDraw2_GetAvailableVidMem(
3057         LPDIRECTDRAW2 this,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
3058 ) {
3059         TRACE(ddraw,"(%p)->(%p,%p,%p)\n",
3060                 this,ddscaps,total,free
3061         );
3062         if (total) *total = this->e.dga.fb_memsize * 1024;
3063         if (free) *free = this->e.dga.fb_memsize * 1024;
3064         return DD_OK;
3065 }
3066
3067 static HRESULT WINAPI Xlib_IDirectDraw2_GetAvailableVidMem(
3068         LPDIRECTDRAW2 this,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
3069 ) {
3070         TRACE(ddraw,"(%p)->(%p,%p,%p)\n",
3071                 this,ddscaps,total,free
3072         );
3073         if (total) *total = 2048 * 1024;
3074         if (free) *free = 2048 * 1024;
3075         return DD_OK;
3076 }
3077
3078 static IDirectDraw2_VTable dga_dd2vt = {
3079         DGA_IDirectDraw2_QueryInterface,
3080         IDirectDraw2_AddRef,
3081         DGA_IDirectDraw2_Release,
3082         IDirectDraw2_Compact,
3083         IDirectDraw2_CreateClipper,
3084         DGA_IDirectDraw2_CreatePalette,
3085         DGA_IDirectDraw2_CreateSurface,
3086         (void*)8,
3087         IDirectDraw2_EnumDisplayModes,
3088         IDirectDraw2_EnumSurfaces,
3089         IDirectDraw2_FlipToGDISurface,
3090         DGA_IDirectDraw2_GetCaps,
3091         DGA_IDirectDraw2_GetDisplayMode,
3092         IDirectDraw2_GetFourCCCodes,
3093         (void*)15,
3094         IDirectDraw2_GetMonitorFrequency,
3095         (void*)17,
3096         IDirectDraw2_GetVerticalBlankStatus,
3097         (void*)19,
3098         DGA_IDirectDraw2_RestoreDisplayMode,
3099         IDirectDraw2_SetCooperativeLevel,
3100         DGA_IDirectDraw2_SetDisplayMode,
3101         IDirectDraw2_WaitForVerticalBlank,
3102         DGA_IDirectDraw2_GetAvailableVidMem
3103 };
3104
3105 static struct IDirectDraw2_VTable xlib_dd2vt = {
3106         Xlib_IDirectDraw2_QueryInterface,
3107         IDirectDraw2_AddRef,
3108         Xlib_IDirectDraw2_Release,
3109         IDirectDraw2_Compact,
3110         IDirectDraw2_CreateClipper,
3111         Xlib_IDirectDraw2_CreatePalette,
3112         Xlib_IDirectDraw2_CreateSurface,
3113         (void*)8,
3114         IDirectDraw2_EnumDisplayModes,
3115         IDirectDraw2_EnumSurfaces,
3116         IDirectDraw2_FlipToGDISurface,
3117         Xlib_IDirectDraw2_GetCaps,
3118         Xlib_IDirectDraw2_GetDisplayMode,
3119         IDirectDraw2_GetFourCCCodes,
3120         (void*)15,
3121         IDirectDraw2_GetMonitorFrequency,
3122         (void*)17,
3123         IDirectDraw2_GetVerticalBlankStatus,
3124         (void*)19,
3125         Xlib_IDirectDraw2_RestoreDisplayMode,
3126         IDirectDraw2_SetCooperativeLevel,
3127         Xlib_IDirectDraw2_SetDisplayMode,
3128         IDirectDraw2_WaitForVerticalBlank,
3129         Xlib_IDirectDraw2_GetAvailableVidMem    
3130 };
3131
3132 /******************************************************************************
3133  *                              DirectDrawCreate
3134  */
3135
3136 LRESULT WINAPI Xlib_DDWndProc(HWND32 hwnd,UINT32 msg,WPARAM32 wParam,LPARAM lParam)
3137 {
3138    LRESULT ret;
3139    LPDIRECTDRAW ddraw = NULL;
3140    DWORD lastError;
3141
3142    /* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
3143
3144    SetLastError( ERROR_SUCCESS );
3145    ddraw  = (LPDIRECTDRAW)GetWindowLong32A( hwnd, ddrawXlibThisOffset );
3146    if( (!ddraw)  &&
3147        ( ( lastError = GetLastError() ) != ERROR_SUCCESS )
3148      ) 
3149    {
3150      ERR( ddraw, "Unable to retrieve this ptr from window. Error %08lx\n", lastError );
3151    }
3152
3153    if( ddraw )
3154    {
3155       /* Perform any special direct draw functions */
3156       if (msg==WM_PAINT)
3157         ddraw->d.paintable = 1;
3158
3159       /* Now let the application deal with the rest of this */
3160       if( ddraw->d.mainWindow )
3161       {
3162     
3163         /* Don't think that we actually need to call this but... 
3164            might as well be on the safe side of things... */
3165
3166         /* I changed hwnd to ddraw->d.mainWindow as I did not see why
3167            it should be the procedures of our fake window that gets called
3168            instead of those of the window provided by the application.
3169            And with this patch, mouse clicks work with Monkey Island III
3170              - Lionel */
3171         ret = DefWindowProc32A( ddraw->d.mainWindow, msg, wParam, lParam );
3172
3173         if( !ret )
3174         {
3175           /* We didn't handle the message - give it to the application */
3176           if (ddraw && ddraw->d.mainWindow && WIN_FindWndPtr(ddraw->d.mainWindow)) {
3177                 ret = CallWindowProc32A( WIN_FindWndPtr( ddraw->d.mainWindow )->winproc,
3178                                    ddraw->d.mainWindow, msg, wParam, lParam );
3179           }
3180         }
3181         
3182       } else {
3183         ret = DefWindowProc32A(hwnd, msg, wParam, lParam );
3184       } 
3185
3186     }
3187     else
3188     {
3189         ret = DefWindowProc32A(hwnd,msg,wParam,lParam);
3190     }
3191
3192     return ret;
3193 }
3194
3195 HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
3196 #ifdef HAVE_LIBXXF86DGA
3197         int     memsize,banksize,width,major,minor,flags,height;
3198         char    *addr;
3199         int     fd;                     
3200
3201         /* Must be able to access /dev/mem for DGA extensions to work, root is not neccessary. --stephenc */
3202         if ((fd = open("/dev/mem", O_RDWR)) != -1)
3203           close(fd);
3204         
3205         if (fd  == -1) {
3206           MSG("Must be able to access /dev/mem to use XF86DGA!\n");
3207           MessageBox32A(0,"Using the XF86DGA extension requires access to /dev/mem.","WINE DirectDraw",MB_OK|MB_ICONSTOP);
3208           return E_UNEXPECTED;
3209         }
3210         if (!DDRAW_DGA_Available()) {
3211                 TRACE(ddraw,"No XF86DGA detected.\n");
3212                 return DDERR_GENERIC;
3213         }
3214         *lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDraw));
3215         (*lplpDD)->lpvtbl = &dga_ddvt;
3216         (*lplpDD)->ref = 1;
3217         TSXF86DGAQueryVersion(display,&major,&minor);
3218         TRACE(ddraw,"XF86DGA is version %d.%d\n",major,minor);
3219         TSXF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
3220         if (!(flags & XF86DGADirectPresent))
3221                 MSG("direct video is NOT PRESENT.\n");
3222         TSXF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
3223         TRACE(ddraw,"video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
3224                 addr,width,banksize,memsize
3225         );
3226         (*lplpDD)->e.dga.fb_width = width;
3227         (*lplpDD)->d.width = width;
3228         (*lplpDD)->e.dga.fb_addr = addr;
3229         (*lplpDD)->e.dga.fb_memsize = memsize;
3230         (*lplpDD)->e.dga.fb_banksize = banksize;
3231
3232         TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
3233         TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
3234         (*lplpDD)->e.dga.fb_height = screenHeight;
3235 #ifdef DIABLO_HACK
3236         (*lplpDD)->e.dga.vpmask = 1;
3237 #else
3238         (*lplpDD)->e.dga.vpmask = 0;
3239 #endif
3240
3241         /* just assume the default depth is the DGA depth too */
3242         (*lplpDD)->d.depth = DefaultDepthOfScreen(screen);
3243 #ifdef RESTORE_SIGNALS
3244         SIGNAL_InitEmulator();
3245 #endif
3246
3247         return DD_OK;
3248 #else /* defined(HAVE_LIBXXF86DGA) */
3249         return DDERR_INVALIDDIRECTDRAWGUID;
3250 #endif /* defined(HAVE_LIBXXF86DGA) */
3251 }
3252
3253 BOOL32
3254 DDRAW_XSHM_Available(void)
3255    {
3256 #ifdef HAVE_LIBXXSHM
3257   if (TSXShmQueryExtension(display))
3258       {
3259       int major, minor;
3260       Bool shpix;
3261
3262       if (TSXShmQueryVersion(display, &major, &minor, &shpix))
3263         return 1;
3264       else
3265         return 0;
3266     }
3267     else
3268     return 0;
3269 #else
3270   return 0;
3271 #endif
3272 }
3273
3274 HRESULT WINAPI Xlib_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
3275
3276         *lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDraw));
3277         (*lplpDD)->lpvtbl = &xlib_ddvt;
3278         (*lplpDD)->ref = 1;
3279         (*lplpDD)->d.drawable = 0; /* in SetDisplayMode */
3280
3281         (*lplpDD)->d.depth = DefaultDepthOfScreen(screen);
3282         (*lplpDD)->d.height = screenHeight;
3283         (*lplpDD)->d.width = screenWidth;
3284
3285 #ifdef HAVE_LIBXXSHM
3286         /* Test if XShm is available.
3287            As XShm is not ready yet for 'prime-time', it is disabled for now */
3288         if (((*lplpDD)->e.xlib.xshm_active = 0 /* DDRAW_XSHM_Available() */))
3289           TRACE(ddraw, "Using XShm extesion.\n");
3290 #endif
3291         
3292         return DD_OK;
3293 }
3294
3295 HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter ) {
3296         char    xclsid[50];
3297         WNDCLASS32A     wc;
3298         WND*            pParentWindow; 
3299         HRESULT ret;
3300
3301         if (HIWORD(lpGUID))
3302                 WINE_StringFromCLSID(lpGUID,xclsid);
3303         else {
3304                 sprintf(xclsid,"<guid-0x%08x>",(int)lpGUID);
3305                 lpGUID = NULL;
3306         }
3307
3308         TRACE(ddraw,"(%s,%p,%p)\n",xclsid,lplpDD,pUnkOuter);
3309
3310         if (!lpGUID) {
3311                 /* if they didn't request a particular interface, use the best
3312                  * supported one */
3313                 if (DDRAW_DGA_Available())
3314                         lpGUID = &DGA_DirectDraw_GUID;
3315                 else
3316                         lpGUID = &XLIB_DirectDraw_GUID;
3317         }
3318
3319         wc.style        = CS_GLOBALCLASS;
3320         wc.lpfnWndProc  = Xlib_DDWndProc;
3321         wc.cbClsExtra   = 0;
3322         wc.cbWndExtra   = /* Defines extra mem for window. This is used for storing this */
3323                           sizeof( LPDIRECTDRAW ); /*  ddrawXlibThisOffset */
3324
3325         /* We can be a child of the desktop since we're really important */
3326         pParentWindow   = WIN_GetDesktop();
3327         wc.hInstance    = pParentWindow ? pParentWindow->hwndSelf : 0;
3328         wc.hInstance    = 0; 
3329
3330         wc.hIcon        = 0;
3331         wc.hCursor      = (HCURSOR32)IDC_ARROW32A;
3332         wc.hbrBackground= NULL_BRUSH;
3333         wc.lpszMenuName = 0;
3334         wc.lpszClassName= "WINE_DirectDraw";
3335         RegisterClass32A(&wc);
3336
3337         if (!memcmp(lpGUID, &DGA_DirectDraw_GUID, sizeof(GUID)))
3338                 ret = DGA_DirectDrawCreate(lplpDD, pUnkOuter);
3339         else if (!memcmp(lpGUID, &XLIB_DirectDraw_GUID, sizeof(GUID)))
3340                 ret = Xlib_DirectDrawCreate(lplpDD, pUnkOuter);
3341         else
3342           goto err;
3343
3344         (*lplpDD)->d.winclass = RegisterClass32A(&wc);
3345         return ret;
3346
3347       err:
3348         fprintf(stderr,"DirectDrawCreate(%s,%p,%p): did not recognize requested GUID\n",xclsid,lplpDD,pUnkOuter);
3349         return DDERR_INVALIDDIRECTDRAWGUID;
3350 }