vl_vertex_buffers.c revision 7a5390b06fea99f85ab47d40d8dc40e40e0f2ab8
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 eb[3][2][2]; 37 uint8_t dct_type_field; 38 uint8_t mb_type_intra; 39 uint8_t mv_wheights[2]; 40 struct vertex2s mv[4]; 41}; 42 43/* vertices for a quad covering a block */ 44static const struct vertex2f block_quad[4] = { 45 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} 46}; 47 48struct pipe_vertex_buffer 49vl_vb_upload_quads(struct pipe_context *pipe, unsigned blocks_x, unsigned blocks_y) 50{ 51 struct pipe_vertex_buffer quad; 52 struct pipe_transfer *buf_transfer; 53 struct vertex4f *v; 54 55 unsigned x, y, i; 56 57 assert(pipe); 58 59 /* create buffer */ 60 quad.stride = sizeof(struct vertex4f); 61 quad.buffer_offset = 0; 62 quad.buffer = pipe_buffer_create 63 ( 64 pipe->screen, 65 PIPE_BIND_VERTEX_BUFFER, 66 PIPE_USAGE_STATIC, 67 sizeof(struct vertex4f) * 4 * blocks_x * blocks_y 68 ); 69 70 if(!quad.buffer) 71 return quad; 72 73 /* and fill it */ 74 v = pipe_buffer_map 75 ( 76 pipe, 77 quad.buffer, 78 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 79 &buf_transfer 80 ); 81 82 for ( y = 0; y < blocks_y; ++y) { 83 for ( x = 0; x < blocks_x; ++x) { 84 for (i = 0; i < 4; ++i, ++v) { 85 v->x = block_quad[i].x; 86 v->y = block_quad[i].y; 87 88 v->z = x; 89 v->w = y; 90 } 91 } 92 } 93 94 pipe_buffer_unmap(pipe, buf_transfer); 95 96 return quad; 97} 98 99static struct pipe_vertex_element 100vl_vb_get_quad_vertex_element(void) 101{ 102 struct pipe_vertex_element element; 103 104 /* setup rectangle element */ 105 element.src_offset = 0; 106 element.instance_divisor = 0; 107 element.vertex_buffer_index = 0; 108 element.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 109 110 return element; 111} 112 113static void 114vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, 115 unsigned vertex_buffer_index) 116{ 117 unsigned i, offset = 0; 118 119 assert(elements && num_elements); 120 121 for ( i = 0; i < num_elements; ++i ) { 122 if (elements[i].src_offset) 123 offset = elements[i].src_offset; 124 else 125 elements[i].src_offset = offset; 126 elements[i].instance_divisor = 1; 127 elements[i].vertex_buffer_index = vertex_buffer_index; 128 offset += util_format_get_blocksize(elements[i].src_format); 129 } 130} 131 132void * 133vl_vb_get_elems_state(struct pipe_context *pipe, int component) 134{ 135 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 136 137 memset(&vertex_elems, 0, sizeof(vertex_elems)); 138 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 139 140 /* Position element */ 141 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; 142 143 /* empty block element of selected component */ 144 vertex_elems[VS_I_EB].src_offset = 4 + component * 4; 145 vertex_elems[VS_I_EB].src_format = PIPE_FORMAT_R8G8B8A8_USCALED; 146 147 /* flags */ 148 vertex_elems[VS_I_FLAGS].src_offset = 16; 149 vertex_elems[VS_I_FLAGS].src_format = PIPE_FORMAT_R8G8B8A8_UNORM; 150 151 /* motion vector 0 TOP element */ 152 vertex_elems[VS_I_MV0_TOP].src_format = PIPE_FORMAT_R16G16_SSCALED; 153 154 /* motion vector 0 BOTTOM element */ 155 vertex_elems[VS_I_MV0_BOTTOM].src_format = PIPE_FORMAT_R16G16_SSCALED; 156 157 /* motion vector 1 TOP element */ 158 vertex_elems[VS_I_MV1_TOP].src_format = PIPE_FORMAT_R16G16_SSCALED; 159 160 /* motion vector 1 BOTTOM element */ 161 vertex_elems[VS_I_MV1_BOTTOM].src_format = PIPE_FORMAT_R16G16_SSCALED; 162 163 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], NUM_VS_INPUTS - 1, 1); 164 165 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems); 166} 167 168struct pipe_vertex_buffer 169vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, unsigned size) 170{ 171 struct pipe_vertex_buffer buf; 172 173 assert(buffer); 174 175 buffer->size = size; 176 buffer->num_not_empty = 0; 177 buffer->num_empty = 0; 178 179 buf.stride = sizeof(struct vl_vertex_stream); 180 buf.buffer_offset = 0; 181 buf.buffer = pipe_buffer_create 182 ( 183 pipe->screen, 184 PIPE_BIND_VERTEX_BUFFER, 185 PIPE_USAGE_STREAM, 186 sizeof(struct vl_vertex_stream) * size 187 ); 188 189 pipe_resource_reference(&buffer->resource, buf.buffer); 190 191 vl_vb_map(buffer, pipe); 192 193 return buf; 194} 195 196void 197vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 198{ 199 assert(buffer && pipe); 200 201 buffer->start = pipe_buffer_map 202 ( 203 pipe, 204 buffer->resource, 205 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 206 &buffer->transfer 207 ); 208 buffer->end = buffer->start + buffer->resource->width0 / sizeof(struct vl_vertex_stream); 209} 210 211static void 212get_motion_vectors(struct pipe_mpeg12_macroblock *mb, struct vertex2s mv[4]) 213{ 214 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { 215 mv[0].x = mv[1].x = mb->mv[0].top.x; 216 mv[0].y = mv[1].y = mb->mv[0].top.y; 217 mv[2].x = mv[3].x = mb->mv[1].top.x; 218 mv[2].y = mv[3].y = mb->mv[1].top.y; 219 220 } else { 221 mv[0].x = mb->mv[0].top.x; 222 mv[0].y = mb->mv[0].top.y - (mb->mv[0].top.y % 4); 223 224 mv[1].x = mb->mv[0].bottom.x; 225 mv[1].y = mb->mv[0].bottom.y - (mb->mv[0].bottom.y % 4); 226 227 if (mb->mv[0].top.field_select) mv[0].y += 2; 228 if (!mb->mv[0].bottom.field_select) mv[1].y -= 2; 229 230 mv[2].x = mb->mv[1].top.x; 231 mv[2].y = mb->mv[1].top.y - (mb->mv[1].top.y % 4); 232 233 mv[3].x = mb->mv[1].bottom.x; 234 mv[3].y = mb->mv[1].bottom.y - (mb->mv[1].bottom.y % 4); 235 236 if (mb->mv[1].top.field_select) mv[2].y += 2; 237 if (!mb->mv[1].bottom.field_select) mv[3].y -= 2; 238 } 239} 240 241void 242vl_vb_add_block(struct vl_vertex_buffer *buffer, struct pipe_mpeg12_macroblock *mb, 243 const unsigned (*empty_block_mask)[3][2][2]) 244{ 245 struct vl_vertex_stream *stream; 246 unsigned i, j, k; 247 248 assert(buffer); 249 assert(mb); 250 assert(buffer->num_not_empty + buffer->num_empty < buffer->size); 251 252 if(mb->cbp) 253 stream = buffer->start + buffer->num_not_empty++; 254 else 255 stream = buffer->end - ++buffer->num_empty; 256 257 stream->pos.x = mb->mbx; 258 stream->pos.y = mb->mby; 259 260 for ( i = 0; i < 3; ++i) 261 for ( j = 0; j < 2; ++j) 262 for ( k = 0; k < 2; ++k) 263 stream->eb[i][j][k] = !(mb->cbp & (*empty_block_mask)[i][j][k]); 264 265 stream->dct_type_field = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD; 266 stream->mb_type_intra = !mb->dct_intra; 267 268 stream->mv_wheights[0] = mb->mv[0].wheight; 269 stream->mv_wheights[1] = mb->mv[1].wheight; 270 get_motion_vectors(mb, stream->mv); 271} 272 273void 274vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 275{ 276 assert(buffer && pipe); 277 278 pipe_buffer_unmap(pipe, buffer->transfer); 279} 280 281void 282vl_vb_restart(struct vl_vertex_buffer *buffer, 283 unsigned *not_empty_start_instance, unsigned *not_empty_num_instances, 284 unsigned *empty_start_instance, unsigned *empty_num_instances) 285{ 286 assert(buffer); 287 288 *not_empty_start_instance = 0; 289 *not_empty_num_instances = buffer->num_not_empty; 290 *empty_start_instance = buffer->size - buffer->num_empty; 291 *empty_num_instances = buffer->num_empty; 292 293 buffer->num_not_empty = 0; 294 buffer->num_empty = 0; 295} 296 297void 298vl_vb_cleanup(struct vl_vertex_buffer *buffer) 299{ 300 assert(buffer); 301 302 pipe_resource_reference(&buffer->resource, NULL); 303} 304