vl_vertex_buffers.c revision d3770d6229d95e9beb67358ae2b2c8824ed3ae58
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/* vertices for a quad covering a block */
34static 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
38struct pipe_vertex_buffer
39vl_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.stride = sizeof(struct vertex2f);
51   quad.buffer_offset = 0;
52   quad.buffer = pipe_buffer_create
53   (
54      pipe->screen,
55      PIPE_BIND_VERTEX_BUFFER,
56      PIPE_USAGE_STATIC,
57      sizeof(struct vertex2f) * 4
58   );
59
60   if(!quad.buffer)
61      return quad;
62
63   /* and fill it */
64   v = pipe_buffer_map
65   (
66      pipe,
67      quad.buffer,
68      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
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
82struct pipe_vertex_buffer
83vl_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.stride = sizeof(struct vertex2s);
95   pos.buffer_offset = 0;
96   pos.buffer = pipe_buffer_create
97   (
98      pipe->screen,
99      PIPE_BIND_VERTEX_BUFFER,
100      PIPE_USAGE_STATIC,
101      sizeof(struct vertex2s) * width * height
102   );
103
104   if(!pos.buffer)
105      return pos;
106
107   /* and fill it */
108   v = pipe_buffer_map
109   (
110      pipe,
111      pos.buffer,
112      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
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
128struct pipe_vertex_buffer
129vl_vb_upload_block_num(struct pipe_context *pipe, unsigned num_blocks)
130{
131   struct pipe_vertex_buffer buf;
132   struct pipe_transfer *buf_transfer;
133   struct vertex2s *v;
134   unsigned i;
135
136   assert(pipe);
137
138   /* create buffer */
139   buf.stride = sizeof(struct vertex2s);
140   buf.buffer_offset = 0;
141   buf.buffer = pipe_buffer_create
142   (
143      pipe->screen,
144      PIPE_BIND_VERTEX_BUFFER,
145      PIPE_USAGE_STATIC,
146      sizeof(struct vertex2s) * num_blocks
147   );
148
149   if(!buf.buffer)
150      return buf;
151
152   /* and fill it */
153   v = pipe_buffer_map
154   (
155      pipe,
156      buf.buffer,
157      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
158      &buf_transfer
159   );
160
161   for ( i = 0; i < num_blocks; ++i, ++v) {
162      v->x = i;
163      v->y = i;
164   }
165
166   pipe_buffer_unmap(pipe, buf_transfer);
167
168   return buf;
169}
170
171static struct pipe_vertex_element
172vl_vb_get_quad_vertex_element(void)
173{
174   struct pipe_vertex_element element;
175
176   /* setup rectangle element */
177   element.src_offset = 0;
178   element.instance_divisor = 0;
179   element.vertex_buffer_index = 0;
180   element.src_format = PIPE_FORMAT_R32G32_FLOAT;
181
182   return element;
183}
184
185static void
186vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements,
187                     unsigned vertex_buffer_index)
188{
189   unsigned i, offset = 0;
190
191   assert(elements && num_elements);
192
193   for ( i = 0; i < num_elements; ++i ) {
194      elements[i].src_offset = offset;
195      elements[i].instance_divisor = 1;
196      elements[i].vertex_buffer_index = vertex_buffer_index;
197      offset += util_format_get_blocksize(elements[i].src_format);
198   }
199}
200
201void *
202vl_vb_get_ves_ycbcr(struct pipe_context *pipe)
203{
204   struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
205
206   assert(pipe);
207
208   memset(&vertex_elems, 0, sizeof(vertex_elems));
209   vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
210
211   /* Position element */
212   vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED;
213
214   vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1);
215
216   /* block num element */
217   vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R16G16_SSCALED;
218
219   vl_vb_element_helper(&vertex_elems[VS_I_BLOCK_NUM], 1, 2);
220
221   return pipe->create_vertex_elements_state(pipe, 3, vertex_elems);
222}
223
224void *
225vl_vb_get_ves_mv(struct pipe_context *pipe)
226{
227   struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
228
229   assert(pipe);
230
231   memset(&vertex_elems, 0, sizeof(vertex_elems));
232   vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
233
234   /* Position element */
235   vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED;
236
237   vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1);
238
239   /* motion vector TOP element */
240   vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
241
242   /* motion vector BOTTOM element */
243   vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
244
245   vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2);
246
247   return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems);
248}
249
250bool
251vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe,
252           unsigned width, unsigned height)
253{
254   unsigned i, size;
255
256   assert(buffer);
257
258   buffer->width = width;
259   buffer->height = height;
260
261   size = width * height;
262
263   for (i = 0; i < VL_MAX_PLANES; ++i) {
264      buffer->ycbcr[i].resource = pipe_buffer_create
265      (
266         pipe->screen,
267         PIPE_BIND_VERTEX_BUFFER,
268         PIPE_USAGE_STREAM,
269         sizeof(struct vl_ycbcr_block) * size * 4
270      );
271      if (!buffer->ycbcr[i].resource)
272         goto error_ycbcr;
273   }
274
275   for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
276      buffer->mv[i].resource = pipe_buffer_create
277      (
278         pipe->screen,
279         PIPE_BIND_VERTEX_BUFFER,
280         PIPE_USAGE_STREAM,
281         sizeof(struct vl_motionvector) * size
282      );
283      if (!buffer->mv[i].resource)
284         goto error_mv;
285   }
286
287   vl_vb_map(buffer, pipe);
288   return true;
289
290error_mv:
291   for (i = 0; i < VL_MAX_PLANES; ++i)
292      pipe_resource_reference(&buffer->mv[i].resource, NULL);
293
294error_ycbcr:
295   for (i = 0; i < VL_MAX_PLANES; ++i)
296      pipe_resource_reference(&buffer->ycbcr[i].resource, NULL);
297   return false;
298}
299
300unsigned
301vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer)
302{
303   return 1;
304}
305
306struct pipe_vertex_buffer
307vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component)
308{
309   struct pipe_vertex_buffer buf;
310
311   assert(buffer);
312
313   buf.stride = sizeof(struct vl_ycbcr_block);
314   buf.buffer_offset = 0;
315   buf.buffer = buffer->ycbcr[component].resource;
316
317   return buf;
318}
319
320struct pipe_vertex_buffer
321vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector)
322{
323   struct pipe_vertex_buffer buf;
324
325   assert(buffer);
326
327   buf.stride = sizeof(struct vl_motionvector);
328   buf.buffer_offset = 0;
329   buf.buffer = buffer->mv[motionvector].resource;
330
331   return buf;
332}
333
334void
335vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
336{
337   unsigned i;
338
339   assert(buffer && pipe);
340
341   for (i = 0; i < VL_MAX_PLANES; ++i) {
342      buffer->ycbcr[i].vertex_stream = pipe_buffer_map
343      (
344         pipe,
345         buffer->ycbcr[i].resource,
346         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
347         &buffer->ycbcr[i].transfer
348      );
349   }
350
351   for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
352      buffer->mv[i].vertex_stream = pipe_buffer_map
353      (
354         pipe,
355         buffer->mv[i].resource,
356         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
357         &buffer->mv[i].transfer
358      );
359   }
360
361}
362
363struct vl_ycbcr_block *
364vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component)
365{
366   assert(buffer);
367   assert(component < VL_MAX_PLANES);
368
369   return buffer->ycbcr[component].vertex_stream;
370}
371
372unsigned
373vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer)
374{
375   assert(buffer);
376
377   return buffer->width;
378}
379
380struct vl_motionvector *
381vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame)
382{
383   assert(buffer);
384   assert(ref_frame < VL_MAX_REF_FRAMES);
385
386   return buffer->mv[ref_frame].vertex_stream;
387}
388
389void
390vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
391{
392   unsigned i;
393
394   assert(buffer && pipe);
395
396   for (i = 0; i < VL_MAX_PLANES; ++i) {
397      pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer);
398   }
399
400   for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
401      pipe_buffer_unmap(pipe, buffer->mv[i].transfer);
402   }
403}
404
405void
406vl_vb_cleanup(struct vl_vertex_buffer *buffer)
407{
408   unsigned i;
409
410   assert(buffer);
411
412   for (i = 0; i < VL_MAX_PLANES; ++i) {
413      pipe_resource_reference(&buffer->ycbcr[i].resource, NULL);
414   }
415
416   for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
417      pipe_resource_reference(&buffer->mv[i].resource, NULL);
418   }
419}
420