vl_vertex_buffers.c revision b8a6e0e6fc451096d684a1e18529ab4879cdba0a
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_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 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 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 182void * 183vl_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 207void * 208vl_vb_get_ves_mv(struct pipe_context *pipe, int motionvector) 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 233void 234vl_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 265struct pipe_vertex_buffer 266vl_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 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 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 320static void 321get_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 342void 343vl_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 374void 375vl_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 387unsigned 388vl_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 399void 400vl_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} 412