From: Rob Clark <r...@ti.com>

TODO:
 + format advertised as I420 appears to actually be NV12
 + add non-fourcc format values for hw decode directly to VRAM
   mapped buffer (skip GART->VRAM move)
 + CSC_MATRIX and OSD support..
---
 src/nouveau_dri2.c    |  214 ++++++++++++++++++++++++++++-----
 src/nouveau_xv.c      |  324 +++++++++++++++++++++++++++++++++++++++----------
 src/nv30_xv_tex.c     |    4 +-
 src/nv40_xv_tex.c     |    4 +-
 src/nv50_xv.c         |    2 +-
 src/nv_accel_common.c |   11 ++
 src/nv_type.h         |    1 +
 src/nvc0_xv.c         |    2 +-
 8 files changed, 459 insertions(+), 103 deletions(-)

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index d14443f..445cd52 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -10,6 +10,10 @@
 #include "dri2.h"
 #endif
 
+// put these somewhere common..
+#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) 
<< 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 ))
+#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
+
 #if defined(DRI2) && DRI2INFOREC_VERSION >= 3
 struct nouveau_dri2_buffer {
        DRI2BufferRec base;
@@ -22,19 +26,87 @@ nouveau_dri2_buffer(DRI2BufferPtr buf)
        return (struct nouveau_dri2_buffer *)buf;
 }
 
-DRI2BufferPtr
-nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment,
-                          unsigned int format)
+static DRI2BufferPtr
+nouveau_dri2_create_buffer_2(DrawablePtr pDraw, unsigned int attachment,
+                  unsigned int format, PixmapPtr ppix)
 {
        ScreenPtr pScreen = pDraw->pScreen;
        NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]);
-       struct nouveau_dri2_buffer *nvbuf;
        struct nouveau_pixmap *nvpix;
-       PixmapPtr ppix;
+       struct nouveau_dri2_buffer *nvbuf;
 
        nvbuf = calloc(1, sizeof(*nvbuf));
-       if (!nvbuf)
+       if (!nvbuf) {
+               // XXX cleanup..
+               return NULL;
+       }
+
+       pNv->exa_force_cp = TRUE;
+       exaMoveInPixmap(ppix);
+       pNv->exa_force_cp = FALSE;
+
+       nvbuf->base.attachment = attachment;
+       nvbuf->base.pitch = ppix->devKind;
+       nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8;
+       nvbuf->base.driverPrivate = nvbuf;
+       nvbuf->base.format = format;
+       nvbuf->base.flags = 0;
+       nvbuf->ppix = ppix;
+
+       nvpix = nouveau_pixmap(ppix);
+       if (!nvpix || !nvpix->bo ||
+           nouveau_bo_handle_get(nvpix->bo, &nvbuf->base.name)) {
+               pScreen->DestroyPixmap(nvbuf->ppix);
+               free(nvbuf);
                return NULL;
+       }
+
+       return &nvbuf->base;
+
+}
+
+static DRI2BufferPtr
+nouveau_dri2_create_buffer_vid(DrawablePtr pDraw, unsigned int attachment,
+                          unsigned int format, unsigned int width, unsigned 
int height)
+{
+       ScreenPtr pScreen = pDraw->pScreen;
+       PixmapPtr ppix;
+       int bpp;
+
+       switch(format) {
+       case FOURCC('I','4','2','0'):
+       case FOURCC('Y','V','1','2'):
+               /* to avoid confusing CreatePixmap too much, call these 1cpp
+                *  and 1.5x height
+                */
+               bpp = 8;
+               height = ((height + 1) & ~1) * 3 / 2;
+               break;
+       case FOURCC('Y','U','Y','2'):
+       case FOURCC('U','Y','V','Y'):
+               bpp = 16;
+               break;
+       case FOURCC('R','G','B','3'):  /* depth=24, bpp=32 */
+       case 24:
+       case FOURCC('R','G','B','4'):  /* depth=32, bpp=32 */
+       case 32:
+               bpp = 32;
+               break;
+       default:
+               return NULL;
+       }
+
+       ppix = pScreen->CreatePixmap(pScreen, width, height, bpp, 
NOUVEAU_CREATE_PIXMAP_VIDEO);
+
+       return nouveau_dri2_create_buffer_2(pDraw, attachment, format, ppix);
+}
+
+DRI2BufferPtr
+nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment,
+                          unsigned int format)
+{
+       ScreenPtr pScreen = pDraw->pScreen;
+       PixmapPtr ppix;
 
        if (attachment == DRI2BufferFrontLeft) {
                if (pDraw->type == DRAWABLE_PIXMAP) {
@@ -59,27 +131,7 @@ nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int 
attachment,
                                             usage_hint);
        }
 
-       pNv->exa_force_cp = TRUE;
-       exaMoveInPixmap(ppix);
-       pNv->exa_force_cp = FALSE;
-
-       nvbuf->base.attachment = attachment;
-       nvbuf->base.pitch = ppix->devKind;
-       nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8;
-       nvbuf->base.driverPrivate = nvbuf;
-       nvbuf->base.format = format;
-       nvbuf->base.flags = 0;
-       nvbuf->ppix = ppix;
-
-       nvpix = nouveau_pixmap(ppix);
-       if (!nvpix || !nvpix->bo ||
-           nouveau_bo_handle_get(nvpix->bo, &nvbuf->base.name)) {
-               pScreen->DestroyPixmap(nvbuf->ppix);
-               free(nvbuf);
-               return NULL;
-       }
-
-       return &nvbuf->base;
+       return nouveau_dri2_create_buffer_2(pDraw, attachment, format, ppix);
 }
 
 void
