st_draw.c revision 50caff5675888c0063c73fa64b88129db7aa11dd
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 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/* 29 * This file implements the st_draw_vbo() function which is called from 30 * Mesa's VBO module. All point/line/triangle rendering is done through 31 * this function whether the user called glBegin/End, glDrawArrays, 32 * glDrawElements, glEvalMesh, or glCalList, etc. 33 * 34 * We basically convert the VBO's vertex attribute/array information into 35 * Gallium vertex state, bind the vertex buffer objects and call 36 * pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays(). 37 * 38 * Authors: 39 * Keith Whitwell <keith@tungstengraphics.com> 40 */ 41 42 43#include "main/imports.h" 44#include "main/image.h" 45#include "main/macros.h" 46#include "shader/prog_uniform.h" 47 48#include "vbo/vbo.h" 49 50#include "st_context.h" 51#include "st_atom.h" 52#include "st_cb_bufferobjects.h" 53#include "st_draw.h" 54#include "st_program.h" 55 56#include "pipe/p_context.h" 57#include "pipe/p_defines.h" 58#include "pipe/p_inlines.h" 59 60 61static GLuint double_types[4] = { 62 PIPE_FORMAT_R64_FLOAT, 63 PIPE_FORMAT_R64G64_FLOAT, 64 PIPE_FORMAT_R64G64B64_FLOAT, 65 PIPE_FORMAT_R64G64B64A64_FLOAT 66}; 67 68static GLuint float_types[4] = { 69 PIPE_FORMAT_R32_FLOAT, 70 PIPE_FORMAT_R32G32_FLOAT, 71 PIPE_FORMAT_R32G32B32_FLOAT, 72 PIPE_FORMAT_R32G32B32A32_FLOAT 73}; 74 75static GLuint uint_types_norm[4] = { 76 PIPE_FORMAT_R32_UNORM, 77 PIPE_FORMAT_R32G32_UNORM, 78 PIPE_FORMAT_R32G32B32_UNORM, 79 PIPE_FORMAT_R32G32B32A32_UNORM 80}; 81 82static GLuint uint_types_scale[4] = { 83 PIPE_FORMAT_R32_USCALED, 84 PIPE_FORMAT_R32G32_USCALED, 85 PIPE_FORMAT_R32G32B32_USCALED, 86 PIPE_FORMAT_R32G32B32A32_USCALED 87}; 88 89static GLuint int_types_norm[4] = { 90 PIPE_FORMAT_R32_SNORM, 91 PIPE_FORMAT_R32G32_SNORM, 92 PIPE_FORMAT_R32G32B32_SNORM, 93 PIPE_FORMAT_R32G32B32A32_SNORM 94}; 95 96static GLuint int_types_scale[4] = { 97 PIPE_FORMAT_R32_SSCALED, 98 PIPE_FORMAT_R32G32_SSCALED, 99 PIPE_FORMAT_R32G32B32_SSCALED, 100 PIPE_FORMAT_R32G32B32A32_SSCALED 101}; 102 103static GLuint ushort_types_norm[4] = { 104 PIPE_FORMAT_R16_UNORM, 105 PIPE_FORMAT_R16G16_UNORM, 106 PIPE_FORMAT_R16G16B16_UNORM, 107 PIPE_FORMAT_R16G16B16A16_UNORM 108}; 109 110static GLuint ushort_types_scale[4] = { 111 PIPE_FORMAT_R16_USCALED, 112 PIPE_FORMAT_R16G16_USCALED, 113 PIPE_FORMAT_R16G16B16_USCALED, 114 PIPE_FORMAT_R16G16B16A16_USCALED 115}; 116 117static GLuint short_types_norm[4] = { 118 PIPE_FORMAT_R16_SNORM, 119 PIPE_FORMAT_R16G16_SNORM, 120 PIPE_FORMAT_R16G16B16_SNORM, 121 PIPE_FORMAT_R16G16B16A16_SNORM 122}; 123 124static GLuint short_types_scale[4] = { 125 PIPE_FORMAT_R16_SSCALED, 126 PIPE_FORMAT_R16G16_SSCALED, 127 PIPE_FORMAT_R16G16B16_SSCALED, 128 PIPE_FORMAT_R16G16B16A16_SSCALED 129}; 130 131static GLuint ubyte_types_norm[4] = { 132 PIPE_FORMAT_R8_UNORM, 133 PIPE_FORMAT_R8G8_UNORM, 134 PIPE_FORMAT_R8G8B8_UNORM, 135 PIPE_FORMAT_R8G8B8A8_UNORM 136}; 137 138static GLuint ubyte_types_scale[4] = { 139 PIPE_FORMAT_R8_USCALED, 140 PIPE_FORMAT_R8G8_USCALED, 141 PIPE_FORMAT_R8G8B8_USCALED, 142 PIPE_FORMAT_R8G8B8A8_USCALED 143}; 144 145static GLuint byte_types_norm[4] = { 146 PIPE_FORMAT_R8_SNORM, 147 PIPE_FORMAT_R8G8_SNORM, 148 PIPE_FORMAT_R8G8B8_SNORM, 149 PIPE_FORMAT_R8G8B8A8_SNORM 150}; 151 152static GLuint byte_types_scale[4] = { 153 PIPE_FORMAT_R8_SSCALED, 154 PIPE_FORMAT_R8G8_SSCALED, 155 PIPE_FORMAT_R8G8B8_SSCALED, 156 PIPE_FORMAT_R8G8B8A8_SSCALED 157}; 158 159static GLuint fixed_types[4] = { 160 PIPE_FORMAT_R32_FIXED, 161 PIPE_FORMAT_R32G32_FIXED, 162 PIPE_FORMAT_R32G32B32_FIXED, 163 PIPE_FORMAT_R32G32B32A32_FIXED 164}; 165 166 167 168/** 169 * Return a PIPE_FORMAT_x for the given GL datatype and size. 170 */ 171GLuint 172st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, 173 GLboolean normalized) 174{ 175 assert((type >= GL_BYTE && type <= GL_DOUBLE) || 176 type == GL_FIXED); 177 assert(size >= 1); 178 assert(size <= 4); 179 assert(format == GL_RGBA || format == GL_BGRA); 180 181 if (format == GL_BGRA) { 182 /* this is an odd-ball case */ 183 assert(type == GL_UNSIGNED_BYTE); 184 assert(normalized); 185 return PIPE_FORMAT_B8G8R8A8_UNORM; 186 } 187 188 if (normalized) { 189 switch (type) { 190 case GL_DOUBLE: return double_types[size-1]; 191 case GL_FLOAT: return float_types[size-1]; 192 case GL_INT: return int_types_norm[size-1]; 193 case GL_SHORT: return short_types_norm[size-1]; 194 case GL_BYTE: return byte_types_norm[size-1]; 195 case GL_UNSIGNED_INT: return uint_types_norm[size-1]; 196 case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; 197 case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; 198 case GL_FIXED: return fixed_types[size-1]; 199 default: assert(0); return 0; 200 } 201 } 202 else { 203 switch (type) { 204 case GL_DOUBLE: return double_types[size-1]; 205 case GL_FLOAT: return float_types[size-1]; 206 case GL_INT: return int_types_scale[size-1]; 207 case GL_SHORT: return short_types_scale[size-1]; 208 case GL_BYTE: return byte_types_scale[size-1]; 209 case GL_UNSIGNED_INT: return uint_types_scale[size-1]; 210 case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; 211 case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; 212 case GL_FIXED: return fixed_types[size-1]; 213 default: assert(0); return 0; 214 } 215 } 216 return 0; /* silence compiler warning */ 217} 218 219 220 221 222 223/** 224 * Examine the active arrays to determine if we have interleaved 225 * vertex arrays all living in one VBO, or all living in user space. 226 * \param userSpace returns whether the arrays are in user space. 227 */ 228static GLboolean 229is_interleaved_arrays(const struct st_vertex_program *vp, 230 const struct st_vp_varient *vpv, 231 const struct gl_client_array **arrays, 232 GLboolean *userSpace) 233{ 234 GLuint attr; 235 const struct gl_buffer_object *firstBufObj = NULL; 236 GLint firstStride = -1; 237 GLuint num_client_arrays = 0; 238 const GLubyte *client_addr = NULL; 239 240 for (attr = 0; attr < vpv->num_inputs; attr++) { 241 const GLuint mesaAttr = vp->index_to_input[attr]; 242 const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj; 243 const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */ 244 245 if (firstStride < 0) { 246 firstStride = stride; 247 } 248 else if (firstStride != stride) { 249 return GL_FALSE; 250 } 251 252 if (!bufObj || !bufObj->Name) { 253 num_client_arrays++; 254 /* Try to detect if the client-space arrays are 255 * "close" to each other. 256 */ 257 if (!client_addr) { 258 client_addr = arrays[mesaAttr]->Ptr; 259 } 260 else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) { 261 /* arrays start too far apart */ 262 return GL_FALSE; 263 } 264 } 265 else if (!firstBufObj) { 266 firstBufObj = bufObj; 267 } 268 else if (bufObj != firstBufObj) { 269 return GL_FALSE; 270 } 271 } 272 273 *userSpace = (num_client_arrays == vpv->num_inputs); 274 /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */ 275 276 return GL_TRUE; 277} 278 279 280/** 281 * Compute the memory range occupied by the arrays. 282 */ 283static void 284get_arrays_bounds(const struct st_vertex_program *vp, 285 const struct st_vp_varient *vpv, 286 const struct gl_client_array **arrays, 287 GLuint max_index, 288 const GLubyte **low, const GLubyte **high) 289{ 290 const GLubyte *low_addr = NULL; 291 const GLubyte *high_addr = NULL; 292 GLuint attr; 293 294 for (attr = 0; attr < vpv->num_inputs; attr++) { 295 const GLuint mesaAttr = vp->index_to_input[attr]; 296 const GLint stride = arrays[mesaAttr]->StrideB; 297 const GLubyte *start = arrays[mesaAttr]->Ptr; 298 const unsigned sz = (arrays[mesaAttr]->Size * 299 _mesa_sizeof_type(arrays[mesaAttr]->Type)); 300 const GLubyte *end = start + (max_index * stride) + sz; 301 302 if (attr == 0) { 303 low_addr = start; 304 high_addr = end; 305 } 306 else { 307 low_addr = MIN2(low_addr, start); 308 high_addr = MAX2(high_addr, end); 309 } 310 } 311 312 *low = low_addr; 313 *high = high_addr; 314} 315 316 317/** 318 * Set up for drawing interleaved arrays that all live in one VBO 319 * or all live in user space. 320 * \param vbuffer returns vertex buffer info 321 * \param velements returns vertex element info 322 */ 323static void 324setup_interleaved_attribs(GLcontext *ctx, 325 const struct st_vertex_program *vp, 326 const struct st_vp_varient *vpv, 327 const struct gl_client_array **arrays, 328 GLuint max_index, 329 GLboolean userSpace, 330 struct pipe_vertex_buffer *vbuffer, 331 struct pipe_vertex_element velements[]) 332{ 333 struct pipe_context *pipe = ctx->st->pipe; 334 GLuint attr; 335 const GLubyte *offset0; 336 337 for (attr = 0; attr < vpv->num_inputs; attr++) { 338 const GLuint mesaAttr = vp->index_to_input[attr]; 339 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 340 struct st_buffer_object *stobj = st_buffer_object(bufobj); 341 GLsizei stride = arrays[mesaAttr]->StrideB; 342 343 /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ 344 345 if (attr == 0) { 346 const GLubyte *low, *high; 347 348 get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); 349 /*printf("buffer range: %p %p %d\n", low, high, high-low);*/ 350 351 offset0 = low; 352 if (userSpace) { 353 vbuffer->buffer = 354 pipe_user_buffer_create(pipe->screen, (void *) low, high - low); 355 vbuffer->buffer_offset = 0; 356 } 357 else { 358 vbuffer->buffer = NULL; 359 pipe_buffer_reference(&vbuffer->buffer, stobj->buffer); 360 vbuffer->buffer_offset = pointer_to_offset(low); 361 } 362 vbuffer->stride = stride; /* in bytes */ 363 vbuffer->max_index = max_index; 364 } 365 366 velements[attr].src_offset = 367 (unsigned) (arrays[mesaAttr]->Ptr - offset0); 368 velements[attr].vertex_buffer_index = 0; 369 velements[attr].nr_components = arrays[mesaAttr]->Size; 370 velements[attr].src_format = 371 st_pipe_vertex_format(arrays[mesaAttr]->Type, 372 arrays[mesaAttr]->Size, 373 arrays[mesaAttr]->Format, 374 arrays[mesaAttr]->Normalized); 375 assert(velements[attr].src_format); 376 } 377} 378 379 380/** 381 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each 382 * vertex attribute. 383 * \param vbuffer returns vertex buffer info 384 * \param velements returns vertex element info 385 */ 386static void 387setup_non_interleaved_attribs(GLcontext *ctx, 388 const struct st_vertex_program *vp, 389 const struct st_vp_varient *vpv, 390 const struct gl_client_array **arrays, 391 GLuint max_index, 392 GLboolean *userSpace, 393 struct pipe_vertex_buffer vbuffer[], 394 struct pipe_vertex_element velements[]) 395{ 396 struct pipe_context *pipe = ctx->st->pipe; 397 GLuint attr; 398 399 for (attr = 0; attr < vpv->num_inputs; attr++) { 400 const GLuint mesaAttr = vp->index_to_input[attr]; 401 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 402 GLsizei stride = arrays[mesaAttr]->StrideB; 403 404 *userSpace = GL_FALSE; 405 406 if (bufobj && bufobj->Name) { 407 /* Attribute data is in a VBO. 408 * Recall that for VBOs, the gl_client_array->Ptr field is 409 * really an offset from the start of the VBO, not a pointer. 410 */ 411 struct st_buffer_object *stobj = st_buffer_object(bufobj); 412 assert(stobj->buffer); 413 /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ 414 415 vbuffer[attr].buffer = NULL; 416 pipe_buffer_reference(&vbuffer[attr].buffer, stobj->buffer); 417 vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); 418 velements[attr].src_offset = 0; 419 } 420 else { 421 /* attribute data is in user-space memory, not a VBO */ 422 uint bytes; 423 /*printf("user-space array %d stride %d\n", attr, stride);*/ 424 425 *userSpace = GL_TRUE; 426 427 /* wrap user data */ 428 if (arrays[mesaAttr]->Ptr) { 429 /* user's vertex array */ 430 if (arrays[mesaAttr]->StrideB) { 431 bytes = arrays[mesaAttr]->StrideB * (max_index + 1); 432 } 433 else { 434 bytes = arrays[mesaAttr]->Size 435 * _mesa_sizeof_type(arrays[mesaAttr]->Type); 436 } 437 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 438 (void *) arrays[mesaAttr]->Ptr, bytes); 439 } 440 else { 441 /* no array, use ctx->Current.Attrib[] value */ 442 bytes = sizeof(ctx->Current.Attrib[0]); 443 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 444 (void *) ctx->Current.Attrib[mesaAttr], bytes); 445 stride = 0; 446 } 447 448 vbuffer[attr].buffer_offset = 0; 449 velements[attr].src_offset = 0; 450 } 451 452 assert(velements[attr].src_offset <= 2048); /* 11-bit field */ 453 454 /* common-case setup */ 455 vbuffer[attr].stride = stride; /* in bytes */ 456 vbuffer[attr].max_index = max_index; 457 velements[attr].vertex_buffer_index = attr; 458 velements[attr].nr_components = arrays[mesaAttr]->Size; 459 velements[attr].src_format 460 = st_pipe_vertex_format(arrays[mesaAttr]->Type, 461 arrays[mesaAttr]->Size, 462 arrays[mesaAttr]->Format, 463 arrays[mesaAttr]->Normalized); 464 assert(velements[attr].src_format); 465 } 466} 467 468 469 470/** 471 * Prior to drawing, check that any uniforms referenced by the 472 * current shader have been set. If a uniform has not been set, 473 * issue a warning. 474 */ 475static void 476check_uniforms(GLcontext *ctx) 477{ 478 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 479 if (shProg && shProg->LinkStatus) { 480 GLuint i; 481 for (i = 0; i < shProg->Uniforms->NumUniforms; i++) { 482 const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i]; 483 if (!u->Initialized) { 484 _mesa_warning(ctx, 485 "Using shader with uninitialized uniform: %s", 486 u->Name); 487 } 488 } 489 } 490} 491 492 493/** 494 * This function gets plugged into the VBO module and is called when 495 * we have something to render. 496 * Basically, translate the information into the format expected by gallium. 497 */ 498void 499st_draw_vbo(GLcontext *ctx, 500 const struct gl_client_array **arrays, 501 const struct _mesa_prim *prims, 502 GLuint nr_prims, 503 const struct _mesa_index_buffer *ib, 504 GLboolean index_bounds_valid, 505 GLuint min_index, 506 GLuint max_index) 507{ 508 struct pipe_context *pipe = ctx->st->pipe; 509 const struct st_vertex_program *vp; 510 const struct st_vp_varient *vpv; 511 const struct pipe_shader_state *vs; 512 struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; 513 GLuint attr; 514 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; 515 unsigned num_vbuffers, num_velements; 516 GLboolean userSpace; 517 518 /* Gallium probably doesn't want this in some cases. */ 519 if (!index_bounds_valid) 520 vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); 521 522 /* sanity check for pointer arithmetic below */ 523 assert(sizeof(arrays[0]->Ptr[0]) == 1); 524 525 st_validate_state(ctx->st); 526 527 /* must get these after state validation! */ 528 vp = ctx->st->vp; 529 vpv = ctx->st->vp_varient; 530 vs = &vpv->state; 531 532#if 0 533 if (MESA_VERBOSE & VERBOSE_GLSL) { 534 check_uniforms(ctx); 535 } 536#else 537 (void) check_uniforms; 538#endif 539 540 /* 541 * Setup the vbuffer[] and velements[] arrays. 542 */ 543 if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { 544 /*printf("Draw interleaved\n");*/ 545 setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, 546 vbuffer, velements); 547 num_vbuffers = 1; 548 num_velements = vpv->num_inputs; 549 if (num_velements == 0) 550 num_vbuffers = 0; 551 } 552 else { 553 /*printf("Draw non-interleaved\n");*/ 554 setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, 555 &userSpace, vbuffer, velements); 556 num_vbuffers = vpv->num_inputs; 557 num_velements = vpv->num_inputs; 558 } 559 560#if 0 561 { 562 GLuint i; 563 for (i = 0; i < num_vbuffers; i++) { 564 printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); 565 printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); 566 printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); 567 printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); 568 } 569 for (i = 0; i < num_velements; i++) { 570 printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); 571 printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); 572 printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components); 573 printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format)); 574 } 575 } 576#endif 577 578 pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); 579 pipe->set_vertex_elements(pipe, num_velements, velements); 580 581 if (num_vbuffers == 0 || num_velements == 0) 582 return; 583 584 /* do actual drawing */ 585 if (ib) { 586 /* indexed primitive */ 587 struct gl_buffer_object *bufobj = ib->obj; 588 struct pipe_buffer *indexBuf = NULL; 589 unsigned indexSize, indexOffset, i; 590 591 switch (ib->type) { 592 case GL_UNSIGNED_INT: 593 indexSize = 4; 594 break; 595 case GL_UNSIGNED_SHORT: 596 indexSize = 2; 597 break; 598 case GL_UNSIGNED_BYTE: 599 indexSize = 1; 600 break; 601 default: 602 assert(0); 603 return; 604 } 605 606 /* get/create the index buffer object */ 607 if (bufobj && bufobj->Name) { 608 /* elements/indexes are in a real VBO */ 609 struct st_buffer_object *stobj = st_buffer_object(bufobj); 610 pipe_buffer_reference(&indexBuf, stobj->buffer); 611 indexOffset = pointer_to_offset(ib->ptr) / indexSize; 612 } 613 else { 614 /* element/indicies are in user space memory */ 615 indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr, 616 ib->count * indexSize); 617 indexOffset = 0; 618 } 619 620 /* draw */ 621 if (nr_prims == 1 && pipe->draw_range_elements != NULL) { 622 i = 0; 623 624 /* XXX: exercise temporary path to pass min/max directly 625 * through to driver & draw module. These interfaces still 626 * need a bit of work... 627 */ 628 pipe->draw_range_elements(pipe, indexBuf, indexSize, 629 min_index, 630 max_index, 631 prims[i].mode, 632 prims[i].start + indexOffset, prims[i].count); 633 } 634 else { 635 for (i = 0; i < nr_prims; i++) { 636 pipe->draw_elements(pipe, indexBuf, indexSize, 637 prims[i].mode, 638 prims[i].start + indexOffset, prims[i].count); 639 } 640 } 641 642 pipe_buffer_reference(&indexBuf, NULL); 643 } 644 else { 645 /* non-indexed */ 646 GLuint i; 647 for (i = 0; i < nr_prims; i++) { 648 pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count); 649 } 650 } 651 652 /* unreference buffers (frees wrapped user-space buffer objects) */ 653 for (attr = 0; attr < num_vbuffers; attr++) { 654 pipe_buffer_reference(&vbuffer[attr].buffer, NULL); 655 assert(!vbuffer[attr].buffer); 656 } 657 658 if (userSpace) 659 { 660 pipe->set_vertex_buffers(pipe, 0, NULL); 661 } 662} 663 664 665void st_init_draw( struct st_context *st ) 666{ 667 GLcontext *ctx = st->ctx; 668 669 vbo_set_draw_func(ctx, st_draw_vbo); 670} 671 672 673void st_destroy_draw( struct st_context *st ) 674{ 675} 676 677 678