gbm: use the loader util lib
[mesa.git] / src / gallium / auxiliary / vl / vl_video_buffer.c
index 0510f59ac12a3cde7a546633d51d125ab5fa54cb..092a03192cc7ccd27ac51e980b97e7c634cdb44d 100644 (file)
@@ -18,7 +18,7 @@
  * 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 NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
@@ -50,6 +50,30 @@ const enum pipe_format const_resource_formats_NV12[3] = {
    PIPE_FORMAT_NONE
 };
 
+const enum pipe_format const_resource_formats_YUVA[3] = {
+   PIPE_FORMAT_R8G8B8A8_UNORM,
+   PIPE_FORMAT_NONE,
+   PIPE_FORMAT_NONE
+};
+
+const enum pipe_format const_resource_formats_VUYA[3] = {
+   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_NONE,
+   PIPE_FORMAT_NONE
+};
+
+const enum pipe_format const_resource_formats_YUYV[3] = {
+   PIPE_FORMAT_R8G8_R8B8_UNORM,
+   PIPE_FORMAT_NONE,
+   PIPE_FORMAT_NONE
+};
+
+const enum pipe_format const_resource_formats_UYVY[3] = {
+   PIPE_FORMAT_G8R8_B8R8_UNORM,
+   PIPE_FORMAT_NONE,
+   PIPE_FORMAT_NONE
+};
+
 const unsigned const_resource_plane_order_YUV[3] = {
    0,
    1,
@@ -72,6 +96,18 @@ vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format)
    case PIPE_FORMAT_NV12:
       return const_resource_formats_NV12;
 
+   case PIPE_FORMAT_R8G8B8A8_UNORM:
+      return const_resource_formats_YUVA;
+
+   case PIPE_FORMAT_B8G8R8A8_UNORM:
+      return const_resource_formats_VUYA;
+
+   case PIPE_FORMAT_YUYV:
+      return const_resource_formats_YUYV;
+
+   case PIPE_FORMAT_UYVY:
+      return const_resource_formats_UYVY;
+
    default:
       return NULL;
    }
@@ -80,11 +116,15 @@ vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format)
 const unsigned *
 vl_video_buffer_plane_order(enum pipe_format format)
 {
-    switch(format) {
+   switch(format) {
    case PIPE_FORMAT_YV12:
       return const_resource_plane_order_YVU;
 
    case PIPE_FORMAT_NV12:
+   case PIPE_FORMAT_R8G8B8A8_UNORM:
+   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_YUYV:
+   case PIPE_FORMAT_UYVY:
       return const_resource_plane_order_YUV;
 
    default:
@@ -92,10 +132,23 @@ vl_video_buffer_plane_order(enum pipe_format format)
    }
 }
 
+static enum pipe_format
+vl_video_buffer_surface_format(enum pipe_format format)
+{
+   const struct util_format_description *desc = util_format_description(format);
+
+   /* a subsampled formats can't work as surface use RGBA instead */
+   if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
+      return PIPE_FORMAT_R8G8B8A8_UNORM;
+
+   return format;
+}
+
 boolean
 vl_video_buffer_is_format_supported(struct pipe_screen *screen,
                                     enum pipe_format format,
-                                    enum pipe_video_profile profile)
+                                    enum pipe_video_profile profile,
+                                    enum pipe_video_entrypoint entrypoint)
 {
    const enum pipe_format *resource_formats;
    unsigned i;
@@ -105,10 +158,17 @@ vl_video_buffer_is_format_supported(struct pipe_screen *screen,
       return false;
 
    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
-      if (!resource_formats[i])
+      enum pipe_format format = resource_formats[i];
+
+      if (format == PIPE_FORMAT_NONE)
          continue;
 
-      if (!screen->is_format_supported(screen, resource_formats[i], PIPE_TEXTURE_2D, 0, PIPE_USAGE_STATIC))
+      /* we at least need to sample from it */
+      if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
+         return false;
+
+      format = vl_video_buffer_surface_format(format);
+      if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
          return false;
    }
 
@@ -127,11 +187,11 @@ vl_video_buffer_max_size(struct pipe_screen *screen)
 
 void
 vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf,
-                                    struct pipe_video_decoder *vdec,
+                                    struct pipe_video_codec *vcodec,
                                     void *associated_data,
                                     void (*destroy_associated_data)(void *))
 {
-   vbuf->decoder = vdec;
+   vbuf->codec = vcodec;
 
    if (vbuf->associated_data == associated_data)
       return;
@@ -145,27 +205,33 @@ vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf,
 
 void *
 vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf,
-                                    struct pipe_video_decoder *vdec)
+                                    struct pipe_video_codec *vcodec)
 {
-   if (vbuf->decoder == vdec)
+   if (vbuf->codec == vcodec)
       return vbuf->associated_data;
    else
       return NULL;
 }
 
 void
