[g3dvl] no need for seperate mv vertex states any more
[mesa.git] / src / gallium / auxiliary / vl / vl_vertex_buffers.c
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 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 #include <util/u_format.h>
30 #include "vl_vertex_buffers.h"
31 #include "vl_types.h"
32
33 struct vl_vertex_stream
34 {
35 struct vertex2s pos;
36 uint8_t mb_type_intra;
37 uint8_t dct_type_field;
38 uint8_t dummy[2];
39 uint8_t eb[3][2][2];
40 };
41
42 struct vl_mv_vertex_stream
43 {
44 struct vertex4s mv[2];
45 };
46
47 /* vertices for a quad covering a block */
48 static const struct vertex2f block_quad[4] = {
49 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
50 };
51
52 struct pipe_vertex_buffer
53 vl_vb_upload_quads(struct pipe_context *pipe, unsigned blocks_x, unsigned blocks_y)
54 {
55 struct pipe_vertex_buffer quad;
56 struct pipe_transfer *buf_transfer;
57 struct vertex4f *v;
58
59 unsigned x, y, i;
60
61 assert(pipe);
62
63 /* create buffer */
64 quad.stride = sizeof(struct vertex4f);
65 quad.buffer_offset = 0;
66 quad.buffer = pipe_buffer_create
67 (
68 pipe->screen,
69 PIPE_BIND_VERTEX_BUFFER,
70 PIPE_USAGE_STATIC,
71 sizeof(struct vertex4f) * 4 * blocks_x * blocks_y
72 );
73
74 if(!quad.buffer)
75 return quad;
76
77 /* and fill it */
78 v = pipe_buffer_map
79 (
80 pipe,
81 quad.buffer,
82 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
83 &buf_transfer
84 );
85
86 for ( y = 0; y < blocks_y; ++y) {
87 for ( x = 0; x < blocks_x; ++x) {
88 for (i = 0; i < 4; ++i, ++v) {
89 v->x = block_quad[i].x;
90 v->y = block_quad[i].y;
91
92 v->z = x;
93 v->w = y;
94 }
95 }
96 }
97
98 pipe_buffer_unmap(pipe, buf_transfer);
99
100 return quad;
101 }
102
103 struct pipe_vertex_buffer
104 vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height)
105 {
106 struct pipe_vertex_buffer pos;
107 struct pipe_transfer *buf_transfer;
108 struct vertex2s *v;
109
110 unsigned x, y;
111
112 assert(pipe);
113
114 /* create buffer */
115 pos.stride = sizeof(struct vertex2s);
116 pos.buffer_offset = 0;
117 pos.buffer = pipe_buffer_create
118 (
119 pipe->screen,
120 PIPE_BIND_VERTEX_BUFFER,
121 PIPE_USAGE_STATIC,
122 sizeof(struct vertex2s) * width * height
123 );
124
125 if(!pos.buffer)
126 return pos;
127
128 /* and fill it */
129 v = pipe_buffer_map
130 (
131 pipe,
132 pos.buffer,
133 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
134 &buf_transfer
135 );
136
137 for ( y = 0; y < height; ++y) {
138 for ( x = 0; x < width; ++x, ++v) {
139 v->x = x;
140 v->y = y;
141 }
142 }
143
144 pipe_buffer_unmap(pipe, buf_transfer);
145
146 return pos;
147 }
148
149 static struct pipe_vertex_element
150 vl_vb_get_quad_vertex_element(void)
151 {
152 struct pipe_vertex_element element;
153
154 /* setup rectangle element */
155 element.src_offset = 0;
156 element.instance_divisor = 0;
157 element.vertex_buffer_index = 0;
158 element.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
159
160 return element;
161 }
162
163 static void
164 vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements,
165 unsigned vertex_buffer_index)
166 {
167 unsigned i, offset = 0;
168
169 assert(elements && num_elements);
170
171 for ( i = 0; i < num_elements; ++i ) {
172 if (elements[i].src_offset)
173 offset = elements[i].src_offset;
174 else
175 elements[i].src_offset = offset;
176 elements[i].instance_divisor = 1;
177 elements[i].vertex_buffer_index = vertex_buffer_index;
178 offset += util_format_get_blocksize(elements[i].src_format);
179 }
180 }
181
182 void *
183 vl_vb_get_ves_eb(struct pipe_context *pipe, int component)
184 {
185 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
186
187 assert(pipe);
188
189 memset(&vertex_elems, 0, sizeof(vertex_elems));
190 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
191
192 /* Position element */
193 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED;
194
195 /* flags */
196 vertex_elems[VS_I_FLAGS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED;
197
198 /* empty block element of selected component */
199 vertex_elems[VS_I_EB].src_offset = offsetof(struct vl_vertex_stream, eb[component]);
200 vertex_elems[VS_I_EB].src_format = PIPE_FORMAT_R8G8B8A8_USCALED;
201
202 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], NUM_VS_INPUTS - 1, 1);
203
204 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems);
205 }
206
207 void *
208 vl_vb_get_ves_mv(struct pipe_context *pipe)
209 {
210 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
211
212 assert(pipe);
213
214 memset(&vertex_elems, 0, sizeof(vertex_elems));
215 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
216
217 /* Position element */
218 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED;
219
220 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1);
221
222 /* motion vector TOP element */
223 vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
224
225 /* motion vector BOTTOM element */
226 vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
227
228 vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2);
229
230 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems);
231 }
232
233 void
234 vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, unsigned width, unsigned height)
235 {
236 unsigned i;
237
238 assert(buffer);
239
240 buffer->width = width;
241 buffer->height = height;
242 buffer->num_instances = 0;
243
244 buffer->resource = pipe_buffer_create
245 (
246 pipe->screen,
247 PIPE_BIND_VERTEX_BUFFER,
248 PIPE_USAGE_STREAM,
249 sizeof(struct vl_vertex_stream) * width * height
250 );
251
252 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
253 buffer->mv[i].resource = pipe_buffer_create
254 (
255 pipe->screen,
256 PIPE_BIND_VERTEX_BUFFER,
257 PIPE_USAGE_STREAM,
258 sizeof(struct vl_mv_vertex_stream) * width * height
259 );
260 }
261
262 vl_vb_map(buffer, pipe);
263 }
264
265 struct pipe_vertex_buffer
266 vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer)
267 {
268 struct pipe_vertex_buffer buf;
269
270 assert(buffer);
271
272 buf.stride = sizeof(struct vl_vertex_stream);
273 buf.buffer_offset = 0;
274 buf.buffer = buffer->resource;
275
276 return buf;
277 }
278
279 struct pipe_vertex_buffer
280 vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector)
281 {
282 struct pipe_vertex_buffer buf;
283
284 assert(buffer);
285
286 buf.stride = sizeof(struct vl_mv_vertex_stream);
287 buf.buffer_offset = 0;
288 buf.buffer = buffer->mv[motionvector].resource;
289
290 return buf;
291 }
292
293 void
294 vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
295 {
296 unsigned i;
297
298 assert(buffer && pipe);
299
300 buffer->buffer = pipe_buffer_map
301 (
302 pipe,
303 buffer->resource,
304 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
305 &buffer->transfer
306 );
307
308 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
309 buffer->mv[i].vertex_stream = pipe_buffer_map
310 (
311 pipe,
312 buffer->mv[i].resource,
313 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
314 &buffer->mv[i].transfer
315 );
316 }
317
318 }
319
320 static void
321 get_motion_vectors(enum pipe_mpeg12_motion_type mo_type, struct pipe_motionvector *src, struct vertex4s dst[2])
322 {
323 if (mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
324 dst[0].x = dst[1].x = src->top.x;
325 dst[0].y = dst[1].y = src->top.y;
326 dst[0].z = dst[1].z = 0;
327
328 } else {
329 dst[0].x = src->top.x;
330 dst[0].y = src->top.y;
331 dst[0].z = src->top.field_select ? 3 : 1;
332
333 dst[1].x = src->bottom.x;
334 dst[1].y = src->bottom.y;
335 dst[1].z = src->bottom.field_select ? 3 : 1;
336 }
337
338 dst[0].w = src->top.wheight;
339 dst[1].w = src->bottom.wheight;
340 }
341
342 void
343 vl_vb_add_block(struct vl_vertex_buffer *buffer, struct pipe_mpeg12_macroblock *mb,
344 const unsigned (*empty_block_mask)[3][2][2])
345 {
346 unsigned i, j, k;
347 unsigned mv_pos;
348
349 assert(buffer);
350 assert(mb);
351 assert(buffer->num_instances < buffer->width * buffer->height);
352
353 if(mb->cbp) {
354 struct vl_vertex_stream *stream;
355 stream = buffer->buffer + buffer->num_instances++;
356
357 stream->pos.x = mb->mbx;
358 stream->pos.y = mb->mby;
359
360 for ( i = 0; i < 3; ++i)
361 for ( j = 0; j < 2; ++j)
362 for ( k = 0; k < 2; ++k)
363 stream->eb[i][j][k] = !(mb->cbp & (*empty_block_mask)[i][j][k]);
364
365 stream->dct_type_field = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD;
366 stream->mb_type_intra = mb->dct_intra;
367 }
368
369 mv_pos = mb->mbx + mb->mby * buffer->width;
370 get_motion_vectors(mb->mo_type, &mb->mv[0], buffer->mv[0].vertex_stream[mv_pos].mv);
371 get_motion_vectors(mb->mo_type, &mb->mv[1], buffer->mv[1].vertex_stream[mv_pos].mv);
372 }
373
374 void
375 vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
376 {
377 unsigned i;
378
379 assert(buffer && pipe);
380
381 pipe_buffer_unmap(pipe, buffer->transfer);
382 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
383 pipe_buffer_unmap(pipe, buffer->mv[i].transfer);
384 }
385 }
386
387 unsigned
388 vl_vb_restart(struct vl_vertex_buffer *buffer)
389 {
390 unsigned num_instances;
391
392 assert(buffer);
393
394 num_instances = buffer->num_instances;
395 buffer->num_instances = 0;
396 return num_instances;
397 }
398
399 void
400 vl_vb_cleanup(struct vl_vertex_buffer *buffer)
401 {
402 unsigned i;
403
404 assert(buffer);
405
406 pipe_resource_reference(&buffer->resource, NULL);
407
408 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
409 pipe_resource_reference(&buffer->mv[i].resource, NULL);
410 }
411 }