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