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 VMWARE 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/format/u_format.h" 30#include "vl_vertex_buffers.h" 31#include "vl_types.h" 32 33/* vertices for a quad covering a block */ 34static 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 38struct pipe_vertex_buffer 39vl_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.resource = pipe_buffer_create 53 ( 54 pipe->screen, 55 PIPE_BIND_VERTEX_BUFFER, 56 PIPE_USAGE_DEFAULT, 57 sizeof(struct vertex2f) * 4 58 ); 59 quad.is_user_buffer = false; 60 61 if(!quad.buffer.resource) 62 return quad; 63 64 /* and fill it */ 65 v = pipe_buffer_map 66 ( 67 pipe, 68 quad.buffer.resource, 69 PIPE_MAP_WRITE | PIPE_MAP_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 83struct pipe_vertex_buffer 84vl_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.resource = pipe_buffer_create 98 ( 99 pipe->screen, 100 PIPE_BIND_VERTEX_BUFFER, 101 PIPE_USAGE_DEFAULT, 102 sizeof(struct vertex2s) * width * height 103 ); 104 pos.is_user_buffer = false; 105 106 if(!pos.buffer.resource) 107 return pos; 108 109 /* and fill it */ 110 v = pipe_buffer_map 111 ( 112 pipe, 113 pos.buffer.resource, 114 PIPE_MAP_WRITE | PIPE_MAP_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 130static struct pipe_vertex_element 131vl_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.dual_slot = false; 140 element.src_format = PIPE_FORMAT_R32G32_FLOAT; 141 142 return element; 143} 144 145static void 146vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, 147 unsigned vertex_buffer_index) 148{ 149 unsigned i, offset = 0; 150 151 assert(elements && num_elements); 152 153 for ( i = 0; i < num_elements; ++i ) { 154 elements[i].src_offset = offset; 155 elements[i].instance_divisor = 1; 156 elements[i].vertex_buffer_index = vertex_buffer_index; 157 offset += util_format_get_blocksize(elements[i].src_format); 158 } 159} 160 161void * 162vl_vb_get_ves_ycbcr(struct pipe_context *pipe) 163{ 164 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; 165 166 assert(pipe); 167 168 memset(&vertex_elems, 0, sizeof(vertex_elems)); 169 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); 170 171 /* Position element */ 172 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED; 173 174 /* block num element */ 175 vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R32_FLOAT; 176 177 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 2, 1); 178 179 return pipe->create_vertex_elements_state(pipe, 3, vertex_elems); 180} 181 182void * 183vl_vb_get_ves_mv(struct pipe_context *pipe) 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 vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1); 196 197 /* motion vector TOP element */ 198 vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; 199 200 /* motion vector BOTTOM element */ 201 vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; 202 203 vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2); 204 205 return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems); 206} 207 208bool 209vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, 210 unsigned width, unsigned height) 211{ 212 unsigned i, size; 213 214 assert(buffer); 215 216 buffer->width = width; 217 buffer->height = height; 218 219 size = width * height; 220 221 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 222 buffer->ycbcr[i].resource = pipe_buffer_create 223 ( 224 pipe->screen, 225 PIPE_BIND_VERTEX_BUFFER, 226 PIPE_USAGE_STREAM, 227 sizeof(struct vl_ycbcr_block) * size * 4 228 ); 229 if (!buffer->ycbcr[i].resource) 230 goto error_ycbcr; 231 } 232 233 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 234 buffer->mv[i].resource = pipe_buffer_create 235 ( 236 pipe->screen, 237 PIPE_BIND_VERTEX_BUFFER, 238 PIPE_USAGE_STREAM, 239 sizeof(struct vl_motionvector) * size 240 ); 241 if (!buffer->mv[i].resource) 242 goto error_mv; 243 } 244 245 return true; 246 247error_mv: 248 for (i = 0; i < VL_NUM_COMPONENTS; ++i) 249 pipe_resource_reference(&buffer->mv[i].resource, NULL); 250 251error_ycbcr: 252 for (i = 0; i < VL_NUM_COMPONENTS; ++i) 253 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); 254 return false; 255} 256 257unsigned 258vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer) 259{ 260 return 1; 261} 262 263struct pipe_vertex_buffer 264vl_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.resource = buffer->ycbcr[component].resource; 273 buf.is_user_buffer = false; 274 275 return buf; 276} 277 278struct pipe_vertex_buffer 279vl_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.resource = buffer->mv[motionvector].resource; 288 buf.is_user_buffer = false; 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_NUM_COMPONENTS; ++i) { 301 buffer->ycbcr[i].vertex_stream = pipe_buffer_map 302 ( 303 pipe, 304 buffer->ycbcr[i].resource, 305 PIPE_MAP_WRITE | PIPE_MAP_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_MAP_WRITE | PIPE_MAP_DISCARD_RANGE, 316 &buffer->mv[i].transfer 317 ); 318 } 319 320} 321 322struct vl_ycbcr_block * 323vl_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 331unsigned 332vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer) 333{ 334 assert(buffer); 335 336 return buffer->width; 337} 338 339struct vl_motionvector * 340vl_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 348void 349vl_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 if (buffer->ycbcr[i].transfer) 357 pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer); 358 } 359 360 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 361 if (buffer->mv[i].transfer) 362 pipe_buffer_unmap(pipe, buffer->mv[i].transfer); 363 } 364} 365 366void 367vl_vb_cleanup(struct vl_vertex_buffer *buffer) 368{ 369 unsigned i; 370 371 assert(buffer); 372 373 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 374 pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); 375 } 376 377 for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { 378 pipe_resource_reference(&buffer->mv[i].resource, NULL); 379 } 380} 381