From 1c649c8e5d46685a263ab539ee1978fe8fa9be03 Mon Sep 17 00:00:00 2001 From: David Reveman Date: Fri, 25 Jul 2008 14:23:38 -0400 Subject: [PATCH] Add initial XVideo support to DMX. --- configure.ac | 2 +- hw/dmx/Makefile.am | 2 + hw/dmx/dmx-config.h | 1 - hw/dmx/dmx.h | 5 + hw/dmx/dmxclient.h | 4 + hw/dmx/dmxextension.c | 7 + hw/dmx/dmxinit.c | 57 +++- hw/dmx/dmxscrinit.c | 13 + hw/dmx/dmxxv.c | 734 ++++++++++++++++++++++++++++++++++++++++++ hw/dmx/dmxxv.h | 35 ++ 10 files changed, 853 insertions(+), 7 deletions(-) create mode 100644 hw/dmx/dmxxv.c create mode 100644 hw/dmx/dmxxv.h diff --git a/configure.ac b/configure.ac index 42d30d85e..18f4c200c 100644 --- a/configure.ac +++ b/configure.ac @@ -1561,7 +1561,7 @@ AM_CONDITIONAL(INTEGRATED_XPBPROXY, [test "x$INTEGRATED_XPBPROXY" = xyes]) dnl DMX DDX -PKG_CHECK_MODULES([DMXMODULES], [xmuu xext x11 xrender xfixes xfont xi dmxproto xau xcomposite xrandr x11-xcb $XDMCP_MODULES], [have_dmx=yes], [have_dmx=no]) +PKG_CHECK_MODULES([DMXMODULES], [xmuu xext x11 xrender xfixes xfont xi dmxproto xau xcomposite xrandr xv x11-xcb $XDMCP_MODULES], [have_dmx=yes], [have_dmx=no]) if test "x$DMX" = xauto; then DMX="$have_dmx" case $host_os in diff --git a/hw/dmx/Makefile.am b/hw/dmx/Makefile.am index e8089d3e6..438c71b5d 100644 --- a/hw/dmx/Makefile.am +++ b/hw/dmx/Makefile.am @@ -84,6 +84,8 @@ Xdmx_SOURCES = dmx.c \ dmxlaunch.h \ dmxcomp.c \ dmxcomp.h \ + dmxxv.c \ + dmxxv.h \ $(top_srcdir)/mi/miinitext.c \ $(top_srcdir)/fb/fbcmap_mi.c \ $(GLX_SRCS) \ diff --git a/hw/dmx/dmx-config.h b/hw/dmx/dmx-config.h index 4948c041f..2cfcd6fd7 100644 --- a/hw/dmx/dmx-config.h +++ b/hw/dmx/dmx-config.h @@ -74,7 +74,6 @@ /* Disable the extensions that are not currently supported */ #undef MULTIBUFFER -#undef XV #undef DBE #undef XF86VIDMODE #undef XFreeXDGA diff --git a/hw/dmx/dmx.h b/hw/dmx/dmx.h index ce1863332..ad364a437 100644 --- a/hw/dmx/dmx.h +++ b/hw/dmx/dmx.h @@ -369,6 +369,11 @@ extern int xRRCrtcsPerScreen; extern DMXPropTrans *dmxPropTrans; extern int dmxPropTransNum; +#ifdef XV +extern char **dmxXvImageFormats; +extern int dmxXvImageFormatsNum; +#endif + /** Wrap screen or GC function pointer */ #define DMX_WRAP(_entry, _newfunc, _saved, _actual) \ do { \ diff --git a/hw/dmx/dmxclient.h b/hw/dmx/dmxclient.h index 8daf817e6..467340977 100644 --- a/hw/dmx/dmxclient.h +++ b/hw/dmx/dmxclient.h @@ -105,6 +105,10 @@ typedef XID KeySym64; #include #endif +#ifdef XV +#include +#endif + #include /* Always include these, since we query them even if we don't export XINPUT. */ diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c index 3d418755e..19dd82579 100644 --- a/hw/dmx/dmxextension.c +++ b/hw/dmx/dmxextension.c @@ -61,6 +61,9 @@ #include "dmxsync.h" #include "dmxscrinit.h" #include "input/dmxinputinit.h" +#ifdef XV +#include "dmxxv.h" +#endif #include "windowstr.h" #include "inputstr.h" /* For DeviceIntRec */ @@ -2433,6 +2436,10 @@ int dmxDetachScreen(int idx) dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx); +#ifdef XV + dmxBEXvScreenFini (screenInfo.screens[idx]); +#endif + /* Detach input */ dmxInputDetachAll(dmxScreen); diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c index a33ab00a0..50a3f236d 100644 --- a/hw/dmx/dmxinit.c +++ b/hw/dmx/dmxinit.c @@ -138,6 +138,11 @@ int xRRCrtcsPerScreen = 2; DMXPropTrans *dmxPropTrans = NULL; int dmxPropTransNum = 0; +#ifdef XV +char **dmxXvImageFormats = NULL; +int dmxXvImageFormatsNum = 0; +#endif + #include static void @@ -1052,11 +1057,6 @@ int ddxProcessArgument(int argc, char *argv[], int i) noPanoramiXExtension = FALSE; PanoramiXExtensionDisabledHack = TRUE; #endif - dmxPropTrans = xalloc (sizeof (DMXPropTrans)); - dmxPropTrans->name = "_COMPIZ_WINDOW_DECOR"; - dmxPropTrans->format = "xP"; - dmxPropTrans->type = 0; - dmxPropTransNum = 1; } if (!strcmp(argv[i], "-display")) { @@ -1186,6 +1186,27 @@ int ddxProcessArgument(int argc, char *argv[], int i) } retval = 3; } +#ifdef XV + else if (!strcmp (argv[i], "-xvimage")) + { + if (++i < argc) + { + char **formats; + + formats = xrealloc (dmxXvImageFormats, + sizeof (char *) * + (dmxXvImageFormatsNum + 1)); + if (formats) + { + formats[dmxXvImageFormatsNum] = argv[i]; + + dmxXvImageFormatsNum++; + dmxXvImageFormats = formats; + } + } + retval = 2; + } +#endif else if ((argv[i][0] == 'v') && (argv[i][1] == 't')) { dmxLaunchVT = argv[i]; @@ -1196,6 +1217,29 @@ int ddxProcessArgument(int argc, char *argv[], int i) retval = argc - i; } + if (i == (argc - 1)) + { + if (!dmxPropTrans) + { + dmxPropTrans = xalloc (sizeof (DMXPropTrans)); + dmxPropTrans->name = "_COMPIZ_WINDOW_DECOR"; + dmxPropTrans->format = "xP"; + dmxPropTrans->type = 0; + dmxPropTransNum = 1; + } + +#ifdef XV + if (!dmxXvImageFormats) + { + dmxXvImageFormats = xalloc (sizeof (char *) * 2); + dmxXvImageFormats[0] = "YV12"; + dmxXvImageFormats[1] = "YUY2"; + dmxXvImageFormatsNum = 2; + } +#endif + + } + if (!serverGeneration) dmxConfigSetMaxScreens(); return retval; } @@ -1241,6 +1285,9 @@ void ddxUseMsg(void) ErrorF("-param ... Specify configuration parameters (e.g.,\n"); ErrorF(" XkbRules, XkbModel, XkbLayout, etc.)\n"); ErrorF("-prop name format Specify property translation\n"); +#ifdef XV + ErrorF("-xvimage fourcc Enable XVideo image format\n"); +#endif ErrorF("\n"); ErrorF(" If the -input string matches a -display string, then input\n" " is taken from that backend display. (XInput cannot be taken\n" diff --git a/hw/dmx/dmxscrinit.c b/hw/dmx/dmxscrinit.c index 39752b97f..f360728b0 100644 --- a/hw/dmx/dmxscrinit.c +++ b/hw/dmx/dmxscrinit.c @@ -70,6 +70,10 @@ #include "randrstr.h" #endif +#ifdef XV +#include "dmxxv.h" +#endif + #include "fb.h" #include "mipointer.h" #include "micmap.h" @@ -1492,6 +1496,10 @@ void dmxBEScreenInit(int idx, ScreenPtr pScreen) RROutputPropertyNotifyMask); #endif +#ifdef XV + dmxBEXvScreenInit (pScreen); +#endif + if (!dmxScreen->beUseRoot) XMapWindow (dmxScreen->beDisplay, dmxScreen->scrnWin); @@ -2216,6 +2224,11 @@ Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[]) return FALSE; #endif +#ifdef XV + if (!dmxXvScreenInit (pScreen)) + return FALSE; +#endif + if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL)) return FALSE; diff --git a/hw/dmx/dmxxv.c b/hw/dmx/dmxxv.c new file mode 100644 index 000000000..03108b0aa --- /dev/null +++ b/hw/dmx/dmxxv.c @@ -0,0 +1,734 @@ +/* + * Copyright © 2008 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#ifdef XV +#include "dmx.h" +#include "dmxsync.h" +#include "dmxgc.h" +#include "dmxwindow.h" +#include "dmxvisual.h" +#include "dmxlog.h" +#include "dmxxv.h" + +#include "xvdix.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "servermd.h" +#include "pixmapstr.h" + +typedef struct _dmxXvAdaptor { + int base; + int n; +} dmxXvAdaptorRec, *dmxXvAdaptorPtr; + +typedef struct _dmxXvPort { + int id; + XvPortID port; + XvImage *image; +} dmxXvPortRec, *dmxXvPortPtr; + +#define DMX_GET_XV_SCREEN(pScreen) \ + ((XvScreenPtr) dixLookupPrivate (&pScreen->devPrivates, \ + XvGetScreenKey ())) + +#define DMX_XV_SCREEN(pScreen) \ + XvScreenPtr pXvScreen = DMX_GET_XV_SCREEN (pScreen) + +#define DMX_GET_XV_ADAPTOR_PRIV(pAdaptor) \ + ((dmxXvAdaptorPtr) ((pAdaptor)->devPriv.ptr)) + +#define DMX_XV_ADAPTOR_PRIV(pAdaptor) \ + dmxXvAdaptorPtr pAdaptorPriv = DMX_GET_XV_ADAPTOR_PRIV (pAdaptor) + +#define DMX_GET_XV_PORT_PRIV(pPort) \ + ((dmxXvPortPtr) ((pPort)->devPriv.ptr)) + +#define DMX_XV_PORT_PRIV(pPort) \ + dmxXvPortPtr pPortPriv = DMX_GET_XV_PORT_PRIV (pPort) + +#define DMX_XV_NUM_PORTS 32 + +#define DMX_XV_IMAGE_MAX_WIDTH 2046 +#define DMX_XV_IMAGE_MAX_HEIGHT 2046 + +#define DMX_FOURCC(a, b, c, d) \ + ((a) | (b) << 8 | (c) << 16 | ((unsigned int) (d)) << 24) + +#define DMX_FOURCC_YUY2 DMX_FOURCC ('Y', 'U', 'Y', '2') +#define DMX_FOURCC_YV12 DMX_FOURCC ('Y', 'V', '1', '2') + +static XvImageRec xvImages[] = { + { + DMX_FOURCC_YUY2, XvYUV, BITMAP_BIT_ORDER, + { + 'Y','U','Y','2', + 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, + 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 + }, + 16, XvPacked, 1, + 0, 0, 0, 0, + 8, 8, 8, 1, 2, 2, 1, 1, 1, + { + 'Y', 'U', 'Y', 'V', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + XvTopToBottom + }, { + DMX_FOURCC_YV12, XvYUV, BITMAP_BIT_ORDER, + { + 'Y', 'V', '1', '2', + 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, + 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 + }, + 12, XvPlanar, 3, + 0, 0, 0, 0, + 8, 8, 8, 1, 2, 2, 1, 2, 2, + { + 'Y', 'V', 'U', 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + XvTopToBottom + } +}; + +static int +dmxXvFreePort (XvPortPtr pPort) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pPort->pAdaptor->pScreen->myNum]; + + DMX_XV_PORT_PRIV (pPort); + + if (pPortPriv->port) + { + XLIB_PROLOGUE (dmxScreen); + XvUngrabPort (dmxScreen->beDisplay, pPortPriv->port, CurrentTime); + XLIB_EPILOGUE (dmxScreen); + + pPortPriv->port = 0; + } + + if (pPortPriv->image) + { + XFree (pPortPriv->image); + pPortPriv->image = NULL; + } + + pPortPriv->id = 0; + + return Success; +} + +static int +dmxXvStopVideo (ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDrawable) +{ + return Success; +} + +static int +dmxSetPortAttribute (ClientPtr client, + XvPortPtr pPort, + Atom atom, + INT32 value) +{ + return BadMatch; +} + +static int +dmxGetPortAttribute (ClientPtr client, + XvPortPtr pPort, + Atom atom, + INT32 *value) +{ + return BadMatch; +} + +static int +dmxXvQueryBestSize (ClientPtr client, + XvPortPtr pPort, + CARD8 motion, + CARD16 srcWidth, + CARD16 srcHeight, + CARD16 dstWidth, + CARD16 dstHeight, + unsigned int *pWidth, + unsigned int *pHeight) +{ + *pWidth = dstWidth; + *pHeight = dstHeight; + + return Success; +} + +static int +dmxXvPutImage (ClientPtr client, + DrawablePtr pDrawable, + XvPortPtr pPort, + GCPtr pGC, + INT16 srcX, + INT16 srcY, + CARD16 srcWidth, + CARD16 srcHeight, + INT16 dstX, + INT16 dstY, + CARD16 dstWidth, + CARD16 dstHeight, + XvImagePtr pImage, + unsigned char *data, + Bool sync, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV ((WindowPtr) pDrawable); + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV (pGC); + + DMX_XV_PORT_PRIV (pPort); + + if (pPortPriv->id != pImage->id) + { + int p, j; + + DMX_XV_ADAPTOR_PRIV (pPort->pAdaptor); + + for (p = pAdaptorPriv->base; + p < pAdaptorPriv->base + pAdaptorPriv->n; + p++) + { + XvImageFormatValues *fo = NULL; + int formats; + + XLIB_PROLOGUE (dmxScreen); + fo = XvListImageFormats (dmxScreen->beDisplay, p, &formats); + XLIB_EPILOGUE (dmxScreen); + + if (fo) + { + for (j = 0; j < formats; j++) + if (fo[j].id == pImage->id) + break; + + XFree (fo); + + if (j < formats) + { + if (p != pPortPriv->port) + { + int ret = !Success; + + XLIB_PROLOGUE (dmxScreen); + ret = XvGrabPort (dmxScreen->beDisplay, + p, + CurrentTime); + XLIB_EPILOGUE (dmxScreen); + + if (ret == Success) + break; + } + else + break; + } + + } + } + + pPortPriv->id = pImage->id; + + if (pPortPriv->image) + { + XFree (pPortPriv->image); + pPortPriv->image = NULL; + } + + if (pPortPriv->port && p != pPortPriv->port) + { + XLIB_PROLOGUE (dmxScreen); + XvUngrabPort (dmxScreen->beDisplay, pPortPriv->port, CurrentTime); + XLIB_EPILOGUE (dmxScreen); + + pPortPriv->port = 0; + } + + if (p < pAdaptorPriv->base + pAdaptorPriv->n) + { + pPortPriv->port = p; + } + else if (pAdaptorPriv->n) + { + dmxLog (dmxWarning, + "XVIDEO: failed to allocated port " + "for image format: 0x%x\n", pImage->id); + } + } + else if (pPortPriv->image) + { + if (width != pPortPriv->image->width || + height != pPortPriv->image->height) + { + XFree (pPortPriv->image); + pPortPriv->image = NULL; + } + } + + if (!pPortPriv->image && pPortPriv->port) + { + XLIB_PROLOGUE (dmxScreen); + pPortPriv->image = XvCreateImage (dmxScreen->beDisplay, + pPortPriv->port, + pImage->id, + NULL, + width, + height); + XLIB_EPILOGUE (dmxScreen); + + if (!pPortPriv->image) + return BadAlloc; + + dmxLogOutput (dmxScreen, + "XVIDEO: created 0x%x image with dimensions %dx%d\n", + pImage->id, width, height); + } + + if (pPortPriv->image) + { + pPortPriv->image->data = (char *) data; + + XLIB_PROLOGUE (dmxScreen); + XvPutImage (dmxScreen->beDisplay, + pPortPriv->port, + pWinPriv->window, + pGCPriv->gc, + pPortPriv->image, + srcX, srcY, srcWidth, srcHeight, + dstX, dstY, dstWidth, dstHeight); + XLIB_EPILOGUE (dmxScreen); + + dmxSync (dmxScreen, FALSE); + } + + return Success; +} + +static int +dmxXvQueryImageAttributes (ClientPtr client, + XvPortPtr pPort, + XvImagePtr pImage, + CARD16 *width, + CARD16 *height, + int *pitches, + int *offsets) +{ + if (*width > DMX_XV_IMAGE_MAX_WIDTH) + *width = DMX_XV_IMAGE_MAX_WIDTH; + + if (*height > DMX_XV_IMAGE_MAX_HEIGHT) + *height = DMX_XV_IMAGE_MAX_HEIGHT; + + *width = (*width + 7) & ~7; + + switch (pImage->id) { + case DMX_FOURCC_YUY2: + if (offsets) + offsets[0] = 0; + + if (pitches) + pitches[0] = *width * 2; + + return *width * *height * 2; + case DMX_FOURCC_YV12: + *height = (*height + 1) & ~1; + + if (offsets) + { + offsets[0] = 0; + offsets[1] = *width * *height; + offsets[2] = *width * *height + (*width >> 1) * (*height >> 1); + } + + if (pitches) + { + pitches[0] = *width; + pitches[1] = pitches[2] = *width >> 1; + } + + return *width * *height + (*width >> 1) * *height; + default: + return 0; + } +} + +static void +dmxXvFreeAdaptor (XvAdaptorPtr pAdaptor) +{ + xfree (pAdaptor->pEncodings); + xfree (pAdaptor->pFormats); + + if (pAdaptor->pPorts) + xfree (pAdaptor->pPorts); +} + +static Bool +dmxXvInitAdaptors (ScreenPtr pScreen) +{ + dmxXvAdaptorPtr pAdaptorPriv; + XvAdaptorPtr pAdaptor; + dmxXvPortPtr pPortPriv; + XvPortPtr pPort; + XvFormatPtr pFormat; + XvEncodingPtr pEncoding; + XvImagePtr pImages; + int i, j, nImages = 0; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + DMX_XV_SCREEN (pScreen); + + pXvScreen->nAdaptors = 0; + pXvScreen->pAdaptors = NULL; + + pImages = xalloc (sizeof (xvImages)); + if (!pImages) + return FALSE; + + for (i = 0; i < dmxXvImageFormatsNum; i++) + { + for (j = 0; j < sizeof (xvImages) / sizeof (XvImageRec); j++) + { + char imageName[5]; + + sprintf (imageName, "%c%c%c%c", + xvImages[j].id & 0xff, + (xvImages[j].id >> 8) & 0xff, + (xvImages[j].id >> 16) & 0xff, + (xvImages[j].id >> 24) & 0xff); + + if (strcmp (imageName, dmxXvImageFormats[i]) == 0 || + strtol (dmxXvImageFormats[i], NULL, 0) == xvImages[j].id) + { + dmxLogOutput (dmxScreen, "XVIDEO: using image format: \n"); + dmxLogOutput (dmxScreen," id: 0x%x", xvImages[j].id); + if (isprint (imageName[0]) && isprint (imageName[1]) && + isprint (imageName[2]) && isprint (imageName[3])) + dmxLogOutputCont (dmxScreen, " (%s)\n", imageName); + else + dmxLogOutputCont (dmxScreen, "\n", imageName); + + dmxLogOutput (dmxScreen, " bits per pixel: %i\n", + xvImages[j].bits_per_pixel); + dmxLogOutput (dmxScreen, " number of planes: %i\n", + xvImages[j].num_planes); + + dmxLogOutput (dmxScreen, " type: %s (%s)\n", + (xvImages[j].type == XvRGB) ? "RGB" : "YUV", + (xvImages[j].format == XvPacked) ? + "packed" : "planar"); + + if (xvImages[j].type == XvRGB) + { + dmxLogOutput (dmxScreen, " depth: %i\n", + xvImages[j].depth); + dmxLogOutput (dmxScreen, + " red, green, blue masks: " + "0x%x, 0x%x, 0x%x\n", + xvImages[j].red_mask, + xvImages[j].green_mask, + xvImages[j].blue_mask); + } + + pImages[nImages++] = xvImages[j]; + break; + } + } + + if (j == sizeof (xvImages) / sizeof (XvImageRec)) + { + dmxLogOutput (dmxScreen, + "XVIDEO: unsupported image format %s\n", + dmxXvImageFormats[i]); + } + } + + if (!nImages) + { + dmxLogOutput (dmxScreen, "XVIDEO: no supported image formats " + "enabled\n"); + xfree (pImages); + return TRUE; + } + + pAdaptor = Xcalloc (1, sizeof (XvAdaptorRec) + sizeof (dmxXvAdaptorRec)); + pAdaptorPriv = (dmxXvAdaptorPtr) (pAdaptor + 1); + if (!pAdaptor) + return FALSE; + + pAdaptor->type = XvInputMask | XvImageMask; + pAdaptor->pScreen = pScreen; + + pAdaptor->ddFreePort = dmxXvFreePort; + pAdaptor->ddStopVideo = dmxXvStopVideo; + pAdaptor->ddSetPortAttribute = dmxSetPortAttribute; + pAdaptor->ddGetPortAttribute = dmxGetPortAttribute; + pAdaptor->ddPutImage = dmxXvPutImage; + pAdaptor->ddQueryBestSize = dmxXvQueryBestSize; + pAdaptor->ddQueryImageAttributes = dmxXvQueryImageAttributes; + + pAdaptor->name = "DMX Video"; + + pEncoding = Xcalloc (1, sizeof (XvEncodingRec)); + if (!pEncoding) + return FALSE; + + pEncoding->id = 0; + pEncoding->pScreen = pScreen; + pEncoding->name = "XV_IMAGE"; + + pEncoding->width = DMX_XV_IMAGE_MAX_WIDTH; + pEncoding->height = DMX_XV_IMAGE_MAX_HEIGHT; + + pEncoding->rate.numerator = 1; + pEncoding->rate.denominator = 1; + + pAdaptor->nEncodings = 1; + pAdaptor->pEncodings = pEncoding; + + pAdaptor->nImages = nImages; + pAdaptor->pImages = pImages; + + pAdaptor->nAttributes = 0; + pAdaptor->pAttributes = 0; + + pFormat = Xcalloc (1, sizeof (XvFormatRec)); + if (!pFormat) + return FALSE; + + pFormat->depth = pScreen->rootDepth; + pFormat->visual = pScreen->rootVisual; + + pAdaptor->nFormats = 1; + pAdaptor->pFormats = pFormat; + + pPort = Xcalloc (DMX_XV_NUM_PORTS, + sizeof (XvPortRec) + sizeof (dmxXvPortRec)); + pPortPriv = (dmxXvPortPtr) (pPort + DMX_XV_NUM_PORTS); + if (!pPort) + return FALSE; + + for (i = 0; i < DMX_XV_NUM_PORTS; i++) + { + pPort[i].id = FakeClientID (0); + + if (!AddResource (pPort[i].id, XvGetRTPort (), &pPort[i])) + return FALSE; + + pPort[i].pAdaptor = pAdaptor; + pPort[i].pNotify = (XvPortNotifyPtr) 0; + pPort[i].pDraw = (DrawablePtr) 0; + pPort[i].client = (ClientPtr) 0; + pPort[i].grab.client = (ClientPtr) 0; + pPort[i].time = currentTime; + pPort[i].devPriv.ptr = pPortPriv + i; + } + + pAdaptor->nPorts = DMX_XV_NUM_PORTS; + pAdaptor->pPorts = pPort; + pAdaptor->base_id = pPort->id; + pAdaptor->devPriv.ptr = pAdaptorPriv; + + pXvScreen->pAdaptors = pAdaptor; + pXvScreen->nAdaptors = 1; + + return TRUE; +} + +static Bool +dmxXvCloseScreen (int i, ScreenPtr pScreen) +{ + int j; + + DMX_XV_SCREEN (pScreen); + + for (j = 0; j < pXvScreen->nAdaptors; j++) + dmxXvFreeAdaptor (&pXvScreen->pAdaptors[j]); + + if (pXvScreen->pAdaptors) + xfree (pXvScreen->pAdaptors); + + return TRUE; +} + +static int +dmxXvQueryAdaptors (ScreenPtr pScreen, + XvAdaptorPtr *pAdaptors, + int *nAdaptors) +{ + DMX_XV_SCREEN (pScreen); + + *nAdaptors = pXvScreen->nAdaptors; + *pAdaptors = pXvScreen->pAdaptors; + + return Success; +} + +void +dmxBEXvScreenInit (ScreenPtr pScreen) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + XvAdaptorInfo *ai; + unsigned int nAdaptors; + int i, j, k, l, ret = !Success; + + DMX_XV_SCREEN (pScreen); + + XLIB_PROLOGUE (dmxScreen); + ret = XvQueryAdaptors (dmxScreen->beDisplay, + DefaultRootWindow (dmxScreen->beDisplay), + &nAdaptors, + &ai); + XLIB_EPILOGUE (dmxScreen); + + if (ret != Success) + { + dmxLogOutput (dmxScreen, + "XVIDEO: back-end support unavailable. " + "XvQueryAdaptors returned %d\n", + ret); + return; + } + + for (i = 0; i < pXvScreen->nAdaptors; i++) + { + XvAdaptorPtr pAdaptor = &pXvScreen->pAdaptors[i]; + + DMX_XV_ADAPTOR_PRIV (pAdaptor); + + for (j = 0; j < nAdaptors; j++) + { + if ((pAdaptor->type & ai[j].type) != pAdaptor->type) + continue; + + for (k = 0; k < pAdaptor->nFormats; k++) + { + Visual *visual; + VisualID vid; + int depth = pAdaptor->pFormats[k].depth; + + visual = dmxLookupVisualFromID (pScreen, + pAdaptor->pFormats[k].visual); + if (visual) + vid = XVisualIDFromVisual (visual); + else + vid = 0; + + for (l = 0; l < ai[j].num_formats; l++) + { + if (ai[j].formats[l].depth == depth && + ai[j].formats[l].visual_id == vid) + break; + } + + if (l == ai[j].num_formats) + break; + } + + if (k < pAdaptor->nFormats) + continue; + + dmxLogOutput (dmxScreen, + "XVIDEO: Using back-end adaptor:\n" + " name: %s\n" + " type: %s%s%s%s%s\n" + " ports: %ld\n" + " first port: %ld\n", + ai[j].name, + (ai[j].type & XvInputMask) ? "input | " : "", + (ai[j].type & XvOutputMask) ? "output | " : "", + (ai[j].type & XvVideoMask) ? "video | " : "", + (ai[j].type & XvStillMask) ? "still | " : "", + (ai[j].type & XvImageMask) ? "image" : "", + ai[j].num_ports, + ai[j].base_id); + + pAdaptorPriv->base = ai[j].base_id; + pAdaptorPriv->n = ai[j].num_ports; + break; + } + + if (j == nAdaptors) + dmxLogOutput (dmxScreen, "XVIDEO: No usable back-end adaptors " + "found for '%s'\n", pAdaptor->name); + } + + if (nAdaptors > 0) + XvFreeAdaptorInfo (ai); +} + +void +dmxBEXvScreenFini (ScreenPtr pScreen) +{ + int i, j; + + DMX_XV_SCREEN (pScreen); + + for (i = 0; i < pXvScreen->nAdaptors; i++) + { + DMX_XV_ADAPTOR_PRIV (&pXvScreen->pAdaptors[i]); + + for (j = 0; j < pXvScreen->pAdaptors[i].nPorts; j++) + dmxXvFreePort (&pXvScreen->pAdaptors[i].pPorts[j]); + + pAdaptorPriv->base = 0; + pAdaptorPriv->n = 0; + } +} + +Bool +dmxXvScreenInit (ScreenPtr pScreen) +{ + XvScreenPtr pXvScreen; + int status; + + status = XvScreenInit (pScreen); + if (status != Success) + return FALSE; + + pXvScreen = DMX_GET_XV_SCREEN (pScreen); + pXvScreen->ddCloseScreen = dmxXvCloseScreen; + pXvScreen->ddQueryAdaptors = dmxXvQueryAdaptors; + pXvScreen->devPriv.ptr = (pointer) 0; + + if (!dmxXvInitAdaptors (pScreen)) + return FALSE; + + return TRUE; +} + +#endif diff --git a/hw/dmx/dmxxv.h b/hw/dmx/dmxxv.h new file mode 100644 index 000000000..06c71adab --- /dev/null +++ b/hw/dmx/dmxxv.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2008 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman + */ + +#ifndef DMXXV_H +#define DMXXV_H + +extern Bool dmxXvScreenInit (ScreenPtr pScreen); +extern void dmxBEXvScreenInit (ScreenPtr pScreen); +extern void dmxBEXvScreenFini (ScreenPtr pScreen); + +#endif /* DMXXV_H */ + +