Fixed some issues found by winapi_check.
[wine] / dlls / ddraw / dsurface / x11.c
1 /*              DirectDrawSurface Xlib implementation
2  *
3  * Copyright 1997-2000 Marcus Meissner
4  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5  */
6 #include "config.h"
7 #include "winerror.h"
8
9 #include <unistd.h>
10 #include <assert.h>
11 #include <fcntl.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15
16 #include "options.h"
17 #include "debugtools.h"
18 #include "x11_private.h"
19 #include "bitmap.h"
20 #include "win.h"
21 #include "d3d.h"
22
23 #ifdef HAVE_OPENGL
24 /* for d3d texture stuff */
25 # include "mesa_private.h"
26 #endif
27
28 DEFAULT_DEBUG_CHANNEL(ddraw);
29
30 #define VISIBLE(x) (SDDSCAPS(x) & (DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE))
31
32 #define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->d->private)
33 #define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
34 #define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
35
36 static BYTE Xlib_TouchData(LPVOID data)
37 {
38     /* this is a function so it doesn't get optimized out */
39     return *(BYTE*)data;
40 }
41
42 /******************************************************************************
43  *              IDirectDrawSurface methods
44  *
45  * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
46  * DDS and DDS2 use those functions. (Function calls did not change (except
47  * using different DirectDrawSurfaceX version), just added flags and functions)
48  */
49 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_QueryInterface(
50     LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
51 ) {
52     ICOM_THIS(IDirectDrawSurface4Impl,iface);
53
54     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
55     
56     /* All DirectDrawSurface versions (1, 2, 3 and 4) use
57      * the same interface. And IUnknown does that too of course.
58      */
59     if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid )        ||
60          IsEqualGUID( &IID_IDirectDrawSurface3, refiid )        ||
61          IsEqualGUID( &IID_IDirectDrawSurface2, refiid )        ||
62          IsEqualGUID( &IID_IDirectDrawSurface,  refiid )        ||
63          IsEqualGUID( &IID_IUnknown,            refiid )
64     ) {
65             *obj = This;
66             IDirectDrawSurface4_AddRef(iface);
67
68             TRACE("  Creating IDirectDrawSurface interface (%p)\n", *obj);
69             return S_OK;
70     }
71 #ifdef HAVE_OPENGL
72     if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ) {
73         /* Texture interface */
74         *obj = d3dtexture2_create(This);
75         IDirectDrawSurface4_AddRef(iface);
76         TRACE("  Creating IDirect3DTexture2 interface (%p)\n", *obj);
77         return S_OK;
78     }
79     if ( IsEqualGUID( &IID_IDirect3DTexture, refiid ) ) {
80         /* Texture interface */
81         *obj = d3dtexture_create(This);
82         IDirectDrawSurface4_AddRef(iface);
83         TRACE("  Creating IDirect3DTexture interface (%p)\n", *obj);
84         return S_OK;
85     }
86 #else
87     if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ||
88          IsEqualGUID( &IID_IDirect3DTexture, refiid )
89        )
90     {
91        ERR( "Cannot provide 3D support without OpenGL/Mesa installed\n" );
92     }
93 #endif /* HAVE_OPENGL */
94     FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
95     return OLE_E_ENUM_NOMORE;
96 }
97
98 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
99     LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
100 ) {
101     ICOM_THIS(IDirectDrawSurface4Impl,iface);
102     DSPRIVATE(This);
103     DDPRIVATE(This->s.ddraw);
104
105     /* DO NOT AddRef the surface! Lock/Unlock are NOT guaranteed to come in 
106      * matched pairs! - Marcus Meissner 20000509 */
107     TRACE("(%p)->Lock(%p,%p,%08lx,%08lx) ret=%p\n",This,lprect,lpddsd,flags,(DWORD)hnd,__builtin_return_address(0));
108     if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
109         WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
110                      This,lprect,lpddsd,flags,(DWORD)hnd);
111
112     /* First, copy the Surface description */
113     *lpddsd = This->s.surface_desc;
114     TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
115           lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
116
117     /* If asked only for a part, change the surface pointer */
118     if (lprect) {
119         TRACE(" lprect: %dx%d-%dx%d\n",
120                 lprect->top,lprect->left,lprect->bottom,lprect->right
121         );
122         if ((lprect->top < 0) ||
123             (lprect->left < 0) ||
124             (lprect->bottom < 0) ||
125             (lprect->right < 0)) {
126           ERR(" Negative values in LPRECT !!!\n");
127           return DDERR_INVALIDPARAMS;
128         }
129         lpddsd->u1.lpSurface=(LPVOID)((char*)This->s.surface_desc.u1.lpSurface+
130                 (lprect->top*This->s.surface_desc.lPitch) +
131                 lprect->left*GET_BPP(This->s.surface_desc));
132     } else
133         assert(This->s.surface_desc.u1.lpSurface);
134     /* wait for any previous operations to complete */
135 #ifdef HAVE_LIBXXSHM
136     if (dspriv->info.image && VISIBLE(This) && ddpriv->xshm_active) {
137 /*
138         int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
139         if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
140 */
141         X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
142     }
143 #endif
144
145     /* If part of a visible 'clipped' surface, copy what is seen on the
146        screen to the surface */
147     if ((dspriv->info.image && VISIBLE(This)) &&
148         (This->s.lpClipper)) {
149           HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
150           WND *wndPtr = WIN_FindWndPtr(hWnd);
151           Drawable drawable = X11DRV_WND_GetXWindow(wndPtr);
152           int width = wndPtr->rectClient.right - wndPtr->rectClient.left;
153           int height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
154           /* Now, get the source / destination coordinates */
155           int dest_x = wndPtr->rectClient.left;
156           int dest_y = wndPtr->rectClient.top;
157
158           if (!drawable) { /* we are running in -desktop mode */
159               drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
160               /* FIXME: not sure whether these are the right offsets */
161               dest_x+=wndPtr->rectWindow.left;
162               dest_y+=wndPtr->rectWindow.top;
163               WIN_ReleaseDesktop();
164           }
165
166           TSXGetSubImage(display, drawable, 0, 0, width, height, 0xFFFFFFFF,
167                        ZPixmap, dspriv->info.image, dest_x, dest_y);
168           
169           WIN_ReleaseWndPtr(wndPtr);
170     }
171     
172     return DD_OK;
173 }
174
175 static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
176   DSPRIVATE(This);
177   DDPRIVATE(This->s.ddraw);
178   Drawable drawable = ddpriv->drawable;
179   POINT adjust[2] = {{0, 0}, {0, 0}};
180   SIZE imgsiz;
181
182   /* Get XImage size */
183   imgsiz.cx = dspriv->info.image->width;
184   imgsiz.cy = dspriv->info.image->height;
185
186   if (This->s.lpClipper) {
187     HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
188     SIZE csiz;
189     WND *wndPtr = WIN_FindWndPtr(hWnd);
190     drawable = X11DRV_WND_GetXWindow(wndPtr);
191     
192     MapWindowPoints(hWnd, 0, adjust, 2);
193
194     imgsiz.cx -= adjust[0].x;
195     imgsiz.cy -= adjust[0].y;
196     /* (note: the rectWindow here should be the X window's interior rect, in
197      *  case anyone thinks otherwise while rewriting managed mode) */
198     adjust[1].x -= wndPtr->rectWindow.left;
199     adjust[1].y -= wndPtr->rectWindow.top;
200     csiz.cx = wndPtr->rectClient.right - wndPtr->rectClient.left;
201     csiz.cy = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
202     if (csiz.cx < imgsiz.cx) imgsiz.cx = csiz.cx;
203     if (csiz.cy < imgsiz.cy) imgsiz.cy = csiz.cy;
204     
205     TRACE("adjust: hwnd=%08x, surface %ldx%ld, drawable %ldx%ld\n", hWnd,
206           adjust[0].x, adjust[0].y,
207           adjust[1].x,adjust[1].y);
208     
209     WIN_ReleaseWndPtr(wndPtr);
210   }
211
212   if (!drawable) {
213     WND *tmpWnd = WIN_FindWndPtr(This->s.ddraw->d->window);
214     drawable = X11DRV_WND_GetXWindow(tmpWnd);
215     WIN_ReleaseWndPtr(tmpWnd);
216
217     /* We don't have a context for this window. Host off the desktop */
218     if( !drawable ) {
219         FIXME("Have to use Desktop Root Window??? Bummer.\n");
220         drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
221         WIN_ReleaseDesktop();
222     }
223     ddpriv->drawable = drawable;
224   }
225   
226   if (This->s.ddraw->d->pixel_convert != NULL)
227     This->s.ddraw->d->pixel_convert(This->s.surface_desc.u1.lpSurface,
228                                    dspriv->info.image->data,
229                                    This->s.surface_desc.dwWidth,
230                                    This->s.surface_desc.dwHeight,
231                                    This->s.surface_desc.lPitch,
232                                    This->s.palette);
233
234   /* if the DIB section is in GdiMod state, we must
235    * touch the surface to get any updates from the DIB */
236   Xlib_TouchData(dspriv->info.image->data);
237 #ifdef HAVE_LIBXXSHM
238     if (ddpriv->xshm_active) {
239 /*
240         X11DRV_EVENT_WaitReplaceShmCompletion( &(ddpriv->xshm_compl), This->s.ddraw->d.drawable );
241 */
242         /* let WaitShmCompletions track 'em for now */
243         /* (you may want to track it again whenever you implement DX7's partial
244         * surface locking, where threads have concurrent access) */
245         X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
246         TSXShmPutImage(display,
247                        drawable,
248                        DefaultGCOfScreen(X11DRV_GetXScreen()),
249                        dspriv->info.image,
250                        adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
251                        imgsiz.cx, imgsiz.cy,
252                        True
253                        );
254         /* make sure the image is transferred ASAP */
255         TSXFlush(display);
256     } else
257 #endif
258         TSXPutImage(display,
259                     drawable,
260                     DefaultGCOfScreen(X11DRV_GetXScreen()),
261                     dspriv->info.image,
262                     adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
263                     imgsiz.cx, imgsiz.cy
264                     );
265 }
266
267 #ifdef HAVE_XVIDEO
268 static void Xlib_copy_overlay_on_screen(IDirectDrawSurface4Impl* This) {
269   DSPRIVATE(This);
270   DDPRIVATE(This->s.ddraw);
271   Drawable drawable = ddpriv->drawable;
272
273   if (!drawable) {
274     WND *tmpWnd = WIN_FindWndPtr(This->s.ddraw->d->window);
275     drawable = X11DRV_WND_GetXWindow(tmpWnd);
276     WIN_ReleaseWndPtr(tmpWnd);
277
278     /* We don't have a context for this window. Host off the desktop */
279     if( !drawable ) {
280         FIXME("Have to use Desktop Root Window??? Bummer.\n");
281         drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
282         WIN_ReleaseDesktop();
283     }
284     ddpriv->drawable = drawable;
285   }
286
287 #ifdef HAVE_LIBXXSHM
288     if (ddpriv->xshm_active) {
289         /* let WaitShmCompletions track 'em for now */
290         /* (you may want to track it again whenever you implement DX7's partial
291         * surface locking, where threads have concurrent access) */
292         X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
293         TSXvShmPutImage(display, ddpriv->port_id, drawable, DefaultGCOfScreen(X11DRV_GetXScreen()),
294                         dspriv->info.overlay.image,
295                         dspriv->info.overlay.src_rect.left, dspriv->info.overlay.src_rect.top,
296                         dspriv->info.overlay.src_rect.right - dspriv->info.overlay.src_rect.left,
297                         dspriv->info.overlay.src_rect.bottom - dspriv->info.overlay.src_rect.top,
298                         dspriv->info.overlay.dst_rect.left, dspriv->info.overlay.dst_rect.top,
299                         dspriv->info.overlay.dst_rect.right - dspriv->info.overlay.dst_rect.left,
300                         dspriv->info.overlay.dst_rect.bottom - dspriv->info.overlay.dst_rect.top,
301                         True);
302         /* make sure the image is transferred ASAP */
303         TSXFlush(display);
304     } else
305 #endif
306       TSXvPutImage(display, ddpriv->port_id, drawable, DefaultGCOfScreen(X11DRV_GetXScreen()),
307                    dspriv->info.overlay.image,
308                    dspriv->info.overlay.src_rect.left, dspriv->info.overlay.src_rect.top,
309                    dspriv->info.overlay.src_rect.right - dspriv->info.overlay.src_rect.left,
310                    dspriv->info.overlay.src_rect.bottom - dspriv->info.overlay.src_rect.top,
311                    dspriv->info.overlay.dst_rect.left, dspriv->info.overlay.dst_rect.top,
312                    dspriv->info.overlay.dst_rect.right - dspriv->info.overlay.dst_rect.left,
313                    dspriv->info.overlay.dst_rect.bottom - dspriv->info.overlay.dst_rect.top);
314 }
315 #endif
316
317 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
318     LPDIRECTDRAWSURFACE4 iface,LPVOID surface
319 ) {
320     ICOM_THIS(IDirectDrawSurface4Impl,iface);
321     DDPRIVATE(This->s.ddraw);
322     DSPRIVATE(This);
323     TRACE("(%p)->Unlock(%p)\n",This,surface);
324
325     /*if (!This->s.ddraw->d.paintable)
326         return DD_OK; */
327
328     /* Only redraw the screen when unlocking the buffer that is on screen */
329     if (dspriv->info.image && VISIBLE(This)) {
330         Xlib_copy_surface_on_screen(This);
331         if (This->s.palette) {
332             DPPRIVATE(This->s.palette);
333             if(dppriv->cm)
334                 TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
335         }
336     } else if (dspriv->is_overlay) {
337       /* Case of an overlay surface */
338 #ifdef HAVE_XVIDEO
339       if (dspriv->info.overlay.shown)
340         Xlib_copy_overlay_on_screen(This);
341 #else
342       ERR("Why was this code activated WITHOUT XVideo support ?\n");
343 #endif
344     } 
345     /* DO NOT Release the surface! Lock/Unlock are NOT guaranteed to come in 
346      * matched pairs! - Marcus Meissner 20000509 */
347     return DD_OK;
348 }
349
350 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
351     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
352 ) {
353     ICOM_THIS(IDirectDrawSurface4Impl,iface);
354     XImage      *image;
355     DDPRIVATE(This->s.ddraw);
356     DSPRIVATE(This);
357     x11_ds_private      *fspriv;
358     LPBYTE      surf;
359     IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
360
361     TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
362     if ((!This->s.ddraw->d->paintable) && (dspriv->is_overlay == FALSE))
363         return DD_OK;
364     
365     iflipto = _common_find_flipto(This,iflipto);
366     fspriv = (x11_ds_private*)iflipto->private;
367
368     /* We need to switch the lowlevel surfaces, for xlib this is: */
369     /* The surface pointer */
370     surf                                = This->s.surface_desc.u1.lpSurface;
371     This->s.surface_desc.u1.lpSurface   = iflipto->s.surface_desc.u1.lpSurface;
372     iflipto->s.surface_desc.u1.lpSurface        = surf;
373
374     /* the associated ximage
375
376        NOTE : for XVideo, the pointer to the XvImage is at the same position
377               in memory than the standard XImage. This means that this code
378               still works :-)
379     */
380     image               = dspriv->info.image;
381     dspriv->info.image  = fspriv->info.image;
382     fspriv->info.image  = image;
383
384     if (dspriv->opengl_flip) {
385 #ifdef HAVE_OPENGL
386       ENTER_GL();
387       glXSwapBuffers(display, ddpriv->drawable);
388       LEAVE_GL();
389 #endif
390     } else if (dspriv->is_overlay) {
391 #ifdef HAVE_XVIDEO
392       if (dspriv->info.overlay.shown)
393         Xlib_copy_overlay_on_screen(This);
394 #else
395       ERR("Why was this code activated WITHOUT XVideo support ?\n");
396 #endif
397     } else {
398 #ifdef HAVE_LIBXXSHM
399       if (ddpriv->xshm_active) {
400         /*
401            int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
402            if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
403            */
404         X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
405       }
406 #endif
407       Xlib_copy_surface_on_screen(This);
408       if (iflipto->s.palette) {
409         DPPRIVATE(iflipto->s.palette);
410         if (dppriv->cm)
411           TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
412       }
413     }
414     return DD_OK;
415 }
416
417 /* The IDirectDrawSurface4::SetPalette method attaches the specified
418  * DirectDrawPalette object to a surface. The surface uses this palette for all
419  * subsequent operations. The palette change takes place immediately.
420  */
421 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_SetPalette(
422     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
423 ) {
424     ICOM_THIS(IDirectDrawSurface4Impl,iface);
425     DDPRIVATE(This->s.ddraw);
426     IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
427     x11_dp_private      *dppriv;
428     int i;
429
430     TRACE("(%p)->(%p)\n",This,ipal);
431
432     if (ipal == NULL) {
433         if( This->s.palette != NULL )
434             IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
435         This->s.palette = ipal;
436         return DD_OK;
437     }
438     dppriv = (x11_dp_private*)ipal->private;
439
440     if (!dppriv->cm &&
441         (This->s.ddraw->d->screen_pixelformat.u.dwRGBBitCount<=8)
442     ) {
443         dppriv->cm = TSXCreateColormap(
444             display,
445             ddpriv->drawable,
446             DefaultVisualOfScreen(X11DRV_GetXScreen()),
447             AllocAll
448         );
449         if (!Options.managed)
450             TSXInstallColormap(display,dppriv->cm);
451
452         for (i=0;i<256;i++) {
453             XColor xc;
454
455             xc.red              = ipal->palents[i].peRed<<8;
456             xc.blue             = ipal->palents[i].peBlue<<8;
457             xc.green    = ipal->palents[i].peGreen<<8;
458             xc.flags    = DoRed|DoBlue|DoGreen;
459             xc.pixel    = i;
460             TSXStoreColor(display,dppriv->cm,&xc);
461         }
462         TSXInstallColormap(display,dppriv->cm);
463     }
464     /* According to spec, we are only supposed to 
465      * AddRef if this is not the same palette.
466      */
467     if ( This->s.palette != ipal ) {
468         if( ipal != NULL )
469             IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
470         if( This->s.palette != NULL )
471             IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
472         This->s.palette = ipal; 
473         /* Perform the refresh, only if a palette was created */
474         if (dppriv->cm)
475           TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
476
477         if (This->s.hdc != 0) {
478             /* hack: set the DIBsection color map */
479             BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
480             X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
481             dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
482             GDI_ReleaseObj(This->s.DIBsection);
483         }
484     }
485     return DD_OK;
486 }
487
488 ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
489     ICOM_THIS(IDirectDrawSurface4Impl,iface);
490     DSPRIVATE(This);
491     DDPRIVATE(This->s.ddraw);
492
493     TRACE( "(%p)->() decrementing from %lu.\n", This, This->ref );
494     if (--(This->ref))
495         return This->ref;
496
497     IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
498
499     /* This frees the program-side surface. In some cases it had been
500      * allocated with MEM_SYSTEM, so it does not get 'really' freed
501      */
502     VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
503
504     /* Now free the XImages and the respective screen-side surfaces */
505     if (dspriv->info.image != NULL) {
506         if (dspriv->info.image->data != This->s.surface_desc.u1.lpSurface)
507             VirtualFree(dspriv->info.image->data, 0, MEM_RELEASE);
508 #ifdef HAVE_LIBXXSHM
509         if (ddpriv->xshm_active) {
510             TSXShmDetach(display, &(dspriv->shminfo));
511             if (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
512               TSXFree(dspriv->info.image);
513             } else {
514               TSXDestroyImage(dspriv->info.image);
515             }
516             shmdt(dspriv->shminfo.shmaddr);
517         } else 
518 #endif
519         {
520           if (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
521             TSXFree(dspriv->info.image);
522           } else {
523             /* normal X Image memory was never allocated by X, but always by 
524              * ourselves -> Don't let X free our imagedata.
525              */
526             dspriv->info.image->data = NULL;
527             TSXDestroyImage(dspriv->info.image);
528           }
529         }
530         dspriv->info.image = 0;
531     }
532
533     if (This->s.palette)
534         IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
535
536     /* Free the DIBSection (if any) */
537     if (This->s.hdc != 0) {
538         /* hack: restore the original DIBsection color map */
539         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
540         X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
541         dib->colorMap = dspriv->oldDIBmap;
542         GDI_ReleaseObj(This->s.DIBsection);
543
544         SelectObject(This->s.hdc, This->s.holdbitmap);
545         DeleteDC(This->s.hdc);
546         DeleteObject(This->s.DIBsection);
547     }
548
549     /* Free the clipper if present */
550     if(This->s.lpClipper)
551         IDirectDrawClipper_Release(This->s.lpClipper);
552     HeapFree(GetProcessHeap(),0,This->private);
553     HeapFree(GetProcessHeap(),0,This);
554     return S_OK;
555 }
556
557 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
558     ICOM_THIS(IDirectDrawSurface4Impl,iface);
559     DSPRIVATE(This);
560     int was_ok = This->s.hdc != 0;
561     HRESULT result = IDirectDrawSurface4Impl_GetDC(iface,lphdc);
562     if (This->s.hdc && !was_ok) {
563         /* hack: take over the DIBsection color map */
564         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
565         X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
566         dspriv->oldDIBmap = dib->colorMap;
567         dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
568         GDI_ReleaseObj(This->s.DIBsection);
569     }
570     return result;
571 }
572
573 #ifdef HAVE_XVIDEO
574 typedef struct {
575   BOOL shown;
576   LPRECT src_rect;
577   LPRECT dst_rect;
578   LPDIRECTDRAWSURFACE dest_surface;
579 } UpdateOverlayEnumerate;
580
581 static HRESULT WINAPI enum_func(LPDIRECTDRAWSURFACE lpDDSurface,
582                                 LPDDSURFACEDESC lpDDSurfaceDesc,  
583                                 LPVOID lpContext) {
584   ICOM_THIS(IDirectDrawSurface4Impl,lpDDSurface);
585   DSPRIVATE(This);
586   UpdateOverlayEnumerate *ctx = (UpdateOverlayEnumerate *) lpContext;
587
588   if ((lpDDSurfaceDesc->ddsCaps.dwCaps) & DDSCAPS_BACKBUFFER) {
589     TRACE("Upgrading surface %p\n", lpDDSurface);
590
591     if (ctx->shown) {
592       dspriv->info.overlay.shown = TRUE;
593       dspriv->info.overlay.src_rect = *(ctx->src_rect);
594       dspriv->info.overlay.dst_rect = *(ctx->dst_rect);
595       dspriv->info.overlay.dest_surface = ctx->dest_surface;
596     } else {
597       dspriv->info.overlay.shown = FALSE;
598     }
599   }
600   
601   return DDENUMRET_OK;
602 }
603 #endif
604
605 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_UpdateOverlay(
606     LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
607     LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
608     LPDDOVERLAYFX lpDDOverlayFx
609 ) {
610   ICOM_THIS(IDirectDrawSurface4Impl,iface);
611 #ifdef HAVE_XVIDEO
612   DSPRIVATE(This);
613   DDPRIVATE(This->s.ddraw);
614
615   if (ddpriv->xvideo_active) {
616     TRACE("(%p)->(%p,%p,%p,0x%08lx,%p)\n", This,
617           lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
618
619     if (TRACE_ON(ddraw)) {
620       DPRINTF(" - dwFlags : ");
621       _dump_DDOVERLAY(dwFlags);
622       
623       if (lpSrcRect)  DPRINTF(" - src  rectangle :%dx%d-%dx%d\n",lpSrcRect->left,lpSrcRect->top,
624                               lpSrcRect->right,lpSrcRect->bottom);
625       if (lpDestRect) DPRINTF(" - dest rectangle :%dx%d-%dx%d\n",lpDestRect->left,lpDestRect->top,
626                               lpDestRect->right,lpDestRect->bottom);
627     }
628     
629     if (dwFlags & DDOVER_SHOW) {
630       UpdateOverlayEnumerate ctx;
631       
632       dwFlags &= ~DDOVER_SHOW;
633
634       if ((lpSrcRect == NULL) || (lpDestRect == NULL)) {
635         FIXME("This is NOT supported yet...\n");
636         return DD_OK;
637       }
638       
639       /* Set the shown BOOL to TRUE and update the rectangles */
640       dspriv->info.overlay.shown = TRUE;
641       dspriv->info.overlay.src_rect = *lpSrcRect;
642       dspriv->info.overlay.dst_rect = *lpDestRect;
643       dspriv->info.overlay.dest_surface = (LPDIRECTDRAWSURFACE) lpDDDestSurface;
644
645       /* Now the same for the backbuffers, except that they are NOT shown */
646       ctx.shown = FALSE;
647       ctx.src_rect = lpSrcRect;
648       ctx.dst_rect = lpDestRect;
649       ctx.dest_surface = (LPDIRECTDRAWSURFACE) lpDDDestSurface;
650
651       IDirectDrawSurface4Impl_EnumAttachedSurfaces(iface, &ctx, enum_func);
652     } else if (dwFlags & DDOVER_HIDE) {
653       UpdateOverlayEnumerate ctx;
654       
655       dwFlags &= ~DDOVER_HIDE;
656
657       /* Set the shown BOOL to FALSE for all overlays */
658       dspriv->info.overlay.shown = FALSE;
659       ctx.shown = FALSE;
660       IDirectDrawSurface4Impl_EnumAttachedSurfaces(iface, &ctx, enum_func);
661     }
662
663     if (dwFlags && TRACE_ON(ddraw)) {
664       WARN("Unsupported flags : ");
665       _dump_DDOVERLAY(dwFlags);   
666     }
667   } else
668 #endif
669     FIXME("(%p)->(%p,%p,%p,0x%08lx,%p) not supported without XVideo !\n", This,
670           lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
671
672   return DD_OK;
673 }
674
675 ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt = 
676 {
677     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
678     Xlib_IDirectDrawSurface4Impl_QueryInterface,
679     IDirectDrawSurface4Impl_AddRef,
680     Xlib_IDirectDrawSurface4Impl_Release,
681     IDirectDrawSurface4Impl_AddAttachedSurface,
682     IDirectDrawSurface4Impl_AddOverlayDirtyRect,
683     IDirectDrawSurface4Impl_Blt,
684     IDirectDrawSurface4Impl_BltBatch,
685     IDirectDrawSurface4Impl_BltFast,
686     IDirectDrawSurface4Impl_DeleteAttachedSurface,
687     IDirectDrawSurface4Impl_EnumAttachedSurfaces,
688     IDirectDrawSurface4Impl_EnumOverlayZOrders,
689     Xlib_IDirectDrawSurface4Impl_Flip,
690     IDirectDrawSurface4Impl_GetAttachedSurface,
691     IDirectDrawSurface4Impl_GetBltStatus,
692     IDirectDrawSurface4Impl_GetCaps,
693     IDirectDrawSurface4Impl_GetClipper,
694     IDirectDrawSurface4Impl_GetColorKey,
695     Xlib_IDirectDrawSurface4Impl_GetDC,
696     IDirectDrawSurface4Impl_GetFlipStatus,
697     IDirectDrawSurface4Impl_GetOverlayPosition,
698     IDirectDrawSurface4Impl_GetPalette,
699     IDirectDrawSurface4Impl_GetPixelFormat,
700     IDirectDrawSurface4Impl_GetSurfaceDesc,
701     IDirectDrawSurface4Impl_Initialize,
702     IDirectDrawSurface4Impl_IsLost,
703     Xlib_IDirectDrawSurface4Impl_Lock,
704     IDirectDrawSurface4Impl_ReleaseDC,
705     IDirectDrawSurface4Impl_Restore,
706     IDirectDrawSurface4Impl_SetClipper,
707     IDirectDrawSurface4Impl_SetColorKey,
708     IDirectDrawSurface4Impl_SetOverlayPosition,
709     Xlib_IDirectDrawSurface4Impl_SetPalette,
710     Xlib_IDirectDrawSurface4Impl_Unlock,
711     Xlib_IDirectDrawSurface4Impl_UpdateOverlay,
712     IDirectDrawSurface4Impl_UpdateOverlayDisplay,
713     IDirectDrawSurface4Impl_UpdateOverlayZOrder,
714     IDirectDrawSurface4Impl_GetDDInterface,
715     IDirectDrawSurface4Impl_PageLock,
716     IDirectDrawSurface4Impl_PageUnlock,
717     IDirectDrawSurface4Impl_SetSurfaceDesc,
718     IDirectDrawSurface4Impl_SetPrivateData,
719     IDirectDrawSurface4Impl_GetPrivateData,
720     IDirectDrawSurface4Impl_FreePrivateData,
721     IDirectDrawSurface4Impl_GetUniquenessValue,
722     IDirectDrawSurface4Impl_ChangeUniquenessValue
723 };