@@ -95,6 +147,13 @@ nouveau_dri2_destroy_buffer(DrawablePtr pDraw, 
DRI2BufferPtr buf)
        free(nvbuf);
 }
 
+/* moveme: */
+int
+nouveau_put_texture_image(DrawablePtr pDraw, PixmapPtr srcPix, int id,
+               short src_x, short src_y, short drw_x, short drw_y,
+               short src_w, short src_h, short drw_w, short drw_h,
+               short width, short height);
+
 void
 nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
                         DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
@@ -332,6 +391,49 @@ fail:
 }
 
 static Bool
+nouveau_dri2_schedule_swap_vid(ClientPtr client, DrawablePtr draw,
+                          DRI2BufferPtr dst, DRI2BufferPtr src,
+                          BoxPtr b, DrawablePtr osd,
+                          CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
+                          DRI2SwapEventPtr func, void *data)
+{
+       ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum];
+       PixmapPtr src_pix = nouveau_dri2_buffer(src)->ppix;
+       short width, height;
+       int ret;
+
+       width  = src_pix->drawable.width;
+       height = src_pix->drawable.height;
+
+       if (src->format == FOURCC_STR("I420") ||
+                       src->format == FOURCC_STR("YV12")) {
+               /* undo the 'height *= 1.5' trick to recover real height */
+               height = (height * 2) / 3;
+       }
+
+       /* attempt to hijack some of the XV USE_TEXTURE code.. maybe not the
+        * cleanest way, or even work on all cards, but just for proof of 
concept..
+        *
+        * XXX this probably won't work for RGB formats, at least not on all
+        * chipset versions (like NV50).. probably want to use the CopyRegion
+        * code path (or something similar?) for RGB??
+        */
+       ret = nouveau_put_texture_image(draw, src_pix, src->format,
+                       b->x1, b->y1, draw->x, draw->y,
+                       b->x2 - b->x1, b->y2 - b->y1, draw->width, draw->height,
+                       width, height);
+
+       if (ret != Success) {
+               xf86DrvMsg(scrn->scrnIndex, X_WARNING, "blit failed: %d\n", 
ret);
+               return FALSE;
+       }
+
+       DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+
+       return TRUE;
+}
+
+static Bool
 nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw,
                           CARD64 target_msc, CARD64 divisor, CARD64 remainder)
 {
@@ -396,6 +498,37 @@ nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 
*msc)
        return TRUE;
 }
 
