1 2 /************************************************************************** 3 * 4 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * Copyright 2012 Marek Olk <maraeo (at) gmail.com> 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 /* 31 * This converts the VBO's vertex attribute/array information into 32 * Gallium vertex state and binds it. 33 * 34 * Authors: 35 * Keith Whitwell <keith (at) tungstengraphics.com> 36 * Marek Olk <maraeo (at) gmail.com> 37 */ 38 39 #include "st_context.h" 40 #include "st_atom.h" 41 #include "st_cb_bufferobjects.h" 42 #include "st_draw.h" 43 #include "st_program.h" 44 45 #include "cso_cache/cso_context.h" 46 #include "util/u_math.h" 47 48 #include "main/bufferobj.h" 49 #include "main/glformats.h" 50 51 52 static GLuint double_types[4] = { 53 PIPE_FORMAT_R64_FLOAT, 54 PIPE_FORMAT_R64G64_FLOAT, 55 PIPE_FORMAT_R64G64B64_FLOAT, 56 PIPE_FORMAT_R64G64B64A64_FLOAT 57 }; 58 59 static GLuint float_types[4] = { 60 PIPE_FORMAT_R32_FLOAT, 61 PIPE_FORMAT_R32G32_FLOAT, 62 PIPE_FORMAT_R32G32B32_FLOAT, 63 PIPE_FORMAT_R32G32B32A32_FLOAT 64 }; 65 66 static GLuint half_float_types[4] = { 67 PIPE_FORMAT_R16_FLOAT, 68 PIPE_FORMAT_R16G16_FLOAT, 69 PIPE_FORMAT_R16G16B16_FLOAT, 70 PIPE_FORMAT_R16G16B16A16_FLOAT 71 }; 72 73 static GLuint uint_types_norm[4] = { 74 PIPE_FORMAT_R32_UNORM, 75 PIPE_FORMAT_R32G32_UNORM, 76 PIPE_FORMAT_R32G32B32_UNORM, 77 PIPE_FORMAT_R32G32B32A32_UNORM 78 }; 79 80 static GLuint uint_types_scale[4] = { 81 PIPE_FORMAT_R32_USCALED, 82 PIPE_FORMAT_R32G32_USCALED, 83 PIPE_FORMAT_R32G32B32_USCALED, 84 PIPE_FORMAT_R32G32B32A32_USCALED 85 }; 86 87 static GLuint uint_types_int[4] = { 88 PIPE_FORMAT_R32_UINT, 89 PIPE_FORMAT_R32G32_UINT, 90 PIPE_FORMAT_R32G32B32_UINT, 91 PIPE_FORMAT_R32G32B32A32_UINT 92 }; 93 94 static GLuint int_types_norm[4] = { 95 PIPE_FORMAT_R32_SNORM, 96 PIPE_FORMAT_R32G32_SNORM, 97 PIPE_FORMAT_R32G32B32_SNORM, 98 PIPE_FORMAT_R32G32B32A32_SNORM 99 }; 100 101 static GLuint int_types_scale[4] = { 102 PIPE_FORMAT_R32_SSCALED, 103 PIPE_FORMAT_R32G32_SSCALED, 104 PIPE_FORMAT_R32G32B32_SSCALED, 105 PIPE_FORMAT_R32G32B32A32_SSCALED 106 }; 107 108 static GLuint int_types_int[4] = { 109 PIPE_FORMAT_R32_SINT, 110 PIPE_FORMAT_R32G32_SINT, 111 PIPE_FORMAT_R32G32B32_SINT, 112 PIPE_FORMAT_R32G32B32A32_SINT 113 }; 114 115 static GLuint ushort_types_norm[4] = { 116 PIPE_FORMAT_R16_UNORM, 117 PIPE_FORMAT_R16G16_UNORM, 118 PIPE_FORMAT_R16G16B16_UNORM, 119 PIPE_FORMAT_R16G16B16A16_UNORM 120 }; 121 122 static GLuint ushort_types_scale[4] = { 123 PIPE_FORMAT_R16_USCALED, 124 PIPE_FORMAT_R16G16_USCALED, 125 PIPE_FORMAT_R16G16B16_USCALED, 126 PIPE_FORMAT_R16G16B16A16_USCALED 127 }; 128 129 static GLuint ushort_types_int[4] = { 130 PIPE_FORMAT_R16_UINT, 131 PIPE_FORMAT_R16G16_UINT, 132 PIPE_FORMAT_R16G16B16_UINT, 133 PIPE_FORMAT_R16G16B16A16_UINT 134 }; 135 136 static GLuint short_types_norm[4] = { 137 PIPE_FORMAT_R16_SNORM, 138 PIPE_FORMAT_R16G16_SNORM, 139 PIPE_FORMAT_R16G16B16_SNORM, 140 PIPE_FORMAT_R16G16B16A16_SNORM 141 }; 142 143 static GLuint short_types_scale[4] = { 144 PIPE_FORMAT_R16_SSCALED, 145 PIPE_FORMAT_R16G16_SSCALED, 146 PIPE_FORMAT_R16G16B16_SSCALED, 147 PIPE_FORMAT_R16G16B16A16_SSCALED 148 }; 149 150 static GLuint short_types_int[4] = { 151 PIPE_FORMAT_R16_SINT, 152 PIPE_FORMAT_R16G16_SINT, 153 PIPE_FORMAT_R16G16B16_SINT, 154 PIPE_FORMAT_R16G16B16A16_SINT 155 }; 156 157 static GLuint ubyte_types_norm[4] = { 158 PIPE_FORMAT_R8_UNORM, 159 PIPE_FORMAT_R8G8_UNORM, 160 PIPE_FORMAT_R8G8B8_UNORM, 161 PIPE_FORMAT_R8G8B8A8_UNORM 162 }; 163 164 static GLuint ubyte_types_scale[4] = { 165 PIPE_FORMAT_R8_USCALED, 166 PIPE_FORMAT_R8G8_USCALED, 167 PIPE_FORMAT_R8G8B8_USCALED, 168 PIPE_FORMAT_R8G8B8A8_USCALED 169 }; 170 171 static GLuint ubyte_types_int[4] = { 172 PIPE_FORMAT_R8_UINT, 173 PIPE_FORMAT_R8G8_UINT, 174 PIPE_FORMAT_R8G8B8_UINT, 175 PIPE_FORMAT_R8G8B8A8_UINT 176 }; 177 178 static GLuint byte_types_norm[4] = { 179 PIPE_FORMAT_R8_SNORM, 180 PIPE_FORMAT_R8G8_SNORM, 181 PIPE_FORMAT_R8G8B8_SNORM, 182 PIPE_FORMAT_R8G8B8A8_SNORM 183 }; 184 185 static GLuint byte_types_scale[4] = { 186 PIPE_FORMAT_R8_SSCALED, 187 PIPE_FORMAT_R8G8_SSCALED, 188 PIPE_FORMAT_R8G8B8_SSCALED, 189 PIPE_FORMAT_R8G8B8A8_SSCALED 190 }; 191 192 static GLuint byte_types_int[4] = { 193 PIPE_FORMAT_R8_SINT, 194 PIPE_FORMAT_R8G8_SINT, 195 PIPE_FORMAT_R8G8B8_SINT, 196 PIPE_FORMAT_R8G8B8A8_SINT 197 }; 198 199 static GLuint fixed_types[4] = { 200 PIPE_FORMAT_R32_FIXED, 201 PIPE_FORMAT_R32G32_FIXED, 202 PIPE_FORMAT_R32G32B32_FIXED, 203 PIPE_FORMAT_R32G32B32A32_FIXED 204 }; 205 206 207 /** 208 * Return a PIPE_FORMAT_x for the given GL datatype and size. 209 */ 210 enum pipe_format 211 st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, 212 GLboolean normalized, GLboolean integer) 213 { 214 assert((type >= GL_BYTE && type <= GL_DOUBLE) || 215 type == GL_FIXED || type == GL_HALF_FLOAT || 216 type == GL_INT_2_10_10_10_REV || 217 type == GL_UNSIGNED_INT_2_10_10_10_REV); 218 assert(size >= 1); 219 assert(size <= 4); 220 assert(format == GL_RGBA || format == GL_BGRA); 221 222 if (type == GL_INT_2_10_10_10_REV || 223 type == GL_UNSIGNED_INT_2_10_10_10_REV) { 224 assert(size == 4); 225 assert(!integer); 226 227 if (format == GL_BGRA) { 228 if (type == GL_INT_2_10_10_10_REV) { 229 if (normalized) 230 return PIPE_FORMAT_B10G10R10A2_SNORM; 231 else 232 return PIPE_FORMAT_B10G10R10A2_SSCALED; 233 } else { 234 if (normalized) 235 return PIPE_FORMAT_B10G10R10A2_UNORM; 236 else 237 return PIPE_FORMAT_B10G10R10A2_USCALED; 238 } 239 } else { 240 if (type == GL_INT_2_10_10_10_REV) { 241 if (normalized) 242 return PIPE_FORMAT_R10G10B10A2_SNORM; 243 else 244 return PIPE_FORMAT_R10G10B10A2_SSCALED; 245 } else { 246 if (normalized) 247 return PIPE_FORMAT_R10G10B10A2_UNORM; 248 else 249 return PIPE_FORMAT_R10G10B10A2_USCALED; 250 } 251 } 252 } 253 254 if (format == GL_BGRA) { 255 /* this is an odd-ball case */ 256 assert(type == GL_UNSIGNED_BYTE); 257 assert(normalized); 258 return PIPE_FORMAT_B8G8R8A8_UNORM; 259 } 260 261 if (integer) { 262 switch (type) { 263 case GL_INT: return int_types_int[size-1]; 264 case GL_SHORT: return short_types_int[size-1]; 265 case GL_BYTE: return byte_types_int[size-1]; 266 case GL_UNSIGNED_INT: return uint_types_int[size-1]; 267 case GL_UNSIGNED_SHORT: return ushort_types_int[size-1]; 268 case GL_UNSIGNED_BYTE: return ubyte_types_int[size-1]; 269 default: assert(0); return 0; 270 } 271 } 272 else if (normalized) { 273 switch (type) { 274 case GL_DOUBLE: return double_types[size-1]; 275 case GL_FLOAT: return float_types[size-1]; 276 case GL_HALF_FLOAT: return half_float_types[size-1]; 277 case GL_INT: return int_types_norm[size-1]; 278 case GL_SHORT: return short_types_norm[size-1]; 279 case GL_BYTE: return byte_types_norm[size-1]; 280 case GL_UNSIGNED_INT: return uint_types_norm[size-1]; 281 case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; 282 case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; 283 case GL_FIXED: return fixed_types[size-1]; 284 default: assert(0); return 0; 285 } 286 } 287 else { 288 switch (type) { 289 case GL_DOUBLE: return double_types[size-1]; 290 case GL_FLOAT: return float_types[size-1]; 291 case GL_HALF_FLOAT: return half_float_types[size-1]; 292 case GL_INT: return int_types_scale[size-1]; 293 case GL_SHORT: return short_types_scale[size-1]; 294 case GL_BYTE: return byte_types_scale[size-1]; 295 case GL_UNSIGNED_INT: return uint_types_scale[size-1]; 296 case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; 297 case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; 298 case GL_FIXED: return fixed_types[size-1]; 299 default: assert(0); return 0; 300 } 301 } 302 return PIPE_FORMAT_NONE; /* silence compiler warning */ 303 } 304 305 /** 306 * Examine the active arrays to determine if we have interleaved 307 * vertex arrays all living in one VBO, or all living in user space. 308 */ 309 static GLboolean 310 is_interleaved_arrays(const struct st_vertex_program *vp, 311 const struct st_vp_variant *vpv, 312 const struct gl_client_array **arrays) 313 { 314 GLuint attr; 315 const struct gl_buffer_object *firstBufObj = NULL; 316 GLint firstStride = -1; 317 const GLubyte *firstPtr = NULL; 318 GLboolean userSpaceBuffer = GL_FALSE; 319 320 for (attr = 0; attr < vpv->num_inputs; attr++) { 321 const GLuint mesaAttr = vp->index_to_input[attr]; 322 const struct gl_client_array *array = arrays[mesaAttr]; 323 const struct gl_buffer_object *bufObj = array->BufferObj; 324 const GLsizei stride = array->StrideB; /* in bytes */ 325 326 if (attr == 0) { 327 /* save info about the first array */ 328 firstStride = stride; 329 firstPtr = array->Ptr; 330 firstBufObj = bufObj; 331 userSpaceBuffer = !bufObj || !bufObj->Name; 332 } 333 else { 334 /* check if other arrays interleave with the first, in same buffer */ 335 if (stride != firstStride) 336 return GL_FALSE; /* strides don't match */ 337 338 if (bufObj != firstBufObj) 339 return GL_FALSE; /* arrays in different VBOs */ 340 341 if (abs(array->Ptr - firstPtr) > firstStride) 342 return GL_FALSE; /* arrays start too far apart */ 343 344 if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer) 345 return GL_FALSE; /* mix of VBO and user-space arrays */ 346 } 347 } 348 349 return GL_TRUE; 350 } 351 352 /** 353 * Set up for drawing interleaved arrays that all live in one VBO 354 * or all live in user space. 355 * \param vbuffer returns vertex buffer info 356 * \param velements returns vertex element info 357 */ 358 static boolean 359 setup_interleaved_attribs(const struct st_vertex_program *vp, 360 const struct st_vp_variant *vpv, 361 const struct gl_client_array **arrays, 362 struct pipe_vertex_buffer *vbuffer, 363 struct pipe_vertex_element velements[]) 364 { 365 GLuint attr; 366 const GLubyte *low_addr = NULL; 367 GLboolean usingVBO; /* all arrays in a VBO? */ 368 struct gl_buffer_object *bufobj; 369 GLsizei stride; 370 371 /* Find the lowest address of the arrays we're drawing, 372 * Init bufobj and stride. 373 */ 374 if (vpv->num_inputs) { 375 const GLuint mesaAttr0 = vp->index_to_input[0]; 376 const struct gl_client_array *array = arrays[mesaAttr0]; 377 378 /* Since we're doing interleaved arrays, we know there'll be at most 379 * one buffer object and the stride will be the same for all arrays. 380 * Grab them now. 381 */ 382 bufobj = array->BufferObj; 383 stride = array->StrideB; 384 385 low_addr = arrays[vp->index_to_input[0]]->Ptr; 386 387 for (attr = 1; attr < vpv->num_inputs; attr++) { 388 const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; 389 low_addr = MIN2(low_addr, start); 390 } 391 } 392 else { 393 /* not sure we'll ever have zero inputs, but play it safe */ 394 bufobj = NULL; 395 stride = 0; 396 low_addr = 0; 397 } 398 399 /* are the arrays in user space? */ 400 usingVBO = _mesa_is_bufferobj(bufobj); 401 402 for (attr = 0; attr < vpv->num_inputs; attr++) { 403 const GLuint mesaAttr = vp->index_to_input[attr]; 404 const struct gl_client_array *array = arrays[mesaAttr]; 405 unsigned src_offset = (unsigned) (array->Ptr - low_addr); 406 GLuint element_size = array->_ElementSize; 407 408 assert(element_size == array->Size * _mesa_sizeof_type(array->Type)); 409 410 velements[attr].src_offset = src_offset; 411 velements[attr].instance_divisor = array->InstanceDivisor; 412 velements[attr].vertex_buffer_index = 0; 413 velements[attr].src_format = st_pipe_vertex_format(array->Type, 414 array->Size, 415 array->Format, 416 array->Normalized, 417 array->Integer); 418 assert(velements[attr].src_format); 419 } 420 421 /* 422 * Return the vbuffer info and setup user-space attrib info, if needed. 423 */ 424 if (vpv->num_inputs == 0) { 425 /* just defensive coding here */ 426 vbuffer->buffer = NULL; 427 vbuffer->user_buffer = NULL; 428 vbuffer->buffer_offset = 0; 429 vbuffer->stride = 0; 430 } 431 else if (usingVBO) { 432 /* all interleaved arrays in a VBO */ 433 struct st_buffer_object *stobj = st_buffer_object(bufobj); 434 435 if (!stobj || !stobj->buffer) { 436 return FALSE; /* out-of-memory error probably */ 437 } 438 439 vbuffer->buffer = stobj->buffer; 440 vbuffer->user_buffer = NULL; 441 vbuffer->buffer_offset = pointer_to_offset(low_addr); 442 vbuffer->stride = stride; 443 } 444 else { 445 /* all interleaved arrays in user memory */ 446 vbuffer->buffer = NULL; 447 vbuffer->user_buffer = low_addr; 448 vbuffer->buffer_offset = 0; 449 vbuffer->stride = stride; 450 } 451 return TRUE; 452 } 453 454 /** 455 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each 456 * vertex attribute. 457 * \param vbuffer returns vertex buffer info 458 * \param velements returns vertex element info 459 */ 460 static boolean 461 setup_non_interleaved_attribs(struct st_context *st, 462 const struct st_vertex_program *vp, 463 const struct st_vp_variant *vpv, 464 const struct gl_client_array **arrays, 465 struct pipe_vertex_buffer vbuffer[], 466 struct pipe_vertex_element velements[]) 467 { 468 struct gl_context *ctx = st->ctx; 469 GLuint attr; 470 471 for (attr = 0; attr < vpv->num_inputs; attr++) { 472 const GLuint mesaAttr = vp->index_to_input[attr]; 473 const struct gl_client_array *array = arrays[mesaAttr]; 474 struct gl_buffer_object *bufobj = array->BufferObj; 475 GLsizei stride = array->StrideB; 476 477 assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type)); 478 479 if (_mesa_is_bufferobj(bufobj)) { 480 /* Attribute data is in a VBO. 481 * Recall that for VBOs, the gl_client_array->Ptr field is 482 * really an offset from the start of the VBO, not a pointer. 483 */ 484 struct st_buffer_object *stobj = st_buffer_object(bufobj); 485 486 if (!stobj || !stobj->buffer) { 487 return FALSE; /* out-of-memory error probably */ 488 } 489 490 vbuffer[attr].buffer = stobj->buffer; 491 vbuffer[attr].user_buffer = NULL; 492 vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr); 493 } 494 else { 495 /* wrap user data */ 496 void *ptr; 497 498 if (array->Ptr) { 499 ptr = (void *) array->Ptr; 500 } 501 else { 502 /* no array, use ctx->Current.Attrib[] value */ 503 ptr = (void *) ctx->Current.Attrib[mesaAttr]; 504 stride = 0; 505 } 506 507 assert(ptr); 508 509 vbuffer[attr].buffer = NULL; 510 vbuffer[attr].user_buffer = ptr; 511 vbuffer[attr].buffer_offset = 0; 512 } 513 514 /* common-case setup */ 515 vbuffer[attr].stride = stride; /* in bytes */ 516 517 velements[attr].src_offset = 0; 518 velements[attr].instance_divisor = array->InstanceDivisor; 519 velements[attr].vertex_buffer_index = attr; 520 velements[attr].src_format = st_pipe_vertex_format(array->Type, 521 array->Size, 522 array->Format, 523 array->Normalized, 524 array->Integer); 525 assert(velements[attr].src_format); 526 } 527 return TRUE; 528 } 529 530 static void update_array(struct st_context *st) 531 { 532 struct gl_context *ctx = st->ctx; 533 const struct gl_client_array **arrays = ctx->Array._DrawArrays; 534 const struct st_vertex_program *vp; 535 const struct st_vp_variant *vpv; 536 struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; 537 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; 538 unsigned num_vbuffers, num_velements; 539 540 st->vertex_array_out_of_memory = FALSE; 541 542 /* No drawing has been done yet, so do nothing. */ 543 if (!arrays) 544 return; 545 546 /* vertex program validation must be done before this */ 547 vp = st->vp; 548 vpv = st->vp_variant; 549 550 memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); 551 552 /* 553 * Setup the vbuffer[] and velements[] arrays. 554 */ 555 if (is_interleaved_arrays(vp, vpv, arrays)) { 556 if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) { 557 st->vertex_array_out_of_memory = TRUE; 558 return; 559 } 560 561 num_vbuffers = 1; 562 num_velements = vpv->num_inputs; 563 if (num_velements == 0) 564 num_vbuffers = 0; 565 } 566 else { 567 if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer, 568 velements)) { 569 st->vertex_array_out_of_memory = TRUE; 570 return; 571 } 572 573 num_vbuffers = vpv->num_inputs; 574 num_velements = vpv->num_inputs; 575 } 576 577 cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer); 578 cso_set_vertex_elements(st->cso_context, num_velements, velements); 579 } 580 581 582 const struct st_tracked_state st_update_array = { 583 "st_update_array", /* name */ 584 { /* dirty */ 585 (_NEW_PROGRAM | _NEW_BUFFER_OBJECT), /* mesa */ 586 ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM, /* st */ 587 }, 588 update_array /* update */ 589 }; 590