[g3dvl] rework video buffer format handling
[mesa.git] / src / gallium / auxiliary / vl / vl_video_buffer.c
index 5ea0dfa37362c13d13ac22634c119210445c73be..93bc096b7332aaa1b590bbc2d5c76fc2fff0bf83 100644 (file)
 
 #include "vl_video_buffer.h"
 
-static inline void
-adjust_swizzle(struct pipe_sampler_view *sv_templ)
+const enum pipe_format const_resource_formats_YV12[3] = {
+   PIPE_FORMAT_R8_UNORM,
+   PIPE_FORMAT_R8_UNORM,
+   PIPE_FORMAT_R8_UNORM
+};
+
+const enum pipe_format const_resource_formats_NV12[3] = {
+   PIPE_FORMAT_R8_UNORM,
+   PIPE_FORMAT_R8G8_UNORM,
+   PIPE_FORMAT_NONE
+};
+
+const enum pipe_format *
+vl_video_buffer_formats(struct pipe_context *pipe, enum pipe_format format)
 {
-   if (util_format_get_nr_components(sv_templ->format) == 1) {
-      sv_templ->swizzle_r = PIPE_SWIZZLE_RED;
-      sv_templ->swizzle_g = PIPE_SWIZZLE_RED;
-      sv_templ->swizzle_b = PIPE_SWIZZLE_RED;
-      sv_templ->swizzle_a = PIPE_SWIZZLE_RED;
+   switch(format) {
+   case PIPE_FORMAT_YV12:
+      return const_resource_formats_YV12;
+
+   case PIPE_FORMAT_NV12:
+      return const_resource_formats_NV12;
+
+   default:
+      return NULL;
    }
 }
 
@@ -59,13 +75,14 @@ vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
 
    for (i = 0; i < VL_MAX_PLANES; ++i) {
       pipe_surface_reference(&buf->surfaces[i], NULL);
-      pipe_sampler_view_reference(&buf->sampler_views[i], NULL);
+      pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
+      pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
       pipe_resource_reference(&buf->resources[i], NULL);
    }
 }
 
 static struct pipe_sampler_view **
-vl_video_buffer_sampler_views(struct pipe_video_buffer *buffer)
+vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
 {
    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
    struct pipe_sampler_view sv_templ;
@@ -77,21 +94,63 @@ vl_video_buffer_sampler_views(struct pipe_video_buffer *buffer)
    pipe = buf->pipe;
 
    for (i = 0; i < buf->num_planes; ++i ) {
-      if (!buf->sampler_views[i]) {
+      if (!buf->sampler_view_planes[i]) {
          memset(&sv_templ, 0, sizeof(sv_templ));
          u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format);
-         adjust_swizzle(&sv_templ);
-         buf->sampler_views[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
-         if (!buf->sampler_views[i])
+
+         if (util_format_get_nr_components(buf->resources[i]->format) == 1)
+            sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED;
+
+         buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
+         if (!buf->sampler_view_planes[i])
             goto error;
       }
    }
 
-   return buf->sampler_views;
+   return buf->sampler_view_planes;
 
 error:
    for (i = 0; i < buf->num_planes; ++i )
-      pipe_sampler_view_reference(&buf->sampler_views[i], NULL);
+      pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
+
+   return NULL;
+}
+
+static struct pipe_sampler_view **
+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;
+   unsigned i, j, component;
+
+   assert(buf);
+
+   pipe = buf->pipe;
+
+   for (component = 0, i = 0; i < buf->num_planes; ++i ) {
+      unsigned nr_components = util_format_get_nr_components(buf->resources[i]->format);
+
+      for (j = 0; j < nr_components; ++j, ++component) {
+         assert(component < VL_MAX_PLANES);
+
+         if (!buf->sampler_view_components[component]) {
+            memset(&sv_templ, 0, sizeof(sv_templ));
+            u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->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, buf->resources[i], &sv_templ);
+            if (!buf->sampler_view_components[component])
+               goto error;
+         }
+      }
+   }
+
+   return buf->sampler_view_components;
+
+error:
+   for (i = 0; i < VL_MAX_PLANES; ++i )
+      pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
 
    return NULL;
 }
@@ -133,7 +192,6 @@ vl_video_buffer_init(struct pipe_video_context *context,
                      struct pipe_context *pipe,
                      unsigned width, unsigned height, unsigned depth,
                      enum pipe_video_chroma_format chroma_format,
-                     unsigned num_planes,
                      const enum pipe_format resource_formats[VL_MAX_PLANES],
                      unsigned usage)
 {
@@ -142,18 +200,21 @@ vl_video_buffer_init(struct pipe_video_context *context,
    unsigned i;
 
    assert(context && pipe);
-   assert(num_planes > 0 && num_planes <= VL_MAX_PLANES);
 
    buffer = CALLOC_STRUCT(vl_video_buffer);
 
    buffer->base.destroy = vl_video_buffer_destroy;
-   buffer->base.get_sampler_views = vl_video_buffer_sampler_views;
+   buffer->base.get_sampler_view_planes = vl_video_buffer_sampler_view_planes;
+   buffer->base.get_sampler_view_components = vl_video_buffer_sampler_view_components;
    buffer->base.get_surfaces = vl_video_buffer_surfaces;
+   buffer->base.chroma_format = chroma_format;
+   buffer->base.width = width;
+   buffer->base.height = height;
    buffer->pipe = pipe;
-   buffer->num_planes = num_planes;
+   buffer->num_planes = 1;
 
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = depth > 1 ? PIPE_TEXTURE_3D : PIPE_TEXTURE_2D;
    templ.format = resource_formats[0];
    templ.width0 = width;
    templ.height0 = height;
@@ -166,31 +227,29 @@ vl_video_buffer_init(struct pipe_video_context *context,
    if (!buffer->resources[0])
       goto error;
 
-   if (num_planes == 1) {
+   if (resource_formats[1] == PIPE_FORMAT_NONE) {
       assert(chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444);
+      assert(resource_formats[2] == PIPE_FORMAT_NONE);
       return &buffer->base;
-   }
+   } else
+      buffer->num_planes = 2;
 
    templ.format = resource_formats[1];
    if (chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
-      if (depth > 1)
-         templ.depth0 /= 2;
-      else
-         templ.width0 /= 2;
+      templ.width0 /= 2;
       templ.height0 /= 2;
    } else if (chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
-      if (depth > 1)
-         templ.depth0 /= 2;
-      else
-         templ.height0 /= 2;
+      templ.height0 /= 2;
    }
 
    buffer->resources[1] = pipe->screen->resource_create(pipe->screen, &templ);
    if (!buffer->resources[1])
       goto error;
 
-   if (num_planes == 2)
+   if (resource_formats[2] == PIPE_FORMAT_NONE)
       return &buffer->base;
+   else
+      buffer->num_planes = 3;
 
    templ.format = resource_formats[2];
    buffer->resources[2] = pipe->screen->resource_create(pipe->screen, &templ);