Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[mesa.git] / src / gallium / state_trackers / xorg / xorg_xv.c
index 2b935c0f73762b4f07e5c4e033d05cb0ffffef8e..19c50051a85a23f3e7a2c902614558d55009ef62 100644 (file)
@@ -73,10 +73,11 @@ static XF86VideoEncodingRec DummyEncoding[1] = {
    }
 };
 
-#define NUM_IMAGES 2
+#define NUM_IMAGES 3
 static XF86ImageRec Images[NUM_IMAGES] = {
    XVIMAGE_UYVY,
    XVIMAGE_YUY2,
+   XVIMAGE_YV12,
 };
 
 struct xorg_xv_port_priv {
@@ -212,17 +213,67 @@ check_yuv_textures(struct xorg_xv_port_priv *priv,  int width, int height)
    return Success;
 }
 
+static int
+query_image_attributes(ScrnInfoPtr pScrn,
+                       int id,
+                       unsigned short *w, unsigned short *h,
+                       int *pitches, int *offsets)
+{
+   int size, tmp;
+
+   if (*w > IMAGE_MAX_WIDTH)
+      *w = IMAGE_MAX_WIDTH;
+   if (*h > IMAGE_MAX_HEIGHT)
+      *h = IMAGE_MAX_HEIGHT;
+
+   *w = (*w + 1) & ~1;
+   if (offsets)
+      offsets[0] = 0;
+
+   switch (id) {
+   case FOURCC_YV12:
+      *h = (*h + 1) & ~1;
+      size = (*w + 3) & ~3;
+      if (pitches) {
+         pitches[0] = size;
+      }
+      size *= *h;
+      if (offsets) {
+         offsets[1] = size;
+      }
+      tmp = ((*w >> 1) + 3) & ~3;
+      if (pitches) {
+         pitches[1] = pitches[2] = tmp;
+      }
+      tmp *= (*h >> 1);
+      size += tmp;
+      if (offsets) {
+         offsets[2] = size;
+      }
+      size += tmp;
+      break;
+   case FOURCC_UYVY:
+   case FOURCC_YUY2:
+   default:
+      size = *w << 1;
+      if (pitches)
+        pitches[0] = size;
+      size *= *h;
+      break;
+   }
+
+   return size;
+}
+
 static void
 copy_packed_data(ScrnInfoPtr pScrn,
                  struct xorg_xv_port_priv *port,
                  int id,
                  unsigned char *buf,
-                 int srcPitch,
                  int left,
                  int top,
-                 int w, int h)
+                 unsigned short w, unsigned short h)
 {
-   unsigned char *src;
    int i, j;
    struct pipe_texture **dst = port->yuv[port->current_set];
    struct pipe_transfer *ytrans, *utrans, *vtrans;
@@ -232,8 +283,6 @@ copy_packed_data(ScrnInfoPtr pScrn,
    int yidx, uidx, vidx;
    int y_array_size = w * h;
 
-   src = buf + (top * srcPitch) + (left << 1);
-
    ytrans = screen->get_tex_transfer(screen, dst[0],
                                      0, 0, 0,
                                      PIPE_TRANSFER_WRITE,
@@ -255,15 +304,22 @@ copy_packed_data(ScrnInfoPtr pScrn,
 
    switch (id) {
    case FOURCC_YV12: {
-      for (i = 0; i < w; ++i) {
-         for (j = 0; i < h; ++j) {
-            /*XXX use src? */
-            y1  = buf[j*w + i];
-            u   = buf[(j/2) * (w/2) + i/2 + y_array_size];
-            v   = buf[(j/2) * (w/2) + i/2 + y_array_size + y_array_size/4];
-            ymap[yidx++] = y1;
-            umap[uidx++] = u;
-            vmap[vidx++] = v;
+      int pitches[3], offsets[3];
+      unsigned char *y, *u, *v;
+      query_image_attributes(pScrn, FOURCC_YV12,
+                             &w, &h, pitches, offsets);
+
+      y = buf + offsets[0];
+      v = buf + offsets[1];
+      u = buf + offsets[2];
+      for (i = 0; i < h; ++i) {
+         for (j = 0; j < w; ++j) {
+            int yoffset = (w*i+j);
+            int ii = (i|1), jj = (j|1);
+            int vuoffset = (w/2)*(ii/2) + (jj/2);
+            ymap[yidx++] = y[yoffset];
+            umap[uidx++] = u[vuoffset];
+            vmap[vidx++] = v[vuoffset];
          }
       }
    }
@@ -317,21 +373,6 @@ copy_packed_data(ScrnInfoPtr pScrn,
 }
 
 
-static void
-setup_vs_video_constants(struct xorg_renderer *r, struct exa_pixmap_priv *dst)
-{
-   int width = dst->tex->width[0];
-   int height = dst->tex->height[0];
-   const int param_bytes = 8 * sizeof(float);
-   float vs_consts[8] = {
-      2.f/width, 2.f/height, 1, 1,
-      -1, -1, 0, 0
-   };
-
-   renderer_set_constants(r, PIPE_SHADER_VERTEX,
-                          vs_consts, param_bytes);
-}
-
 static void
 setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
 {
@@ -445,6 +486,12 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
    Bool hdtv;
    int x, y, w, h;
    struct exa_pixmap_priv *dst = exaGetPixmapDriverPrivate(pPixmap);
+   struct pipe_surface *dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
+
+   if (dst && !dst->tex) {
+       xorg_exa_set_shared_usage(pPixmap);
+       pScrn->pScreen->ModifyPixmapHeader(pPixmap, 0, 0, 0, 0, 0, NULL);
+   }
 
    if (!dst || !dst->tex)
       XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
@@ -460,15 +507,17 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
    pbox = REGION_RECTS(dstRegion);
    nbox = REGION_NUM_RECTS(dstRegion);
 
-   renderer_bind_framebuffer(pPriv->r, dst);
-   renderer_bind_viewport(pPriv->r, dst);
+   renderer_bind_destination(pPriv->r, dst_surf, 
+                             dst_surf->width, dst_surf->height);
+
    bind_blend_state(pPriv);
-   renderer_bind_rasterizer(pPriv->r);
    bind_shaders(pPriv);
    bind_samplers(pPriv);
-   setup_vs_video_constants(pPriv->r, dst);
    setup_fs_video_constants(pPriv->r, hdtv);
 
+   exaMoveInPixmap(pPixmap);
+   DamageDamageRegion(&pPixmap->drawable, dstRegion);
+
    while (nbox--) {
       int box_x1 = pbox->x1;
       int box_y1 = pbox->y1;
@@ -476,8 +525,8 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
       int box_y2 = pbox->y2;
       float diff_x = (float)src_w / (float)dst_w;
       float diff_y = (float)src_h / (float)dst_h;
-      int offset_x = box_x1 - dstX;
-      int offset_y = box_y1 - dstY;
+      int offset_x = box_x1 - dstX + pPixmap->screen_x;
+      int offset_y = box_y1 - dstY + pPixmap->screen_y;
       int offset_w;
       int offset_h;
 
@@ -495,7 +544,9 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
 
       pbox++;
    }
-   DamageDamageRegion(&pPixmap->drawable, dstRegion);
+   DamageRegionProcessPending(&pPixmap->drawable);
+
+   pipe_surface_reference(&dst_surf, NULL);
 
    return TRUE;
 }
@@ -515,7 +566,6 @@ put_image(ScrnInfoPtr pScrn,
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
    PixmapPtr pPixmap;
    INT32 x1, x2, y1, y2;
-   int srcPitch;
    BoxRec dstBox;
    int ret;
 
@@ -534,20 +584,12 @@ put_image(ScrnInfoPtr pScrn,
                              width, height))
       return Success;
 
-   switch (id) {
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      srcPitch = width << 1;
-      break;
-   }
-
    ret = check_yuv_textures(pPriv, width, height);
 
    if (ret)
       return ret;
 
-   copy_packed_data(pScrn, pPriv, id, buf, srcPitch,
+   copy_packed_data(pScrn, pPriv, id, buf,
                     src_x, src_y, width, height);
 
    if (pDraw->type == DRAWABLE_WINDOW) {
@@ -565,37 +607,6 @@ put_image(ScrnInfoPtr pScrn,
    return Success;
 }
 
-static int
-query_image_attributes(ScrnInfoPtr pScrn,
-                       int id,
-                       unsigned short *w, unsigned short *h,
-                       int *pitches, int *offsets)
-{
-   int size;
-
-   if (*w > IMAGE_MAX_WIDTH)
-      *w = IMAGE_MAX_WIDTH;
-   if (*h > IMAGE_MAX_HEIGHT)
-      *h = IMAGE_MAX_HEIGHT;
-
-   *w = (*w + 1) & ~1;
-   if (offsets)
-      offsets[0] = 0;
-
-   switch (id) {
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      size = *w << 1;
-      if (pitches)
-        pitches[0] = size;
-      size *= *h;
-      break;
-   }
-
-   return size;
-}
-
 static struct xorg_xv_port_priv *
 port_priv_create(struct xorg_renderer *r)
 {
@@ -678,7 +689,7 @@ xorg_setup_textured_adapter(ScreenPtr pScreen)
 }
 
 void
-xorg_init_video(ScreenPtr pScreen)
+xorg_xv_init(ScreenPtr pScreen)
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    /*modesettingPtr ms = modesettingPTR(pScrn);*/