1 /**************************************************************************
2 *
3 * Copyright 2010 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 VMWARE 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 #include "util/format/u_format.h"
30 #include "vl_vertex_buffers.h"
31 #include "vl_types.h"
32
33 /* vertices for a quad covering a block */
34 static const struct vertex2f block_quad[4] = {
35 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
36 };
37
38 struct pipe_vertex_buffer
vl_vb_upload_quads(struct pipe_context * pipe)39 vl_vb_upload_quads(struct pipe_context *pipe)
40 {
41 struct pipe_vertex_buffer quad;
42 struct pipe_transfer *buf_transfer;
43 struct vertex2f *v;
44
45 unsigned i;
46
47 assert(pipe);
48
49 /* create buffer */
50 quad.buffer_offset = 0;
51 quad.buffer.resource = pipe_buffer_create
52 (
53 pipe->screen,
54 PIPE_BIND_VERTEX_BUFFER,
55 PIPE_USAGE_DEFAULT,
56 sizeof(struct vertex2f) * 4
57 );
58 quad.is_user_buffer = false;
59
60 if(!quad.buffer.resource)
61 return quad;
62
63 /* and fill it */
64 v = pipe_buffer_map
65 (
66 pipe,
67 quad.buffer.resource,
68 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
69 &buf_transfer
70 );
71
72 for (i = 0; i < 4; ++i, ++v) {
73 v->x = block_quad[i].x;
74 v->y = block_quad[i].y;
75 }
76
77 pipe_buffer_unmap(pipe, buf_transfer);
78
79 return quad;
80 }
81
82 struct pipe_vertex_buffer
vl_vb_upload_pos(struct pipe_context * pipe,unsigned width,unsigned height)83 vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height)
84 {
85 struct pipe_vertex_buffer pos;
86 struct pipe_transfer *buf_transfer;
87 struct vertex2s *v;
88
89 unsigned x, y;
90
91 assert(pipe);
92
93 /* create buffer */
94 pos.buffer_offset = 0;
95 pos.buffer.resource = pipe_buffer_create
96 (
97 pipe->screen,
98 PIPE_BIND_VERTEX_BUFFER,
99 PIPE_USAGE_DEFAULT,
100 sizeof(struct vertex2s) * width * height
101 );
102 pos.is_user_buffer = false;
103
104 if(!pos.buffer.resource)
105 return pos;
106
107 /* and fill it */
108 v = pipe_buffer_map
109 (
110 pipe,
111 pos.buffer.resource,
112 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
113 &buf_transfer
114 );
115
116 for ( y = 0; y < height; ++y) {
117 for ( x = 0; x < width; ++x, ++v) {
118 v->x = x;
119 v->y = y;
120 }
121 }
122
123 pipe_buffer_unmap(pipe, buf_transfer);
124
125 return pos;
126 }
127
128 static struct pipe_vertex_element
vl_vb_get_quad_vertex_element(void)129 vl_vb_get_quad_vertex_element(void)
130 {
131 struct pipe_vertex_element element;
132
133 /* setup rectangle element */
134 element.src_offset = 0;
135 element.instance_divisor = 0;
136 element.vertex_buffer_index = 0;
137 element.dual_slot = false;
138 element.src_format = PIPE_FORMAT_R32G32_FLOAT;
139
140 return element;
141 }
142
143 static void
vl_vb_element_helper(struct pipe_vertex_element * elements,unsigned num_elements,unsigned vertex_buffer_index)144 vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements,
145 unsigned vertex_buffer_index)
146 {
147 unsigned i, offset = 0;
148
149 assert(elements && num_elements);
150
151 for ( i = 0; i < num_elements; ++i ) {
152 elements[i].src_offset = offset;
153 elements[i].instance_divisor = 1;
154 elements[i].vertex_buffer_index = vertex_buffer_index;
155 offset += util_format_get_blocksize(elements[i].src_format);
156 }
157 }
158
159 void *
vl_vb_get_ves_ycbcr(struct pipe_context * pipe)160 vl_vb_get_ves_ycbcr(struct pipe_context *pipe)
161 {
162 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
163
164 assert(pipe);
165
166 memset(&vertex_elems, 0, sizeof(vertex_elems));
167 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
168 vertex_elems[VS_I_RECT].src_stride = sizeof(struct vertex2f);
169
170 /* Position element */
171 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED;
172
173 /* block num element */
174 vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R32_FLOAT;
175 vertex_elems[VS_I_BLOCK_NUM].src_stride = sizeof(struct vertex2f);
176
177 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 2, 1);
178 vertex_elems[VS_I_VPOS].src_stride = sizeof(struct vl_ycbcr_block);
179
180 return pipe->create_vertex_elements_state(pipe, 3, vertex_elems);
181 }
182
183 void *
vl_vb_get_ves_mv(struct pipe_context * pipe)184 vl_vb_get_ves_mv(struct pipe_context *pipe)
185 {
186 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
187
188 assert(pipe);
189
190 memset(&vertex_elems, 0, sizeof(vertex_elems));
191 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
192 vertex_elems[VS_I_RECT].src_stride = sizeof(struct vertex2f);
193
194 /* Position element */
195 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED;
196
197 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1);
198 vertex_elems[VS_I_VPOS].src_stride = sizeof(struct vertex2s);
199
200 /* motion vector TOP element */
201 vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
202 vertex_elems[VS_I_MV_TOP].src_stride = sizeof(struct vertex2f);
203
204 /* motion vector BOTTOM element */
205 vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
206 vertex_elems[VS_I_MV_BOTTOM].src_stride = sizeof(struct vertex2f);
207
208 vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2);
209 vertex_elems[VS_I_MV_TOP].src_stride = sizeof(struct vl_motionvector);
210
211 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems);
212 }
213
214 bool
vl_vb_init(struct vl_vertex_buffer * buffer,struct pipe_context * pipe,unsigned width,unsigned height)215 vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe,
216 unsigned width, unsigned height)
217 {
218 unsigned i, size;
219
220 assert(buffer);
221
222 buffer->width = width;
223 buffer->height = height;
224
225 size = width * height;
226
227 for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
228 buffer->ycbcr[i].resource = pipe_buffer_create
229 (
230 pipe->screen,
231 PIPE_BIND_VERTEX_BUFFER,
232 PIPE_USAGE_STREAM,
233 sizeof(struct vl_ycbcr_block) * size * 4
234 );
235 if (!buffer->ycbcr[i].resource)
236 goto error_ycbcr;
237 }
238
239 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
240 buffer->mv[i].resource = pipe_buffer_create
241 (
242 pipe->screen,
243 PIPE_BIND_VERTEX_BUFFER,
244 PIPE_USAGE_STREAM,
245 sizeof(struct vl_motionvector) * size
246 );
247 if (!buffer->mv[i].resource)
248 goto error_mv;
249 }
250
251 return true;
252
253 error_mv:
254 for (i = 0; i < VL_NUM_COMPONENTS; ++i)
255 pipe_resource_reference(&buffer->mv[i].resource, NULL);
256
257 error_ycbcr:
258 for (i = 0; i < VL_NUM_COMPONENTS; ++i)
259 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL);
260 return false;
261 }
262
263 unsigned
vl_vb_attributes_per_plock(struct vl_vertex_buffer * buffer)264 vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer)
265 {
266 return 1;
267 }
268
269 struct pipe_vertex_buffer
vl_vb_get_ycbcr(struct vl_vertex_buffer * buffer,int component)270 vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component)
271 {
272 struct pipe_vertex_buffer buf;
273
274 assert(buffer);
275
276 buf.buffer_offset = 0;
277 buf.buffer.resource = buffer->ycbcr[component].resource;
278 buf.is_user_buffer = false;
279
280 return buf;
281 }
282
283 struct pipe_vertex_buffer
vl_vb_get_mv(struct vl_vertex_buffer * buffer,int motionvector)284 vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector)
285 {
286 struct pipe_vertex_buffer buf;
287
288 assert(buffer);
289
290 buf.buffer_offset = 0;
291 buf.buffer.resource = buffer->mv[motionvector].resource;
292 buf.is_user_buffer = false;
293
294 return buf;
295 }
296
297 void
vl_vb_map(struct vl_vertex_buffer * buffer,struct pipe_context * pipe)298 vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
299 {
300 unsigned i;
301
302 assert(buffer && pipe);
303
304 for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
305 buffer->ycbcr[i].vertex_stream = pipe_buffer_map
306 (
307 pipe,
308 buffer->ycbcr[i].resource,
309 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
310 &buffer->ycbcr[i].transfer
311 );
312 }
313
314 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
315 buffer->mv[i].vertex_stream = pipe_buffer_map
316 (
317 pipe,
318 buffer->mv[i].resource,
319 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
320 &buffer->mv[i].transfer
321 );
322 }
323
324 }
325
326 struct vl_ycbcr_block *
vl_vb_get_ycbcr_stream(struct vl_vertex_buffer * buffer,int component)327 vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component)
328 {
329 assert(buffer);
330 assert(component < VL_NUM_COMPONENTS);
331
332 return buffer->ycbcr[component].vertex_stream;
333 }
334
335 unsigned
vl_vb_get_mv_stream_stride(struct vl_vertex_buffer * buffer)336 vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer)
337 {
338 assert(buffer);
339
340 return buffer->width;
341 }
342
343 struct vl_motionvector *
vl_vb_get_mv_stream(struct vl_vertex_buffer * buffer,int ref_frame)344 vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame)
345 {
346 assert(buffer);
347 assert(ref_frame < VL_MAX_REF_FRAMES);
348
349 return buffer->mv[ref_frame].vertex_stream;
350 }
351
352 void
vl_vb_unmap(struct vl_vertex_buffer * buffer,struct pipe_context * pipe)353 vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
354 {
355 unsigned i;
356
357 assert(buffer && pipe);
358
359 for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
360 if (buffer->ycbcr[i].transfer)
361 pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer);
362 }
363
364 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
365 if (buffer->mv[i].transfer)
366 pipe_buffer_unmap(pipe, buffer->mv[i].transfer);
367 }
368 }
369
370 void
vl_vb_cleanup(struct vl_vertex_buffer * buffer)371 vl_vb_cleanup(struct vl_vertex_buffer *buffer)
372 {
373 unsigned i;
374
375 assert(buffer);
376
377 for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
378 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL);
379 }
380
381 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
382 pipe_resource_reference(&buffer->mv[i].resource, NULL);
383 }
384 }
385