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