XVideo improvements

This commit is contained in:
David Reveman 2006-04-13 13:44:32 +00:00
parent eb16fa5323
commit 5e4ef5afc5
8 changed files with 172 additions and 26 deletions

View file

@ -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.

View file

@ -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

View file

@ -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 } },

View file

@ -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

View file

@ -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 } },

View file

@ -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;

View file

@ -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)

View file

@ -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,