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"
24 /* for d3d texture stuff */
25 # include "mesa_private.h"
28 DEFAULT_DEBUG_CHANNEL(ddraw
);
30 #define VISIBLE(x) (SDDSCAPS(x) & (DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE))
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)
36 static BYTE
Xlib_TouchData(LPVOID data
)
38 /* this is a function so it doesn't get optimized out */
42 /******************************************************************************
43 * IDirectDrawSurface methods
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)
49 HRESULT WINAPI
Xlib_IDirectDrawSurface4Impl_QueryInterface(
50 LPDIRECTDRAWSURFACE4 iface
,REFIID refiid
,LPVOID
*obj
52 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
54 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(refiid
),obj
);
56 /* All DirectDrawSurface versions (1, 2, 3 and 4) use
57 * the same interface. And IUnknown does that too of course.
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
)
66 IDirectDrawSurface4_AddRef(iface
);
68 TRACE(" Creating IDirectDrawSurface interface (%p)\n", *obj
);
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
);
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
);
87 if ( IsEqualGUID( &IID_IDirect3DTexture2
, refiid
) ||
88 IsEqualGUID( &IID_IDirect3DTexture
, refiid
)
91 ERR( "Cannot provide 3D support without OpenGL/Mesa installed\n" );
93 #endif /* HAVE_OPENGL */
94 FIXME("(%p):interface for IID %s NOT found!\n",This
,debugstr_guid(refiid
));
95 return OLE_E_ENUM_NOMORE
;
98 HRESULT WINAPI
Xlib_IDirectDrawSurface4Impl_Lock(
99 LPDIRECTDRAWSURFACE4 iface
,LPRECT lprect
,LPDDSURFACEDESC lpddsd
,DWORD flags
, HANDLE hnd
101 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
103 DDPRIVATE(This
->s
.ddraw
);
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
);
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
);
117 /* If asked only for a part, change the surface pointer */
119 TRACE(" lprect: %dx%d-%dx%d\n",
120 lprect
->top
,lprect
->left
,lprect
->bottom
,lprect
->right
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
;
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
));
133 assert(This
->s
.surface_desc
.u1
.lpSurface
);
134 /* wait for any previous operations to complete */
136 if (dspriv
->image
&& VISIBLE(This
) && ddpriv
->xshm_active
) {
138 int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
139 if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
141 X11DRV_EVENT_WaitShmCompletions( ddpriv
->drawable
);
145 /* If part of a visible 'clipped' surface, copy what is seen on the
146 screen to the surface */
147 if ((dspriv
->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
;
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();
166 TSXGetSubImage(display
, drawable
, 0, 0, width
, height
, 0xFFFFFFFF,
167 ZPixmap
, dspriv
->image
, dest_x
, dest_y
);
169 WIN_ReleaseWndPtr(wndPtr
);
175 static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl
* This
) {
177 DDPRIVATE(This
->s
.ddraw
);
178 Drawable drawable
= ddpriv
->drawable
;
179 POINT adjust
[2] = {{0, 0}, {0, 0}};
182 /* Get XImage size */
183 imgsiz
.cx
= dspriv
->image
->width
;
184 imgsiz
.cy
= dspriv
->image
->height
;
186 if (This
->s
.lpClipper
) {
187 HWND hWnd
= ((IDirectDrawClipperImpl
*) This
->s
.lpClipper
)->hWnd
;
189 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
190 drawable
= X11DRV_WND_GetXWindow(wndPtr
);
192 MapWindowPoints(hWnd
, 0, adjust
, 2);
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
;
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
);
209 WIN_ReleaseWndPtr(wndPtr
);
213 WND
*tmpWnd
= WIN_FindWndPtr(This
->s
.ddraw
->d
->window
);
214 drawable
= X11DRV_WND_GetXWindow(tmpWnd
);
215 WIN_ReleaseWndPtr(tmpWnd
);
217 /* We don't have a context for this window. Host off the desktop */
219 FIXME("Have to use Desktop Root Window??? Bummer.\n");
220 drawable
= X11DRV_WND_GetXWindow(WIN_GetDesktop());
221 WIN_ReleaseDesktop();
223 ddpriv
->drawable
= drawable
;
226 if (This
->s
.ddraw
->d
->pixel_convert
!= NULL
)
227 This
->s
.ddraw
->d
->pixel_convert(This
->s
.surface_desc
.u1
.lpSurface
,
229 This
->s
.surface_desc
.dwWidth
,
230 This
->s
.surface_desc
.dwHeight
,
231 This
->s
.surface_desc
.lPitch
,
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
->image
->data
);
238 if (ddpriv
->xshm_active
) {
240 X11DRV_EVENT_WaitReplaceShmCompletion( &(ddpriv->xshm_compl), This->s.ddraw->d.drawable );
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
,
248 DefaultGCOfScreen(X11DRV_GetXScreen()),
250 adjust
[0].x
, adjust
[0].y
, adjust
[1].x
, adjust
[1].y
,
251 imgsiz
.cx
, imgsiz
.cy
,
254 /* make sure the image is transferred ASAP */
260 DefaultGCOfScreen(X11DRV_GetXScreen()),
262 adjust
[0].x
, adjust
[0].y
, adjust
[1].x
, adjust
[1].y
,
267 HRESULT WINAPI
Xlib_IDirectDrawSurface4Impl_Unlock(
268 LPDIRECTDRAWSURFACE4 iface
,LPVOID surface
270 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
271 DDPRIVATE(This
->s
.ddraw
);
273 TRACE("(%p)->Unlock(%p)\n",This
,surface
);
275 /*if (!This->s.ddraw->d.paintable)
278 /* Only redraw the screen when unlocking the buffer that is on screen */
279 if (dspriv
->image
&& VISIBLE(This
)) {
280 Xlib_copy_surface_on_screen(This
);
281 if (This
->s
.palette
) {
282 DPPRIVATE(This
->s
.palette
);
284 TSXSetWindowColormap(display
,ddpriv
->drawable
,dppriv
->cm
);
287 /* DO NOT Release the surface! Lock/Unlock are NOT guaranteed to come in
288 * matched pairs! - Marcus Meissner 20000509 */
292 HRESULT WINAPI
Xlib_IDirectDrawSurface4Impl_Flip(
293 LPDIRECTDRAWSURFACE4 iface
,LPDIRECTDRAWSURFACE4 flipto
,DWORD dwFlags
295 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
297 DDPRIVATE(This
->s
.ddraw
);
299 x11_ds_private
*fspriv
;
301 IDirectDrawSurface4Impl
* iflipto
=(IDirectDrawSurface4Impl
*)flipto
;
303 TRACE("(%p)->Flip(%p,%08lx)\n",This
,iflipto
,dwFlags
);
304 if (!This
->s
.ddraw
->d
->paintable
)
307 iflipto
= _common_find_flipto(This
,iflipto
);
308 fspriv
= (x11_ds_private
*)iflipto
->private;
310 /* We need to switch the lowlevel surfaces, for xlib this is: */
311 /* The surface pointer */
312 surf
= This
->s
.surface_desc
.u1
.lpSurface
;
313 This
->s
.surface_desc
.u1
.lpSurface
= iflipto
->s
.surface_desc
.u1
.lpSurface
;
314 iflipto
->s
.surface_desc
.u1
.lpSurface
= surf
;
316 /* the associated ximage */
317 image
= dspriv
->image
;
318 dspriv
->image
= fspriv
->image
;
319 fspriv
->image
= image
;
321 if (dspriv
->opengl_flip
) {
324 glXSwapBuffers(display
, ddpriv
->drawable
);
329 if (ddpriv
->xshm_active
) {
331 int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
332 if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
334 X11DRV_EVENT_WaitShmCompletions( ddpriv
->drawable
);
337 Xlib_copy_surface_on_screen(This
);
338 if (iflipto
->s
.palette
) {
339 DPPRIVATE(iflipto
->s
.palette
);
341 TSXSetWindowColormap(display
,ddpriv
->drawable
,dppriv
->cm
);
347 /* The IDirectDrawSurface4::SetPalette method attaches the specified
348 * DirectDrawPalette object to a surface. The surface uses this palette for all
349 * subsequent operations. The palette change takes place immediately.
351 HRESULT WINAPI
Xlib_IDirectDrawSurface4Impl_SetPalette(
352 LPDIRECTDRAWSURFACE4 iface
,LPDIRECTDRAWPALETTE pal
354 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
355 DDPRIVATE(This
->s
.ddraw
);
356 IDirectDrawPaletteImpl
* ipal
=(IDirectDrawPaletteImpl
*)pal
;
357 x11_dp_private
*dppriv
;
360 TRACE("(%p)->(%p)\n",This
,ipal
);
363 if( This
->s
.palette
!= NULL
)
364 IDirectDrawPalette_Release((IDirectDrawPalette
*)This
->s
.palette
);
365 This
->s
.palette
= ipal
;
368 dppriv
= (x11_dp_private
*)ipal
->private;
371 (This
->s
.ddraw
->d
->screen_pixelformat
.u
.dwRGBBitCount
<=8)
373 dppriv
->cm
= TSXCreateColormap(
376 DefaultVisualOfScreen(X11DRV_GetXScreen()),
379 if (!Options
.managed
)
380 TSXInstallColormap(display
,dppriv
->cm
);
382 for (i
=0;i
<256;i
++) {
385 xc
.red
= ipal
->palents
[i
].peRed
<<8;
386 xc
.blue
= ipal
->palents
[i
].peBlue
<<8;
387 xc
.green
= ipal
->palents
[i
].peGreen
<<8;
388 xc
.flags
= DoRed
|DoBlue
|DoGreen
;
390 TSXStoreColor(display
,dppriv
->cm
,&xc
);
392 TSXInstallColormap(display
,dppriv
->cm
);
394 /* According to spec, we are only supposed to
395 * AddRef if this is not the same palette.
397 if ( This
->s
.palette
!= ipal
) {
399 IDirectDrawPalette_AddRef( (IDirectDrawPalette
*)ipal
);
400 if( This
->s
.palette
!= NULL
)
401 IDirectDrawPalette_Release( (IDirectDrawPalette
*)This
->s
.palette
);
402 This
->s
.palette
= ipal
;
403 /* Perform the refresh, only if a palette was created */
405 TSXSetWindowColormap(display
,ddpriv
->drawable
,dppriv
->cm
);
407 if (This
->s
.hdc
!= 0) {
408 /* hack: set the DIBsection color map */
409 BITMAPOBJ
*bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(This
->s
.DIBsection
, BITMAP_MAGIC
);
410 X11DRV_DIBSECTION
*dib
= (X11DRV_DIBSECTION
*)bmp
->dib
;
411 dib
->colorMap
= This
->s
.palette
? This
->s
.palette
->screen_palents
: NULL
;
412 GDI_ReleaseObj(This
->s
.DIBsection
);
418 ULONG WINAPI
Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface
) {
419 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
421 DDPRIVATE(This
->s
.ddraw
);
423 TRACE( "(%p)->() decrementing from %lu.\n", This
, This
->ref
);
427 IDirectDraw2_Release((IDirectDraw2
*)This
->s
.ddraw
);
429 /* This frees the program-side surface. In some cases it had been
430 * allocated with MEM_SYSTEM, so it does not get 'really' freed
432 VirtualFree(This
->s
.surface_desc
.u1
.lpSurface
, 0, MEM_RELEASE
);
434 /* Now free the XImages and the respective screen-side surfaces */
435 if (dspriv
->image
!= NULL
) {
436 if (dspriv
->image
->data
!= This
->s
.surface_desc
.u1
.lpSurface
)
437 VirtualFree(dspriv
->image
->data
, 0, MEM_RELEASE
);
439 if (ddpriv
->xshm_active
) {
440 TSXShmDetach(display
, &(dspriv
->shminfo
));
441 TSXDestroyImage(dspriv
->image
);
442 shmdt(dspriv
->shminfo
.shmaddr
);
446 /* normal X Image memory was never allocated by X, but always by
447 * ourselves -> Don't let X free our imagedata.
449 dspriv
->image
->data
= NULL
;
450 TSXDestroyImage(dspriv
->image
);
456 IDirectDrawPalette_Release((IDirectDrawPalette
*)This
->s
.palette
);
458 /* Free the DIBSection (if any) */
459 if (This
->s
.hdc
!= 0) {
460 /* hack: restore the original DIBsection color map */
461 BITMAPOBJ
*bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(This
->s
.DIBsection
, BITMAP_MAGIC
);
462 X11DRV_DIBSECTION
*dib
= (X11DRV_DIBSECTION
*)bmp
->dib
;
463 dib
->colorMap
= dspriv
->oldDIBmap
;
464 GDI_ReleaseObj(This
->s
.DIBsection
);
466 SelectObject(This
->s
.hdc
, This
->s
.holdbitmap
);
467 DeleteDC(This
->s
.hdc
);
468 DeleteObject(This
->s
.DIBsection
);
471 /* Free the clipper if present */
472 if(This
->s
.lpClipper
)
473 IDirectDrawClipper_Release(This
->s
.lpClipper
);
474 HeapFree(GetProcessHeap(),0,This
->private);
475 HeapFree(GetProcessHeap(),0,This
);
479 HRESULT WINAPI
Xlib_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface
,HDC
* lphdc
) {
480 ICOM_THIS(IDirectDrawSurface4Impl
,iface
);
482 int was_ok
= This
->s
.hdc
!= 0;
483 HRESULT result
= IDirectDrawSurface4Impl_GetDC(iface
,lphdc
);
484 if (This
->s
.hdc
&& !was_ok
) {
485 /* hack: take over the DIBsection color map */
486 BITMAPOBJ
*bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(This
->s
.DIBsection
, BITMAP_MAGIC
);
487 X11DRV_DIBSECTION
*dib
= (X11DRV_DIBSECTION
*)bmp
->dib
;
488 dspriv
->oldDIBmap
= dib
->colorMap
;
489 dib
->colorMap
= This
->s
.palette
? This
->s
.palette
->screen_palents
: NULL
;
490 GDI_ReleaseObj(This
->s
.DIBsection
);
495 ICOM_VTABLE(IDirectDrawSurface4
) xlib_dds4vt
=
497 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
498 Xlib_IDirectDrawSurface4Impl_QueryInterface
,
499 IDirectDrawSurface4Impl_AddRef
,
500 Xlib_IDirectDrawSurface4Impl_Release
,
501 IDirectDrawSurface4Impl_AddAttachedSurface
,
502 IDirectDrawSurface4Impl_AddOverlayDirtyRect
,
503 IDirectDrawSurface4Impl_Blt
,
504 IDirectDrawSurface4Impl_BltBatch
,
505 IDirectDrawSurface4Impl_BltFast
,
506 IDirectDrawSurface4Impl_DeleteAttachedSurface
,
507 IDirectDrawSurface4Impl_EnumAttachedSurfaces
,
508 IDirectDrawSurface4Impl_EnumOverlayZOrders
,
509 Xlib_IDirectDrawSurface4Impl_Flip
,
510 IDirectDrawSurface4Impl_GetAttachedSurface
,
511 IDirectDrawSurface4Impl_GetBltStatus
,
512 IDirectDrawSurface4Impl_GetCaps
,
513 IDirectDrawSurface4Impl_GetClipper
,
514 IDirectDrawSurface4Impl_GetColorKey
,
515 Xlib_IDirectDrawSurface4Impl_GetDC
,
516 IDirectDrawSurface4Impl_GetFlipStatus
,
517 IDirectDrawSurface4Impl_GetOverlayPosition
,
518 IDirectDrawSurface4Impl_GetPalette
,
519 IDirectDrawSurface4Impl_GetPixelFormat
,
520 IDirectDrawSurface4Impl_GetSurfaceDesc
,
521 IDirectDrawSurface4Impl_Initialize
,
522 IDirectDrawSurface4Impl_IsLost
,
523 Xlib_IDirectDrawSurface4Impl_Lock
,
524 IDirectDrawSurface4Impl_ReleaseDC
,
525 IDirectDrawSurface4Impl_Restore
,
526 IDirectDrawSurface4Impl_SetClipper
,
527 IDirectDrawSurface4Impl_SetColorKey
,
528 IDirectDrawSurface4Impl_SetOverlayPosition
,
529 Xlib_IDirectDrawSurface4Impl_SetPalette
,
530 Xlib_IDirectDrawSurface4Impl_Unlock
,
531 IDirectDrawSurface4Impl_UpdateOverlay
,
532 IDirectDrawSurface4Impl_UpdateOverlayDisplay
,
533 IDirectDrawSurface4Impl_UpdateOverlayZOrder
,
534 IDirectDrawSurface4Impl_GetDDInterface
,
535 IDirectDrawSurface4Impl_PageLock
,
536 IDirectDrawSurface4Impl_PageUnlock
,
537 IDirectDrawSurface4Impl_SetSurfaceDesc
,
538 IDirectDrawSurface4Impl_SetPrivateData
,
539 IDirectDrawSurface4Impl_GetPrivateData
,
540 IDirectDrawSurface4Impl_FreePrivateData
,
541 IDirectDrawSurface4Impl_GetUniquenessValue
,
542 IDirectDrawSurface4Impl_ChangeUniquenessValue