1 2/************************************************************************** 3 * 4 * Copyright 2007 VMware, Inc. 5 * Copyright 2012 Marek Olšák <maraeo@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 <keithw@vmware.com> 36 * Marek Olšák <maraeo@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#include "main/bufferobj.h" 48#include "main/glformats.h" 49 50 51static GLuint double_types[4] = { 52 PIPE_FORMAT_R64_FLOAT, 53 PIPE_FORMAT_R64G64_FLOAT, 54 PIPE_FORMAT_R64G64B64_FLOAT, 55 PIPE_FORMAT_R64G64B64A64_FLOAT 56}; 57 58static GLuint float_types[4] = { 59 PIPE_FORMAT_R32_FLOAT, 60 PIPE_FORMAT_R32G32_FLOAT, 61 PIPE_FORMAT_R32G32B32_FLOAT, 62 PIPE_FORMAT_R32G32B32A32_FLOAT 63}; 64 65static GLuint half_float_types[4] = { 66 PIPE_FORMAT_R16_FLOAT, 67 PIPE_FORMAT_R16G16_FLOAT, 68 PIPE_FORMAT_R16G16B16_FLOAT, 69 PIPE_FORMAT_R16G16B16A16_FLOAT 70}; 71 72static GLuint uint_types_norm[4] = { 73 PIPE_FORMAT_R32_UNORM, 74 PIPE_FORMAT_R32G32_UNORM, 75 PIPE_FORMAT_R32G32B32_UNORM, 76 PIPE_FORMAT_R32G32B32A32_UNORM 77}; 78 79static GLuint uint_types_scale[4] = { 80 PIPE_FORMAT_R32_USCALED, 81 PIPE_FORMAT_R32G32_USCALED, 82 PIPE_FORMAT_R32G32B32_USCALED, 83 PIPE_FORMAT_R32G32B32A32_USCALED 84}; 85 86static GLuint uint_types_int[4] = { 87 PIPE_FORMAT_R32_UINT, 88 PIPE_FORMAT_R32G32_UINT, 89 PIPE_FORMAT_R32G32B32_UINT, 90 PIPE_FORMAT_R32G32B32A32_UINT 91}; 92 93static GLuint int_types_norm[4] = { 94 PIPE_FORMAT_R32_SNORM, 95 PIPE_FORMAT_R32G32_SNORM, 96 PIPE_FORMAT_R32G32B32_SNORM, 97 PIPE_FORMAT_R32G32B32A32_SNORM 98}; 99 100static GLuint int_types_scale[4] = { 101 PIPE_FORMAT_R32_SSCALED, 102 PIPE_FORMAT_R32G32_SSCALED, 103 PIPE_FORMAT_R32G32B32_SSCALED, 104 PIPE_FORMAT_R32G32B32A32_SSCALED 105}; 106 107static GLuint int_types_int[4] = { 108 PIPE_FORMAT_R32_SINT, 109 PIPE_FORMAT_R32G32_SINT, 110 PIPE_FORMAT_R32G32B32_SINT, 111 PIPE_FORMAT_R32G32B32A32_SINT 112}; 113 114static GLuint ushort_types_norm[4] = { 115 PIPE_FORMAT_R16_UNORM, 116 PIPE_FORMAT_R16G16_UNORM, 117 PIPE_FORMAT_R16G16B16_UNORM, 118 PIPE_FORMAT_R16G16B16A16_UNORM 119}; 120 121static GLuint ushort_types_scale[4] = { 122 PIPE_FORMAT_R16_USCALED, 123 PIPE_FORMAT_R16G16_USCALED, 124 PIPE_FORMAT_R16G16B16_USCALED, 125 PIPE_FORMAT_R16G16B16A16_USCALED 126}; 127 128static GLuint ushort_types_int[4] = { 129 PIPE_FORMAT_R16_UINT, 130 PIPE_FORMAT_R16G16_UINT, 131 PIPE_FORMAT_R16G16B16_UINT, 132 PIPE_FORMAT_R16G16B16A16_UINT 133}; 134 135static GLuint short_types_norm[4] = { 136 PIPE_FORMAT_R16_SNORM, 137 PIPE_FORMAT_R16G16_SNORM, 138 PIPE_FORMAT_R16G16B16_SNORM, 139 PIPE_FORMAT_R16G16B16A16_SNORM 140}; 141 142static GLuint short_types_scale[4] = { 143 PIPE_FORMAT_R16_SSCALED, 144 PIPE_FORMAT_R16G16_SSCALED, 145 PIPE_FORMAT_R16G16B16_SSCALED, 146 PIPE_FORMAT_R16G16B16A16_SSCALED 147}; 148 149static GLuint short_types_int[4] = { 150 PIPE_FORMAT_R16_SINT, 151 PIPE_FORMAT_R16G16_SINT, 152 PIPE_FORMAT_R16G16B16_SINT, 153 PIPE_FORMAT_R16G16B16A16_SINT 154}; 155 156static GLuint ubyte_types_norm[4] = { 157 PIPE_FORMAT_R8_UNORM, 158 PIPE_FORMAT_R8G8_UNORM, 159 PIPE_FORMAT_R8G8B8_UNORM, 160 PIPE_FORMAT_R8G8B8A8_UNORM 161}; 162 163static GLuint ubyte_types_scale[4] = { 164 PIPE_FORMAT_R8_USCALED, 165 PIPE_FORMAT_R8G8_USCALED, 166 PIPE_FORMAT_R8G8B8_USCALED, 167 PIPE_FORMAT_R8G8B8A8_USCALED 168}; 169 170static GLuint ubyte_types_int[4] = { 171 PIPE_FORMAT_R8_UINT, 172 PIPE_FORMAT_R8G8_UINT, 173 PIPE_FORMAT_R8G8B8_UINT, 174 PIPE_FORMAT_R8G8B8A8_UINT 175}; 176 177static GLuint byte_types_norm[4] = { 178 PIPE_FORMAT_R8_SNORM, 179 PIPE_FORMAT_R8G8_SNORM, 180 PIPE_FORMAT_R8G8B8_SNORM, 181 PIPE_FORMAT_R8G8B8A8_SNORM 182}; 183 184static GLuint byte_types_scale[4] = { 185 PIPE_FORMAT_R8_SSCALED, 186 PIPE_FORMAT_R8G8_SSCALED, 187 PIPE_FORMAT_R8G8B8_SSCALED, 188 PIPE_FORMAT_R8G8B8A8_SSCALED 189}; 190 191static GLuint byte_types_int[4] = { 192 PIPE_FORMAT_R8_SINT, 193 PIPE_FORMAT_R8G8_SINT, 194 PIPE_FORMAT_R8G8B8_SINT, 195 PIPE_FORMAT_R8G8B8A8_SINT 196}; 197 198static GLuint fixed_types[4] = { 199 PIPE_FORMAT_R32_FIXED, 200 PIPE_FORMAT_R32G32_FIXED, 201 PIPE_FORMAT_R32G32B32_FIXED, 202 PIPE_FORMAT_R32G32B32A32_FIXED 203}; 204 205 206/** 207 * Return a PIPE_FORMAT_x for the given GL datatype and size. 208 */ 209enum pipe_format 210st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, 211 GLboolean normalized, GLboolean integer) 212{ 213 assert((type >= GL_BYTE && type <= GL_DOUBLE) || 214 type == GL_FIXED || type == GL_HALF_FLOAT || 215 type == GL_HALF_FLOAT_OES || 216 type == GL_INT_2_10_10_10_REV || 217 type == GL_UNSIGNED_INT_2_10_10_10_REV || 218 type == GL_UNSIGNED_INT_10F_11F_11F_REV); 219 assert(size >= 1); 220 assert(size <= 4); 221 assert(format == GL_RGBA || format == GL_BGRA); 222 223 if (type == GL_INT_2_10_10_10_REV || 224 type == GL_UNSIGNED_INT_2_10_10_10_REV) { 225 assert(size == 4); 226 assert(!integer); 227 228 if (format == GL_BGRA) { 229 if (type == GL_INT_2_10_10_10_REV) { 230 if (normalized) 231 return PIPE_FORMAT_B10G10R10A2_SNORM; 232 else 233 return PIPE_FORMAT_B10G10R10A2_SSCALED; 234 } else { 235 if (normalized) 236 return PIPE_FORMAT_B10G10R10A2_UNORM; 237 else 238 return PIPE_FORMAT_B10G10R10A2_USCALED; 239 } 240 } else { 241 if (type == GL_INT_2_10_10_10_REV) { 242 if (normalized) 243 return PIPE_FORMAT_R10G10B10A2_SNORM; 244 else 245 return PIPE_FORMAT_R10G10B10A2_SSCALED; 246 } else { 247 if (normalized) 248 return PIPE_FORMAT_R10G10B10A2_UNORM; 249 else 250 return PIPE_FORMAT_R10G10B10A2_USCALED; 251 } 252 } 253 } 254 255 if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) { 256 assert(size == 3); 257 assert(!integer); 258 assert(format == GL_RGBA); 259 260 return PIPE_FORMAT_R11G11B10_FLOAT; 261 } 262 263 if (format == GL_BGRA) { 264 /* this is an odd-ball case */ 265 assert(type == GL_UNSIGNED_BYTE); 266 assert(normalized); 267 return PIPE_FORMAT_B8G8R8A8_UNORM; 268 } 269 270 if (integer) { 271 switch (type) { 272 case GL_INT: return int_types_int[size-1]; 273 case GL_SHORT: return short_types_int[size-1]; 274 case GL_BYTE: return byte_types_int[size-1]; 275 case GL_UNSIGNED_INT: return uint_types_int[size-1]; 276 case GL_UNSIGNED_SHORT: return ushort_types_int[size-1]; 277 case GL_UNSIGNED_BYTE: return ubyte_types_int[size-1]; 278 default: assert(0); return 0; 279 } 280 } 281 else if (normalized) { 282 switch (type) { 283 case GL_DOUBLE: return double_types[size-1]; 284 case GL_FLOAT: return float_types[size-1]; 285 case GL_HALF_FLOAT: 286 case GL_HALF_FLOAT_OES: return half_float_types[size-1]; 287 case GL_INT: return int_types_norm[size-1]; 288 case GL_SHORT: return short_types_norm[size-1]; 289 case GL_BYTE: return byte_types_norm[size-1]; 290 case GL_UNSIGNED_INT: return uint_types_norm[size-1]; 291 case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; 292 case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; 293 case GL_FIXED: return fixed_types[size-1]; 294 default: assert(0); return 0; 295 } 296 } 297 else { 298 switch (type) { 299 case GL_DOUBLE: return double_types[size-1]; 300 case GL_FLOAT: return float_types[size-1]; 301 case GL_HALF_FLOAT: 302 case GL_HALF_FLOAT_OES: return half_float_types[size-1]; 303 case GL_INT: return int_types_scale[size-1]; 304 case GL_SHORT: return short_types_scale[size-1]; 305 case GL_BYTE: return byte_types_scale[size-1]; 306 case GL_UNSIGNED_INT: return uint_types_scale[size-1]; 307 case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; 308 case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; 309 case GL_FIXED: return fixed_types[size-1]; 310 default: assert(0); return 0; 311 } 312 } 313 return PIPE_FORMAT_NONE; /* silence compiler warning */ 314} 315 316static const struct gl_vertex_array * 317get_client_array(const struct st_vertex_program *vp, 318 const struct gl_vertex_array **arrays, 319 int attr) 320{ 321 const GLuint mesaAttr = vp->index_to_input[attr]; 322 /* st_program uses 0xffffffff to denote a double placeholder attribute */ 323 if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER) 324 return NULL; 325 return arrays[mesaAttr]; 326} 327 328/** 329 * Examine the active arrays to determine if we have interleaved 330 * vertex arrays all living in one VBO, or all living in user space. 331 */ 332static GLboolean 333is_interleaved_arrays(const struct st_vertex_program *vp, 334 const struct st_vp_variant *vpv, 335 const struct gl_vertex_array **arrays) 336{ 337 GLuint attr; 338 const struct gl_buffer_object *firstBufObj = NULL; 339 GLint firstStride = -1; 340 const GLubyte *firstPtr = NULL; 341 GLboolean userSpaceBuffer = GL_FALSE; 342 343 for (attr = 0; attr < vpv->num_inputs; attr++) { 344 const struct gl_vertex_array *array; 345 const struct gl_buffer_object *bufObj; 346 GLsizei stride; 347 348 array = get_client_array(vp, arrays, attr); 349 if (!array) 350 continue; 351 352 stride = array->StrideB; /* in bytes */ 353 bufObj = array->BufferObj; 354 if (attr == 0) { 355 /* save info about the first array */ 356 firstStride = stride; 357 firstPtr = array->Ptr; 358 firstBufObj = bufObj; 359 userSpaceBuffer = !bufObj || !bufObj->Name; 360 } 361 else { 362 /* check if other arrays interleave with the first, in same buffer */ 363 if (stride != firstStride) 364 return GL_FALSE; /* strides don't match */ 365 366 if (bufObj != firstBufObj) 367 return GL_FALSE; /* arrays in different VBOs */ 368 369 if (llabs(array->Ptr - firstPtr) > firstStride) 370 return GL_FALSE; /* arrays start too far apart */ 371 372 if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer) 373 return GL_FALSE; /* mix of VBO and user-space arrays */ 374 } 375 } 376 377 return GL_TRUE; 378} 379 380static void init_velement(struct pipe_vertex_element *velement, 381 int src_offset, int format, 382 int instance_divisor, int vbo_index) 383{ 384 velement->src_offset = src_offset; 385 velement->src_format = format; 386 velement->instance_divisor = instance_divisor; 387 velement->vertex_buffer_index = vbo_index; 388 assert(velement->src_format); 389} 390 391static void init_velement_lowered(struct st_context *st, 392 const struct st_vertex_program *vp, 393 struct pipe_vertex_element *velements, 394 int src_offset, int format, 395 int instance_divisor, int vbo_index, 396 int nr_components, GLboolean doubles, 397 GLuint *attr_idx) 398{ 399 int idx = *attr_idx; 400 if (doubles) { 401 int lower_format; 402 403 if (nr_components < 2) 404 lower_format = PIPE_FORMAT_R32G32_UINT; 405 else 406 lower_format = PIPE_FORMAT_R32G32B32A32_UINT; 407 408 init_velement(&velements[idx], src_offset, 409 lower_format, instance_divisor, vbo_index); 410 idx++; 411 412 if (idx < vp->num_inputs && 413 vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) { 414 if (nr_components >= 3) { 415 if (nr_components == 3) 416 lower_format = PIPE_FORMAT_R32G32_UINT; 417 else 418 lower_format = PIPE_FORMAT_R32G32B32A32_UINT; 419 420 init_velement(&velements[idx], src_offset + 4 * sizeof(float), 421 lower_format, instance_divisor, vbo_index); 422 } else { 423 /* The values here are undefined. Fill in some conservative 424 * dummy values. 425 */ 426 init_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT, 427 instance_divisor, vbo_index); 428 } 429 430 idx++; 431 } 432 } else { 433 init_velement(&velements[idx], src_offset, 434 format, instance_divisor, vbo_index); 435 idx++; 436 } 437 *attr_idx = idx; 438} 439 440/** 441 * Set up for drawing interleaved arrays that all live in one VBO 442 * or all live in user space. 443 * \param vbuffer returns vertex buffer info 444 * \param velements returns vertex element info 445 */ 446static boolean 447setup_interleaved_attribs(struct st_context *st, 448 const struct st_vertex_program *vp, 449 const struct st_vp_variant *vpv, 450 const struct gl_vertex_array **arrays, 451 struct pipe_vertex_buffer *vbuffer, 452 struct pipe_vertex_element velements[]) 453{ 454 GLuint attr; 455 const GLubyte *low_addr = NULL; 456 GLboolean usingVBO; /* all arrays in a VBO? */ 457 struct gl_buffer_object *bufobj; 458 GLsizei stride; 459 460 /* Find the lowest address of the arrays we're drawing, 461 * Init bufobj and stride. 462 */ 463 if (vpv->num_inputs) { 464 const struct gl_vertex_array *array; 465 466 array = get_client_array(vp, arrays, 0); 467 assert(array); 468 469 /* Since we're doing interleaved arrays, we know there'll be at most 470 * one buffer object and the stride will be the same for all arrays. 471 * Grab them now. 472 */ 473 bufobj = array->BufferObj; 474 stride = array->StrideB; 475 476 low_addr = arrays[vp->index_to_input[0]]->Ptr; 477 478 for (attr = 1; attr < vpv->num_inputs; attr++) { 479 const GLubyte *start; 480 array = get_client_array(vp, arrays, attr); 481 if (!array) 482 continue; 483 start = array->Ptr; 484 low_addr = MIN2(low_addr, start); 485 } 486 } 487 else { 488 /* not sure we'll ever have zero inputs, but play it safe */ 489 bufobj = NULL; 490 stride = 0; 491 low_addr = 0; 492 } 493 494 /* are the arrays in user space? */ 495 usingVBO = _mesa_is_bufferobj(bufobj); 496 497 for (attr = 0; attr < vpv->num_inputs;) { 498 const struct gl_vertex_array *array; 499 unsigned src_offset; 500 unsigned src_format; 501 502 array = get_client_array(vp, arrays, attr); 503 assert(array); 504 505 src_offset = (unsigned) (array->Ptr - low_addr); 506 assert(array->_ElementSize == 507 _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); 508 509 src_format = st_pipe_vertex_format(array->Type, 510 array->Size, 511 array->Format, 512 array->Normalized, 513 array->Integer); 514 515 init_velement_lowered(st, vp, velements, src_offset, src_format, 516 array->InstanceDivisor, 0, 517 array->Size, array->Doubles, &attr); 518 } 519 520 /* 521 * Return the vbuffer info and setup user-space attrib info, if needed. 522 */ 523 if (vpv->num_inputs == 0) { 524 /* just defensive coding here */ 525 vbuffer->buffer = NULL; 526 vbuffer->user_buffer = NULL; 527 vbuffer->buffer_offset = 0; 528 vbuffer->stride = 0; 529 } 530 else if (usingVBO) { 531 /* all interleaved arrays in a VBO */ 532 struct st_buffer_object *stobj = st_buffer_object(bufobj); 533 534 if (!stobj || !stobj->buffer) { 535 return FALSE; /* out-of-memory error probably */ 536 } 537 538 vbuffer->buffer = stobj->buffer; 539 vbuffer->user_buffer = NULL; 540 vbuffer->buffer_offset = pointer_to_offset(low_addr); 541 vbuffer->stride = stride; 542 } 543 else { 544 /* all interleaved arrays in user memory */ 545 vbuffer->buffer = NULL; 546 vbuffer->user_buffer = low_addr; 547 vbuffer->buffer_offset = 0; 548 vbuffer->stride = stride; 549 } 550 return TRUE; 551} 552 553/** 554 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each 555 * vertex attribute. 556 * \param vbuffer returns vertex buffer info 557 * \param velements returns vertex element info 558 */ 559static boolean 560setup_non_interleaved_attribs(struct st_context *st, 561 const struct st_vertex_program *vp, 562 const struct st_vp_variant *vpv, 563 const struct gl_vertex_array **arrays, 564 struct pipe_vertex_buffer vbuffer[], 565 struct pipe_vertex_element velements[], 566 unsigned *num_vbuffers) 567{ 568 struct gl_context *ctx = st->ctx; 569 GLuint attr; 570 571 *num_vbuffers = 0; 572 573 for (attr = 0; attr < vpv->num_inputs;) { 574 const GLuint mesaAttr = vp->index_to_input[attr]; 575 const struct gl_vertex_array *array; 576 struct gl_buffer_object *bufobj; 577 GLsizei stride; 578 unsigned src_format; 579 unsigned bufidx; 580 581 array = get_client_array(vp, arrays, attr); 582 assert(array); 583 584 bufidx = (*num_vbuffers)++; 585 586 stride = array->StrideB; 587 bufobj = array->BufferObj; 588 assert(array->_ElementSize == 589 _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); 590 591 if (_mesa_is_bufferobj(bufobj)) { 592 /* Attribute data is in a VBO. 593 * Recall that for VBOs, the gl_vertex_array->Ptr field is 594 * really an offset from the start of the VBO, not a pointer. 595 */ 596 struct st_buffer_object *stobj = st_buffer_object(bufobj); 597 598 if (!stobj || !stobj->buffer) { 599 return FALSE; /* out-of-memory error probably */ 600 } 601 602 vbuffer[bufidx].buffer = stobj->buffer; 603 vbuffer[bufidx].user_buffer = NULL; 604 vbuffer[bufidx].buffer_offset = pointer_to_offset(array->Ptr); 605 } 606 else { 607 /* wrap user data */ 608 void *ptr; 609 610 if (array->Ptr) { 611 ptr = (void *) array->Ptr; 612 } 613 else { 614 /* no array, use ctx->Current.Attrib[] value */ 615 ptr = (void *) ctx->Current.Attrib[mesaAttr]; 616 stride = 0; 617 } 618 619 assert(ptr); 620 621 vbuffer[bufidx].buffer = NULL; 622 vbuffer[bufidx].user_buffer = ptr; 623 vbuffer[bufidx].buffer_offset = 0; 624 } 625 626 /* common-case setup */ 627 vbuffer[bufidx].stride = stride; /* in bytes */ 628 629 src_format = st_pipe_vertex_format(array->Type, 630 array->Size, 631 array->Format, 632 array->Normalized, 633 array->Integer); 634 635 init_velement_lowered(st, vp, velements, 0, src_format, 636 array->InstanceDivisor, bufidx, 637 array->Size, array->Doubles, &attr); 638 } 639 640 return TRUE; 641} 642 643static void update_array(struct st_context *st) 644{ 645 struct gl_context *ctx = st->ctx; 646 const struct gl_vertex_array **arrays = ctx->Array._DrawArrays; 647 const struct st_vertex_program *vp; 648 const struct st_vp_variant *vpv; 649 struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; 650 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; 651 unsigned num_vbuffers; 652 653 st->vertex_array_out_of_memory = FALSE; 654 655 /* No drawing has been done yet, so do nothing. */ 656 if (!arrays) 657 return; 658 659 /* vertex program validation must be done before this */ 660 vp = st->vp; 661 vpv = st->vp_variant; 662 663 memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); 664 665 /* 666 * Setup the vbuffer[] and velements[] arrays. 667 */ 668 if (is_interleaved_arrays(vp, vpv, arrays)) { 669 if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements)) { 670 st->vertex_array_out_of_memory = TRUE; 671 return; 672 } 673 674 num_vbuffers = 1; 675 if (vpv->num_inputs == 0) 676 num_vbuffers = 0; 677 } 678 else { 679 if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer, 680 velements, &num_vbuffers)) { 681 st->vertex_array_out_of_memory = TRUE; 682 return; 683 } 684 } 685 686 cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer); 687 if (st->last_num_vbuffers > num_vbuffers) { 688 /* Unbind remaining buffers, if any. */ 689 cso_set_vertex_buffers(st->cso_context, num_vbuffers, 690 st->last_num_vbuffers - num_vbuffers, NULL); 691 } 692 st->last_num_vbuffers = num_vbuffers; 693 cso_set_vertex_elements(st->cso_context, vpv->num_inputs, velements); 694} 695 696 697const struct st_tracked_state st_update_array = { 698 update_array /* update */ 699}; 700