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