Like the AUTORADIOBUTTON, the parent of a RADIOBUTTON style button
[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
20 #ifdef HAVE_OPENGL
21 /* for d3d texture stuff */
22 # include "mesa_private.h"
23 #endif
24
25 DEFAULT_DEBUG_CHANNEL(ddraw);
26
27 #define VISIBLE(x) (SDDSCAPS(x) & (DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE))
28
29 #define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->private)
30 #define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
31 #define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
32
33 /******************************************************************************
34  *              IDirectDrawSurface methods
35  *
36  * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
37  * DDS and DDS2 use those functions. (Function calls did not change (except
38  * using different DirectDrawSurfaceX version), just added flags and functions)
39  */
40 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_QueryInterface(
41     LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
42 ) {
43     ICOM_THIS(IDirectDrawSurface4Impl,iface);
44
45     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
46     
47     /* All DirectDrawSurface versions (1, 2, 3 and 4) use
48      * the same interface. And IUnknown does that too of course.
49      */
50     if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid )        ||
51          IsEqualGUID( &IID_IDirectDrawSurface3, refiid )        ||
52          IsEqualGUID( &IID_IDirectDrawSurface2, refiid )        ||
53          IsEqualGUID( &IID_IDirectDrawSurface,  refiid )        ||
54          IsEqualGUID( &IID_IUnknown,            refiid )
55     ) {
56             *obj = This;
57             IDirectDrawSurface4_AddRef(iface);
58
59             TRACE("  Creating IDirectDrawSurface interface (%p)\n", *obj);
60             return S_OK;
61     }
62 #ifdef HAVE_OPENGL
63     if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ) {
64         /* Texture interface */
65         *obj = d3dtexture2_create(This);
66         IDirectDrawSurface4_AddRef(iface);
67         TRACE("  Creating IDirect3DTexture2 interface (%p)\n", *obj);
68         return S_OK;
69     }
70     if ( IsEqualGUID( &IID_IDirect3DTexture, refiid ) ) {
71         /* Texture interface */
72         *obj = d3dtexture_create(This);
73         IDirectDrawSurface4_AddRef(iface);
74         TRACE("  Creating IDirect3DTexture interface (%p)\n", *obj);
75         return S_OK;
76     }
77 #endif /* HAVE_OPENGL */
78     FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
79     return OLE_E_ENUM_NOMORE;
80 }
81
82 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
83     LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
84 ) {
85     ICOM_THIS(IDirectDrawSurface4Impl,iface);
86     DSPRIVATE(This);
87     DDPRIVATE(This->s.ddraw);
88     
89     /* DO NOT AddRef the surface! Lock/Unlock are NOT guaranteed to come in 
90      * matched pairs! - Marcus Meissner 20000509 */
91     TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,lprect,lpddsd,flags,(DWORD)hnd);
92     if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
93         WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
94                      This,lprect,lpddsd,flags,(DWORD)hnd);
95
96     /* First, copy the Surface description */
97     *lpddsd = This->s.surface_desc;
98     TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
99           lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
100
101     /* If asked only for a part, change the surface pointer */
102     if (lprect) {
103         TRACE(" lprect: %dx%d-%dx%d\n",
104                 lprect->top,lprect->left,lprect->bottom,lprect->right
105         );
106         if ((lprect->top < 0) ||
107             (lprect->left < 0) ||
108             (lprect->bottom < 0) ||
109             (lprect->right < 0)) {
110           ERR(" Negative values in LPRECT !!!\n");
111           IDirectDrawSurface4_Release(iface);
112           return DDERR_INVALIDPARAMS;
113         }
114         lpddsd->u1.lpSurface=(LPVOID)((char*)This->s.surface_desc.u1.lpSurface+
115                 (lprect->top*This->s.surface_desc.lPitch) +
116                 lprect->left*GET_BPP(This->s.surface_desc));
117     } else
118         assert(This->s.surface_desc.u1.lpSurface);
119     /* wait for any previous operations to complete */
120 #ifdef HAVE_LIBXXSHM
121     if (dspriv->image && VISIBLE(This) && ddpriv->xshm_active) {
122 /*
123         int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
124         if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
125 */
126         X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
127     }
128 #endif
129     return DD_OK;
130 }
131
132 static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
133   DSPRIVATE(This);
134   DDPRIVATE(This->s.ddraw);
135   if (This->s.ddraw->d.pixel_convert != NULL)
136     This->s.ddraw->d.pixel_convert(This->s.surface_desc.u1.lpSurface,
137                                    dspriv->image->data,
138                                    This->s.surface_desc.dwWidth,
139                                    This->s.surface_desc.dwHeight,
140                                    This->s.surface_desc.lPitch,
141                                    This->s.palette);
142
143 #ifdef HAVE_LIBXXSHM
144     if (ddpriv->xshm_active) {
145 /*
146         X11DRV_EVENT_WaitReplaceShmCompletion( &(ddpriv->xshm_compl), This->s.ddraw->d.drawable );
147 */
148         /* let WaitShmCompletions track 'em for now */
149         /* (you may want to track it again whenever you implement DX7's partial
150         * surface locking, where threads have concurrent access) */
151         X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
152         TSXShmPutImage(display,
153             ddpriv->drawable,
154             DefaultGCOfScreen(X11DRV_GetXScreen()),
155             dspriv->image,
156             0, 0, 0, 0,
157             dspriv->image->width,
158             dspriv->image->height,
159             True
160         );
161         /* make sure the image is transferred ASAP */
162         TSXFlush(display);
163     } else
164 #endif
165         TSXPutImage(    
166             display,
167             ddpriv->drawable,
168             DefaultGCOfScreen(X11DRV_GetXScreen()),
169             dspriv->image,
170             0, 0, 0, 0,
171             dspriv->image->width,
172             dspriv->image->height
173         );
174 }
175
176 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
177     LPDIRECTDRAWSURFACE4 iface,LPVOID surface
178 ) {
179     ICOM_THIS(IDirectDrawSurface4Impl,iface);
180     DDPRIVATE(This->s.ddraw);
181     DSPRIVATE(This);
182     TRACE("(%p)->Unlock(%p)\n",This,surface);
183
184     /*if (!This->s.ddraw->d.paintable)
185         return DD_OK; */
186
187     /* Only redraw the screen when unlocking the buffer that is on screen */
188     if (dspriv->image && VISIBLE(This)) {
189         Xlib_copy_surface_on_screen(This);
190         if (This->s.palette) {
191             DPPRIVATE(This->s.palette);
192             if(dppriv->cm)
193                 TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
194         }
195     }
196     /* DO NOT Release the surface! Lock/Unlock are NOT guaranteed to come in 
197      * matched pairs! - Marcus Meissner 20000509 */
198     return DD_OK;
199 }
200
201 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
202     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
203 ) {
204     ICOM_THIS(IDirectDrawSurface4Impl,iface);
205     XImage      *image;
206     DDPRIVATE(This->s.ddraw);
207     DSPRIVATE(This);
208     x11_ds_private      *fspriv;
209     LPBYTE      surf;
210     IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
211
212     TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
213     if (!This->s.ddraw->d.paintable)
214         return DD_OK;
215
216     iflipto = _common_find_flipto(This,iflipto);
217     fspriv = (x11_ds_private*)iflipto->private;
218
219     /* We need to switch the lowlevel surfaces, for xlib this is: */
220     /* The surface pointer */
221     surf                                = This->s.surface_desc.u1.lpSurface;
222     This->s.surface_desc.u1.lpSurface   = iflipto->s.surface_desc.u1.lpSurface;
223     iflipto->s.surface_desc.u1.lpSurface        = surf;
224
225     /* the associated ximage */
226     image               = dspriv->image;
227     dspriv->image       = fspriv->image;
228     fspriv->image       = image;
229
230 #ifdef HAVE_LIBXXSHM
231     if (ddpriv->xshm_active) {
232 /*
233         int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
234         if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
235 */
236         X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
237     }
238 #endif
239     Xlib_copy_surface_on_screen(This);
240     if (iflipto->s.palette) {
241         DPPRIVATE(iflipto->s.palette);
242         if (dppriv->cm)
243             TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
244     }
245     return DD_OK;
246 }
247
248 /* The IDirectDrawSurface4::SetPalette method attaches the specified
249  * DirectDrawPalette object to a surface. The surface uses this palette for all
250  * subsequent operations. The palette change takes place immediately.
251  */
252 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_SetPalette(
253     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
254 ) {
255     ICOM_THIS(IDirectDrawSurface4Impl,iface);
256     DDPRIVATE(This->s.ddraw);
257     IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
258     x11_dp_private      *dppriv;
259     int i;
260
261     TRACE("(%p)->(%p)\n",This,ipal);
262
263     if (ipal == NULL) {
264         if( This->s.palette != NULL )
265             IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
266         This->s.palette = ipal;
267         return DD_OK;
268     }
269     dppriv = (x11_dp_private*)ipal->private;
270
271     if (!dppriv->cm &&
272         (This->s.ddraw->d.screen_pixelformat.u.dwRGBBitCount<=8)
273     ) {
274         dppriv->cm = TSXCreateColormap(
275             display,
276             ddpriv->drawable,
277             DefaultVisualOfScreen(X11DRV_GetXScreen()),
278             AllocAll
279         );
280         if (!Options.managed)
281             TSXInstallColormap(display,dppriv->cm);
282
283         for (i=0;i<256;i++) {
284             XColor xc;
285
286             xc.red              = ipal->palents[i].peRed<<8;
287             xc.blue             = ipal->palents[i].peBlue<<8;
288             xc.green    = ipal->palents[i].peGreen<<8;
289             xc.flags    = DoRed|DoBlue|DoGreen;
290             xc.pixel    = i;
291             TSXStoreColor(display,dppriv->cm,&xc);
292         }
293         TSXInstallColormap(display,dppriv->cm);
294     }
295     /* According to spec, we are only supposed to 
296      * AddRef if this is not the same palette.
297      */
298     if ( This->s.palette != ipal ) {
299         if( ipal != NULL )
300             IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
301         if( This->s.palette != NULL )
302             IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
303         This->s.palette = ipal; 
304         /* Perform the refresh */
305         TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
306     }
307     return DD_OK;
308 }
309
310 ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
311     ICOM_THIS(IDirectDrawSurface4Impl,iface);
312     DSPRIVATE(This);
313     DDPRIVATE(This->s.ddraw);
314
315     TRACE( "(%p)->() decrementing from %lu.\n", This, This->ref );
316     if (--(This->ref))
317         return This->ref;
318
319     IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
320
321     if (dspriv->image != NULL) {
322         if (This->s.ddraw->d.pixel_convert != NULL) {
323             /* In pixel conversion mode, there are 2 buffers to release. */
324             HeapFree(GetProcessHeap(),0,This->s.surface_desc.u1.lpSurface);
325
326 #ifdef HAVE_LIBXXSHM
327             if (ddpriv->xshm_active) {
328                 TSXShmDetach(display, &(dspriv->shminfo));
329                 TSXDestroyImage(dspriv->image);
330                 shmdt(dspriv->shminfo.shmaddr);
331             } else
332 #endif
333             {
334                 HeapFree(GetProcessHeap(),0,dspriv->image->data);
335                 dspriv->image->data = NULL;
336                 TSXDestroyImage(dspriv->image);
337             }
338         } else {
339             dspriv->image->data = NULL;
340
341 #ifdef HAVE_LIBXXSHM
342             if (ddpriv->xshm_active) {
343                 TSXShmDetach(display, &(dspriv->shminfo));
344                 TSXDestroyImage(dspriv->image);
345                 shmdt(dspriv->shminfo.shmaddr);
346             } else
347 #endif
348             {
349                 HeapFree(GetProcessHeap(),0,This->s.surface_desc.u1.lpSurface);
350                 TSXDestroyImage(dspriv->image);
351             }
352         }
353         dspriv->image = 0;
354     } else
355         HeapFree(GetProcessHeap(),0,This->s.surface_desc.u1.lpSurface);
356
357     if (This->s.palette)
358         IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
359
360     /* Free the DIBSection (if any) */
361     if (This->s.hdc != 0) {
362         SelectObject(This->s.hdc, This->s.holdbitmap);
363         DeleteDC(This->s.hdc);
364         DeleteObject(This->s.DIBsection);
365     }
366
367     /* Free the clipper if present */
368     if(This->s.lpClipper)
369         IDirectDrawClipper_Release(This->s.lpClipper);
370     HeapFree(GetProcessHeap(),0,This->private);
371     HeapFree(GetProcessHeap(),0,This);
372     return S_OK;
373 }
374
375 ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt = 
376 {
377     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
378     Xlib_IDirectDrawSurface4Impl_QueryInterface,
379     IDirectDrawSurface4Impl_AddRef,
380     Xlib_IDirectDrawSurface4Impl_Release,
381     IDirectDrawSurface4Impl_AddAttachedSurface,
382     IDirectDrawSurface4Impl_AddOverlayDirtyRect,
383     IDirectDrawSurface4Impl_Blt,
384     IDirectDrawSurface4Impl_BltBatch,
385     IDirectDrawSurface4Impl_BltFast,
386     IDirectDrawSurface4Impl_DeleteAttachedSurface,
387     IDirectDrawSurface4Impl_EnumAttachedSurfaces,
388     IDirectDrawSurface4Impl_EnumOverlayZOrders,
389     Xlib_IDirectDrawSurface4Impl_Flip,
390     IDirectDrawSurface4Impl_GetAttachedSurface,
391     IDirectDrawSurface4Impl_GetBltStatus,
392     IDirectDrawSurface4Impl_GetCaps,
393     IDirectDrawSurface4Impl_GetClipper,
394     IDirectDrawSurface4Impl_GetColorKey,
395     IDirectDrawSurface4Impl_GetDC,
396     IDirectDrawSurface4Impl_GetFlipStatus,
397     IDirectDrawSurface4Impl_GetOverlayPosition,
398     IDirectDrawSurface4Impl_GetPalette,
399     IDirectDrawSurface4Impl_GetPixelFormat,
400     IDirectDrawSurface4Impl_GetSurfaceDesc,
401     IDirectDrawSurface4Impl_Initialize,
402     IDirectDrawSurface4Impl_IsLost,
403     Xlib_IDirectDrawSurface4Impl_Lock,
404     IDirectDrawSurface4Impl_ReleaseDC,
405     IDirectDrawSurface4Impl_Restore,
406     IDirectDrawSurface4Impl_SetClipper,
407     IDirectDrawSurface4Impl_SetColorKey,
408     IDirectDrawSurface4Impl_SetOverlayPosition,
409     Xlib_IDirectDrawSurface4Impl_SetPalette,
410     Xlib_IDirectDrawSurface4Impl_Unlock,
411     IDirectDrawSurface4Impl_UpdateOverlay,
412     IDirectDrawSurface4Impl_UpdateOverlayDisplay,
413     IDirectDrawSurface4Impl_UpdateOverlayZOrder,
414     IDirectDrawSurface4Impl_GetDDInterface,
415     IDirectDrawSurface4Impl_PageLock,
416     IDirectDrawSurface4Impl_PageUnlock,
417     IDirectDrawSurface4Impl_SetSurfaceDesc,
418     IDirectDrawSurface4Impl_SetPrivateData,
419     IDirectDrawSurface4Impl_GetPrivateData,
420     IDirectDrawSurface4Impl_FreePrivateData,
421     IDirectDrawSurface4Impl_GetUniquenessValue,
422     IDirectDrawSurface4Impl_ChangeUniquenessValue
423 };