724 lines
24 KiB
C
724 lines
24 KiB
C
/* DirectDrawSurface Xlib implementation
|
|
*
|
|
* Copyright 1997-2000 Marcus Meissner
|
|
* Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
|
|
*/
|
|
#include "config.h"
|
|
#include "winerror.h"
|
|
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "options.h"
|
|
#include "debugtools.h"
|
|
#include "x11_private.h"
|
|
#include "bitmap.h"
|
|
#include "win.h"
|
|
#include "d3d.h"
|
|
|
|
#ifdef HAVE_OPENGL
|
|
/* for d3d texture stuff */
|
|
# include "mesa_private.h"
|
|
#endif
|
|
|
|
DEFAULT_DEBUG_CHANNEL(ddraw);
|
|
|
|
#define VISIBLE(x) (SDDSCAPS(x) & (DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE))
|
|
|
|
#define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->d->private)
|
|
#define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
|
|
#define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
|
|
|
|
static BYTE Xlib_TouchData(LPVOID data)
|
|
{
|
|
/* this is a function so it doesn't get optimized out */
|
|
return *(BYTE*)data;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* IDirectDrawSurface methods
|
|
*
|
|
* Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
|
|
* DDS and DDS2 use those functions. (Function calls did not change (except
|
|
* using different DirectDrawSurfaceX version), just added flags and functions)
|
|
*/
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_QueryInterface(
|
|
LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
|
|
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
|
|
|
|
/* All DirectDrawSurface versions (1, 2, 3 and 4) use
|
|
* the same interface. And IUnknown does that too of course.
|
|
*/
|
|
if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid ) ||
|
|
IsEqualGUID( &IID_IDirectDrawSurface3, refiid ) ||
|
|
IsEqualGUID( &IID_IDirectDrawSurface2, refiid ) ||
|
|
IsEqualGUID( &IID_IDirectDrawSurface, refiid ) ||
|
|
IsEqualGUID( &IID_IUnknown, refiid )
|
|
) {
|
|
*obj = This;
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
|
|
TRACE(" Creating IDirectDrawSurface interface (%p)\n", *obj);
|
|
return S_OK;
|
|
}
|
|
#ifdef HAVE_OPENGL
|
|
if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ) {
|
|
/* Texture interface */
|
|
*obj = d3dtexture2_create(This);
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
TRACE(" Creating IDirect3DTexture2 interface (%p)\n", *obj);
|
|
return S_OK;
|
|
}
|
|
if ( IsEqualGUID( &IID_IDirect3DTexture, refiid ) ) {
|
|
/* Texture interface */
|
|
*obj = d3dtexture_create(This);
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
TRACE(" Creating IDirect3DTexture interface (%p)\n", *obj);
|
|
return S_OK;
|
|
}
|
|
#else
|
|
if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ||
|
|
IsEqualGUID( &IID_IDirect3DTexture, refiid )
|
|
)
|
|
{
|
|
ERR( "Cannot provide 3D support without OpenGL/Mesa installed\n" );
|
|
}
|
|
#endif /* HAVE_OPENGL */
|
|
FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
|
|
return OLE_E_ENUM_NOMORE;
|
|
}
|
|
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
|
|
LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
DSPRIVATE(This);
|
|
DDPRIVATE(This->s.ddraw);
|
|
|
|
/* DO NOT AddRef the surface! Lock/Unlock are NOT guaranteed to come in
|
|
* matched pairs! - Marcus Meissner 20000509 */
|
|
TRACE("(%p)->Lock(%p,%p,%08lx,%08lx) ret=%p\n",This,lprect,lpddsd,flags,(DWORD)hnd,__builtin_return_address(0));
|
|
if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
|
|
WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
|
|
This,lprect,lpddsd,flags,(DWORD)hnd);
|
|
|
|
/* First, copy the Surface description */
|
|
*lpddsd = This->s.surface_desc;
|
|
TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
|
|
lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
|
|
|
|
/* If asked only for a part, change the surface pointer */
|
|
if (lprect) {
|
|
TRACE(" lprect: %dx%d-%dx%d\n",
|
|
lprect->top,lprect->left,lprect->bottom,lprect->right
|
|
);
|
|
if ((lprect->top < 0) ||
|
|
(lprect->left < 0) ||
|
|
(lprect->bottom < 0) ||
|
|
(lprect->right < 0)) {
|
|
ERR(" Negative values in LPRECT !!!\n");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
lpddsd->u1.lpSurface=(LPVOID)((char*)This->s.surface_desc.u1.lpSurface+
|
|
(lprect->top*This->s.surface_desc.lPitch) +
|
|
lprect->left*GET_BPP(This->s.surface_desc));
|
|
} else
|
|
assert(This->s.surface_desc.u1.lpSurface);
|
|
/* wait for any previous operations to complete */
|
|
#ifdef HAVE_LIBXXSHM
|
|
if (dspriv->info.image && VISIBLE(This) && ddpriv->xshm_active) {
|
|
/*
|
|
int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
|
|
if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
|
|
*/
|
|
X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
|
|
}
|
|
#endif
|
|
|
|
/* If part of a visible 'clipped' surface, copy what is seen on the
|
|
screen to the surface */
|
|
if ((dspriv->info.image && VISIBLE(This)) &&
|
|
(This->s.lpClipper)) {
|
|
HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
|
|
WND *wndPtr = WIN_FindWndPtr(hWnd);
|
|
Drawable drawable = X11DRV_WND_GetXWindow(wndPtr);
|
|
int width = wndPtr->rectClient.right - wndPtr->rectClient.left;
|
|
int height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
|
|
/* Now, get the source / destination coordinates */
|
|
int dest_x = wndPtr->rectClient.left;
|
|
int dest_y = wndPtr->rectClient.top;
|
|
|
|
if (!drawable) { /* we are running in -desktop mode */
|
|
drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
|
|
/* FIXME: not sure whether these are the right offsets */
|
|
dest_x+=wndPtr->rectWindow.left;
|
|
dest_y+=wndPtr->rectWindow.top;
|
|
WIN_ReleaseDesktop();
|
|
}
|
|
|
|
TSXGetSubImage(display, drawable, 0, 0, width, height, 0xFFFFFFFF,
|
|
ZPixmap, dspriv->info.image, dest_x, dest_y);
|
|
|
|
WIN_ReleaseWndPtr(wndPtr);
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
|
|
DSPRIVATE(This);
|
|
DDPRIVATE(This->s.ddraw);
|
|
Drawable drawable = ddpriv->drawable;
|
|
POINT adjust[2] = {{0, 0}, {0, 0}};
|
|
SIZE imgsiz;
|
|
|
|
/* Get XImage size */
|
|
imgsiz.cx = dspriv->info.image->width;
|
|
imgsiz.cy = dspriv->info.image->height;
|
|
|
|
if (This->s.lpClipper) {
|
|
HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
|
|
SIZE csiz;
|
|
WND *wndPtr = WIN_FindWndPtr(hWnd);
|
|
drawable = X11DRV_WND_GetXWindow(wndPtr);
|
|
|
|
MapWindowPoints(hWnd, 0, adjust, 2);
|
|
|
|
imgsiz.cx -= adjust[0].x;
|
|
imgsiz.cy -= adjust[0].y;
|
|
/* (note: the rectWindow here should be the X window's interior rect, in
|
|
* case anyone thinks otherwise while rewriting managed mode) */
|
|
adjust[1].x -= wndPtr->rectWindow.left;
|
|
adjust[1].y -= wndPtr->rectWindow.top;
|
|
csiz.cx = wndPtr->rectClient.right - wndPtr->rectClient.left;
|
|
csiz.cy = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
|
|
if (csiz.cx < imgsiz.cx) imgsiz.cx = csiz.cx;
|
|
if (csiz.cy < imgsiz.cy) imgsiz.cy = csiz.cy;
|
|
|
|
TRACE("adjust: hwnd=%08x, surface %ldx%ld, drawable %ldx%ld\n", hWnd,
|
|
adjust[0].x, adjust[0].y,
|
|
adjust[1].x,adjust[1].y);
|
|
|
|
WIN_ReleaseWndPtr(wndPtr);
|
|
}
|
|
|
|
if (!drawable) {
|
|
WND *tmpWnd = WIN_FindWndPtr(This->s.ddraw->d->window);
|
|
drawable = X11DRV_WND_GetXWindow(tmpWnd);
|
|
WIN_ReleaseWndPtr(tmpWnd);
|
|
|
|
/* We don't have a context for this window. Host off the desktop */
|
|
if( !drawable ) {
|
|
FIXME("Have to use Desktop Root Window??? Bummer.\n");
|
|
drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
|
|
WIN_ReleaseDesktop();
|
|
}
|
|
ddpriv->drawable = drawable;
|
|
}
|
|
|
|
if (This->s.ddraw->d->pixel_convert != NULL)
|
|
This->s.ddraw->d->pixel_convert(This->s.surface_desc.u1.lpSurface,
|
|
dspriv->info.image->data,
|
|
This->s.surface_desc.dwWidth,
|
|
This->s.surface_desc.dwHeight,
|
|
This->s.surface_desc.lPitch,
|
|
This->s.palette);
|
|
|
|
/* if the DIB section is in GdiMod state, we must
|
|
* touch the surface to get any updates from the DIB */
|
|
Xlib_TouchData(dspriv->info.image->data);
|
|
#ifdef HAVE_LIBXXSHM
|
|
if (ddpriv->xshm_active) {
|
|
/*
|
|
X11DRV_EVENT_WaitReplaceShmCompletion( &(ddpriv->xshm_compl), This->s.ddraw->d.drawable );
|
|
*/
|
|
/* let WaitShmCompletions track 'em for now */
|
|
/* (you may want to track it again whenever you implement DX7's partial
|
|
* surface locking, where threads have concurrent access) */
|
|
X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
|
|
TSXShmPutImage(display,
|
|
drawable,
|
|
DefaultGCOfScreen(X11DRV_GetXScreen()),
|
|
dspriv->info.image,
|
|
adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
|
|
imgsiz.cx, imgsiz.cy,
|
|
True
|
|
);
|
|
/* make sure the image is transferred ASAP */
|
|
TSXFlush(display);
|
|
} else
|
|
#endif
|
|
TSXPutImage(display,
|
|
drawable,
|
|
DefaultGCOfScreen(X11DRV_GetXScreen()),
|
|
dspriv->info.image,
|
|
adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
|
|
imgsiz.cx, imgsiz.cy
|
|
);
|
|
}
|
|
|
|
#ifdef HAVE_XVIDEO
|
|
static void Xlib_copy_overlay_on_screen(IDirectDrawSurface4Impl* This) {
|
|
DSPRIVATE(This);
|
|
DDPRIVATE(This->s.ddraw);
|
|
Drawable drawable = ddpriv->drawable;
|
|
|
|
if (!drawable) {
|
|
WND *tmpWnd = WIN_FindWndPtr(This->s.ddraw->d->window);
|
|
drawable = X11DRV_WND_GetXWindow(tmpWnd);
|
|
WIN_ReleaseWndPtr(tmpWnd);
|
|
|
|
/* We don't have a context for this window. Host off the desktop */
|
|
if( !drawable ) {
|
|
FIXME("Have to use Desktop Root Window??? Bummer.\n");
|
|
drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
|
|
WIN_ReleaseDesktop();
|
|
}
|
|
ddpriv->drawable = drawable;
|
|
}
|
|
|
|
#ifdef HAVE_LIBXXSHM
|
|
if (ddpriv->xshm_active) {
|
|
/* let WaitShmCompletions track 'em for now */
|
|
/* (you may want to track it again whenever you implement DX7's partial
|
|
* surface locking, where threads have concurrent access) */
|
|
X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
|
|
TSXvShmPutImage(display, ddpriv->port_id, drawable, DefaultGCOfScreen(X11DRV_GetXScreen()),
|
|
dspriv->info.overlay.image,
|
|
dspriv->info.overlay.src_rect.left, dspriv->info.overlay.src_rect.top,
|
|
dspriv->info.overlay.src_rect.right - dspriv->info.overlay.src_rect.left,
|
|
dspriv->info.overlay.src_rect.bottom - dspriv->info.overlay.src_rect.top,
|
|
dspriv->info.overlay.dst_rect.left, dspriv->info.overlay.dst_rect.top,
|
|
dspriv->info.overlay.dst_rect.right - dspriv->info.overlay.dst_rect.left,
|
|
dspriv->info.overlay.dst_rect.bottom - dspriv->info.overlay.dst_rect.top,
|
|
True);
|
|
/* make sure the image is transferred ASAP */
|
|
TSXFlush(display);
|
|
} else
|
|
#endif
|
|
TSXvPutImage(display, ddpriv->port_id, drawable, DefaultGCOfScreen(X11DRV_GetXScreen()),
|
|
dspriv->info.overlay.image,
|
|
dspriv->info.overlay.src_rect.left, dspriv->info.overlay.src_rect.top,
|
|
dspriv->info.overlay.src_rect.right - dspriv->info.overlay.src_rect.left,
|
|
dspriv->info.overlay.src_rect.bottom - dspriv->info.overlay.src_rect.top,
|
|
dspriv->info.overlay.dst_rect.left, dspriv->info.overlay.dst_rect.top,
|
|
dspriv->info.overlay.dst_rect.right - dspriv->info.overlay.dst_rect.left,
|
|
dspriv->info.overlay.dst_rect.bottom - dspriv->info.overlay.dst_rect.top);
|
|
}
|
|
#endif
|
|
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
|
|
LPDIRECTDRAWSURFACE4 iface,LPVOID surface
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
DDPRIVATE(This->s.ddraw);
|
|
DSPRIVATE(This);
|
|
TRACE("(%p)->Unlock(%p)\n",This,surface);
|
|
|
|
/*if (!This->s.ddraw->d.paintable)
|
|
return DD_OK; */
|
|
|
|
/* Only redraw the screen when unlocking the buffer that is on screen */
|
|
if (dspriv->info.image && VISIBLE(This)) {
|
|
Xlib_copy_surface_on_screen(This);
|
|
if (This->s.palette) {
|
|
DPPRIVATE(This->s.palette);
|
|
if(dppriv->cm)
|
|
TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
|
|
}
|
|
} else if (dspriv->is_overlay) {
|
|
/* Case of an overlay surface */
|
|
#ifdef HAVE_XVIDEO
|
|
if (dspriv->info.overlay.shown)
|
|
Xlib_copy_overlay_on_screen(This);
|
|
#else
|
|
ERR("Why was this code activated WITHOUT XVideo support ?\n");
|
|
#endif
|
|
}
|
|
/* DO NOT Release the surface! Lock/Unlock are NOT guaranteed to come in
|
|
* matched pairs! - Marcus Meissner 20000509 */
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
XImage *image;
|
|
DDPRIVATE(This->s.ddraw);
|
|
DSPRIVATE(This);
|
|
x11_ds_private *fspriv;
|
|
LPBYTE surf;
|
|
IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
|
|
|
|
TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
|
|
if ((!This->s.ddraw->d->paintable) && (dspriv->is_overlay == FALSE))
|
|
return DD_OK;
|
|
|
|
iflipto = _common_find_flipto(This,iflipto);
|
|
fspriv = (x11_ds_private*)iflipto->private;
|
|
|
|
/* We need to switch the lowlevel surfaces, for xlib this is: */
|
|
/* The surface pointer */
|
|
surf = This->s.surface_desc.u1.lpSurface;
|
|
This->s.surface_desc.u1.lpSurface = iflipto->s.surface_desc.u1.lpSurface;
|
|
iflipto->s.surface_desc.u1.lpSurface = surf;
|
|
|
|
/* the associated ximage
|
|
|
|
NOTE : for XVideo, the pointer to the XvImage is at the same position
|
|
in memory than the standard XImage. This means that this code
|
|
still works :-)
|
|
*/
|
|
image = dspriv->info.image;
|
|
dspriv->info.image = fspriv->info.image;
|
|
fspriv->info.image = image;
|
|
|
|
if (dspriv->opengl_flip) {
|
|
#ifdef HAVE_OPENGL
|
|
ENTER_GL();
|
|
glXSwapBuffers(display, ddpriv->drawable);
|
|
LEAVE_GL();
|
|
#endif
|
|
} else if (dspriv->is_overlay) {
|
|
#ifdef HAVE_XVIDEO
|
|
if (dspriv->info.overlay.shown)
|
|
Xlib_copy_overlay_on_screen(This);
|
|
#else
|
|
ERR("Why was this code activated WITHOUT XVideo support ?\n");
|
|
#endif
|
|
} else {
|
|
#ifdef HAVE_LIBXXSHM
|
|
if (ddpriv->xshm_active) {
|
|
/*
|
|
int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
|
|
if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
|
|
*/
|
|
X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
|
|
}
|
|
#endif
|
|
Xlib_copy_surface_on_screen(This);
|
|
if (iflipto->s.palette) {
|
|
DPPRIVATE(iflipto->s.palette);
|
|
if (dppriv->cm)
|
|
TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
/* The IDirectDrawSurface4::SetPalette method attaches the specified
|
|
* DirectDrawPalette object to a surface. The surface uses this palette for all
|
|
* subsequent operations. The palette change takes place immediately.
|
|
*/
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_SetPalette(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
DDPRIVATE(This->s.ddraw);
|
|
IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
|
|
x11_dp_private *dppriv;
|
|
int i;
|
|
|
|
TRACE("(%p)->(%p)\n",This,ipal);
|
|
|
|
if (ipal == NULL) {
|
|
if( This->s.palette != NULL )
|
|
IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
|
|
This->s.palette = ipal;
|
|
return DD_OK;
|
|
}
|
|
dppriv = (x11_dp_private*)ipal->private;
|
|
|
|
if (!dppriv->cm &&
|
|
(This->s.ddraw->d->screen_pixelformat.u.dwRGBBitCount<=8)
|
|
) {
|
|
dppriv->cm = TSXCreateColormap(
|
|
display,
|
|
ddpriv->drawable,
|
|
DefaultVisualOfScreen(X11DRV_GetXScreen()),
|
|
AllocAll
|
|
);
|
|
if (!Options.managed)
|
|
TSXInstallColormap(display,dppriv->cm);
|
|
|
|
for (i=0;i<256;i++) {
|
|
XColor xc;
|
|
|
|
xc.red = ipal->palents[i].peRed<<8;
|
|
xc.blue = ipal->palents[i].peBlue<<8;
|
|
xc.green = ipal->palents[i].peGreen<<8;
|
|
xc.flags = DoRed|DoBlue|DoGreen;
|
|
xc.pixel = i;
|
|
TSXStoreColor(display,dppriv->cm,&xc);
|
|
}
|
|
TSXInstallColormap(display,dppriv->cm);
|
|
}
|
|
/* According to spec, we are only supposed to
|
|
* AddRef if this is not the same palette.
|
|
*/
|
|
if ( This->s.palette != ipal ) {
|
|
if( ipal != NULL )
|
|
IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
|
|
if( This->s.palette != NULL )
|
|
IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
|
|
This->s.palette = ipal;
|
|
/* Perform the refresh, only if a palette was created */
|
|
if (dppriv->cm)
|
|
TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
|
|
|
|
if (This->s.hdc != 0) {
|
|
/* hack: set the DIBsection color map */
|
|
BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
|
|
X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
|
|
dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
|
|
GDI_ReleaseObj(This->s.DIBsection);
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
DSPRIVATE(This);
|
|
DDPRIVATE(This->s.ddraw);
|
|
|
|
TRACE( "(%p)->() decrementing from %lu.\n", This, This->ref );
|
|
if (--(This->ref))
|
|
return This->ref;
|
|
|
|
IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
|
|
|
|
/* This frees the program-side surface. In some cases it had been
|
|
* allocated with MEM_SYSTEM, so it does not get 'really' freed
|
|
*/
|
|
VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
|
|
|
|
/* Now free the XImages and the respective screen-side surfaces */
|
|
if (dspriv->info.image != NULL) {
|
|
if (dspriv->info.image->data != This->s.surface_desc.u1.lpSurface)
|
|
VirtualFree(dspriv->info.image->data, 0, MEM_RELEASE);
|
|
#ifdef HAVE_LIBXXSHM
|
|
if (ddpriv->xshm_active) {
|
|
TSXShmDetach(display, &(dspriv->shminfo));
|
|
if (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
|
|
TSXFree(dspriv->info.image);
|
|
} else {
|
|
TSXDestroyImage(dspriv->info.image);
|
|
}
|
|
shmdt(dspriv->shminfo.shmaddr);
|
|
} else
|
|
#endif
|
|
{
|
|
if (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
|
|
TSXFree(dspriv->info.image);
|
|
} else {
|
|
/* normal X Image memory was never allocated by X, but always by
|
|
* ourselves -> Don't let X free our imagedata.
|
|
*/
|
|
dspriv->info.image->data = NULL;
|
|
TSXDestroyImage(dspriv->info.image);
|
|
}
|
|
}
|
|
dspriv->info.image = 0;
|
|
}
|
|
|
|
if (This->s.palette)
|
|
IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
|
|
|
|
/* Free the DIBSection (if any) */
|
|
if (This->s.hdc != 0) {
|
|
/* hack: restore the original DIBsection color map */
|
|
BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
|
|
X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
|
|
dib->colorMap = dspriv->oldDIBmap;
|
|
GDI_ReleaseObj(This->s.DIBsection);
|
|
|
|
SelectObject(This->s.hdc, This->s.holdbitmap);
|
|
DeleteDC(This->s.hdc);
|
|
DeleteObject(This->s.DIBsection);
|
|
}
|
|
|
|
/* Free the clipper if present */
|
|
if(This->s.lpClipper)
|
|
IDirectDrawClipper_Release(This->s.lpClipper);
|
|
HeapFree(GetProcessHeap(),0,This->private);
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
DSPRIVATE(This);
|
|
int was_ok = This->s.hdc != 0;
|
|
HRESULT result = IDirectDrawSurface4Impl_GetDC(iface,lphdc);
|
|
if (This->s.hdc && !was_ok) {
|
|
/* hack: take over the DIBsection color map */
|
|
BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
|
|
X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
|
|
dspriv->oldDIBmap = dib->colorMap;
|
|
dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
|
|
GDI_ReleaseObj(This->s.DIBsection);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#ifdef HAVE_XVIDEO
|
|
typedef struct {
|
|
BOOL shown;
|
|
LPRECT src_rect;
|
|
LPRECT dst_rect;
|
|
LPDIRECTDRAWSURFACE dest_surface;
|
|
} UpdateOverlayEnumerate;
|
|
|
|
static HRESULT WINAPI enum_func(LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDSURFACEDESC lpDDSurfaceDesc,
|
|
LPVOID lpContext) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,lpDDSurface);
|
|
DSPRIVATE(This);
|
|
UpdateOverlayEnumerate *ctx = (UpdateOverlayEnumerate *) lpContext;
|
|
|
|
if ((lpDDSurfaceDesc->ddsCaps.dwCaps) & DDSCAPS_BACKBUFFER) {
|
|
TRACE("Upgrading surface %p\n", lpDDSurface);
|
|
|
|
if (ctx->shown) {
|
|
dspriv->info.overlay.shown = TRUE;
|
|
dspriv->info.overlay.src_rect = *(ctx->src_rect);
|
|
dspriv->info.overlay.dst_rect = *(ctx->dst_rect);
|
|
dspriv->info.overlay.dest_surface = ctx->dest_surface;
|
|
} else {
|
|
dspriv->info.overlay.shown = FALSE;
|
|
}
|
|
}
|
|
|
|
return DDENUMRET_OK;
|
|
}
|
|
#endif
|
|
|
|
HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_UpdateOverlay(
|
|
LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
|
|
LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
|
|
LPDDOVERLAYFX lpDDOverlayFx
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
#ifdef HAVE_XVIDEO
|
|
DSPRIVATE(This);
|
|
DDPRIVATE(This->s.ddraw);
|
|
|
|
if (ddpriv->xvideo_active) {
|
|
TRACE("(%p)->(%p,%p,%p,0x%08lx,%p)\n", This,
|
|
lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
|
|
|
|
if (TRACE_ON(ddraw)) {
|
|
DPRINTF(" - dwFlags : ");
|
|
_dump_DDOVERLAY(dwFlags);
|
|
|
|
if (lpSrcRect) DPRINTF(" - src rectangle :%dx%d-%dx%d\n",lpSrcRect->left,lpSrcRect->top,
|
|
lpSrcRect->right,lpSrcRect->bottom);
|
|
if (lpDestRect) DPRINTF(" - dest rectangle :%dx%d-%dx%d\n",lpDestRect->left,lpDestRect->top,
|
|
lpDestRect->right,lpDestRect->bottom);
|
|
}
|
|
|
|
if (dwFlags & DDOVER_SHOW) {
|
|
UpdateOverlayEnumerate ctx;
|
|
|
|
dwFlags &= ~DDOVER_SHOW;
|
|
|
|
if ((lpSrcRect == NULL) || (lpDestRect == NULL)) {
|
|
FIXME("This is NOT supported yet...\n");
|
|
return DD_OK;
|
|
}
|
|
|
|
/* Set the shown BOOL to TRUE and update the rectangles */
|
|
dspriv->info.overlay.shown = TRUE;
|
|
dspriv->info.overlay.src_rect = *lpSrcRect;
|
|
dspriv->info.overlay.dst_rect = *lpDestRect;
|
|
dspriv->info.overlay.dest_surface = (LPDIRECTDRAWSURFACE) lpDDDestSurface;
|
|
|
|
/* Now the same for the backbuffers, except that they are NOT shown */
|
|
ctx.shown = FALSE;
|
|
ctx.src_rect = lpSrcRect;
|
|
ctx.dst_rect = lpDestRect;
|
|
ctx.dest_surface = (LPDIRECTDRAWSURFACE) lpDDDestSurface;
|
|
|
|
IDirectDrawSurface4Impl_EnumAttachedSurfaces(iface, &ctx, enum_func);
|
|
} else if (dwFlags & DDOVER_HIDE) {
|
|
UpdateOverlayEnumerate ctx;
|
|
|
|
dwFlags &= ~DDOVER_HIDE;
|
|
|
|
/* Set the shown BOOL to FALSE for all overlays */
|
|
dspriv->info.overlay.shown = FALSE;
|
|
ctx.shown = FALSE;
|
|
IDirectDrawSurface4Impl_EnumAttachedSurfaces(iface, &ctx, enum_func);
|
|
}
|
|
|
|
if (dwFlags && TRACE_ON(ddraw)) {
|
|
WARN("Unsupported flags : ");
|
|
_dump_DDOVERLAY(dwFlags);
|
|
}
|
|
} else
|
|
#endif
|
|
FIXME("(%p)->(%p,%p,%p,0x%08lx,%p) not supported without XVideo !\n", This,
|
|
lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
Xlib_IDirectDrawSurface4Impl_QueryInterface,
|
|
IDirectDrawSurface4Impl_AddRef,
|
|
Xlib_IDirectDrawSurface4Impl_Release,
|
|
IDirectDrawSurface4Impl_AddAttachedSurface,
|
|
IDirectDrawSurface4Impl_AddOverlayDirtyRect,
|
|
IDirectDrawSurface4Impl_Blt,
|
|
IDirectDrawSurface4Impl_BltBatch,
|
|
IDirectDrawSurface4Impl_BltFast,
|
|
IDirectDrawSurface4Impl_DeleteAttachedSurface,
|
|
IDirectDrawSurface4Impl_EnumAttachedSurfaces,
|
|
IDirectDrawSurface4Impl_EnumOverlayZOrders,
|
|
Xlib_IDirectDrawSurface4Impl_Flip,
|
|
IDirectDrawSurface4Impl_GetAttachedSurface,
|
|
IDirectDrawSurface4Impl_GetBltStatus,
|
|
IDirectDrawSurface4Impl_GetCaps,
|
|
IDirectDrawSurface4Impl_GetClipper,
|
|
IDirectDrawSurface4Impl_GetColorKey,
|
|
Xlib_IDirectDrawSurface4Impl_GetDC,
|
|
IDirectDrawSurface4Impl_GetFlipStatus,
|
|
IDirectDrawSurface4Impl_GetOverlayPosition,
|
|
IDirectDrawSurface4Impl_GetPalette,
|
|
IDirectDrawSurface4Impl_GetPixelFormat,
|
|
IDirectDrawSurface4Impl_GetSurfaceDesc,
|
|
IDirectDrawSurface4Impl_Initialize,
|
|
IDirectDrawSurface4Impl_IsLost,
|
|
Xlib_IDirectDrawSurface4Impl_Lock,
|
|
IDirectDrawSurface4Impl_ReleaseDC,
|
|
IDirectDrawSurface4Impl_Restore,
|
|
IDirectDrawSurface4Impl_SetClipper,
|
|
IDirectDrawSurface4Impl_SetColorKey,
|
|
IDirectDrawSurface4Impl_SetOverlayPosition,
|
|
Xlib_IDirectDrawSurface4Impl_SetPalette,
|
|
Xlib_IDirectDrawSurface4Impl_Unlock,
|
|
Xlib_IDirectDrawSurface4Impl_UpdateOverlay,
|
|
IDirectDrawSurface4Impl_UpdateOverlayDisplay,
|
|
IDirectDrawSurface4Impl_UpdateOverlayZOrder,
|
|
IDirectDrawSurface4Impl_GetDDInterface,
|
|
IDirectDrawSurface4Impl_PageLock,
|
|
IDirectDrawSurface4Impl_PageUnlock,
|
|
IDirectDrawSurface4Impl_SetSurfaceDesc,
|
|
IDirectDrawSurface4Impl_SetPrivateData,
|
|
IDirectDrawSurface4Impl_GetPrivateData,
|
|
IDirectDrawSurface4Impl_FreePrivateData,
|
|
IDirectDrawSurface4Impl_GetUniquenessValue,
|
|
IDirectDrawSurface4Impl_ChangeUniquenessValue
|
|
};
|