vl_vertex_buffers.c revision e87bd8c9578dee384ff03039aa792e1a8dae7f36
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 struct { 37 int8_t y; 38 int8_t cr; 39 int8_t cb; 40 int8_t flag; 41 } eb[2][2]; 42 struct vertex2s mv[4]; 43}; 44 45/* vertices for a quad covering a block */ 46static const struct vertex2f block_quad[4] = { 47 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} 48}; 49 50struct pipe_vertex_buffer 51vl_vb_upload_quads(struct pipe_context *pipe, unsigned blocks_x, unsigned blocks_y) 52{ 53 struct pipe_vertex_buffer quad; 54 struct pipe_transfer *buf_transfer; 55 struct vertex4f *v; 56 57 unsigned x, y, i; 58 59 assert(pipe); 60 61 /* create buffer */ 62 quad.stride = sizeof(struct vertex4f); 63 quad.buffer_offset = 0; 64 quad.buffer = pipe_buffer_create 65 ( 66 pipe->screen, 67 PIPE_BIND_VERTEX_BUFFER, 68 PIPE_USAGE_STATIC, 69 sizeof(struct vertex4f) * 4 * blocks_x * blocks_y 70 ); 71 72 if(!quad.buffer) 73 return quad; 74 75 /* and fill it */ 76 v = pipe_buffer_map 77 ( 78 pipe, 79 quad.buffer, 80 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 81 &buf_transfer 82 ); 83 84 for ( y = 0; y < blocks_y; ++y) { 85 for ( x = 0; x < blocks_x; ++x) { 86 for (i = 0; i < 4; ++i, ++v) { 87 v->x = block_quad[i].x; 88 v->y = block_quad[i].y; 89 90 v->z = x; 91 v->w = y; 92 } 93 } 94 } 95 96 pipe_buffer_unmap(pipe, buf_transfer); 97 98 return quad; 99} 100 101static struct pipe_vertex_element 102vl_vb_get_quad_vertex_element(void) 103{ 104 struct pipe_vertex_element element; 105 106 /* setup rectangle element */ 107 element.src_offset = 0; 108 element.instance_divisor = 0; 109 element.vertex_buffer_index = 0; 110 element.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 111 112 return element; 113} 114 115static void 116vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, 117 unsigned vertex_buffer_index) 118{ 119 unsigned i, offset = 0; 120 121 assert(elements && num_elements); 122 123 for ( i = 0; i < num_elements; ++i ) { 124 elements[i].src_offset = offset; 125 elements[i].instance_divisor = 1; 126 elements[i].vertex_buffer_index = vertex_buffer_index; 127 offset += util_format_get_blocksize(elements[i].src_format); 128 } 129} 130 131void * 132vl_vb_get_elems_state(struct pipe_context *pipe, bool include_mvs) 133{ 134 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 135 136 unsigned i; 137 138 memset(&vertex_elems, 0, sizeof(vertex_elems)); 139 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 140 141 /* Position element */ 142 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; 143 144 /* y, cr, cb empty block element top left block */ 145 vertex_elems[VS_I_EB_0_0].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; 146 147 /* y, cr, cb empty block element top right block */ 148 vertex_elems[VS_I_EB_0_1].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; 149 150 /* y, cr, cb empty block element bottom left block */ 151 vertex_elems[VS_I_EB_1_0].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; 152 153 /* y, cr, cb empty block element bottom right block */ 154 vertex_elems[VS_I_EB_1_1].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; 155 156 for (i = 0; i < 4; ++i) 157 /* motion vector 0..4 element */ 158 vertex_elems[VS_I_MV0 + i].src_format = PIPE_FORMAT_R16G16_SSCALED; 159 160 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], NUM_VS_INPUTS - (include_mvs ? 1 : 5), 1); 161 162 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS - (include_mvs ? 0 : 4), vertex_elems); 163} 164 165struct pipe_vertex_buffer 166vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, unsigned size) 167{ 168 struct pipe_vertex_buffer buf; 169 170 assert(buffer); 171 172 buffer->size = size; 173 buffer->num_not_empty = 0; 174 buffer->num_empty = 0; 175 176 buf.stride = sizeof(struct vl_vertex_stream); 177 buf.buffer_offset = 0; 178 buf.buffer = pipe_buffer_create 179 ( 180 pipe->screen, 181 PIPE_BIND_VERTEX_BUFFER, 182 PIPE_USAGE_STREAM, 183 sizeof(struct vl_vertex_stream) * size 184 ); 185 186 pipe_resource_reference(&buffer->resource, buf.buffer); 187 188 vl_vb_map(buffer, pipe); 189 190 return buf; 191} 192 193void 194vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 195{ 196 assert(buffer && pipe); 197 198 buffer->start = pipe_buffer_map 199 ( 200 pipe, 201 buffer->resource, 202 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 203 &buffer->transfer 204 ); 205 buffer->end = buffer->start + buffer->resource->width0 / sizeof(struct vl_vertex_stream); 206} 207 208static void 209get_motion_vectors(struct pipe_mpeg12_macroblock *mb, struct vertex2s mv[4]) 210{ 211 switch (mb->mb_type) { 212 case PIPE_MPEG12_MACROBLOCK_TYPE_BI: 213 { 214 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { 215 mv[2].x = mb->pmv[0][1][0]; 216 mv[2].y = mb->pmv[0][1][1]; 217 218 } else { 219 mv[2].x = mb->pmv[0][1][0]; 220 mv[2].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4); 221 222 mv[3].x = mb->pmv[1][1][0]; 223 mv[3].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4); 224 225 if(mb->mvfs[0][1]) mv[2].y += 2; 226 if(!mb->mvfs[1][1]) mv[3].y -= 2; 227 } 228 229 /* fall-through */ 230 } 231 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD: 232 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD: 233 { 234 if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) { 235 236 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { 237 mv[0].x = mb->pmv[0][1][0]; 238 mv[0].y = mb->pmv[0][1][1]; 239 240 } else { 241 mv[0].x = mb->pmv[0][1][0]; 242 mv[0].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4); 243 244 mv[1].x = mb->pmv[1][1][0]; 245 mv[1].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4); 246 247 if(mb->mvfs[0][1]) mv[0].y += 2; 248 if(!mb->mvfs[1][1]) mv[1].y -= 2; 249 } 250 251 } else { 252 253 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { 254 mv[0].x = mb->pmv[0][0][0]; 255 mv[0].y = mb->pmv[0][0][1]; 256 257 } else { 258 mv[0].x = mb->pmv[0][0][0]; 259 mv[0].y = mb->pmv[0][0][1] - (mb->pmv[0][0][1] % 4); 260 261 mv[1].x = mb->pmv[1][0][0]; 262 mv[1].y = mb->pmv[1][0][1] - (mb->pmv[1][0][1] % 4); 263 264 if(mb->mvfs[0][0]) mv[0].y += 2; 265 if(!mb->mvfs[1][0]) mv[1].y -= 2; 266 } 267 } 268 } 269 default: 270 break; 271 } 272} 273 274void 275vl_vb_add_block(struct vl_vertex_buffer *buffer, struct pipe_mpeg12_macroblock *mb, 276 const unsigned (*empty_block_mask)[3][2][2]) 277{ 278 struct vl_vertex_stream *stream; 279 unsigned i, j; 280 281 assert(buffer); 282 assert(mb); 283 284 if(mb->cbp) 285 stream = buffer->start + buffer->num_not_empty++; 286 else 287 stream = buffer->end - ++buffer->num_empty; 288 289 stream->pos.x = mb->mbx; 290 stream->pos.y = mb->mby; 291 292 for ( i = 0; i < 2; ++i) { 293 for ( j = 0; j < 2; ++j) { 294 stream->eb[i][j].y = !(mb->cbp & (*empty_block_mask)[0][i][j]); 295 stream->eb[i][j].cr = !(mb->cbp & (*empty_block_mask)[1][i][j]); 296 stream->eb[i][j].cb = !(mb->cbp & (*empty_block_mask)[2][i][j]); 297 } 298 } 299 stream->eb[0][0].flag = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD; 300 stream->eb[0][1].flag = mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME; 301 stream->eb[1][0].flag = mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD; 302 switch (mb->mb_type) { 303 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA: 304 stream->eb[1][1].flag = -1; 305 break; 306 307 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD: 308 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD: 309 stream->eb[1][1].flag = 1; 310 break; 311 312 case PIPE_MPEG12_MACROBLOCK_TYPE_BI: 313 stream->eb[1][1].flag = 0; 314 break; 315 316 default: 317 assert(0); 318 } 319 320 get_motion_vectors(mb, stream->mv); 321} 322 323void 324vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 325{ 326 assert(buffer && pipe); 327 328 pipe_buffer_unmap(pipe, buffer->transfer); 329} 330 331void 332vl_vb_restart(struct vl_vertex_buffer *buffer, 333 unsigned *not_empty_start_instance, unsigned *not_empty_num_instances, 334 unsigned *empty_start_instance, unsigned *empty_num_instances) 335{ 336 assert(buffer); 337 338 *not_empty_start_instance = 0; 339 *not_empty_num_instances = buffer->num_not_empty; 340 *empty_start_instance = buffer->size - buffer->num_empty; 341 *empty_num_instances = buffer->num_empty; 342 343 buffer->num_not_empty = 0; 344 buffer->num_empty = 0; 345} 346 347void 348vl_vb_cleanup(struct vl_vertex_buffer *buffer) 349{ 350 assert(buffer); 351 352 pipe_resource_reference(&buffer->resource, NULL); 353} 354