Merge branch '7.8'
[mesa.git] / src / gallium / state_trackers / xorg / xorg_xv.c
index b8eca8c81765d65325fece99e6bb1110e48cca0b..a221594454e79baabf0358618fa897558d27c3a1 100644 (file)
@@ -9,9 +9,9 @@
 #include "xorg_exa_tgsi.h"
 
 #include "cso_cache/cso_context.h"
+#include "util/u_sampler.h"
 
 #include "pipe/p_screen.h"
-#include "pipe/p_inlines.h"
 
 /*XXX get these from pipe's texture limits */
 #define IMAGE_MAX_WIDTH                2048
@@ -91,7 +91,8 @@ struct xorg_xv_port_priv {
    int current_set;
    /* juggle two sets of seperate Y, U and V
     * textures */
-   struct pipe_texture *yuv[2][3];
+   struct pipe_resource *yuv[2][3];
+   struct pipe_sampler_view *yuv_views[2][3];
 };
 
 
@@ -155,13 +156,13 @@ query_best_size(ScrnInfoPtr pScrn,
    *p_h = drw_h;
 }
 
-static INLINE struct pipe_texture *
+static INLINE struct pipe_resource *
 create_component_texture(struct pipe_context *pipe,
                          int width, int height)
 {
    struct pipe_screen *screen = pipe->screen;
-   struct pipe_texture *tex = 0;
-   struct pipe_texture templ;
+   struct pipe_resource *tex = 0;
+   struct pipe_resource templ;
 
    memset(&templ, 0, sizeof(templ));
    templ.target = PIPE_TEXTURE_2D;
@@ -170,10 +171,9 @@ create_component_texture(struct pipe_context *pipe,
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
-   pf_get_block(PIPE_FORMAT_L8_UNORM, &templ.block);
-   templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+   templ.bind = PIPE_BIND_SAMPLER_VIEW;
 
-   tex = screen->texture_create(screen, &templ);
+   tex = screen->resource_create(screen, &templ);
 
    return tex;
 }
@@ -181,90 +181,173 @@ create_component_texture(struct pipe_context *pipe,
 static int
 check_yuv_textures(struct xorg_xv_port_priv *priv,  int width, int height)
 {
-   struct pipe_texture **dst = priv->yuv[priv->current_set];
+   struct pipe_resource **dst = priv->yuv[priv->current_set];
+   struct pipe_sampler_view **dst_view = priv->yuv_views[priv->current_set];
+   struct pipe_sampler_view view_templ;
+   struct pipe_context *pipe = priv->r->pipe;
+
    if (!dst[0] ||
        dst[0]->width0 != width ||
        dst[0]->height0 != height) {
-      pipe_texture_reference(&dst[0], NULL);
+      pipe_resource_reference(&dst[0], NULL);
+      pipe_sampler_view_reference(&dst_view[0], NULL);
    }
    if (!dst[1] ||
        dst[1]->width0 != width ||
        dst[1]->height0 != height) {
-      pipe_texture_reference(&dst[1], NULL);
+      pipe_resource_reference(&dst[1], NULL);
+      pipe_sampler_view_reference(&dst_view[1], NULL);
    }
    if (!dst[2] ||
        dst[2]->width0 != width ||
        dst[2]->height0 != height) {
-      pipe_texture_reference(&dst[2], NULL);
+      pipe_resource_reference(&dst[2], NULL);
+      pipe_sampler_view_reference(&dst_view[2], NULL);
    }
 
-   if (!dst[0])
+   if (!dst[0]) {
       dst[0] = create_component_texture(priv->r->pipe, width, height);
+      if (dst[0]) {
+         u_sampler_view_default_template(&view_templ,
+                                         dst[0],
+                                         dst[0]->format);
+         dst_view[0] = pipe->create_sampler_view(pipe, dst[0], &view_templ);
+      }
+   }
 
-   if (!dst[1])
+   if (!dst[1]) {
       dst[1] = create_component_texture(priv->r->pipe, width, height);
+      if (dst[1]) {
+         u_sampler_view_default_template(&view_templ,
+                                         dst[1],
+                                         dst[1]->format);
+         dst_view[1] = pipe->create_sampler_view(pipe, dst[1], &view_templ);
+      }
+   }
 
-   if (!dst[2])
+   if (!dst[2]) {
       dst[2] = create_component_texture(priv->r->pipe, width, height);
+      if (dst[2]) {
+         u_sampler_view_default_template(&view_templ,
+                                      dst[2],
+                                      dst[2]->format);
+         dst_view[2] = pipe->create_sampler_view(pipe, dst[2], &view_templ);
+      }
+   }
 
-   if (!dst[0] || !dst[1] || !dst[2])
+   if (!dst[0] || !dst[1] || !dst[2] || !dst_view[0] || !dst_view[1] || !dst_view[2] )
       return BadAlloc;
 
    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_resource **dst = port->yuv[port->current_set];
    struct pipe_transfer *ytrans, *utrans, *vtrans;
-   struct pipe_screen *screen = port->r->pipe->screen;
+   struct pipe_context *pipe = port->r->pipe;
    char *ymap, *vmap, *umap;
    unsigned char y1, y2, u, v;
    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,
-                                     left, top, w, h);
-   utrans = screen->get_tex_transfer(screen, dst[1],
-                                     0, 0, 0,
-                                     PIPE_TRANSFER_WRITE,
-                                     left, top, w, h);
-   vtrans = screen->get_tex_transfer(screen, dst[2],
-                                     0, 0, 0,
-                                     PIPE_TRANSFER_WRITE,
-                                     left, top, w, h);
-
-   ymap = (char*)screen->transfer_map(screen, ytrans);
-   umap = (char*)screen->transfer_map(screen, utrans);
-   vmap = (char*)screen->transfer_map(screen, vtrans);
+   ytrans = pipe_get_transfer(pipe, dst[0],
+                                   0, 0, 0,
+                                   PIPE_TRANSFER_WRITE,
+                                   left, top, w, h);
+   utrans = pipe_get_transfer(pipe, dst[1],
+                                   0, 0, 0,
+                                   PIPE_TRANSFER_WRITE,
+                                   left, top, w, h);
+   vtrans = pipe_get_transfer(pipe, dst[2],
+                                   0, 0, 0,
+                                   PIPE_TRANSFER_WRITE,
+                                   left, top, w, h);
+
+   ymap = (char*)pipe->transfer_map(pipe, ytrans);
+   umap = (char*)pipe->transfer_map(pipe, utrans);
+   vmap = (char*)pipe->transfer_map(pipe, vtrans);
 
    yidx = uidx = vidx = 0;
 
    switch (id) {
    case FOURCC_YV12: {
-      for (i = 0; i < w; ++i) {
-         for (j = 0; j < 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];
          }
       }
    }
@@ -309,12 +392,12 @@ copy_packed_data(ScrnInfoPtr pScrn,
       break;
    }
 
-   screen->transfer_unmap(screen, ytrans);
-   screen->transfer_unmap(screen, utrans);
-   screen->transfer_unmap(screen, vtrans);
-   screen->tex_transfer_destroy(ytrans);
-   screen->tex_transfer_destroy(utrans);
-   screen->tex_transfer_destroy(vtrans);
+   pipe->transfer_unmap(pipe, ytrans);
+   pipe->transfer_unmap(pipe, utrans);
+   pipe->transfer_unmap(pipe, vtrans);
+   pipe->transfer_destroy(pipe, ytrans);
+   pipe->transfer_destroy(pipe, utrans);
+   pipe->transfer_destroy(pipe, vtrans);
 }
 
 
@@ -333,8 +416,11 @@ draw_yuv(struct xorg_xv_port_priv *port,
          int src_x, int src_y, int src_w, int src_h,
          int dst_x, int dst_y, int dst_w, int dst_h)
 {
-   struct pipe_texture **textures = port->yuv[port->current_set];
+   struct pipe_resource **textures = port->yuv[port->current_set];
 
+   /*debug_printf("  draw_yuv([%d, %d, %d ,%d], [%d, %d, %d, %d])\n",
+                src_x, src_y, src_w, src_h,
+                dst_x, dst_y, dst_w, dst_h);*/
    renderer_draw_yuv(port->r,
                      src_x, src_y, src_w, src_h,
                      dst_x, dst_y, dst_w, dst_h,
@@ -347,14 +433,14 @@ bind_blend_state(struct xorg_xv_port_priv *port)
    struct pipe_blend_state blend;
 
    memset(&blend, 0, sizeof(struct pipe_blend_state));
-   blend.blend_enable = 1;
-   blend.colormask |= PIPE_MASK_RGBA;
+   blend.rt[0].blend_enable = 0;
+   blend.rt[0].colormask = PIPE_MASK_RGBA;
 
    /* porter&duff src */
-   blend.rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
-   blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-   blend.rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
-   blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+   blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
+   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+   blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
+   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
 
    cso_set_blend(port->r->cso, &blend);
 }
@@ -375,12 +461,12 @@ bind_shaders(struct xorg_xv_port_priv *port)
 }
 
 static INLINE void
-conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex,
+conditional_flush(struct pipe_context *pipe, struct pipe_resource **tex,
                   int num)
 {
    int i;
    for (i = 0; i < num; ++i) {
-      if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) &
+      if (tex[i] && pipe->is_resource_referenced(pipe, tex[i], 0, 0) &
           PIPE_REFERENCED_FOR_WRITE) {
          pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
          return;
@@ -393,7 +479,8 @@ bind_samplers(struct xorg_xv_port_priv *port)
 {
    struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
    struct pipe_sampler_state sampler;
-   struct pipe_texture **dst = port->yuv[port->current_set];
+   struct pipe_resource **dst = port->yuv[port->current_set];
+   struct pipe_sampler_view **dst_views = port->yuv_views[port->current_set];
 
    memset(&sampler, 0, sizeof(struct pipe_sampler_state));
 
@@ -413,8 +500,7 @@ bind_samplers(struct xorg_xv_port_priv *port)
 
    cso_set_samplers(port->r->cso, 3,
                     (const struct pipe_sampler_state **)samplers);
-   cso_set_sampler_textures(port->r->cso, 3,
-                            dst);
+   cso_set_fragment_sampler_views(port->r->cso, 3, dst_views);
 }
 
 static int
@@ -430,8 +516,14 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
    int dxo, dyo;
    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);
+   struct exa_pixmap_priv *dst;
+   struct pipe_surface *dst_surf = NULL;
+
+   exaMoveInPixmap(pPixmap);
+   dst = exaGetPixmapDriverPrivate(pPixmap);
+
+   /*debug_printf("display_video([%d, %d, %d, %d], [%d, %d, %d, %d])\n",
+     src_x, src_y, src_w, src_h, dstX, dstY, dst_w, dst_h);*/
 
    if (dst && !dst->tex) {
        xorg_exa_set_shared_usage(pPixmap);
@@ -441,6 +533,7 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
    if (!dst || !dst->tex)
       XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
 
+   dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
    hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
 
    REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
@@ -460,7 +553,6 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
    bind_samplers(pPriv);
    setup_fs_video_constants(pPriv->r, hdtv);
 
-   exaMoveInPixmap(pPixmap);
    DamageDamageRegion(&pPixmap->drawable, dstRegion);
 
    while (nbox--) {
@@ -483,8 +575,9 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
       offset_w = dst_w - w;
       offset_h = dst_h - h;
 
-      draw_yuv(pPriv, src_x + offset_x*diff_x, src_y + offset_y*diff_y,
-               src_w - offset_w*diff_x, src_h - offset_h*diff_x,
+      draw_yuv(pPriv,
+               src_x + offset_x*diff_x, src_y + offset_y*diff_y,
+               src_w - offset_w*diff_x, src_h - offset_h*diff_y,
                x, y, w, h);
 
       pbox++;
@@ -511,7 +604,6 @@ put_image(ScrnInfoPtr pScrn,
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
    PixmapPtr pPixmap;
    INT32 x1, x2, y1, y2;
-   int srcPitch;
    BoxRec dstBox;
    int ret;
 
@@ -530,21 +622,12 @@ put_image(ScrnInfoPtr pScrn,
                              width, height))
       return Success;
 
-   switch (id) {
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   case FOURCC_YV12:
-   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) {
@@ -562,38 +645,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:
-   case FOURCC_YV12:
-   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)
 {