Merge remote-tracking branch 'mareko/r300g-draw-instanced' into pipe-video
[mesa.git] / src / gallium / auxiliary / vl / vl_video_buffer.c
1 /**************************************************************************
2 *
3 * Copyright 2011 Christian König.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <assert.h>
29
30 #include <pipe/p_screen.h>
31 #include <pipe/p_context.h>
32 #include <pipe/p_state.h>
33
34 #include <util/u_format.h>
35 #include <util/u_inlines.h>
36 #include <util/u_sampler.h>
37 #include <util/u_memory.h>
38
39 #include "vl_video_buffer.h"
40
41 static void
42 vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
43 {
44 struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
45 unsigned i;
46
47 assert(buf);
48
49 for (i = 0; i < VL_MAX_PLANES; ++i) {
50 pipe_surface_reference(&buf->surfaces[i], NULL);
51 pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
52 pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
53 pipe_resource_reference(&buf->resources[i], NULL);
54 }
55 }
56
57 static struct pipe_sampler_view **
58 vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
59 {
60 struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
61 struct pipe_sampler_view sv_templ;
62 struct pipe_context *pipe;
63 unsigned i;
64
65 assert(buf);
66
67 pipe = buf->pipe;
68
69 for (i = 0; i < buf->num_planes; ++i ) {
70 if (!buf->sampler_view_planes[i]) {
71 memset(&sv_templ, 0, sizeof(sv_templ));
72 u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format);
73
74 if (util_format_get_nr_components(buf->resources[i]->format) == 1)
75 sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED;
76
77 buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
78 if (!buf->sampler_view_planes[i])
79 goto error;
80 }
81 }
82
83 return buf->sampler_view_planes;
84
85 error:
86 for (i = 0; i < buf->num_planes; ++i )
87 pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
88
89 return NULL;
90 }
91
92 static struct pipe_sampler_view **
93 vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
94 {
95 struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
96 struct pipe_sampler_view sv_templ;
97 struct pipe_context *pipe;
98 unsigned i, j, component;
99
100 assert(buf);
101
102 pipe = buf->pipe;
103
104 for (component = 0, i = 0; i < buf->num_planes; ++i ) {
105 unsigned nr_components = util_format_get_nr_components(buf->resources[i]->format);
106
107 for (j = 0; j < nr_components; ++j, ++component) {
108 assert(component < VL_MAX_PLANES);
109
110 if (!buf->sampler_view_components[component]) {
111 memset(&sv_templ, 0, sizeof(sv_templ));
112 u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format);
113 sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
114 sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
115 buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
116 if (!buf->sampler_view_components[component])
117 goto error;
118 }
119 }
120 }
121
122 return buf->sampler_view_components;
123
124 error:
125 for (i = 0; i < VL_MAX_PLANES; ++i )
126 pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
127
128 return NULL;
129 }
130
131 static struct pipe_surface **
132 vl_video_buffer_surfaces(struct pipe_video_buffer *buffer)
133 {
134 struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
135 struct pipe_surface surf_templ;
136 struct pipe_context *pipe;
137 unsigned i;
138
139 assert(buf);
140
141 pipe = buf->pipe;
142
143 for (i = 0; i < buf->num_planes; ++i ) {
144 if (!buf->surfaces[i]) {
145 memset(&surf_templ, 0, sizeof(surf_templ));
146 surf_templ.format = buf->resources[i]->format;
147 surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
148 buf->surfaces[i] = pipe->create_surface(pipe, buf->resources[i], &surf_templ);
149 if (!buf->surfaces[i])
150 goto error;
151 }
152 }
153
154 return buf->surfaces;
155
156 error:
157 for (i = 0; i < buf->num_planes; ++i )
158 pipe_surface_reference(&buf->surfaces[i], NULL);
159
160 return NULL;
161 }
162
163 struct pipe_video_buffer *
164 vl_video_buffer_init(struct pipe_video_context *context,
165 struct pipe_context *pipe,
166 unsigned width, unsigned height, unsigned depth,
167 enum pipe_video_chroma_format chroma_format,
168 const enum pipe_format resource_formats[VL_MAX_PLANES],
169 unsigned usage)
170 {
171 struct vl_video_buffer *buffer;
172 struct pipe_resource templ;
173 unsigned i;
174
175 assert(context && pipe);
176
177 buffer = CALLOC_STRUCT(vl_video_buffer);
178
179 buffer->base.destroy = vl_video_buffer_destroy;
180 buffer->base.get_sampler_view_planes = vl_video_buffer_sampler_view_planes;
181 buffer->base.get_sampler_view_components = vl_video_buffer_sampler_view_components;
182 buffer->base.get_surfaces = vl_video_buffer_surfaces;
183 buffer->base.chroma_format = chroma_format;
184 buffer->base.width = width;
185 buffer->base.height = height;
186 buffer->pipe = pipe;
187 buffer->num_planes = 1;
188
189 memset(&templ, 0, sizeof(templ));
190 templ.target = depth > 1 ? PIPE_TEXTURE_3D : PIPE_TEXTURE_2D;
191 templ.format = resource_formats[0];
192 templ.width0 = width;
193 templ.height0 = height;
194 templ.depth0 = depth;
195 templ.array_size = 1;
196 templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
197 templ.usage = usage;
198
199 buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
200 if (!buffer->resources[0])
201 goto error;
202
203 if (resource_formats[1] == PIPE_FORMAT_NONE) {
204 assert(chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444);
205 assert(resource_formats[2] == PIPE_FORMAT_NONE);
206 return &buffer->base;
207 } else
208 buffer->num_planes = 2;
209
210 templ.format = resource_formats[1];
211 if (chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
212 templ.width0 /= 2;
213 templ.height0 /= 2;
214 } else if (chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
215 templ.height0 /= 2;
216 }
217
218 buffer->resources[1] = pipe->screen->resource_create(pipe->screen, &templ);
219 if (!buffer->resources[1])
220 goto error;
221
222 if (resource_formats[2] == PIPE_FORMAT_NONE)
223 return &buffer->base;
224 else
225 buffer->num_planes = 3;
226
227 templ.format = resource_formats[2];
228 buffer->resources[2] = pipe->screen->resource_create(pipe->screen, &templ);
229 if (!buffer->resources[2])
230 goto error;
231
232 return &buffer->base;
233
234 error:
235 for (i = 0; i < VL_MAX_PLANES; ++i)
236 pipe_resource_reference(&buffer->resources[i], NULL);
237 FREE(buffer);
238
239 return NULL;
240 }