+#define ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static int
+nouveau_set_attribute(DrawablePtr pDraw, Atom attribute,
+               int len, const CARD32 *val)
+{
+       /* just for testing.. bogus colorspace conversion matrix.. */
+       if (attribute == ATOM("XV_CSC_MATRIX")) {
+               return Success;
+       }
+       return BadMatch;
+}
+
+static int
+nouveau_get_attribute(DrawablePtr pDraw, Atom attribute,
+               int *len, const CARD32 **val)
+{
+       /* just for testing.. bogus colorspace conversion matrix.. */
+       if (attribute == ATOM("XV_CSC_MATRIX")) {
+               static const CARD32 csc[] = {
+                               0x00, 0x01, 0x02, 0x03,
+                               0x10, 0x11, 0x12, 0x13,
+                               0x20, 0x21, 0x22, 0x23,
+               };
+               *val = csc;
+               *len = sizeof(csc) / 4;
+               return Success;
+       }
+       return BadMatch;
+}
+
 void
 nouveau_dri2_vblank_handler(int fd, unsigned int frame,
                            unsigned int tv_sec, unsigned int tv_usec,
@@ -428,28 +561,47 @@ nouveau_dri2_init(ScreenPtr pScreen)
        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
        NVPtr pNv = NVPTR(pScrn);
        DRI2InfoRec dri2 = { 0 };
-       const char *drivernames[2][2] = {
-               { "nouveau", "nouveau" },
-               { "nouveau_vieux", "nouveau_vieux" }
+       const char *drivernames[2][3] = {
+               { "nouveau", "nouveau", "nouveau" },
+               { "nouveau_vieux", "nouveau_vieux", NULL }
+       };
+       const unsigned int formats[] = {
+                       FOURCC_STR("YUY2"),
+                       FOURCC_STR("YV12"),
+                       FOURCC_STR("UYVY"),
+                       FOURCC_STR("I420"),
+                       FOURCC_STR("RGB3"),  /* depth=24, bpp=32 */
+                       FOURCC_STR("RGB4"),  /* depth=32, bpp=32 */
+                       /* non-common formats: */
+                       // XXX check what might have been passed by mesa!!
+                       24,
+                       32,
        };
 
        if (pNv->Architecture >= NV_ARCH_30)
                dri2.driverNames = drivernames[0];
        else
                dri2.driverNames = drivernames[1];
-       dri2.numDrivers = 2;
+       dri2.numDrivers = 3;
        dri2.driverName = dri2.driverNames[0];
 
+       dri2.numFormats = ARRAY_SIZE(formats);
+       dri2.formats = formats;
+
        dri2.fd = nouveau_device(pNv->dev)->fd;
        dri2.deviceName = pNv->drm_device_name;
 
        dri2.version = DRI2INFOREC_VERSION;
        dri2.CreateBuffer = nouveau_dri2_create_buffer;
+       dri2.CreateBufferVid = nouveau_dri2_create_buffer_vid;
        dri2.DestroyBuffer = nouveau_dri2_destroy_buffer;
        dri2.CopyRegion = nouveau_dri2_copy_region;
        dri2.ScheduleSwap = nouveau_dri2_schedule_swap;
+       dri2.ScheduleSwapVid = nouveau_dri2_schedule_swap_vid;
        dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait;
        dri2.GetMSC = nouveau_dri2_get_msc;
+       dri2.SetAttribute = nouveau_set_attribute;
+       dri2.GetAttribute = nouveau_get_attribute;
 
        return DRI2ScreenInit(pScreen, &dri2);
 }
diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c
index 5a5337c..2733a2c 100644
--- a/src/nouveau_xv.c
+++ b/src/nouveau_xv.c
@@ -561,6 +561,10 @@ NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char 
*src2,
 }
 
 
