summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Reveman <c99drn@cs.umu.se>2006-04-13 13:44:32 +0000
committerDavid Reveman <c99drn@cs.umu.se>2006-04-13 13:44:32 +0000
commit5e4ef5afc5247a5f1e4512af3dd8b8da6ce609cc (patch)
tree15cf08e1d199dccffdc337a00913e557f13e9548
parenteb16fa53237549d6a1a96abd355699439339ca9e (diff)
XVideo improvements
-rw-r--r--ChangeLog14
-rw-r--r--hw/xgl/egl/xeglinit.c9
-rw-r--r--hw/xgl/glx/xglxinit.c2
-rw-r--r--hw/xgl/xgl.h5
-rw-r--r--hw/xgl/xglinit.c2
-rw-r--r--hw/xgl/xglparse.c30
-rw-r--r--hw/xgl/xglscreen.c2
-rw-r--r--hw/xgl/xglxv.c134
8 files changed, 172 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index eb0336b70..f30d77c11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2006-04-13 David Reveman <davidr@novell.com>
+ * hw/xgl/xglparse.c (xglProcessArgument, xglUseMsg):
+ * hw/xgl/xglxv.c:
+ * hw/xgl/egl/xeglinit.c:
+ * hw/xgl/glx/xglxinit.c:
+ * hw/xgl/xglinit.c:
+ * hw/xgl/xglscreen.c (xglScreenInit):
+ * hw/xgl/xgl.h: Add xvfilter and noyuv options. xvfilter can be used
+ to set the filter used for XVideo, currently available filters are
+ nearest and linear (default is linear). Nearest filter can improve
+ performance signifcantly when XVideo isn't accelerated. noyuv
+ option can be used to force use of software YUV to RGB conversions,
+ which can improve performance when GL_ARB_fragment_program support
+ isn't fast enough.
+
* fb/fbpict.c (fbComposite):
* fb/fbmmx.h:
* fb/fbmmx.c: Add fast YUV conversion code.
diff --git a/hw/xgl/egl/xeglinit.c b/hw/xgl/egl/xeglinit.c
index 7547a6a46..372b232a9 100644
--- a/hw/xgl/egl/xeglinit.c
+++ b/hw/xgl/egl/xeglinit.c
@@ -32,7 +32,14 @@ static xglScreenInfoRec xglScreenInfo = {
FALSE,
XGL_DEFAULT_PBO_MASK,
FALSE,
- FALSE
+ FALSE,
+ FilterBilinear,
+ {
+ { FALSE, FALSE, { 0, 0, 0, 0 } },
+ { FALSE, FALSE, { 0, 0, 0, 0 } },
+ { FALSE, FALSE, { 0, 0, 0, 0 } },
+ { FALSE, FALSE, { 0, 0, 0, 0 } }
+ }
};
#ifdef GLXEXT
diff --git a/hw/xgl/glx/xglxinit.c b/hw/xgl/glx/xglxinit.c
index 4de4ae668..a1fdb9853 100644
--- a/hw/xgl/glx/xglxinit.c
+++ b/hw/xgl/glx/xglxinit.c
@@ -33,6 +33,8 @@ xglScreenInfoRec xglScreenInfo = {
FALSE,
XGL_DEFAULT_PBO_MASK,
FALSE,
+ FALSE,
+ FilterBilinear,
{
{ FALSE, FALSE, { 0, 0, 0, 0 } },
{ FALSE, FALSE, { 0, 0, 0, 0 } },
diff --git a/hw/xgl/xgl.h b/hw/xgl/xgl.h
index cd4cec162..2a841bdbf 100644
--- a/hw/xgl/xgl.h
+++ b/hw/xgl/xgl.h
@@ -102,6 +102,8 @@ typedef struct _xglScreenInfo {
Bool yInverted;
int pboMask;
Bool lines;
+ Bool noYuv;
+ char *xvFilter;
xglScreenAccelInfoRec accel;
} xglScreenInfoRec, *xglScreenInfoPtr;
@@ -255,6 +257,8 @@ typedef struct _xglScreen {
Bool yInverted;
int pboMask;
Bool lines;
+ Bool noYuv;
+ char *xvFilter;
xglGeometryRec scratchGeometry;
xglScreenAccelInfoRec accel;
@@ -372,6 +376,7 @@ typedef struct _xglXvPort {
PixmapPtr pPixmap;
PicturePtr pSrc;
PicturePtr pDst;
+ PicturePtr pTmp;
} xglXvPortRec, *xglXvPortPtr;
#endif
diff --git a/hw/xgl/xglinit.c b/hw/xgl/xglinit.c
index a016a16dc..50b374d2d 100644
--- a/hw/xgl/xglinit.c
+++ b/hw/xgl/xglinit.c
@@ -44,6 +44,8 @@ xglScreenInfoRec xglScreenInfo = {
FALSE,
XGL_DEFAULT_PBO_MASK,
FALSE,
+ FALSE,
+ FilterBilinear,
{
{ FALSE, FALSE, { 0, 0, 0, 0 } },
{ FALSE, FALSE, { 0, 0, 0, 0 } },
diff --git a/hw/xgl/xglparse.c b/hw/xgl/xglparse.c
index 5292692a4..e3e3028c4 100644
--- a/hw/xgl/xglparse.c
+++ b/hw/xgl/xglparse.c
@@ -188,6 +188,13 @@ xglUseMsg (void)
ErrorF ("-yinverted Y is upside-down\n");
ErrorF ("-lines "
"accelerate lines that are not vertical or horizontal\n");
+ ErrorF ("-noyuv "
+ "turns off hardware color-space conversion of YUV data\n");
+
+#ifdef XV
+ ErrorF ("-xvfilter [nearest|linear] set xvideo filter\n");
+#endif
+
ErrorF ("-vbo "
"use vertex buffer objects for streaming of vertex data\n");
ErrorF ("-pbomask [1|4|8|16|32] "
@@ -225,6 +232,29 @@ xglProcessArgument (int argc,
xglScreenInfo.lines = TRUE;
return 1;
}
+ else if (!strcmp (argv[i], "-noyuv"))
+ {
+ xglScreenInfo.noYuv = TRUE;
+ return 1;
+ }
+
+#ifdef XV
+ else if (!strcmp (argv[i], "-xvfilter"))
+ {
+ if ((i + 1) < argc)
+ {
+ if (!strcasecmp (argv[i + 1], "nearest"))
+ xglScreenInfo.xvFilter = FilterNearest;
+ else if (!strcasecmp (argv[i + 1], "linear"))
+ xglScreenInfo.xvFilter = FilterBilinear;
+ }
+ else
+ return 1;
+
+ return 2;
+ }
+#endif
+
else if (!strcmp (argv[i], "-vbo"))
{
xglScreenInfo.geometryUsage = GEOMETRY_USAGE_STREAM;
diff --git a/hw/xgl/xglscreen.c b/hw/xgl/xglscreen.c
index 4bd86c18f..b7d7b2db9 100644
--- a/hw/xgl/xglscreen.c
+++ b/hw/xgl/xglscreen.c
@@ -173,6 +173,8 @@ xglScreenInit (ScreenPtr pScreen)
pScreenPriv->yInverted = xglScreenInfo.yInverted;
pScreenPriv->pboMask = xglScreenInfo.pboMask;
pScreenPriv->lines = xglScreenInfo.lines;
+ pScreenPriv->noYuv = xglScreenInfo.noYuv;
+ pScreenPriv->xvFilter = xglScreenInfo.xvFilter;
pScreenPriv->accel = xglScreenInfo.accel;
if (monitorResolution)
diff --git a/hw/xgl/xglxv.c b/hw/xgl/xglxv.c
index aaa66c738..faef674c4 100644
--- a/hw/xgl/xglxv.c
+++ b/hw/xgl/xglxv.c
@@ -200,6 +200,12 @@ xglXvFreePort (XvPortPtr pPort)
pPortPriv->pSrc = (PicturePtr) 0;
}
+ if (pPortPriv->pTmp)
+ {
+ FreePicture ((pointer) pPortPriv->pTmp, 0);
+ pPortPriv->pTmp = (PicturePtr) 0;
+ }
+
if (pPortPriv->pPixmap)
{
ScreenPtr pScreen;
@@ -239,6 +245,37 @@ xglXvStopVideo (ClientPtr client,
return Success;
}
+static PicturePtr
+xglXvCreateDstPict (DrawablePtr pDrawable,
+ Mask vmask,
+ XID *vlist,
+ int *error)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ PictFormatPtr pFormat = 0;
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ {
+ if (pScreen->visuals[i].nplanes == pDrawable->depth)
+ {
+ pFormat = PictureMatchVisual (pScreen, pDrawable->depth,
+ &pScreen->visuals[i]);
+ break;
+ }
+ }
+
+ if (!pFormat)
+ {
+ *error = BadImplementation;
+ return (PicturePtr) 0;
+ }
+
+ return CreatePicture (0, pDrawable,
+ pFormat, vmask, vlist, serverClient,
+ error);
+}
+
static int
xglXvPutImage (ClientPtr client,
DrawablePtr pDrawable,
@@ -259,8 +296,9 @@ xglXvPutImage (ClientPtr client,
CARD16 height)
{
ScreenPtr pScreen = pDrawable->pScreen;
+ PicturePtr pSrc;
PictTransform transform;
- int depth, bpp;
+ int depth, bpp, noVisual = FALSE;
CARD32 format;
XGL_SCREEN_PRIV (pScreen);
@@ -272,10 +310,12 @@ xglXvPutImage (ClientPtr client,
case GLITZ_FOURCC_YUY2:
bpp = depth = 16;
format = PICT_yuy2;
+ noVisual = !pScreenPriv->pXvVisual[XGL_XV_FORMAT_YUY2].format.surface;
break;
case GLITZ_FOURCC_YV12:
depth = bpp = 12;
format = PICT_yv12;
+ noVisual = !pScreenPriv->pXvVisual[XGL_XV_FORMAT_YV12].format.surface;
break;
case GLITZ_FOURCC_RGB:
depth = 24;
@@ -326,34 +366,21 @@ xglXvPutImage (ClientPtr client,
}
SetPictureFilter (pPortPriv->pSrc,
- FilterBilinear, strlen (FilterBilinear),
+ pScreenPriv->xvFilter,
+ strlen (pScreenPriv->xvFilter),
0, 0);
}
+ pSrc = pPortPriv->pSrc;
+
if (!pPortPriv->pDst || pPortPriv->pDst->pDrawable != pDrawable)
{
- PictFormatPtr pFormat = 0;
- int i, error;
-
- for (i = 0; i < pScreen->numVisuals; i++)
- {
- if (pScreen->visuals[i].nplanes == pDrawable->depth)
- {
- pFormat = PictureMatchVisual (pScreen, pDrawable->depth,
- &pScreen->visuals[i]);
- break;
- }
- }
-
- if (!pFormat)
- return BadImplementation;
+ int error;
if (pPortPriv->pDst)
FreePicture ((pointer) pPortPriv->pDst, 0);
- pPortPriv->pDst = CreatePicture (0, pDrawable,
- pFormat, 0, 0, serverClient,
- &error);
+ pPortPriv->pDst = xglXvCreateDstPict (pDrawable, 0, NULL, &error);
if (!pPortPriv->pDst)
{
xglXvFreePort (pPort);
@@ -361,6 +388,66 @@ xglXvPutImage (ClientPtr client,
}
}
+ if (pPixmap != pScreenPriv->pScreenPixmap && !pPixmapPriv->target)
+ xglEnablePixmapAccel (pPixmap, &pScreenPriv->accel.xv);
+
+ /* software color-space conversion */
+ if (pPixmapPriv->target && (noVisual || pScreenPriv->noYuv))
+ {
+ if (!pPortPriv->pTmp ||
+ srcWidth != pPortPriv->pTmp->pDrawable->width ||
+ srcHeight != pPortPriv->pTmp->pDrawable->height)
+ {
+ static XID value = RepeatPad;
+ int error;
+
+ if (pPortPriv->pTmp)
+ FreePicture ((pointer) pPortPriv->pTmp, 0);
+
+ pPixmap = (*pScreen->CreatePixmap) (pScreen,
+ srcWidth, srcHeight,
+ pDrawable->depth);
+ if (!pPixmap)
+ {
+ xglXvFreePort (pPort);
+ return BadAlloc;
+ }
+
+ pPortPriv->pTmp = xglXvCreateDstPict (&pPixmap->drawable,
+ CPRepeat, &value,
+ &error);
+ if (!pPortPriv->pTmp)
+ {
+ (*pScreen->DestroyPixmap) (pPixmap);
+ xglXvFreePort (pPort);
+ return error;
+ }
+
+ /* no accelerated drawing */
+ XGL_GET_PIXMAP_PRIV (pPixmap)->target = xglPixmapTargetNo;
+
+ (*pScreen->DestroyPixmap) (pPixmap);
+
+ SetPictureFilter (pPortPriv->pTmp,
+ pScreenPriv->xvFilter,
+ strlen (pScreenPriv->xvFilter),
+ 0, 0);
+ }
+
+ SetPictureTransform (pSrc, 0);
+
+ CompositePicture (PictOpSrc,
+ pSrc,
+ (PicturePtr) 0,
+ pPortPriv->pTmp,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ srcWidth, srcHeight);
+
+ pSrc = pPortPriv->pTmp;
+ }
+
transform.matrix[0][0] = ((srcWidth << 16) + (dstWidth >> 1))
/ dstWidth;
transform.matrix[0][1] = 0;
@@ -376,13 +463,10 @@ xglXvPutImage (ClientPtr client,
transform.matrix[2][1] = 0;
transform.matrix[2][2] = 1 << 16;
- SetPictureTransform (pPortPriv->pSrc, &transform);
-
- if (pPixmap != pScreenPriv->pScreenPixmap && !pPixmapPriv->target)
- xglEnablePixmapAccel (pPixmap, &pScreenPriv->accel.xv);
+ SetPictureTransform (pSrc, &transform);
CompositePicture (PictOpSrc,
- pPortPriv->pSrc,
+ pSrc,
(PicturePtr) 0,
pPortPriv->pDst,
srcX, srcY,