1 /* DirectDrawSurface Xlib implementation
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
17 #include "debugtools.h"
18 #include "x11_private.h"
22 /* for d3d texture stuff */
23 # include "mesa_private.h"
26 DEFAULT_DEBUG_CHANNEL(ddraw);
28 #define VISIBLE(x) (SDDSCAPS(x) & (DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE))
30 #define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->private)
31 #define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
32 #define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
34 static BYTE Xlib_TouchData(LPVOID data)
36 /* this is a function so it doesn't get optimized out */
40 /******************************************************************************
41 * IDirectDrawSurface methods
43 * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
44 * DDS and DDS2 use those functions. (Function calls did not change (except
45 * using different DirectDrawSurfaceX version), just added flags and functions)
47 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_QueryInterface(
48 LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
50 ICOM_THIS(IDirectDrawSurface4Impl,iface);
52 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
54 /* All DirectDrawSurface versions (1, 2, 3 and 4) use
55 * the same interface. And IUnknown does that too of course.
57 if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid ) ||
58 IsEqualGUID( &IID_IDirectDrawSurface3, refiid ) ||
59 IsEqualGUID( &IID_IDirectDrawSurface2, refiid ) ||
60 IsEqualGUID( &IID_IDirectDrawSurface, refiid ) ||
61 IsEqualGUID( &IID_IUnknown, refiid )
64 IDirectDrawSurface4_AddRef(iface);
66 TRACE(" Creating IDirectDrawSurface interface (%p)\n", *obj);
70 if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ) {
71 /* Texture interface */
72 *obj = d3dtexture2_create(This);
73 IDirectDrawSurface4_AddRef(iface);
74 TRACE(" Creating IDirect3DTexture2 interface (%p)\n", *obj);
77 if ( IsEqualGUID( &IID_IDirect3DTexture, refiid ) ) {
78 /* Texture interface */
79 *obj = d3dtexture_create(This);
80 IDirectDrawSurface4_AddRef(iface);
81 TRACE(" Creating IDirect3DTexture interface (%p)\n", *obj);
84 #endif /* HAVE_OPENGL */
85 FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
86 return OLE_E_ENUM_NOMORE;
89 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
90 LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
92 ICOM_THIS(IDirectDrawSurface4Impl,iface);
94 DDPRIVATE(This->s.ddraw);
96 /* DO NOT AddRef the surface! Lock/Unlock are NOT guaranteed to come in
97 * matched pairs! - Marcus Meissner 20000509 */
98 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,lprect,lpddsd,flags,(DWORD)hnd);
99 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
100 WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
101 This,lprect,lpddsd,flags,(DWORD)hnd);
103 /* First, copy the Surface description */
104 *lpddsd = This->s.surface_desc;
105 TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
106 lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
108 /* If asked only for a part, change the surface pointer */
110 TRACE(" lprect: %dx%d-%dx%d\n",
111 lprect->top,lprect->left,lprect->bottom,lprect->right
113 if ((lprect->top < 0) ||
114 (lprect->left < 0) ||
115 (lprect->bottom < 0) ||
116 (lprect->right < 0)) {
117 ERR(" Negative values in LPRECT !!!\n");
118 IDirectDrawSurface4_Release(iface);
119 return DDERR_INVALIDPARAMS;
121 lpddsd->u1.lpSurface=(LPVOID)((char*)This->s.surface_desc.u1.lpSurface+
122 (lprect->top*This->s.surface_desc.lPitch) +
123 lprect->left*GET_BPP(This->s.surface_desc));
125 assert(This->s.surface_desc.u1.lpSurface);
126 /* wait for any previous operations to complete */
128 if (dspriv->image && VISIBLE(This) && ddpriv->xshm_active) {
130 int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
131 if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
133 X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
140 static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
142 DDPRIVATE(This->s.ddraw);
143 if (This->s.ddraw->d.pixel_convert != NULL)
144 This->s.ddraw->d.pixel_convert(This->s.surface_desc.u1.lpSurface,
146 This->s.surface_desc.dwWidth,
147 This->s.surface_desc.dwHeight,
148 This->s.surface_desc.lPitch,
151 /* if the DIB section is in GdiMod state, we must
152 * touch the surface to get any updates from the DIB */
153 Xlib_TouchData(dspriv->image->data);
155 if (ddpriv->xshm_active) {
157 X11DRV_EVENT_WaitReplaceShmCompletion( &(ddpriv->xshm_compl), This->s.ddraw->d.drawable );
159 /* let WaitShmCompletions track 'em for now */
160 /* (you may want to track it again whenever you implement DX7's partial
161 * surface locking, where threads have concurrent access) */
162 X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
163 TSXShmPutImage(display,
165 DefaultGCOfScreen(X11DRV_GetXScreen()),
168 dspriv->image->width,
169 dspriv->image->height,
172 /* make sure the image is transferred ASAP */
179 DefaultGCOfScreen(X11DRV_GetXScreen()),
182 dspriv->image->width,
183 dspriv->image->height
187 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
188 LPDIRECTDRAWSURFACE4 iface,LPVOID surface
190 ICOM_THIS(IDirectDrawSurface4Impl,iface);
191 DDPRIVATE(This->s.ddraw);
193 TRACE("(%p)->Unlock(%p)\n",This,surface);
195 /*if (!This->s.ddraw->d.paintable)
198 /* Only redraw the screen when unlocking the buffer that is on screen */
199 if (dspriv->image && VISIBLE(This)) {
200 Xlib_copy_surface_on_screen(This);
201 if (This->s.palette) {
202 DPPRIVATE(This->s.palette);
204 TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
207 /* DO NOT Release the surface! Lock/Unlock are NOT guaranteed to come in
208 * matched pairs! - Marcus Meissner 20000509 */
212 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
213 LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
215 ICOM_THIS(IDirectDrawSurface4Impl,iface);
217 DDPRIVATE(This->s.ddraw);
219 x11_ds_private *fspriv;
221 IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
223 TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
224 if (!This->s.ddraw->d.paintable)
227 iflipto = _common_find_flipto(This,iflipto);
228 fspriv = (x11_ds_private*)iflipto->private;
230 /* We need to switch the lowlevel surfaces, for xlib this is: */
231 /* The surface pointer */
232 surf = This->s.surface_desc.u1.lpSurface;
233 This->s.surface_desc.u1.lpSurface = iflipto->s.surface_desc.u1.lpSurface;
234 iflipto->s.surface_desc.u1.lpSurface = surf;
236 /* the associated ximage */
237 image = dspriv->image;
238 dspriv->image = fspriv->image;
239 fspriv->image = image;
242 if (ddpriv->xshm_active) {
244 int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
245 if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
247 X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
250 Xlib_copy_surface_on_screen(This);
251 if (iflipto->s.palette) {
252 DPPRIVATE(iflipto->s.palette);
254 TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
259 /* The IDirectDrawSurface4::SetPalette method attaches the specified
260 * DirectDrawPalette object to a surface. The surface uses this palette for all
261 * subsequent operations. The palette change takes place immediately.
263 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_SetPalette(
264 LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
266 ICOM_THIS(IDirectDrawSurface4Impl,iface);
267 DDPRIVATE(This->s.ddraw);
268 IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
269 x11_dp_private *dppriv;
272 TRACE("(%p)->(%p)\n",This,ipal);
275 if( This->s.palette != NULL )
276 IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
277 This->s.palette = ipal;
280 dppriv = (x11_dp_private*)ipal->private;
283 (This->s.ddraw->d.screen_pixelformat.u.dwRGBBitCount<=8)
285 dppriv->cm = TSXCreateColormap(
288 DefaultVisualOfScreen(X11DRV_GetXScreen()),
291 if (!Options.managed)
292 TSXInstallColormap(display,dppriv->cm);
294 for (i=0;i<256;i++) {
297 xc.red = ipal->palents[i].peRed<<8;
298 xc.blue = ipal->palents[i].peBlue<<8;
299 xc.green = ipal->palents[i].peGreen<<8;
300 xc.flags = DoRed|DoBlue|DoGreen;
302 TSXStoreColor(display,dppriv->cm,&xc);
304 TSXInstallColormap(display,dppriv->cm);
306 /* According to spec, we are only supposed to
307 * AddRef if this is not the same palette.
309 if ( This->s.palette != ipal ) {
311 IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
312 if( This->s.palette != NULL )
313 IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
314 This->s.palette = ipal;
315 /* Perform the refresh, only if a palette was created */
317 TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
319 if (This->s.hdc != 0) {
320 /* hack: set the DIBsection color map */
321 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
322 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
323 dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
324 GDI_HEAP_UNLOCK(This->s.DIBsection);
330 ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
331 ICOM_THIS(IDirectDrawSurface4Impl,iface);
333 DDPRIVATE(This->s.ddraw);
335 TRACE( "(%p)->() decrementing from %lu.\n", This, This->ref );
339 IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
341 if (dspriv->image != NULL) {
342 if (This->s.ddraw->d.pixel_convert != NULL) {
343 /* In pixel conversion mode, there are 2 buffers to release. */
344 VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
347 if (ddpriv->xshm_active) {
348 TSXShmDetach(display, &(dspriv->shminfo));
349 TSXDestroyImage(dspriv->image);
350 shmdt(dspriv->shminfo.shmaddr);
354 HeapFree(GetProcessHeap(),0,dspriv->image->data);
355 dspriv->image->data = NULL;
356 TSXDestroyImage(dspriv->image);
359 dspriv->image->data = NULL;
362 if (ddpriv->xshm_active) {
363 VirtualFree(dspriv->image->data, 0, MEM_RELEASE);
364 TSXShmDetach(display, &(dspriv->shminfo));
365 TSXDestroyImage(dspriv->image);
366 shmdt(dspriv->shminfo.shmaddr);
370 VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
371 TSXDestroyImage(dspriv->image);
376 VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
379 IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
381 /* Free the DIBSection (if any) */
382 if (This->s.hdc != 0) {
383 /* hack: restore the original DIBsection color map */
384 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
385 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
386 dib->colorMap = dspriv->oldDIBmap;
387 GDI_HEAP_UNLOCK(This->s.DIBsection);
389 SelectObject(This->s.hdc, This->s.holdbitmap);
390 DeleteDC(This->s.hdc);
391 DeleteObject(This->s.DIBsection);
394 /* Free the clipper if present */
395 if(This->s.lpClipper)
396 IDirectDrawClipper_Release(This->s.lpClipper);
397 HeapFree(GetProcessHeap(),0,This->private);
398 HeapFree(GetProcessHeap(),0,This);
402 HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
403 ICOM_THIS(IDirectDrawSurface4Impl,iface);
405 int was_ok = This->s.hdc != 0;
406 HRESULT result = IDirectDrawSurface4Impl_GetDC(iface,lphdc);
407 if (This->s.hdc && !was_ok) {
408 /* hack: take over the DIBsection color map */
409 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
410 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
411 dspriv->oldDIBmap = dib->colorMap;
412 dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
413 GDI_HEAP_UNLOCK(This->s.DIBsection);
418 ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt =
420 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
421 Xlib_IDirectDrawSurface4Impl_QueryInterface,
422 IDirectDrawSurface4Impl_AddRef,
423 Xlib_IDirectDrawSurface4Impl_Release,
424 IDirectDrawSurface4Impl_AddAttachedSurface,
425 IDirectDrawSurface4Impl_AddOverlayDirtyRect,
426 IDirectDrawSurface4Impl_Blt,
427 IDirectDrawSurface4Impl_BltBatch,
428 IDirectDrawSurface4Impl_BltFast,
429 IDirectDrawSurface4Impl_DeleteAttachedSurface,
430 IDirectDrawSurface4Impl_EnumAttachedSurfaces,
431 IDirectDrawSurface4Impl_EnumOverlayZOrders,
432 Xlib_IDirectDrawSurface4Impl_Flip,
433 IDirectDrawSurface4Impl_GetAttachedSurface,
434 IDirectDrawSurface4Impl_GetBltStatus,
435 IDirectDrawSurface4Impl_GetCaps,
436 IDirectDrawSurface4Impl_GetClipper,
437 IDirectDrawSurface4Impl_GetColorKey,
438 Xlib_IDirectDrawSurface4Impl_GetDC,
439 IDirectDrawSurface4Impl_GetFlipStatus,
440 IDirectDrawSurface4Impl_GetOverlayPosition,
441 IDirectDrawSurface4Impl_GetPalette,
442 IDirectDrawSurface4Impl_GetPixelFormat,
443 IDirectDrawSurface4Impl_GetSurfaceDesc,
444 IDirectDrawSurface4Impl_Initialize,
445 IDirectDrawSurface4Impl_IsLost,
446 Xlib_IDirectDrawSurface4Impl_Lock,
447 IDirectDrawSurface4Impl_ReleaseDC,
448 IDirectDrawSurface4Impl_Restore,
449 IDirectDrawSurface4Impl_SetClipper,
450 IDirectDrawSurface4Impl_SetColorKey,
451 IDirectDrawSurface4Impl_SetOverlayPosition,
452 Xlib_IDirectDrawSurface4Impl_SetPalette,
453 Xlib_IDirectDrawSurface4Impl_Unlock,
454 IDirectDrawSurface4Impl_UpdateOverlay,
455 IDirectDrawSurface4Impl_UpdateOverlayDisplay,
456 IDirectDrawSurface4Impl_UpdateOverlayZOrder,
457 IDirectDrawSurface4Impl_GetDDInterface,
458 IDirectDrawSurface4Impl_PageLock,
459 IDirectDrawSurface4Impl_PageUnlock,
460 IDirectDrawSurface4Impl_SetSurfaceDesc,
461 IDirectDrawSurface4Impl_SetPrivateData,
462 IDirectDrawSurface4Impl_GetPrivateData,
463 IDirectDrawSurface4Impl_FreePrivateData,
464 IDirectDrawSurface4Impl_GetUniquenessValue,
465 IDirectDrawSurface4Impl_ChangeUniquenessValue