summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2012-01-22 18:38:24 -0600
committerRob Clark <rob@ti.com>2012-01-23 22:39:04 +0000
commit447d4134017d4c390a97a82e232150bc34173407 (patch)
tree7c5e7376eed1dbfdeb2bafeccb96ba4ab34b6389
parent60f5bad81b5632d32b2f64be0909cf664f56fe7e (diff)
add XV support
Not really the best way to do video, because it forces a copy on server side, but still useful for legacy apps that aren't fully supporting hw decode and render.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/omap_driver.c8
-rw-r--r--src/omap_driver.h38
-rw-r--r--src/omap_exa.h10
-rw-r--r--src/omap_exa_utils.c135
-rw-r--r--src/omap_xv.c470
6 files changed, 663 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index dea0e6e..efe151a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,5 +45,7 @@ omap_drv_la_SOURCES = \
drmmode_display.c \
omap_exa.c \
omap_exa_null.c \
+ omap_exa_utils.c \
+ omap_xv.c \
omap_dri2.c \
omap_driver.c
diff --git a/src/omap_driver.c b/src/omap_driver.c
index 3d8b412..f7d4944 100644
--- a/src/omap_driver.c
+++ b/src/omap_driver.c
@@ -670,6 +670,12 @@ OMAPAccelInit(ScreenPtr pScreen)
} else {
pOMAP->dri = FALSE;
}
+
+ if (OMAPVideoScreenInit(pScreen)) {
+ INFO_MSG("Initialized XV");
+ } else {
+ ERROR_MSG("Could not initialize XV");
+ }
}
/**
@@ -877,6 +883,8 @@ OMAPCloseScreen(int scrnIndex, ScreenPtr pScreen)
OMAPDRI2CloseScreen(pScreen);
}
+ OMAPVideoCloseScreen(pScreen);
+
OMAPUnmapMem(pScrn);
pScrn->vtSema = FALSE;
diff --git a/src/omap_driver.h b/src/omap_driver.h
index d4beaef..be5d3d1 100644
--- a/src/omap_driver.h
+++ b/src/omap_driver.h
@@ -156,12 +156,22 @@ typedef struct _OMAPRec
/** Pointer to the entity structure for this screen. */
EntityInfoPtr pEntityInfo;
+ XF86VideoAdaptorPtr textureAdaptor;
+
} OMAPRec, *OMAPPtr;
/*
* Misc utility macros:
*/
+/* do we support video? */
+static inline Bool has_video(OMAPPtr pOMAP)
+{
+ return pOMAP->pOMAPEXA &&
+ pOMAP->pOMAPEXA->GetFormats &&
+ pOMAP->pOMAPEXA->PutTextureImage;
+}
+
/** Return a pointer to the driver's private structure. */
#define OMAPPTR(p) ((OMAPPtr)((p)->driverPrivate))
#define OMAPPTR_FROM_SCREEN(pScreen) \
@@ -188,6 +198,12 @@ typedef struct _OMAPRec
b = tmp; \
}
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
+#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
+
+
/**
* drmmode functions..
*/
@@ -208,4 +224,26 @@ Bool OMAPDRI2ScreenInit(ScreenPtr pScreen);
void OMAPDRI2CloseScreen(ScreenPtr pScreen);
void OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd);
+/**
+ * XV functions..
+ */
+Bool OMAPVideoScreenInit(ScreenPtr pScreen);
+void OMAPVideoCloseScreen(ScreenPtr pScreen);
+
+/**
+ * EXA util functions.. move to EXA core?
+ */
+
+typedef int (*OMAPPutTextureImageProc)(
+ PixmapPtr pSrcPix, BoxPtr pSrcBox,
+ PixmapPtr pOsdPix, BoxPtr pOsdBox,
+ PixmapPtr pDstPix, BoxPtr pDstBox,
+ void *closure);
+
+Bool OMAPVidCopyArea(DrawablePtr pSrcDraw, BoxPtr pSrcBox,
+ DrawablePtr pOsdDraw, BoxPtr pOsdBox,
+ DrawablePtr pDstDraw, BoxPtr pDstBox,
+ OMAPPutTextureImageProc PutTextureImage, void *closure,
+ RegionPtr clipBoxes);
+
#endif /* __OMAP_DRV_H__ */
diff --git a/src/omap_exa.h b/src/omap_exa.h
index 9ad11df..4dc818d 100644
--- a/src/omap_exa.h
+++ b/src/omap_exa.h
@@ -59,6 +59,16 @@ typedef struct _OMAPEXARec
*/
void (*FreeScreen)(int scrnIndex, int flags);
+ /** get formats supported by PutTextureImage() (for dri2 video..) */
+#define MAX_FORMATS 16
+ unsigned int (*GetFormats)(unsigned int *formats);
+
+ Bool (*PutTextureImage)(PixmapPtr pSrcPix, BoxPtr pSrcBox,
+ PixmapPtr pOsdPix, BoxPtr pOsdBox,
+ PixmapPtr pDstPix, BoxPtr pDstBox,
+ unsigned int extraCount, PixmapPtr *extraPix,
+ unsigned int format);
+
/* add new fields here at end, to preserve ABI */
diff --git a/src/omap_exa_utils.c b/src/omap_exa_utils.c
new file mode 100644
index 0000000..74032b3
--- /dev/null
+++ b/src/omap_exa_utils.c
@@ -0,0 +1,135 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2012 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "omap_driver.h"
+#include "omap_exa.h"
+
+
+/***** move to common helper code?? in EXA or DRI2? *****/
+/* if this is in DRI2, then the driver can't rely on pixmap migration, etc
+ * before PutTextureImage cb is called.. I guess it should be in EXA..
+ */
+#include <pixman.h>
+
+/**
+ * Helper function to implement video blit, handling clipping, damage, etc..
+ *
+ * TODO: move to EXA?
+ */
+int
+OMAPVidCopyArea(DrawablePtr pSrcDraw, BoxPtr pSrcBox,
+ DrawablePtr pOsdDraw, BoxPtr pOsdBox,
+ DrawablePtr pDstDraw, BoxPtr pDstBox,
+ OMAPPutTextureImageProc PutTextureImage, void *closure,
+ RegionPtr clipBoxes)
+{
+ ScreenPtr pScreen = pDstDraw->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ PixmapPtr pSrcPix = draw2pix(pSrcDraw);
+ PixmapPtr pOsdPix = draw2pix(pOsdDraw);
+ PixmapPtr pDstPix = draw2pix(pDstDraw);
+ pixman_fixed_t sx, sy, tx, ty;
+ pixman_transform_t srcxfrm;
+ BoxPtr pbox;
+ int nbox, dx, dy, ret = Success;
+
+#ifdef COMPOSITE
+ DEBUG_MSG("--> %dx%d, %dx%d", pDstPix->screen_x, pDstPix->screen_y,
+ pDstDraw->x, pDstDraw->y);
+ /* Convert screen coords to pixmap coords */
+ if (pDstPix->screen_x || pDstPix->screen_y) {
+ RegionTranslate(clipBoxes, -pDstPix->screen_x, -pDstPix->screen_y);
+ }
+ dx = pDstPix->screen_x;
+ dy = pDstPix->screen_y;
+#else
+ dx = 0;
+ dy = 0;
+#endif
+
+ /* the clip-region gives coordinates in dst's coord space.. generate
+ * a transform that can be used to work backwards from dst->src coord
+ * space:
+ */
+ sx = ((pixman_fixed_48_16_t) (pSrcBox->x2 - pSrcBox->x1) << 16) /
+ (pDstBox->x2 - pDstBox->x1);
+ sy = ((pixman_fixed_48_16_t) (pSrcBox->y2 - pSrcBox->y1) << 16) /
+ (pDstBox->y2 - pDstBox->y1);
+ tx = ((pixman_fixed_48_16_t)(pDstBox->x1 - pSrcBox->x1 - dx) << 16);
+ ty = ((pixman_fixed_48_16_t)(pDstBox->y1 - pSrcBox->y1 - dy) << 16);
+
+ pixman_transform_init_scale(&srcxfrm, sx, sy);
+ pixman_transform_translate(NULL, &srcxfrm, tx, ty);
+
+ // TODO generate transform for osd as well
+
+ pbox = RegionRects(clipBoxes);
+ nbox = RegionNumRects(clipBoxes);
+
+ while (nbox--) {
+ RegionRec damage;
+ BoxRec dstb = *pbox;
+ BoxRec srcb = *pbox;
+ BoxRec osdb = *pbox;
+
+ pixman_transform_bounds(&srcxfrm, &srcb);
+ //pixman_transform_bounds(&osdxfrm, &osdb);
+
+ DEBUG_MSG("%d,%d %d,%d -> %d,%d %d,%d",
+ srcb.x1, srcb.y1, srcb.x2, srcb.y2,
+ dstb.x1, dstb.y1, dstb.x2, dstb.y2);
+
+ ret = PutTextureImage(pSrcPix, &srcb, pOsdPix, &osdb,
+ pDstPix, &dstb, closure);
+ if (ret != Success) {
+ break;
+ }
+
+ RegionInit(&damage, &dstb, 1);
+
+#ifdef COMPOSITE
+ /* Convert screen coords to pixmap coords */
+ if (pDstPix->screen_x || pDstPix->screen_y) {
+ RegionTranslate(&damage, pDstPix->screen_x, pDstPix->screen_y);
+ }
+#endif
+
+ DamageRegionAppend(pDstDraw, &damage);
+ RegionUninit(&damage);
+
+ pbox++;
+ }
+
+ DamageRegionProcessPending(pDstDraw);
+
+ return ret;
+}
diff --git a/src/omap_xv.c b/src/omap_xv.c
new file mode 100644
index 0000000..f4393d6
--- /dev/null
+++ b/src/omap_xv.c
@@ -0,0 +1,470 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2012 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "fourcc.h"
+
+#include "omap_driver.h"
+#include "omap_exa.h"
+
+#define NUM_TEXTURE_PORTS 32 /* this is basically arbitrary */
+
+#define IMAGE_MAX_W 2048
+#define IMAGE_MAX_H 2048
+
+typedef struct {
+ unsigned int format;
+ int nplanes;
+ PixmapPtr pSrcPix[3];
+} OMAPPortPrivRec, *OMAPPortPrivPtr;
+
+
+static XF86VideoEncodingRec OMAPVideoEncoding[] =
+{
+ { 0, (char *)"XV_IMAGE", IMAGE_MAX_W, IMAGE_MAX_H, {1, 1} },
+};
+
+static XF86VideoFormatRec OMAPVideoFormats[] =
+{
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
+ {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
+};
+
+static XF86AttributeRec OMAPVideoTexturedAttributes[] =
+{
+};
+
+static XF86ImageRec OMAPVideoTexturedImages[MAX_FORMATS];
+
+
+
+static PixmapPtr
+setupplane(ScreenPtr pScreen, PixmapPtr pSrcPix, int width, int height,
+ int depth, int srcpitch, int bufpitch, unsigned char **bufp)
+{
+ struct omap_bo *bo;
+ unsigned char *src, *buf = *bufp;
+ int i;
+
+ if (pSrcPix && ((pSrcPix->drawable.height != height) ||
+ (pSrcPix->drawable.width != width))) {
+ pScreen->DestroyPixmap(pSrcPix);
+ pSrcPix = NULL;
+ }
+
+ if (!pSrcPix) {
+ pSrcPix = pScreen->CreatePixmap(pScreen, width, height, depth, 0);
+ }
+
+ bo = OMAPPixmapBo(pSrcPix);
+ omap_bo_cpu_prep(bo, OMAP_GEM_WRITE);
+ src = omap_bo_map(bo);
+
+ /* copy from buf to src pixmap: */
+ for (i = 0; i < height; i++) {
+ memcpy(src, buf, srcpitch);
+ src += srcpitch;
+ buf += bufpitch;
+ }
+
+ omap_bo_cpu_fini(bo, OMAP_GEM_WRITE);
+
+ *bufp = buf;
+
+ return pSrcPix;
+}
+
+static void
+freebufs(ScreenPtr pScreen, OMAPPortPrivPtr pPriv)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(pPriv->pSrcPix); i++) {
+ if (pPriv->pSrcPix[i])
+ pScreen->DestroyPixmap(pPriv->pSrcPix[i]);
+ pPriv->pSrcPix[i] = NULL;
+ }
+}
+
+
+static void
+OMAPVideoStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
+{
+ /* maybe we can deallocate pSrcPix here?? */
+}
+
+static int
+OMAPVideoSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 value, pointer data)
+{
+ return BadMatch;
+}
+
+static int
+OMAPVideoGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 *value, pointer data)
+{
+ return BadMatch;
+}
+
+static void
+OMAPVideoQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data)
+{
+ /* currently no constraints.. */
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+static int OMAPVideoPutTextureImage(
+ PixmapPtr pSrcPix, BoxPtr pSrcBox,
+ PixmapPtr pOsdPix, BoxPtr pOsdBox,
+ PixmapPtr pDstPix, BoxPtr pDstBox,
+ void *closure)
+{
+ ScreenPtr pScreen = pDstPix->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ OMAPPortPrivPtr pPriv = closure;
+ Bool ret;
+
+ DEBUG_MSG("src: %dx%d; %d,%d %d,%d",
+ pSrcPix->drawable.width, pSrcPix->drawable.height,
+ pSrcBox->x1, pSrcBox->y1, pSrcBox->x2, pSrcBox->y2);
+ DEBUG_MSG("dst: %dx%d; %d,%d %d,%d",
+ pDstPix->drawable.width, pDstPix->drawable.height,
+ pDstBox->x1, pDstBox->y1, pDstBox->x2, pDstBox->y2);
+
+ ret = pOMAP->pOMAPEXA->PutTextureImage(pSrcPix, pSrcBox,
+ pOsdPix, pOsdBox, pDstPix, pDstBox,
+ pPriv->nplanes - 1, &pPriv->pSrcPix[1],
+ pPriv->format);
+ if (ret) {
+ return Success;
+ }
+ DEBUG_MSG("PutTextureImage failed");
+
+ return BadImplementation;
+}
+
+/**
+ * The main function for XV, called to blit/scale/colorcvt an image
+ * to it's destination drawable
+ *
+ * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
+ * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
+ * id is a fourcc code for the format of the video.
+ * buf is the pointer to the source data in system memory.
+ * width and height are the w/h of the source data.
+ * If "sync" is TRUE, then we must be finished with *buf at the point of return
+ * (which we always are).
+ * clipBoxes is the clipping region in screen space.
+ * data is a pointer to our port private.
+ * drawable is some Drawable, which might not be the screen in the case of
+ * compositing. It's a new argument to the function in the 1.1 server.
+ */
+static int
+OMAPVideoPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
+ short drw_y, short src_w, short src_h, short drw_w, short drw_h,
+ int id, unsigned char *buf, short width, short height,
+ Bool Sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDstDraw)
+{
+ ScreenPtr pScreen = pDstDraw->pScreen;
+ OMAPPortPrivPtr pPriv = (OMAPPortPrivPtr)data;
+ BoxRec srcb = {
+ .x1 = src_x,
+ .y1 = src_y,
+ .x2 = src_x + src_w,
+ .y2 = src_y + src_h,
+ };
+ BoxRec dstb = {
+ .x1 = drw_x,
+ .y1 = drw_y,
+ .x2 = drw_x + drw_w,
+ .y2 = drw_y + drw_h,
+ };
+ int i, depth, nplanes;
+ int srcpitch1, srcpitch2, bufpitch1, bufpitch2, src_h2, src_w2;
+
+ switch (id) {
+// case FOURCC('N','V','1','2'):
+// break;
+ case FOURCC('Y','V','1','2'):
+ case FOURCC('I','4','2','0'):
+ nplanes = 3;
+ srcpitch1 = ALIGN(src_w, 4);
+ srcpitch2 = ALIGN(src_w / 2, 4);
+ bufpitch1 = ALIGN(width, 4);
+ bufpitch2 = ALIGN(width / 2, 4);
+ depth = 8;
+ src_h2 = src_h / 2;
+ src_w2 = src_w / 2;
+ break;
+ case FOURCC('U','Y','V','Y'):
+ case FOURCC('Y','U','Y','V'):
+ case FOURCC('Y','U','Y','2'):
+ nplanes = 1;
+ srcpitch1 = src_w * 2;
+ bufpitch1 = width * 2;
+ depth = 16;
+ srcpitch2 = bufpitch2 = src_h2 = src_w2 = 0;
+ break;
+ default:
+ ERROR_MSG("unexpected format: %08x (%4.4s)", id, (char *)&id);
+ return BadMatch;
+ }
+
+ if (pPriv->format != id) {
+ freebufs(pScreen, pPriv);
+ }
+
+ pPriv->format = id;
+ pPriv->nplanes = nplanes;
+
+ pPriv->pSrcPix[0] = setupplane(pScreen, pPriv->pSrcPix[0],
+ src_w, src_h, depth, srcpitch1, bufpitch1, &buf);
+
+ for (i = 1; i < pPriv->nplanes; i++) {
+ pPriv->pSrcPix[i] = setupplane(pScreen, pPriv->pSrcPix[i],
+ src_w2, src_h2, depth, srcpitch2, bufpitch2, &buf);
+ }
+
+ /* note: OMAPVidCopyArea() handles the composite-clip, so we can
+ * ignore clipBoxes
+ */
+ return OMAPVidCopyArea(&pPriv->pSrcPix[0]->drawable, &srcb,
+ NULL, NULL, pDstDraw, &dstb,
+ OMAPVideoPutTextureImage, pPriv, clipBoxes);
+}
+
+/**
+ * QueryImageAttributes
+ *
+ * calculates
+ * - size (memory required to store image),
+ * - pitches,
+ * - offsets
+ * of image
+ * depending on colorspace (id) and dimensions (w,h) of image
+ * values of
+ * - w,
+ * - h
+ * may be adjusted as needed
+ *
+ * @param pScrn unused
+ * @param id colorspace of image
+ * @param w pointer to width of image
+ * @param h pointer to height of image
+ * @param pitches pitches[i] = length of a scanline in plane[i]
+ * @param offsets offsets[i] = offset of plane i from the beginning of the image
+ * @return size of the memory required for the XvImage queried
+ */
+static int
+OMAPVideoQueryImageAttributes(ScrnInfoPtr pScrn, int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets)
+{
+ int size, tmp;
+
+ if (*w > IMAGE_MAX_W)
+ *w = IMAGE_MAX_W;
+ if (*h > IMAGE_MAX_H)
+ *h = IMAGE_MAX_H;
+
+ *w = (*w + 1) & ~1; // width rounded up to an even number
+ if (offsets)
+ offsets[0] = 0;
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1; // height rounded up to an even number
+ size = (*w + 3) & ~3; // width rounded up to a multiple of 4
+ if (pitches)
+ pitches[0] = size; // width rounded up to a multiple of 4
+ size *= *h;
+ if (offsets)
+ offsets[1] = size; // number of pixels in "rounded up" image
+ tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4
+ if (pitches)
+ pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4
+ tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image
+ size += tmp; // 5/4*number of pixels in "rounded up" image
+ if (offsets)
+ offsets[2] = size; // 5/4*number of pixels in "rounded up" image
+ size += tmp; // = 3/2*number of pixels in "rounded up" image
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ size = *w << 1; // 2*width
+ if (pitches)
+ pitches[0] = size; // 2*width
+ size *= *h; // 2*width*height
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown colorspace: %x\n", id);
+ *w = *h = size = 0;
+ break;
+ }
+
+ return size;
+}
+
+static XF86VideoAdaptorPtr
+OMAPVideoSetupTexturedVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ OMAPPortPrivPtr pPriv;
+ int i, nformats, nsupported;
+ static unsigned int formats[MAX_FORMATS];
+
+ if (!has_video(pOMAP)) {
+ return NULL;
+ }
+
+ if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
+ sizeof(OMAPPortPrivRec) +
+ (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) {
+ return NULL;
+ }
+
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = 0;
+ adapt->name = (char *)"OMAP Textured Video";
+ adapt->nEncodings = ARRAY_SIZE(OMAPVideoEncoding);
+ adapt->pEncodings = OMAPVideoEncoding;
+ adapt->nFormats = ARRAY_SIZE(OMAPVideoFormats);
+ adapt->pFormats = OMAPVideoFormats;
+ adapt->nPorts = NUM_TEXTURE_PORTS;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+ pPriv = (OMAPPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]);
+ for(i = 0; i < NUM_TEXTURE_PORTS; i++)
+ adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
+
+ adapt->nAttributes = ARRAY_SIZE(OMAPVideoTexturedAttributes);
+ adapt->pAttributes = OMAPVideoTexturedAttributes;
+
+ nformats = pOMAP->pOMAPEXA->GetFormats(formats);
+ nsupported = 0;
+ for (i = 0; i < nformats; i++) {
+ switch (formats[i]) {
+// case FOURCC('N','V','1','2'):
+// break;
+ case FOURCC('Y','V','1','2'):
+ OMAPVideoTexturedImages[nsupported++] =
+ (XF86ImageRec)XVIMAGE_YV12;
+ break;
+ case FOURCC('I','4','2','0'):
+ OMAPVideoTexturedImages[nsupported++] =
+ (XF86ImageRec)XVIMAGE_I420;
+ break;
+ case FOURCC('U','Y','V','Y'):
+ OMAPVideoTexturedImages[nsupported++] =
+ (XF86ImageRec)XVIMAGE_UYVY;
+ break;
+ case FOURCC('Y','U','Y','V'):
+ case FOURCC('Y','U','Y','2'):
+ OMAPVideoTexturedImages[nsupported++] =
+ (XF86ImageRec)XVIMAGE_YUY2;
+ break;
+ default:
+ /* ignore unsupported formats */
+ break;
+ }
+ }
+
+ adapt->nImages = nsupported;
+ adapt->pImages = OMAPVideoTexturedImages;
+
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = OMAPVideoStopVideo;
+ adapt->SetPortAttribute = OMAPVideoSetPortAttribute;
+ adapt->GetPortAttribute = OMAPVideoGetPortAttribute;
+ adapt->QueryBestSize = OMAPVideoQueryBestSize;
+ adapt->PutImage = OMAPVideoPutImage;
+ adapt->QueryImageAttributes = OMAPVideoQueryImageAttributes;
+
+ return adapt;
+}
+
+/**
+ * If EXA implementation supports GetFormats() and PutTextureImage() we can
+ * use that to implement XV. There is a copy involve because we need to
+ * copy the buffer to a texture (TODO possibly we can support wrapping
+ * external buffers, but current EXA submodule API doesn't give us a way to
+ * do that). So for optimal path from hw decoders to display, dri2video
+ * should be used. But this at least helps out legacy apps.
+ */
+Bool
+OMAPVideoScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ XF86VideoAdaptorPtr textureAdaptor =
+ OMAPVideoSetupTexturedVideo(pScreen);
+
+ if (textureAdaptor) {
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors;
+ int n = xf86XVListGenericAdaptors(pScrn, &adaptors);
+ newAdaptors = calloc(n + 1, sizeof(XF86VideoAdaptorPtr *));
+ memcpy(newAdaptors, adaptors, n * sizeof(XF86VideoAdaptorPtr *));
+ pOMAP->textureAdaptor = textureAdaptor;
+ newAdaptors[n] = textureAdaptor;
+ xf86XVScreenInit(pScreen, newAdaptors, n + 1);
+ free(newAdaptors);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+OMAPVideoCloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ if (pOMAP->textureAdaptor) {
+ OMAPPortPrivPtr pPriv = (OMAPPortPrivPtr)
+ pOMAP->textureAdaptor->pPortPrivates[0].ptr;
+ freebufs(pScreen, pPriv);
+ }
+}