summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau/nouveau_vp3_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nouveau/nouveau_vp3_video.c')
-rw-r--r--src/gallium/drivers/nouveau/nouveau_vp3_video.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.c b/src/gallium/drivers/nouveau/nouveau_vp3_video.c
new file mode 100644
index 0000000..a55c2e8
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2011-2013 Maarten Lankhorst
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "nouveau_screen.h"
+#include "nouveau_context.h"
+#include "nouveau_vp3_video.h"
+
+#include "util/u_video.h"
+#include "util/u_format.h"
+#include "util/u_sampler.h"
+
+static struct pipe_sampler_view **
+nouveau_vp3_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
+{
+ struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
+ return buf->sampler_view_planes;
+}
+
+static struct pipe_sampler_view **
+nouveau_vp3_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
+{
+ struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
+ return buf->sampler_view_components;
+}
+
+static struct pipe_surface **
+nouveau_vp3_video_buffer_surfaces(struct pipe_video_buffer *buffer)
+{
+ struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
+ return buf->surfaces;
+}
+
+static void
+nouveau_vp3_video_buffer_destroy(struct pipe_video_buffer *buffer)
+{
+ struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
+ unsigned i;
+
+ assert(buf);
+
+ for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
+ pipe_resource_reference(&buf->resources[i], NULL);
+ pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
+ pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
+ pipe_surface_reference(&buf->surfaces[i * 2], NULL);
+ pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
+ }
+ FREE(buffer);
+}
+
+struct pipe_video_buffer *
+nouveau_vp3_video_buffer_create(struct pipe_context *pipe,
+ const struct pipe_video_buffer *templat,
+ int flags)
+{
+ struct nouveau_vp3_video_buffer *buffer;
+ struct pipe_resource templ;
+ unsigned i, j, component;
+ struct pipe_sampler_view sv_templ;
+ struct pipe_surface surf_templ;
+
+ assert(templat->interlaced);
+ if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12)
+ return vl_video_buffer_create(pipe, templat);
+
+ assert(templat->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
+
+ buffer = CALLOC_STRUCT(nouveau_vp3_video_buffer);
+ if (!buffer)
+ return NULL;
+
+ buffer->base.buffer_format = templat->buffer_format;
+ buffer->base.context = pipe;
+ buffer->base.destroy = nouveau_vp3_video_buffer_destroy;
+ buffer->base.chroma_format = templat->chroma_format;
+ buffer->base.width = templat->width;
+ buffer->base.height = templat->height;
+ buffer->base.get_sampler_view_planes = nouveau_vp3_video_buffer_sampler_view_planes;
+ buffer->base.get_sampler_view_components = nouveau_vp3_video_buffer_sampler_view_components;
+ buffer->base.get_surfaces = nouveau_vp3_video_buffer_surfaces;
+ buffer->base.interlaced = true;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D_ARRAY;
+ templ.depth0 = 1;
+ templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+ templ.format = PIPE_FORMAT_R8_UNORM;
+ templ.width0 = buffer->base.width;
+ templ.height0 = (buffer->base.height + 1)/2;
+ templ.flags = flags;
+ templ.array_size = 2;
+
+ buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
+ if (!buffer->resources[0])
+ goto error;
+
+ templ.format = PIPE_FORMAT_R8G8_UNORM;
+ buffer->num_planes = 2;
+ templ.width0 = (templ.width0 + 1) / 2;
+ templ.height0 = (templ.height0 + 1) / 2;
+ for (i = 1; i < buffer->num_planes; ++i) {
+ buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
+ if (!buffer->resources[i])
+ goto error;
+ }
+
+ memset(&sv_templ, 0, sizeof(sv_templ));
+ for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
+ struct pipe_resource *res = buffer->resources[i];
+ unsigned nr_components = util_format_get_nr_components(res->format);
+
+ u_sampler_view_default_template(&sv_templ, res, res->format);
+ buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
+ if (!buffer->sampler_view_planes[i])
+ goto error;
+
+ for (j = 0; j < nr_components; ++j, ++component) {
+ sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
+ sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
+
+ buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
+ if (!buffer->sampler_view_components[component])
+ goto error;
+ }
+ }
+
+ memset(&surf_templ, 0, sizeof(surf_templ));
+ for (j = 0; j < buffer->num_planes; ++j) {
+ surf_templ.format = buffer->resources[j]->format;
+ surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
+ buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
+ if (!buffer->surfaces[j * 2])
+ goto error;
+
+ surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
+ buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
+ if (!buffer->surfaces[j * 2 + 1])
+ goto error;
+ }
+
+ return &buffer->base;
+
+error:
+ nouveau_vp3_video_buffer_destroy(&buffer->base);
+ return NULL;
+}