+// put these somewhere common..
+#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) 
<< 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 ))
+#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
+
 static int
 NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 *xa, INT32 *xb,
                  INT32 *ya, INT32 *yb, short *src_x, short *src_y,
@@ -887,6 +891,87 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, 
NVPortPrivPtr pPriv,
        }
 }
 
+/* move from GART -> VRAM */
+static int
+nouveau_xv_m2mf(ScrnInfoPtr pScrn, int action_flags,
+               struct nouveau_bo *src /* GART buffer */,
+               struct nouveau_bo *dst /* VRAM buffer */,
+               int offset, int uv_offset, int nlines, int line_len, int 
dstPitch)
+{
+       NVPtr pNv = NVPTR(pScrn);
+       struct nouveau_channel *chan = pNv->chan;
+       struct nouveau_grobj *m2mf = pNv->NvMemFormat;
+
+       if (pNv->Architecture >= NV_ARCH_C0) {
+               nvc0_xv_m2mf(m2mf, dst, uv_offset, dstPitch,
+                            nlines, src, line_len);
+               return Success;
+       }
+
+       if (MARK_RING(chan, 64, 4))
+               return BadAlloc;
+
+       BEGIN_RING(chan, m2mf,
+                  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+       OUT_RING  (chan, pNv->chan->gart->handle);
+       OUT_RING  (chan, pNv->chan->vram->handle);
+
+       if (pNv->Architecture >= NV_ARCH_50) {
+               BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 
1);
+               OUT_RING  (chan, 1);
+
+               BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 
7);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, src->tile_mode << 4);
+               OUT_RING  (chan, dstPitch);
+               OUT_RING  (chan, nlines);
+               OUT_RING  (chan, 1);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, 0);
+       }
+
+       /* DMA to VRAM */
+       if ( (action_flags & IS_YV12) &&
+           !(action_flags & CONVERT_TO_YUY2)) {
+               /* we start the color plane transfer separately */
+
+               BEGIN_RING(chan, m2mf,
+                          NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+               if (OUT_RELOCl(chan, src,
+                              line_len * nlines,
+                              NOUVEAU_BO_GART | NOUVEAU_BO_RD) ||
+                   OUT_RELOCl(chan, dst,
+                              offset + uv_offset,
+                              NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
+                       MARK_UNDO(chan);
+                       return BadAlloc;
+               }
+               OUT_RING  (chan, line_len);
+               OUT_RING  (chan, dstPitch);
+               OUT_RING  (chan, line_len);
+               OUT_RING  (chan, (nlines >> 1));
+               OUT_RING  (chan, (1<<8)|1);
+               OUT_RING  (chan, 0);
+       }
+
+       BEGIN_RING(chan, m2mf,
+                  NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+       if (OUT_RELOCl(chan, src, 0,
+                      NOUVEAU_BO_GART | NOUVEAU_BO_RD) ||
+           OUT_RELOCl(chan, dst, offset,
+                      NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
+               MARK_UNDO(chan);
+               return BadAlloc;
+       }
+       OUT_RING  (chan, line_len);
+       OUT_RING  (chan, dstPitch);
+       OUT_RING  (chan, line_len);
+       OUT_RING  (chan, nlines);
+       OUT_RING  (chan, (1<<8)|1);
+       OUT_RING  (chan, 0);
+
+       return Success;
+}
 
 /**
  * NVPutImage
@@ -936,8 +1021,6 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, 
short drw_x,
         * and lines we are interested in
         */
        int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0;
-       struct nouveau_channel *chan = pNv->chan;
-       struct nouveau_grobj *m2mf = pNv->NvMemFormat;
        Bool skip = FALSE;
        BoxRec dstBox;
        CARD32 tmp = 0;
@@ -1111,73 +1194,17 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, 
short drw_x,
 
                nouveau_bo_unmap(destination_buffer);
 
-               if (pNv->Architecture >= NV_ARCH_C0) {
-                       nvc0_xv_m2mf(m2mf, pPriv->video_mem, uv_offset, 
dstPitch,
-                                    nlines, destination_buffer, line_len);
-                       goto put_image;
-               }
-
-               if (MARK_RING(chan, 64, 4))
-                       return FALSE;
-
-               BEGIN_RING(chan, m2mf,
-                          NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
-               OUT_RING  (chan, pNv->chan->gart->handle);
-               OUT_RING  (chan, pNv->chan->vram->handle);
-
-               if (pNv->Architecture >= NV_ARCH_50) {
-                       BEGIN_RING(chan, m2mf, 
NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1);
-                       OUT_RING  (chan, 1);
-
-                       BEGIN_RING(chan, m2mf, 
NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 7);
-                       OUT_RING  (chan, 0);
-                       OUT_RING  (chan, destination_buffer->tile_mode << 4);
-                       OUT_RING  (chan, dstPitch);
-                       OUT_RING  (chan, nlines);
-                       OUT_RING  (chan, 1);
-                       OUT_RING  (chan, 0);
-                       OUT_RING  (chan, 0);
-               }
-
-               /* DMA to VRAM */
-               if ( (action_flags & IS_YV12) &&
-                   !(action_flags & CONVERT_TO_YUY2)) {
-                       /* we start the color plane transfer separately */
-
-                       BEGIN_RING(chan, m2mf,
-                                  NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-                       if (OUT_RELOCl(chan, destination_buffer,
-                                      line_len * nlines,
-                                      NOUVEAU_BO_GART | NOUVEAU_BO_RD) ||
-                           OUT_RELOCl(chan, pPriv->video_mem,
-                                      offset + uv_offset,
-                                      NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
-                               MARK_UNDO(chan);
-                               return BadAlloc;
-                       }
-                       OUT_RING  (chan, line_len);
-                       OUT_RING  (chan, dstPitch);
-                       OUT_RING  (chan, line_len);
-                       OUT_RING  (chan, (nlines >> 1));
-                       OUT_RING  (chan, (1<<8)|1);
-                       OUT_RING  (chan, 0);
+               ret = nouveau_xv_m2mf(pScrn, action_flags,
+                               destination_buffer, pPriv->video_mem,
+                               offset, uv_offset, nlines, line_len, dstPitch);
+               if (ret != Success) {
+                       return ret;
                }
 
-               BEGIN_RING(chan, m2mf,
-                          NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-               if (OUT_RELOCl(chan, destination_buffer, 0,
-                              NOUVEAU_BO_GART | NOUVEAU_BO_RD) ||
-                   OUT_RELOCl(chan, pPriv->video_mem, offset,
-                              NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
-                       MARK_UNDO(chan);
-                       return BadAlloc;
+               if (pNv->Architecture >= NV_ARCH_C0) {
+                       /* is this needed?  It is to preserve the original code 
flow */
+                       goto put_image;
                }
-               OUT_RING  (chan, line_len);
-               OUT_RING  (chan, dstPitch);
-               OUT_RING  (chan, line_len);
-               OUT_RING  (chan, nlines);
-               OUT_RING  (chan, (1<<8)|1);
-               OUT_RING  (chan, 0);
        } else {
 CPU_copy:
                nouveau_bo_map(pPriv->video_mem, NOUVEAU_BO_WR);
@@ -1356,6 +1383,171 @@ put_image:
        return Success;
 }
 
+int
+nouveau_put_texture_image(DrawablePtr pDraw, PixmapPtr srcPix, int id,
+               short src_x, short src_y, short drw_x, short drw_y,
+               short src_w, short src_h, short drw_w, short drw_h,
+               short width, short height)
+{
+       ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
+       NVPtr pNv = NVPTR(pScrn);
+       PixmapPtr dstPix = NVGetDrawablePixmap(pDraw);
+       BoxRec dstBox;
+       RegionRec clipRegion;
+       int action_flags;
+       struct nouveau_bo *src;
+       int ret = BadImplementation;
+
+       // XXX we just need pPriv->video_mem... maybe there is a better way?
+       NVPortPrivPtr pPriv = 
(NVPortPrivPtr)((pNv)->textureAdaptor[0]->pPortPrivates[0].ptr);
+
+       /* source box */
+       INT32 xa = 0, xb = 0, ya = 0, yb = 0;
+       /* size to allocate in VRAM and in GART respectively */
+       int newFBSize = 0, newTTSize = 0;  /* ignored */
+       /* card VRAM offsets, source offsets for U and V planes */
+       int offset = 0, uv_offset = 0, s2offset = 0, s3offset = 0;
+       /* source pitch, source pitch of U and V planes in case of YV12,
+        * VRAM destination pitch
+        */
+       int srcPitch = 0, srcPitch2 = 0, dstPitch = 0;
+       /* position of the given source data (using src_*), number of pixels
+        * and lines we are interested in
+        */
+       int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0;
+       /* length of a line, like npixels, but in bytes */
+       int line_len = 0;
+
+       RegionInit(&clipRegion, (&(BoxRec){ 0, 0, pDraw->width, pDraw->height 
}), 0);
+       RegionTranslate(&clipRegion, pDraw->x, pDraw->y);
+
+       action_flags = USE_TEXTURE;
+
+       switch(id) {
+       case FOURCC_YUY2:
+       case FOURCC_UYVY:
+               action_flags |= IS_YUY2;
+               break;
+       case FOURCC_I420:
+               action_flags |= SWAP_UV;
+               /* fallthrough */
+       case FOURCC_YV12:
+               action_flags |= IS_YV12;
+               break;
+       case FOURCC_RGB:
+       case FOURCC('R','G','B','4'):
+       case FOURCC('R','G','B','3'):
+               action_flags |= IS_RGB;
+               break;
+       default:
+               return BadColor;
+       }
+
+       if (NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb,
+                             &src_x,  &src_y, &src_w, &src_h,
+                             &drw_x, &drw_y, &drw_w, &drw_h,
+                             &left, &top, &right, &bottom, &dstBox,
+                             &npixels, &nlines, &clipRegion, width, height)) {
+               return Success;
+       }
+
+       /* note: in Xv code, pixel buffer is src, uploaded YUV data is dst
+        * which becomes the src for the PutTextureImage() step.. so dstPitch
+        * is really our srcPitch (of src pixmap) and srcPitch's are ignored..
+        * as are a couple other things..
+        */
+       if (NV_calculate_pitches_and_mem_size(pNv, action_flags, &srcPitch,
+                                             &srcPitch2, &dstPitch, &s2offset,
+                                             &s3offset, &uv_offset,
+                                             &newFBSize, &newTTSize,
+                                             &line_len, npixels, nlines,
+                                             width, height)) {
+               return BadImplementation;
+       }
+
+       /* Ensure src and dst pixmap is in offscreen memory */
+       pNv->exa_force_cp = TRUE;
+       exaMoveInPixmap(dstPix);
+       exaMoveInPixmap(srcPix);
+       pNv->exa_force_cp = FALSE;
+
+       if (!exaGetPixmapDriverPrivate(dstPix) ||
+                       !exaGetPixmapDriverPrivate(srcPix)) {
+               return BadAlloc;
+       }
+
+       src = nouveau_pixmap_bo(srcPix);
+
+#ifdef COMPOSITE
+       /* Convert screen coords to pixmap coords */
+       if (dstPix->screen_x || dstPix->screen_y) {
+               REGION_TRANSLATE(pScrn->pScreen, &clipRegion,
+                                -dstPix->screen_x, -dstPix->screen_y);
+               dstBox.x1 -= dstPix->screen_x;
+               dstBox.x2 -= dstPix->screen_x;
+               dstBox.y1 -= dstPix->screen_y;
+               dstBox.y2 -= dstPix->screen_y;
+       }
+#endif
+
+       /* TODO check if src buffer is already in VRAM.. for hw decode
+        * we probably want to allow giving the client buffers in VRAM
+        * directly (via non-fourcc format values)
+        */
+
+       ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize,
+                                   &pPriv->video_mem);
+       if (ret)
+               return BadAlloc;
+
+       ret = nouveau_xv_m2mf(pScrn, action_flags, src, pPriv->video_mem,
+                       offset, uv_offset, nlines, line_len, dstPitch);
+       if (ret != Success) {
+               return ret;
+       }
+
+       if (pNv->Architecture == NV_ARCH_30) {
+               ret = NV30PutTextureImage(pScrn, pPriv->video_mem,
+                                         offset, uv_offset,
+                                         id, dstPitch, &dstBox, 0, 0,
+                                         xb, yb, npixels, nlines,
+                                         src_w, src_h, drw_w, drw_h,
+                                         &clipRegion, dstPix, NULL);
+       } else if (pNv->Architecture == NV_ARCH_40) {
+               ret = NV40PutTextureImage(pScrn, pPriv->video_mem,
+                                         offset, uv_offset,
+                                         id, dstPitch, &dstBox, 0, 0,
+                                         xb, yb, npixels, nlines,
+                                         src_w, src_h, drw_w, drw_h,
+                                         &clipRegion, dstPix, NULL);
+       } else if (pNv->Architecture == NV_ARCH_50) {
+               ret = nv50_xv_image_put(pScrn, pPriv->video_mem,
+                                       offset, uv_offset,
+                                       id, dstPitch, &dstBox, 0, 0,
+                                       xb, yb, npixels, nlines,
+                                       src_w, src_h, drw_w, drw_h,
+                                       &clipRegion, dstPix, NULL);
+       } else {
+               ret = nvc0_xv_image_put(pScrn, pPriv->video_mem,
+                                       offset, uv_offset,
+                                       id, dstPitch, &dstBox, 0, 0,
+                                       xb, yb, npixels, nlines,
+                                       src_w, src_h, drw_w, drw_h,
+                                       &clipRegion, dstPix, NULL);
+       }
+
+#ifdef COMPOSITE
+       /* Damage tracking */
+       if (!(action_flags & USE_OVERLAY))
+               DamageDamageRegion(&dstPix->drawable, &clipRegion);
+#endif
+
+       RegionUninit(&clipRegion);
+
+       return ret;
+}
+
+
 /**
  * QueryImageAttributes
  *
diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c
index 6d4e089..9c0e828 100644
--- a/src/nv30_xv_tex.c
+++ b/src/nv30_xv_tex.c
@@ -259,7 +259,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo 
*src, int src_offset,
        struct nouveau_channel *chan = pNv->chan;
        struct nouveau_grobj *rankine = pNv->Nv3D;
        struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
-       Bool bicubic = pPriv->bicubic;
+       Bool bicubic = pPriv && pPriv->bicubic;
        float X1, X2, Y1, Y2;
        BoxPtr pbox;
        int nbox;
@@ -349,7 +349,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo 
*src, int src_offset,
        }
 
        /* Just before rendering we wait for vblank in the non-composited case. 
*/
-       if (pPriv->SyncToVBlank) {
+       if (pPriv && pPriv->SyncToVBlank) {
                FIRE_RING(chan);
                NV11SyncToVBlank(ppix, dstBox);
        }
diff --git a/src/nv40_xv_tex.c b/src/nv40_xv_tex.c
index 0910e12..6249faf 100644
--- a/src/nv40_xv_tex.c
+++ b/src/nv40_xv_tex.c
@@ -263,7 +263,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn,
        struct nouveau_channel *chan = pNv->chan;
        struct nouveau_grobj *curie = pNv->Nv3D;
        struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
-       Bool bicubic = pPriv->bicubic;
+       Bool bicubic = pPriv && pPriv->bicubic;
        float X1, X2, Y1, Y2;
        BoxPtr pbox;
        int nbox;
@@ -338,7 +338,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn,
        OUT_RING  (chan, 1);
 
        /* Just before rendering we wait for vblank in the non-composited case. 
*/
-       if (pPriv->SyncToVBlank) {
+       if (pPriv && pPriv->SyncToVBlank) {
                FIRE_RING(chan);
                NV11SyncToVBlank(ppix, dstBox);
        }
diff --git a/src/nv50_xv.c b/src/nv50_xv.c
index ddeb5bb..8b6bd67 100644
--- a/src/nv50_xv.c
+++ b/src/nv50_xv.c
@@ -290,7 +290,7 @@ nv50_xv_image_put(ScrnInfoPtr pScrn,
        if (!nv50_xv_state_emit(ppix, id, src, packed_y, uv, width, height))
                return BadAlloc;
 
-       if (pPriv->SyncToVBlank) {
+       if (pPriv && pPriv->SyncToVBlank) {
                NV50SyncToVBlank(ppix, dstBox);
        }
 
diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c
index 735f47f..7775331 100644
--- a/src/nv_accel_common.c
+++ b/src/nv_accel_common.c
@@ -30,6 +30,7 @@ nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int 
height, int bpp,
        NVPtr pNv = NVPTR(scrn);
        Bool scanout = (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT);
        Bool tiled = (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED);
+       Bool video = (usage_hint & NOUVEAU_CREATE_PIXMAP_VIDEO);
        int tile_mode = 0, tile_flags = 0;
        int flags = NOUVEAU_BO_MAP | (bpp >= 8 ? NOUVEAU_BO_VRAM : 0);
        int cpp = bpp / 8, ret;
@@ -114,6 +115,16 @@ nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int 
height, int bpp,
        if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT)
                tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
 
+       if (video) {
+               if (pNv->Architecture == NV_ARCH_50)
+                       tile_flags = 0x7000;
+               else if (pNv->Architecture == NV_ARCH_C0)
+                       tile_flags = 0xfe00;
+               tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
+               tile_mode = 0;
+               flags = NOUVEAU_BO_MAP | NOUVEAU_BO_GART;
+       }
+
        ret = nouveau_bo_new_tile(pNv->dev, flags, 0, *pitch * height,
                                  tile_mode, tile_flags, bo);
        if (ret)
diff --git a/src/nv_type.h b/src/nv_type.h
index 4204556..c73c156 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -156,6 +156,7 @@ typedef struct _NVPortPrivRec {
 #define NOUVEAU_CREATE_PIXMAP_ZETA     0x10000000
 #define NOUVEAU_CREATE_PIXMAP_TILED    0x20000000
 #define NOUVEAU_CREATE_PIXMAP_SCANOUT  0x40000000
+#define NOUVEAU_CREATE_PIXMAP_VIDEO    0x80000000
 
 struct nouveau_pixmap {
        struct nouveau_bo *bo;
diff --git a/src/nvc0_xv.c b/src/nvc0_xv.c
index 41ec7a8..149eaaf 100644
--- a/src/nvc0_xv.c
+++ b/src/nvc0_xv.c
@@ -343,7 +343,7 @@ nvc0_xv_image_put(ScrnInfoPtr pScrn,
        if (!nvc0_xv_state_emit(ppix, id, src, packed_y, uv, width, height))
                return BadAlloc;
 
-       if (0 && pPriv->SyncToVBlank) {
+       if (0 && pPriv && pPriv->SyncToVBlank) {
                NV50SyncToVBlank(ppix, dstBox);
        }
 
-- 
1.7.5.4

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to