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