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