Added support for DirectDraw overlays using the XVideo extension.

This commit is contained in:
Lionel Ulmer 2000-09-26 00:38:03 +00:00 committed by Alexandre Julliard
parent dc71c0c954
commit fc67be9a01
8 changed files with 587 additions and 54 deletions

View File

@ -267,7 +267,7 @@ static XImage *create_ximage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lp
void *img_data;
int bpp = PFGET_BPP(This->d->directdraw_pixelformat);
int screen_bpp = PFGET_BPP(This->d->screen_pixelformat);
#ifdef HAVE_LIBXXSHM
if (ddpriv->xshm_active)
img = create_xshmimage(This, lpdsf);
@ -318,6 +318,164 @@ static XImage *create_ximage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lp
return img;
}
#ifdef HAVE_XVIDEO
#ifdef HAVE_LIBXXSHM
static XvImage *create_xvshmimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf) {
DSPRIVATE(lpdsf);
DDPRIVATE(This);
XvImage *img;
int (*WineXHandler)(Display *, XErrorEvent *);
img = TSXvShmCreateImage(display,
ddpriv->port_id,
(int) lpdsf->s.surface_desc.ddpfPixelFormat.dwFourCC,
NULL,
lpdsf->s.surface_desc.dwWidth,
lpdsf->s.surface_desc.dwHeight,
&(dspriv->shminfo));
if (img == NULL) {
FIXME("Couldn't create XShm XvImage (due to X11 remote display or failure).\nReverting to standard X images !\n");
ddpriv->xshm_active = 0;
return NULL;
}
dspriv->shminfo.shmid = shmget( IPC_PRIVATE, img->data_size, IPC_CREAT|0777 );
if (dspriv->shminfo.shmid < 0) {
FIXME("Couldn't create shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
ddpriv->xshm_active = 0;
TSXFree(img);
return NULL;
}
dspriv->shminfo.shmaddr=img->data=(char*)shmat(dspriv->shminfo.shmid,0,0);
if (img->data == (char *) -1) {
FIXME("Couldn't attach shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
ddpriv->xshm_active = 0;
TSXFree(img);
shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
return NULL;
}
dspriv->shminfo.readOnly = False;
/* This is where things start to get trickier....
* First, we flush the current X connections to be sure to catch all
* non-XShm related errors
*/
TSXSync(display, False);
/* Then we enter in the non-thread safe part of the tests */
EnterCriticalSection( &X11DRV_CritSection );
/* Reset the error flag, sets our new error handler and try to attach
* the surface
*/
XShmErrorFlag = 0;
WineXHandler = XSetErrorHandler(XShmErrorHandler);
XShmAttach(display, &(dspriv->shminfo));
XSync(display, False);
/* Check the error flag */
if (XShmErrorFlag) {
/* An error occured */
XFlush(display);
XShmErrorFlag = 0;
XFree(img);
shmdt(dspriv->shminfo.shmaddr);
shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
XSetErrorHandler(WineXHandler);
FIXME("Couldn't attach shared memory segment to X server (due to X11 remote display or failure).\nReverting to standard X images !\n");
ddpriv->xshm_active = 0;
/* Leave the critical section */
LeaveCriticalSection( &X11DRV_CritSection );
return NULL;
}
/* Here, to be REALLY sure, I should do a XShmPutImage to check if
* this works, but it may be a bit overkill....
*/
XSetErrorHandler(WineXHandler);
LeaveCriticalSection( &X11DRV_CritSection );
shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
lpdsf->s.surface_desc.u1.lpSurface = img->data;
VirtualAlloc(img->data, img->data_size, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
return img;
}
#endif
static XvImage *create_xvimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf, HRESULT *err_code) {
XvImage *img = NULL;
DDPRIVATE(This);
void *img_data;
XvImageFormatValues *fo;
int formats, i;
int bpp = PFGET_BPP(lpdsf->s.surface_desc.ddpfPixelFormat);
*err_code = DDERR_OUTOFVIDEOMEMORY;
if (!(lpdsf->s.surface_desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
/* Hmmm, overlay without FOURCC code.. Baaaaaad */
ERR("Overlay without a FOURCC pixel format !\n");
*err_code = DDERR_INVALIDPIXELFORMAT;
return NULL;
}
/* First, find out if we support this PixelFormat.
I make the assumption here that the id of the XvImage format is the
same as the Windows FOURCC code. */
fo = TSXvListImageFormats(display, ddpriv->port_id, &formats);
for (i = 0; i < formats; i++)
if (fo[i].id == lpdsf->s.surface_desc.ddpfPixelFormat.dwFourCC) break;
if (fo)
TSXFree(fo);
if (i == formats) {
ERR("FOURCC code not supported by the video card !\n");
*err_code = DDERR_INVALIDPIXELFORMAT;
return NULL;
}
#ifdef HAVE_LIBXXSHM
if (ddpriv->xshm_active)
img = create_xvshmimage(This, lpdsf);
if (img == NULL) {
#endif
/* Allocate surface memory */
lpdsf->s.surface_desc.u1.lpSurface =
VirtualAlloc(NULL,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
bpp,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
img_data = lpdsf->s.surface_desc.u1.lpSurface;
/* In this case, create an XvImage */
img = TSXvCreateImage(display,
ddpriv->port_id,
(int) lpdsf->s.surface_desc.ddpfPixelFormat.dwFourCC,
img_data,
lpdsf->s.surface_desc.dwWidth,
lpdsf->s.surface_desc.dwHeight);
#ifdef HAVE_LIBXXSHM
}
#endif
lpdsf->s.surface_desc.lPitch = ((XvImage *) img)->pitches[0];
return img;
}
#else
static XvImage *create_xvimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf, HRESULT *err_code) {
*err_code = DDERR_INVALIDPIXELFORMAT;
return NULL;
}
#endif
static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
IUnknown *lpunk
@ -350,7 +508,8 @@ static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
dsurf->s.palette = NULL;
dsurf->s.lpClipper = NULL;
dspriv->image = NULL; /* This is for off-screen buffers */
dspriv->is_overlay = FALSE;
dspriv->info.image = NULL; /* This is for off-screen buffers */
/* Copy the surface description */
dsurf->s.surface_desc = *lpddsd;
@ -361,30 +520,43 @@ static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
dsurf->s.surface_desc.dwHeight = This->d->height;
dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
/* Check if this a 'primary surface' or not */
/* Check if this a 'primary surface' or an overlay */
if ((lpddsd->dwFlags & DDSD_CAPS) &&
(lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
((lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) ||
(lpddsd->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
) {
XImage *img;
/* Add flags if there were not present */
dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
dsurf->s.surface_desc.dwWidth = This->d->width;
dsurf->s.surface_desc.dwHeight = This->d->height;
dsurf->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
dsurf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
dsurf->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
TRACE("using standard XImage for a primary surface (%p)\n", dsurf);
/* Create the XImage */
img = create_ximage(This,(IDirectDrawSurface4Impl*)dsurf);
if (img == NULL)
if (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
dsurf->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
dsurf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
dsurf->s.surface_desc.dwWidth = This->d->width;
dsurf->s.surface_desc.dwHeight = This->d->height;
} else {
dspriv->is_overlay = TRUE;
/* In the case of Overlay surfaces, copy the one provided by the application */
dsurf->s.surface_desc.ddpfPixelFormat = lpddsd->ddpfPixelFormat;
}
if (lpddsd->ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
HRESULT err_code;
TRACE("using an XvImage for the overlay (%p)\n", dsurf);
dspriv->info.overlay.image = create_xvimage(This,(IDirectDrawSurface4Impl*)dsurf, &err_code);
if (dspriv->info.overlay.image == NULL)
return err_code;
} else {
TRACE("using standard XImage for a primary surface (%p)\n", dsurf);
/* Create the XImage */
dspriv->info.image = create_ximage(This,(IDirectDrawSurface4Impl*)dsurf);
if (dspriv->info.image == NULL)
return DDERR_OUTOFMEMORY;
dspriv->image = img;
}
/* Check for backbuffers */
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
IDirectDrawSurface4Impl* back;
XImage *img;
int i;
for (i=lpddsd->dwBackBufferCount;i--;) {
@ -413,11 +585,18 @@ static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
bspriv = (x11_ds_private*)back->private;
/* Create the XImage. */
img = create_ximage(This, back);
if (img == NULL)
if (lpddsd->ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
HRESULT err_code;
dspriv->is_overlay = TRUE;
bspriv->info.overlay.image = create_xvimage(This, back, &err_code);
if (bspriv->info.overlay.image == NULL)
return err_code;
} else {
bspriv->info.image = create_ximage(This, back);
if (bspriv->info.image == NULL)
return DDERR_OUTOFMEMORY;
}
TRACE("bspriv = %p\n",bspriv);
bspriv->image = img;
/* Add relevant info to front and back buffers */
/* FIXME: backbuffer/frontbuffer handling broken here, but
@ -521,7 +700,7 @@ static HRESULT WINAPI Xlib_IDirectDrawImpl_SetDisplayMode(
return DD_OK;
}
static void fill_caps(LPDDCAPS caps) {
static void fill_caps(LPDDCAPS caps, x11_dd_private *x11ddp) {
/* This function tries to fill the capabilities of Wine's DDraw implementation.
Need to be fixed, though.. */
if (caps == NULL)
@ -545,24 +724,39 @@ static void fill_caps(LPDDCAPS caps) {
/* These are all the supported capabilities of the surfaces */
caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
/*DDSCAPS_OVERLAY |*/ DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
#ifdef HAVE_OPENGL
caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
caps->dwCaps2 |= DDCAPS2_NO2DDURING3DSCENE;
caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
#endif
#ifdef HAVE_XVIDEO
if (x11ddp->xvideo_active) {
caps->dwCaps |= DDCAPS_OVERLAY | DDCAPS_OVERLAYFOURCC | DDCAPS_OVERLAYSTRETCH | DDCAPS_BLTFOURCC;
caps->dwCaps2 |= DDCAPS2_VIDEOPORT;
caps->dwMaxVisibleOverlays = 16;
caps->dwCurrVisibleOverlays = 0;
caps->dwMinOverlayStretch = 1; /* Apparently there is no 'down' stretching in XVideo, but well, Windows
Media player refuses to work when I put 1000 here :-/ */
caps->dwMaxOverlayStretch = 100000; /* This is a 'bogus' value, I do not know the maximum stretching */
TSXvListImageFormats(display, x11ddp->port_id, (unsigned int *) &(caps->dwNumFourCCCodes));
caps->ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
}
#endif
}
static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetCaps(
LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
) {
ICOM_THIS(IDirectDraw2Impl,iface);
DDPRIVATE(This);
TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
/* Put the same caps for the two capabilities */
fill_caps(caps1);
fill_caps(caps2);
fill_caps(caps1, ddpriv);
fill_caps(caps2, ddpriv);
return DD_OK;
}
@ -843,6 +1037,18 @@ static HRESULT WINAPI Xlib_IDirectDraw2Impl_EnumDisplayModes(
return DD_OK;
}
HRESULT WINAPI Xlib_IDirectDraw2Impl_GetFourCCCodes(
LPDIRECTDRAW2 iface,LPDWORD x,LPDWORD y
) {
#ifdef HAVE_XVIDEO
ICOM_THIS(IDirectDraw2Impl,iface);
FIXME("(%p,%p,%p), stub\n",This,x,y);
return DD_OK;
#else
return IDirectDraw2Impl_GetFourCCCodes(iface, x, y);
#endif
}
/* Note: Hack so we can reuse the old functions without compiler warnings */
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun) (typeof(xlib_ddvt.fn##fun))
@ -865,7 +1071,7 @@ ICOM_VTABLE(IDirectDraw) xlib_ddvt = {
XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
XCAST(GetFourCCCodes)Xlib_IDirectDraw2Impl_GetFourCCCodes,
XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
@ -916,7 +1122,7 @@ ICOM_VTABLE(IDirectDraw2) xlib_dd2vt = {
IDirectDraw2Impl_FlipToGDISurface,
Xlib_IDirectDraw2Impl_GetCaps,
IDirectDraw2Impl_GetDisplayMode,
IDirectDraw2Impl_GetFourCCCodes,
Xlib_IDirectDraw2Impl_GetFourCCCodes,
IDirectDraw2Impl_GetGDISurface,
IDirectDraw2Impl_GetMonitorFrequency,
IDirectDraw2Impl_GetScanLine,
@ -950,7 +1156,7 @@ ICOM_VTABLE(IDirectDraw4) xlib_dd4vt = {
XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
XCAST(GetFourCCCodes)Xlib_IDirectDraw2Impl_GetFourCCCodes,
XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,

View File

@ -402,4 +402,5 @@ extern void _dump_surface_desc(DDSURFACEDESC *lpddsd);
extern void _dump_cooperativelevel(DWORD cooplevel);
extern void _dump_surface_desc(DDSURFACEDESC *lpddsd);
extern void _dump_DDCOLORKEY(void *in);
extern void _dump_DDOVERLAY(DWORD flagmask) ;
#endif /* __WINE_DLLS_DDRAW_DDRAW_PRIVATE_H */

View File

@ -133,7 +133,7 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
assert(This->s.surface_desc.u1.lpSurface);
/* wait for any previous operations to complete */
#ifdef HAVE_LIBXXSHM
if (dspriv->image && VISIBLE(This) && ddpriv->xshm_active) {
if (dspriv->info.image && VISIBLE(This) && ddpriv->xshm_active) {
/*
int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
@ -144,7 +144,7 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
/* If part of a visible 'clipped' surface, copy what is seen on the
screen to the surface */
if ((dspriv->image && VISIBLE(This)) &&
if ((dspriv->info.image && VISIBLE(This)) &&
(This->s.lpClipper)) {
HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
WND *wndPtr = WIN_FindWndPtr(hWnd);
@ -164,7 +164,7 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
}
TSXGetSubImage(display, drawable, 0, 0, width, height, 0xFFFFFFFF,
ZPixmap, dspriv->image, dest_x, dest_y);
ZPixmap, dspriv->info.image, dest_x, dest_y);
WIN_ReleaseWndPtr(wndPtr);
}
@ -180,8 +180,8 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
SIZE imgsiz;
/* Get XImage size */
imgsiz.cx = dspriv->image->width;
imgsiz.cy = dspriv->image->height;
imgsiz.cx = dspriv->info.image->width;
imgsiz.cy = dspriv->info.image->height;
if (This->s.lpClipper) {
HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
@ -225,7 +225,7 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
if (This->s.ddraw->d->pixel_convert != NULL)
This->s.ddraw->d->pixel_convert(This->s.surface_desc.u1.lpSurface,
dspriv->image->data,
dspriv->info.image->data,
This->s.surface_desc.dwWidth,
This->s.surface_desc.dwHeight,
This->s.surface_desc.lPitch,
@ -233,7 +233,7 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
/* if the DIB section is in GdiMod state, we must
* touch the surface to get any updates from the DIB */
Xlib_TouchData(dspriv->image->data);
Xlib_TouchData(dspriv->info.image->data);
#ifdef HAVE_LIBXXSHM
if (ddpriv->xshm_active) {
/*
@ -246,7 +246,7 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
TSXShmPutImage(display,
drawable,
DefaultGCOfScreen(X11DRV_GetXScreen()),
dspriv->image,
dspriv->info.image,
adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
imgsiz.cx, imgsiz.cy,
True
@ -258,7 +258,7 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
TSXPutImage(display,
drawable,
DefaultGCOfScreen(X11DRV_GetXScreen()),
dspriv->image,
dspriv->info.image,
adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
imgsiz.cx, imgsiz.cy
);
@ -276,7 +276,7 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
return DD_OK; */
/* Only redraw the screen when unlocking the buffer that is on screen */
if (dspriv->image && VISIBLE(This)) {
if (dspriv->info.image && VISIBLE(This)) {
Xlib_copy_surface_on_screen(This);
if (This->s.palette) {
DPPRIVATE(This->s.palette);
@ -289,6 +289,56 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
return DD_OK;
}
#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_Flip(
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
) {
@ -301,9 +351,9 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
if (!This->s.ddraw->d->paintable)
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;
@ -313,16 +363,28 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
This->s.surface_desc.u1.lpSurface = iflipto->s.surface_desc.u1.lpSurface;
iflipto->s.surface_desc.u1.lpSurface = surf;
/* the associated ximage */
image = dspriv->image;
dspriv->image = fspriv->image;
fspriv->image = image;
/* 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
@ -432,24 +494,32 @@ ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
/* Now free the XImages and the respective screen-side surfaces */
if (dspriv->image != NULL) {
if (dspriv->image->data != This->s.surface_desc.u1.lpSurface)
VirtualFree(dspriv->image->data, 0, MEM_RELEASE);
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));
TSXDestroyImage(dspriv->image);
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->image->data = NULL;
TSXDestroyImage(dspriv->image);
dspriv->info.image->data = NULL;
TSXDestroyImage(dspriv->info.image);
}
}
dspriv->image = 0;
dspriv->info.image = 0;
}
if (This->s.palette)
@ -492,6 +562,108 @@ HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC
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 */
ctx.shown = TRUE;
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
@ -528,7 +700,7 @@ ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt =
IDirectDrawSurface4Impl_SetOverlayPosition,
Xlib_IDirectDrawSurface4Impl_SetPalette,
Xlib_IDirectDrawSurface4Impl_Unlock,
IDirectDrawSurface4Impl_UpdateOverlay,
Xlib_IDirectDrawSurface4Impl_UpdateOverlay,
IDirectDrawSurface4Impl_UpdateOverlayDisplay,
IDirectDrawSurface4Impl_UpdateOverlayZOrder,
IDirectDrawSurface4Impl_GetDDInterface,

View File

@ -51,6 +51,44 @@ void _dump_DDBLTFX(DWORD flagmask) {
DPRINTF("\n");
}
void _dump_DDOVERLAY(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDOVER_ALPHADEST)
FE(DDOVER_ALPHADESTCONSTOVERRIDE)
FE(DDOVER_ALPHADESTNEG)
FE(DDOVER_ALPHADESTSURFACEOVERRIDE)
FE(DDOVER_ALPHAEDGEBLEND)
FE(DDOVER_ALPHASRC)
FE(DDOVER_ALPHASRCCONSTOVERRIDE)
FE(DDOVER_ALPHASRCNEG)
FE(DDOVER_ALPHASRCSURFACEOVERRIDE)
FE(DDOVER_HIDE)
FE(DDOVER_KEYDEST)
FE(DDOVER_KEYDESTOVERRIDE)
FE(DDOVER_KEYSRC)
FE(DDOVER_KEYSRCOVERRIDE)
FE(DDOVER_SHOW)
FE(DDOVER_ADDDIRTYRECT)
FE(DDOVER_REFRESHDIRTYRECTS)
FE(DDOVER_REFRESHALL)
FE(DDOVER_DDFX)
FE(DDOVER_AUTOFLIP)
FE(DDOVER_BOB)
FE(DDOVER_OVERRIDEBOBWEAVE)
FE(DDOVER_INTERLEAVED)
#undef FE
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask)
DPRINTF("%s ",flags[i].name);
DPRINTF("\n");
}
void _dump_DDBLTFAST(DWORD flagmask) {
int i;
const struct {
@ -216,12 +254,13 @@ void _dump_pixelformat(void *in) {
DPRINTF("( ");
_dump_pixelformat_flag(pf->dwFlags);
if (pf->dwFlags & DDPF_FOURCC) {
DPRINTF(", dwFourCC (%08lx) : %c%c%c%c",
pf->dwFourCC,
DPRINTF(", dwFourCC code '%c%c%c%c' (0x%08lx) - %ld bits per pixel",
(unsigned char)( pf->dwFourCC &0xff),
(unsigned char)((pf->dwFourCC>> 8)&0xff),
(unsigned char)((pf->dwFourCC>>16)&0xff),
(unsigned char)((pf->dwFourCC>>24)&0xff)
(unsigned char)((pf->dwFourCC>>24)&0xff),
pf->dwFourCC,
pf->u.dwYUVBitCount
);
}
if (pf->dwFlags & DDPF_RGB) {

View File

@ -44,6 +44,64 @@ DDRAW_XSHM_Available(void) {
return FALSE;
}
#ifdef HAVE_XVIDEO
static BOOL
DDRAW_XVIDEO_Available(x11_dd_private *x11ddp) {
unsigned int p_version, p_release, p_request_base, p_event_base, p_error_base;
if (TSXvQueryExtension(display, &p_version, &p_release, &p_request_base,
&p_event_base, &p_error_base) == Success) {
XvAdaptorInfo *ai;
int num_adaptators, i, default_port;
if ((p_version < 2) || ((p_version == 2) && (p_release < 2))) {
TRACE("XVideo extension does NOT support needed features (need version 2.2) !\n");
return FALSE;
}
if (TSXvQueryAdaptors(display, X11DRV_GetXRootWindow(), &num_adaptators, &ai) != Success) {
TRACE("Failed to get list of adaptators.\n");
return FALSE;
}
if (num_adaptators == 0) {
TRACE("No XVideo supporting adaptators found.\n");
return FALSE;
}
default_port = PROFILE_GetWineIniInt("x11drv", "XVideoPort", -1);
for (i = 0; i < num_adaptators; i++) {
if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask)) {
/* This supports everything I want : XvImages and the possibility to put something */
if (default_port == -1) {
default_port = ai[i].base_id;
break;
} else {
if ((ai[i].base_id <= default_port) &&
((ai[i].base_id + ai[i].num_ports) > default_port)) {
break;
}
}
}
}
if (i == num_adaptators) {
if (default_port != -1) {
ERR("User specified port (%d) not found.\n", default_port);
} else {
TRACE("No input + image capable device found.\n");
}
TSXvFreeAdaptorInfo(ai);
return FALSE;
}
x11ddp->port_id = default_port;
TRACE("XVideo support available (using version %d.%d)\n", p_version, p_release);
TSXvFreeAdaptorInfo(ai);
return TRUE;
}
return FALSE;
}
#endif
static HRESULT X11_Create( LPDIRECTDRAW *lplpDD ) {
IDirectDrawImpl* ddraw;
int depth;
@ -88,6 +146,13 @@ static HRESULT X11_Create( LPDIRECTDRAW *lplpDD ) {
TRACE("Using XShm extension.\n");
}
#endif
#ifdef HAVE_XVIDEO
/* Test if XVideo support is available */
if ((x11priv->xvideo_active = DDRAW_XVIDEO_Available(x11priv))) {
TRACE("Using XVideo extension on port '%ld'.\n", x11priv->port_id);
}
#endif
return DD_OK;
}

View File

@ -18,6 +18,13 @@
# include "ts_xshm.h"
#endif /* defined(HAVE_LIBXXSHM) */
#ifdef HAVE_XVIDEO
#include "ts_xvideo.h"
#else
/* Fake type so that NOT to have too many #ifdef XVideo lying around */
typedef int XvImage;
#endif
#include "x11drv.h"
#include "ddraw_private.h"
@ -34,6 +41,10 @@ typedef struct x11_dd_private {
#ifdef HAVE_LIBXXSHM
int xshm_active, xshm_compl;
#endif /* defined(HAVE_LIBXXSHM) */
#ifdef HAVE_XVIDEO
BOOL xvideo_active;
XvPortID port_id;
#endif
Window drawable;
void *device_capabilities;
} x11_dd_private;
@ -47,7 +58,18 @@ extern HRESULT WINAPI Xlib_IDirectDrawPaletteImpl_SetEntries(LPDIRECTDRAWPALETTE
extern ULONG WINAPI Xlib_IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE iface);
typedef struct x11_ds_private {
XImage *image;
BOOL is_overlay;
union {
XImage *image;
struct {
/* The 'image' field should be in FIRST !!!! The Flip function depends on that... */
XvImage *image;
BOOL shown;
RECT src_rect;
RECT dst_rect;
LPDIRECTDRAWSURFACE dest_surface;
} overlay;
} info;
#ifdef HAVE_LIBXXSHM
XShmSegmentInfo shminfo;
#endif

View File

@ -811,6 +811,31 @@ typedef struct _DDPIXELFORMAT {
#define DDOVERFX_MIRRORLEFTRIGHT 0x00000002
#define DDOVERFX_MIRRORUPDOWN 0x00000004
/* UpdateOverlay flags */
#define DDOVER_ALPHADEST 0x00000001
#define DDOVER_ALPHADESTCONSTOVERRIDE 0x00000002
#define DDOVER_ALPHADESTNEG 0x00000004
#define DDOVER_ALPHADESTSURFACEOVERRIDE 0x00000008
#define DDOVER_ALPHAEDGEBLEND 0x00000010
#define DDOVER_ALPHASRC 0x00000020
#define DDOVER_ALPHASRCCONSTOVERRIDE 0x00000040
#define DDOVER_ALPHASRCNEG 0x00000080
#define DDOVER_ALPHASRCSURFACEOVERRIDE 0x00000100
#define DDOVER_HIDE 0x00000200
#define DDOVER_KEYDEST 0x00000400
#define DDOVER_KEYDESTOVERRIDE 0x00000800
#define DDOVER_KEYSRC 0x00001000
#define DDOVER_KEYSRCOVERRIDE 0x00002000
#define DDOVER_SHOW 0x00004000
#define DDOVER_ADDDIRTYRECT 0x00008000
#define DDOVER_REFRESHDIRTYRECTS 0x00010000
#define DDOVER_REFRESHALL 0x00020000
#define DDOVER_DDFX 0x00080000
#define DDOVER_AUTOFLIP 0x00100000
#define DDOVER_BOB 0x00200000
#define DDOVER_OVERRIDEBOBWEAVE 0x00400000
#define DDOVER_INTERLEAVED 0x00800000
/* DDCOLORKEY.dwFlags */
#define DDPF_ALPHAPIXELS 0x00000001
#define DDPF_ALPHA 0x00000002

View File

@ -113,6 +113,9 @@ DesktopDoubleBuffered = N
; Code page used for captions in managed mode
; 0 means default ANSI code page (CP_ACP == 0)
TextCP=0
; Use this if you have more than one port for video on your setup
; (Wine uses for now the first 'input image' it founds).
;; XVideoPort = 43
[fonts]
;Read documentation/fonts before adding aliases