st/va: Fix up YV12 to NV12 putImage conversion
authorThomas Hellstrom <thellstrom@vmware.com>
Wed, 22 Feb 2017 12:07:47 +0000 (13:07 +0100)
committerThomas Hellstrom <thellstrom@vmware.com>
Fri, 24 Feb 2017 15:44:34 +0000 (16:44 +0100)
Use the utility u_copy_nv12_from_yv12 to implement this similarly to
how it's been done in the VPAU state tracker. The old code mixed up
planes and fields and didn't correctly handle video surfaces in
interlaced format.

Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
src/gallium/auxiliary/util/u_video.h
src/gallium/state_trackers/va/image.c

index 7cd6268d1fcde2257f5fa0030a212c4c1deebba5..251e144c7926b7cbb9ea411db5b2ed52288aa95a 100644 (file)
@@ -172,43 +172,6 @@ u_copy_yv12_to_nv12(void *const *destination_data,
    }
 }
 
-static inline void
-u_copy_yv12_img_to_nv12_surf(ubyte *const *src,
-                             ubyte *dst,
-                             unsigned width,
-                             unsigned height,
-                             unsigned src_stride,
-                             unsigned dst_stride,
-                             int field)
-{
-   if (field == 0) {
-      ubyte *src_0 = src[field];
-      for (int i = 0; i < height ; i++) {
-         memcpy(dst, src_0, width);
-         dst += dst_stride;
-         src_0 += src_stride;
-      }
-   } else if (field == 1) {
-      const ubyte *src_1 = src[field];
-      const ubyte *src_2 = src[field+1];
-      bool odd = true;
-      for (unsigned i = 0; i < height ; i++) {
-         for (unsigned j = 0; j < width*2 ; j++) {
-            if (odd == false) {
-               dst[j] = src_1[j/2];
-               odd = true;
-            } else {
-               dst[j] = src_2[j/2];
-               odd = false;
-            }
-         }
-         dst += dst_stride;
-         src_1 += src_stride;
-         src_2 += src_stride;
-      }
-   }
-}
-
 static inline void
 u_copy_swap422_packed(void *const *destination_data,
                        uint32_t const *destination_pitches,
index bd60d3eb1d8c4a527aa5c05fe541e2e3a09fee39..47d31de2dbedc15166e989bdf7b0fddb20a62b65 100644 (file)
@@ -513,28 +513,36 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
 
    for (i = 0; i < vaimage->num_planes; ++i) {
       unsigned width, height;
+      struct pipe_resource *tex;
+
       if (!views[i]) continue;
-      vlVaVideoSurfaceSize(surf, i, &width, &height);
-      if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV)) &&
-            (surf->buffer->buffer_format == PIPE_FORMAT_NV12)) {
-         struct pipe_transfer *transfer = NULL;
-         uint8_t *map = NULL;
-         struct pipe_box dst_box_1 = {0, 0, 0, width, height, 1};
-         map = drv->pipe->transfer_map(drv->pipe,
-                                       views[i]->texture,
-                                       0,
-                                       PIPE_TRANSFER_DISCARD_RANGE,
-                                       &dst_box_1, &transfer);
-         if (map == NULL)
-            return VA_STATUS_ERROR_OPERATION_FAILED;
+      tex = views[i]->texture;
 
-         u_copy_yv12_img_to_nv12_surf ((ubyte * const*)data, map, width, height,
-                                      pitches[i], transfer->stride, i);
-         pipe_transfer_unmap(drv->pipe, transfer);
-      } else {
-         for (j = 0; j < views[i]->texture->array_size; ++j) {
-            struct pipe_box dst_box = {0, 0, j, width, height, 1};
-            drv->pipe->texture_subdata(drv->pipe, views[i]->texture, 0,
+      vlVaVideoSurfaceSize(surf, i, &width, &height);
+      for (j = 0; j < tex->array_size; ++j) {
+         struct pipe_box dst_box = {0, 0, j, width, height, 1};
+
+         if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV))
+             && (surf->buffer->buffer_format == PIPE_FORMAT_NV12)
+             && i == 1) {
+            struct pipe_transfer *transfer = NULL;
+            uint8_t *map = NULL;
+
+            map = drv->pipe->transfer_map(drv->pipe,
+                                          tex,
+                                          0,
+                                          PIPE_TRANSFER_WRITE |
+                                          PIPE_TRANSFER_DISCARD_RANGE,
+                                          &dst_box, &transfer);
+            if (map == NULL)
+               return VA_STATUS_ERROR_OPERATION_FAILED;
+
+            u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j,
+                                  transfer->stride, tex->array_size,
+                                  map, dst_box.width, dst_box.height);
+            pipe_transfer_unmap(drv->pipe, transfer);
+         } else {
+            drv->pipe->texture_subdata(drv->pipe, tex, 0,
                                        PIPE_TRANSFER_WRITE, &dst_box,
                                        data[i] + pitches[i] * j,
                                        pitches[i] * views[i]->texture->array_size, 0);