1 /************************************************************************** 2 * 3 * Copyright 2010 Christian Knig 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 33 /* vertices for a quad covering a block */ 34 static const struct vertex2f block_quad[4] = { 35 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} 36 }; 37 38 struct pipe_vertex_buffer 39 vl_vb_upload_quads(struct pipe_context *pipe) 40 { 41 struct pipe_vertex_buffer quad; 42 struct pipe_transfer *buf_transfer; 43 struct vertex2f *v; 44 45 unsigned i; 46 47 assert(pipe); 48 49 /* create buffer */ 50 quad.stride = sizeof(struct vertex2f); 51 quad.buffer_offset = 0; 52 quad.buffer = pipe_buffer_create 53 ( 54 pipe->screen, 55 PIPE_BIND_VERTEX_BUFFER, 56 PIPE_USAGE_STATIC, 57 sizeof(struct vertex2f) * 4 58 ); 59 quad.user_buffer = NULL; 60 61 if(!quad.buffer) 62 return quad; 63 64 /* and fill it */ 65 v = pipe_buffer_map 66 ( 67 pipe, 68 quad.buffer, 69 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, 70 &buf_transfer 71 ); 72 73 for (i = 0; i < 4; ++i, ++v) { 74 v->x = block_quad[i].x; 75 v->y = block_quad[i].y; 76 } 77 78 pipe_buffer_unmap(pipe, buf_transfer); 79 80 return quad; 81 } 82 83 struct pipe_vertex_buffer 84 vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height) 85 { 86 struct pipe_vertex_buffer pos; 87 struct pipe_transfer *buf_transfer; 88 struct vertex2s *v; 89 90 unsigned x, y; 91 92 assert(pipe); 93 94 /* create buffer */ 95 pos.stride = sizeof(struct vertex2s); 96 pos.buffer_offset = 0; 97 pos.buffer = pipe_buffer_create 98 ( 99 pipe->screen, 100 PIPE_BIND_VERTEX_BUFFER, 101 PIPE_USAGE_STATIC, 102 sizeof(struct vertex2s) * width * height 103 ); 104 pos.user_buffer = NULL; 105 106 if(!pos.buffer) 107 return pos; 108 109 /* and fill it */ 110 v = pipe_buffer_map 111 ( 112 pipe, 113 pos.buffer, 114 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, 115 &buf_transfer 116 ); 117 118 for ( y = 0; y < height; ++y) { 119 for ( x = 0; x < width; ++x, ++v) { 120 v->x = x; 121 v->y = y; 122 } 123 } 124 125 pipe_buffer_unmap(pipe, buf_transfer); 126 127 return pos; 128 } 129 130 static struct pipe_vertex_element 131 vl_vb_get_quad_vertex_element(void) 132 { 133 struct pipe_vertex_element element; 134 135 /* setup rectangle element */ 136 element.src_offset = 0; 137 element.instance_divisor = 0; 138 element.vertex_buffer_index = 0; 139 element.src_format = PIPE_FORMAT_R32G32_FLOAT; 140 141 return element; 142 } 143 144 static void 145 vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, 146 unsigned vertex_buffer_index) 147 { 148 unsigned i, offset = 0; 149 150 assert(elements && num_elements); 151 152 for ( i = 0; i < num_elements; ++i ) { 153 elements[i].src_offset = offset; 154 elements[i].instance_divisor = 1; 155 elements[i].vertex_buffer_index = vertex_buffer_index; 156 offset += util_format_get_blocksize(elements[i].src_format); 157 } 158 } 159 160 void * 161 vl_vb_get_ves_ycbcr(struct pipe_context *pipe) 162 { 163 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 164 165 assert(pipe); 166 167 memset(&vertex_elems, 0, sizeof(vertex_elems)); 168 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 169 170 /* Position element */ 171 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED; 172 173 /* block num element */ 174 vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R32_FLOAT; 175 176 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 2, 1); 177 178 return pipe->create_vertex_elements_state(pipe, 3, vertex_elems); 179 } 180 181 void * 182 vl_vb_get_ves_mv(struct pipe_context *pipe) 183 { 184 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 185 186 assert(pipe); 187 188 memset(&vertex_elems, 0, sizeof(vertex_elems)); 189 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 190 191 /* Position element */ 192 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; 193 194 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1); 195 196 /* motion vector TOP element */ 197 vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; 198 199 /* motion vector BOTTOM element */ 200 vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; 201 202 vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2); 203 204 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems); 205 } 206 207 bool 208 vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, 209 unsigned width, unsigned height) 210 { 211 unsigned i, size; 212 213 assert(buffer); 214 215 buffer->width = width; 216 buffer->height = height; 217 218 size = width * height; 219 220 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 221 buffer->ycbcr[i].resource = pipe_buffer_create 222 ( 223 pipe->screen, 224 PIPE_BIND_VERTEX_BUFFER, 225 PIPE_USAGE_STREAM, 226 sizeof(struct vl_ycbcr_block) * size * 4 227 ); 228 if (!buffer->ycbcr[i].resource) 229 goto error_ycbcr; 230 } 231 232 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 233 buffer->mv[i].resource = pipe_buffer_create 234 ( 235 pipe->screen, 236 PIPE_BIND_VERTEX_BUFFER, 237 PIPE_USAGE_STREAM, 238 sizeof(struct vl_motionvector) * size 239 ); 240 if (!buffer->mv[i].resource) 241 goto error_mv; 242 } 243 244 vl_vb_map(buffer, pipe); 245 return true; 246 247 error_mv: 248 for (i = 0; i < VL_NUM_COMPONENTS; ++i) 249 pipe_resource_reference(&buffer->mv[i].resource, NULL); 250 251 error_ycbcr: 252 for (i = 0; i < VL_NUM_COMPONENTS; ++i) 253 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); 254 return false; 255 } 256 257 unsigned 258 vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer) 259 { 260 return 1; 261 } 262 263 struct pipe_vertex_buffer 264 vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component) 265 { 266 struct pipe_vertex_buffer buf; 267 268 assert(buffer); 269 270 buf.stride = sizeof(struct vl_ycbcr_block); 271 buf.buffer_offset = 0; 272 buf.buffer = buffer->ycbcr[component].resource; 273 buf.user_buffer = NULL; 274 275 return buf; 276 } 277 278 struct pipe_vertex_buffer 279 vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector) 280 { 281 struct pipe_vertex_buffer buf; 282 283 assert(buffer); 284 285 buf.stride = sizeof(struct vl_motionvector); 286 buf.buffer_offset = 0; 287 buf.buffer = buffer->mv[motionvector].resource; 288 buf.user_buffer = NULL; 289 290 return buf; 291 } 292 293 void 294 vl_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_NUM_COMPONENTS; ++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_RANGE, 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_RANGE, 316 &buffer->mv[i].transfer 317 ); 318 } 319 320 } 321 322 struct vl_ycbcr_block * 323 vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component) 324 { 325 assert(buffer); 326 assert(component < VL_NUM_COMPONENTS); 327 328 return buffer->ycbcr[component].vertex_stream; 329 } 330 331 unsigned 332 vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer) 333 { 334 assert(buffer); 335 336 return buffer->width; 337 } 338 339 struct vl_motionvector * 340 vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame) 341 { 342 assert(buffer); 343 assert(ref_frame < VL_MAX_REF_FRAMES); 344 345 return buffer->mv[ref_frame].vertex_stream; 346 } 347 348 void 349 vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) 350 { 351 unsigned i; 352 353 assert(buffer && pipe); 354 355 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 356 pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer); 357 } 358 359 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 360 pipe_buffer_unmap(pipe, buffer->mv[i].transfer); 361 } 362 } 363 364 void 365 vl_vb_cleanup(struct vl_vertex_buffer *buffer) 366 { 367 unsigned i; 368 369 assert(buffer); 370 371 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 372 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); 373 } 374 375 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 376 pipe_resource_reference(&buffer->mv[i].resource, NULL); 377 } 378 } 379