-vl_vide_buffer_template(struct pipe_resource *templ,
-                        const struct pipe_video_buffer *tmpl,
-                        enum pipe_format resource_format,
-                        unsigned depth, unsigned usage, unsigned plane)
+vl_video_buffer_template(struct pipe_resource *templ,
+                         const struct pipe_video_buffer *tmpl,
+                         enum pipe_format resource_format,
+                         unsigned depth, unsigned array_size,
+                         unsigned usage, unsigned plane)
 {
    memset(templ, 0, sizeof(*templ));
-   templ->target = depth > 1 ? PIPE_TEXTURE_3D : PIPE_TEXTURE_2D;
+   if (depth > 1)
+      templ->target = PIPE_TEXTURE_3D;
+   else if (array_size > 1)
+      templ->target = PIPE_TEXTURE_2D_ARRAY;
+   else
+      templ->target = PIPE_TEXTURE_2D;
    templ->format = resource_format;
    templ->width0 = tmpl->width;
    templ->height0 = tmpl->height;
    templ->depth0 = depth;
-   templ->array_size = 1;
+   templ->array_size = array_size;
    templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
    templ->usage = usage;
 
@@ -174,7 +240,7 @@ vl_vide_buffer_template(struct pipe_resource *templ,
          templ->width0 /= 2;
          templ->height0 /= 2;
       } else if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
-         templ->height0 /= 2;
+         templ->width0 /= 2;
       }
    }
 }
@@ -193,7 +259,7 @@ vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
       pipe_resource_reference(&buf->resources[i], NULL);
    }
 
-   for (i = 0; i < VL_NUM_COMPONENTS * 2; ++i)
+   for (i = 0; i < VL_MAX_SURFACES; ++i)
       pipe_surface_reference(&buf->surfaces[i], NULL);
 
    vl_video_buffer_set_associated_data(buffer, NULL, NULL, NULL);
@@ -242,6 +308,7 @@ vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
    struct pipe_sampler_view sv_templ;
    struct pipe_context *pipe;
+   const enum pipe_format *sampler_format;
    const unsigned *plane_order;
    unsigned i, j, component;
 
@@ -249,26 +316,30 @@ vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
 
    pipe = buf->base.context;
 
