vl_vertex_buffers.c revision 849bc838e81f930e6f090e6c6597bb92e822b4c9
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 struct vertex2s pos; 36 uint8_t mb_type_intra; 37 uint8_t dct_type_field; 38 uint8_t dummy[2]; 39 uint8_t eb[2][2]; 40}; 41 42struct vl_mv_vertex_stream 43{ 44 struct vertex4s mv[2]; 45}; 46 47/* vertices for a quad covering a block */ 48static 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 52struct pipe_vertex_buffer 53vl_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 103struct pipe_vertex_buffer 104vl_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 149static struct pipe_vertex_element 150vl_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 163static void 164vl_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 elements[i].src_offset = offset; 173 elements[i].instance_divisor = 1; 174 elements[i].vertex_buffer_index = vertex_buffer_index; 175 offset += util_format_get_blocksize(elements[i].src_format); 176 } 177} 178 179void * 180vl_vb_get_ves_ycbcr(struct pipe_context *pipe) 181{ 182 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 183 184 assert(pipe); 185 186 memset(&vertex_elems, 0, sizeof(vertex_elems)); 187 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 188 189 /* Position element */ 190 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; 191 192 /* flags */ 193 vertex_elems[VS_I_FLAGS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED; 194 195 /* empty block element of selected component */ 196 vertex_elems[VS_I_EB].src_format = PIPE_FORMAT_R8G8B8A8_USCALED; 197 198 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], NUM_VS_INPUTS - 1, 1); 199 200 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems); 201} 202 203void * 204vl_vb_get_ves_mv(struct pipe_context *pipe) 205{ 206 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 207 208 assert(pipe); 209 210 memset(&vertex_elems, 0, sizeof(vertex_elems)); 211 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 212 213 /* Position element */ 214 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; 215 216 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1); 217 218 /* motion vector TOP element */ 219 vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; 220 221 /* motion vector BOTTOM element */ 222 vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; 223 224 vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2); 225 226 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems); 227} 228 229void 230vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, unsigned width, unsigned height) 231{ 232 unsigned i, size; 233 234 assert(buffer); 235 236 buffer->width = width; 237 buffer->height = height; 238 239 size = width * height; 240 241 for (i = 0; i < VL_MAX_PLANES; ++i) { 242 buffer->ycbcr[i].num_instances = 0; 243 buffer->ycbcr[i].resource = pipe_buffer_create 244 ( 245 pipe->screen, 246 PIPE_BIND_VERTEX_BUFFER, 247 PIPE_USAGE_STREAM, 248 sizeof(struct vl_ycbcr_vertex_stream) * size 249 ); 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) * size 259 ); 260 } 261 262 vl_vb_map(buffer, pipe); 263} 264 265struct pipe_vertex_buffer 266vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component) 267{ 268 struct pipe_vertex_buffer buf; 269 270 assert(buffer); 271 272 buf.stride = sizeof(struct vl_ycbcr_vertex_stream); 273 buf.buffer_offset = 0; 274 buf.buffer = buffer->ycbcr[component].resource; 275 276 return buf; 277} 278 279struct pipe_vertex_buffer 280vl_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 293void 294vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 295{ 296 unsigned i; 297 298 assert(buffer && pipe); 299 300 for (i = 0; i < VL_MAX_PLANES; ++i) { 301 buffer->ycbcr[i].vertex_stream = pipe_buffer_map 302 ( 303 pipe, 304 buffer->ycbcr[i].resource, 305 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 306 &buffer->ycbcr[i].transfer 307 ); 308 } 309 310 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 311 buffer->mv[i].vertex_stream = pipe_buffer_map 312 ( 313 pipe, 314 buffer->mv[i].resource, 315 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 316 &buffer->mv[i].transfer 317 ); 318 } 319 320} 321 322static void 323get_motion_vectors(enum pipe_mpeg12_motion_type mo_type, struct pipe_motionvector *src, struct vertex4s dst[2]) 324{ 325 if (mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { 326 dst[0].x = dst[1].x = src->top.x; 327 dst[0].y = dst[1].y = src->top.y; 328 dst[0].z = dst[1].z = 0; 329 330 } else { 331 dst[0].x = src->top.x; 332 dst[0].y = src->top.y; 333 dst[0].z = src->top.field_select ? 3 : 1; 334 335 dst[1].x = src->bottom.x; 336 dst[1].y = src->bottom.y; 337 dst[1].z = src->bottom.field_select ? 3 : 1; 338 } 339 340 dst[0].w = src->top.wheight; 341 dst[1].w = src->bottom.wheight; 342} 343 344static bool 345get_ycbcr_vectors(struct vl_ycbcr_vertex_stream *stream, 346 struct pipe_mpeg12_macroblock *mb, const unsigned (*empty_block_mask)[2][2]) 347{ 348 bool completely_empty = true; 349 unsigned i, j; 350 351 stream->pos.x = mb->mbx; 352 stream->pos.y = mb->mby; 353 stream->dct_type_field = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD; 354 stream->mb_type_intra = mb->dct_intra; 355 356 for ( i = 0; i < 2; ++i) 357 for ( j = 0; j < 2; ++j) { 358 bool empty = !(mb->cbp & (*empty_block_mask)[i][j]); 359 stream->eb[i][j] = empty; 360 completely_empty &= empty; 361 } 362 363 return !completely_empty; 364} 365 366void 367vl_vb_add_block(struct vl_vertex_buffer *buffer, struct pipe_mpeg12_macroblock *mb, 368 const unsigned (*empty_block_mask)[3][2][2]) 369{ 370 unsigned i, mv_pos; 371 372 assert(buffer); 373 assert(mb); 374 375 if(mb->cbp) { 376 for (i = 0; i < VL_MAX_PLANES; ++i) { 377 assert(buffer->ycbcr[i].num_instances < buffer->width * buffer->height); 378 if (get_ycbcr_vectors(buffer->ycbcr[i].vertex_stream, mb, &(*empty_block_mask)[i])) { 379 buffer->ycbcr[i].vertex_stream++; 380 buffer->ycbcr[i].num_instances++; 381 } 382 } 383 } 384 385 mv_pos = mb->mbx + mb->mby * buffer->width; 386 get_motion_vectors(mb->mo_type, &mb->mv[0], buffer->mv[0].vertex_stream[mv_pos].mv); 387 get_motion_vectors(mb->mo_type, &mb->mv[1], buffer->mv[1].vertex_stream[mv_pos].mv); 388} 389 390void 391vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 392{ 393 unsigned i; 394 395 assert(buffer && pipe); 396 397 for (i = 0; i < VL_MAX_PLANES; ++i) { 398 pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer); 399 } 400 401 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 402 pipe_buffer_unmap(pipe, buffer->mv[i].transfer); 403 } 404} 405 406unsigned 407vl_vb_restart(struct vl_vertex_buffer *buffer, int component) 408{ 409 unsigned num_instances; 410 411 assert(buffer); 412 413 num_instances = buffer->ycbcr[component].num_instances; 414 buffer->ycbcr[component].num_instances = 0; 415 return num_instances; 416} 417 418void 419vl_vb_cleanup(struct vl_vertex_buffer *buffer) 420{ 421 unsigned i; 422 423 assert(buffer); 424 425 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 426 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); 427 } 428 429 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 430 pipe_resource_reference(&buffer->mv[i].resource, NULL); 431 } 432} 433