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