+   sampler_format = vl_video_buffer_formats(pipe->screen, buf->base.buffer_format);
    plane_order = vl_video_buffer_plane_order(buf->base.buffer_format);
 
    for (component = 0, i = 0; i < buf->num_planes; ++i ) {
       struct pipe_resource *res = buf->resources[plane_order[i]];
+      const struct util_format_description *desc = util_format_description(res->format);
       unsigned nr_components = util_format_get_nr_components(res->format);
+      if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
+         nr_components = 3;
 
-      for (j = 0; j < nr_components; ++j, ++component) {
-         assert(component < VL_NUM_COMPONENTS);
+      for (j = 0; j < nr_components && component < VL_NUM_COMPONENTS; ++j, ++component) {
+         if (buf->sampler_view_components[component])
+            continue;
 
-         if (!buf->sampler_view_components[component]) {
-            memset(&sv_templ, 0, sizeof(sv_templ));
-            u_sampler_view_default_template(&sv_templ, res, res->format);
-            sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
-            sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
-            buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
-            if (!buf->sampler_view_components[component])
-               goto error;
-         }
+         memset(&sv_templ, 0, sizeof(sv_templ));
+         u_sampler_view_default_template(&sv_templ, res, sampler_format[plane_order[i]]);
+         sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
+         sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
+         buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
+         if (!buf->sampler_view_components[component])
+            goto error;
       }
    }
+   assert(component == VL_NUM_COMPONENTS);
 
    return buf->sampler_view_components;
 
@@ -285,28 +356,27 @@ vl_video_buffer_surfaces(struct pipe_video_buffer *buffer)
    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
    struct pipe_surface surf_templ;
    struct pipe_context *pipe;
-   unsigned i, j, depth, surf;
+   unsigned i, j, array_size, surf;
 
    assert(buf);
 
    pipe = buf->base.context;
 
-   depth = buffer->interlaced ? 2 : 1;
-   for (i = 0, surf = 0; i < depth; ++i ) {
-      for (j = 0; j < VL_NUM_COMPONENTS; ++j, ++surf) {
-         assert(surf < (VL_NUM_COMPONENTS * 2));
+   array_size = buffer->interlaced ? 2 : 1;
+   for (i = 0, surf = 0; i < VL_NUM_COMPONENTS; ++i) {
+      for (j = 0; j < array_size; ++j, ++surf) {
+         assert(surf < VL_MAX_SURFACES);
 
-         if (!buf->resources[j]) {
+         if (!buf->resources[i]) {
             pipe_surface_reference(&buf->surfaces[surf], NULL);
             continue;
          }
 
          if (!buf->surfaces[surf]) {
             memset(&surf_templ, 0, sizeof(surf_templ));
-            surf_templ.format = buf->resources[j]->format;
-            surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
-            surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = i;
-            buf->surfaces[surf] = pipe->create_surface(pipe, buf->resources[j], &surf_templ);
+            surf_templ.format = vl_video_buffer_surface_format(buf->resources[i]->format);
+            surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = j;
+            buf->surfaces[surf] = pipe->create_surface(pipe, buf->resources[i], &surf_templ);
             if (!buf->surfaces[surf])
                goto error;
          }
@@ -316,7 +386,7 @@ vl_video_buffer_surfaces(struct pipe_video_buffer *buffer)
    return buf->surfaces;
 
 error:
-   for (i = 0; i < (VL_NUM_COMPONENTS * 2); ++i )
+   for (i = 0; i < VL_MAX_SURFACES; ++i )
       pipe_surface_reference(&buf->surfaces[i], NULL);
 
    return NULL;
@@ -337,6 +407,7 @@ vl_video_buffer_create(struct pipe_context *pipe,
    (
       pipe->screen,
       PIPE_VIDEO_PROFILE_UNKNOWN,
+      PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
       PIPE_VIDEO_CAP_NPOT_TEXTURES
    );
 
@@ -356,7 +427,7 @@ vl_video_buffer_create(struct pipe_context *pipe,
    result = vl_video_buffer_create_ex
    (
       pipe, &templat, resource_formats,
-      tmpl->interlaced ? 2 : 1, PIPE_USAGE_STATIC
+      1, tmpl->interlaced ? 2 : 1, PIPE_USAGE_STATIC
    );
 
 
@@ -370,7 +441,7 @@ struct pipe_video_buffer *
 vl_video_buffer_create_ex(struct pipe_context *pipe,
                           const struct pipe_video_buffer *tmpl,
                           const enum pipe_format resource_formats[VL_NUM_COMPONENTS],
-                          unsigned depth, unsigned usage)
+                          unsigned depth, unsigned array_size, unsigned usage)
 {
    struct pipe_resource res_tmpl;
    struct pipe_resource *resources[VL_NUM_COMPONENTS];
@@ -380,18 +451,17 @@ vl_video_buffer_create_ex(struct pipe_context *pipe,
 
    memset(resources, 0, sizeof resources);
 
-   vl_vide_buffer_template(&res_tmpl, tmpl, resource_formats[0], depth, usage, 0);
+   vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[0], depth, array_size, usage, 0);
    resources[0] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
    if (!resources[0])
       goto error;
 
    if (resource_formats[1] == PIPE_FORMAT_NONE) {
-      assert(tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444);
       assert(resource_formats[2] == PIPE_FORMAT_NONE);
       return vl_video_buffer_create_ex2(pipe, tmpl, resources);
    }
 
-   vl_vide_buffer_template(&res_tmpl, tmpl, resource_formats[1], depth, usage, 1);
+   vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[1], depth, array_size, usage, 1);
    resources[1] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
    if (!resources[1])
       goto error;
@@ -399,7 +469,7 @@ vl_video_buffer_create_ex(struct pipe_context *pipe,
    if (resource_formats[2] == PIPE_FORMAT_NONE)
       return vl_video_buffer_create_ex2(pipe, tmpl, resources);
 
-   vl_vide_buffer_template(&res_tmpl, tmpl, resource_formats[2], depth, usage, 2);
+   vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[2], depth, array_size, usage, 2);
    resources[2] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
    if (!resources[2])
       goto error;
@@ -422,6 +492,8 @@ vl_video_buffer_create_ex2(struct pipe_context *pipe,
    unsigned i;
 
    buffer = CALLOC_STRUCT(vl_video_buffer);
+   if (!buffer)
+      return NULL;
 
    buffer->base = *tmpl;
    buffer->base.context = pipe;