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