st_draw.c revision 28486880ca3ec39419ccee0cb1a3bedc9ef7117c
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 "util/u_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 = NULL; 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].instance_divisor = 0; 369 velements[attr].vertex_buffer_index = 0; 370 velements[attr].nr_components = arrays[mesaAttr]->Size; 371 velements[attr].src_format = 372 st_pipe_vertex_format(arrays[mesaAttr]->Type, 373 arrays[mesaAttr]->Size, 374 arrays[mesaAttr]->Format, 375 arrays[mesaAttr]->Normalized); 376 assert(velements[attr].src_format); 377 } 378} 379 380 381/** 382 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each 383 * vertex attribute. 384 * \param vbuffer returns vertex buffer info 385 * \param velements returns vertex element info 386 */ 387static void 388setup_non_interleaved_attribs(GLcontext *ctx, 389 const struct st_vertex_program *vp, 390 const struct st_vp_varient *vpv, 391 const struct gl_client_array **arrays, 392 GLuint max_index, 393 GLboolean *userSpace, 394 struct pipe_vertex_buffer vbuffer[], 395 struct pipe_vertex_element velements[]) 396{ 397 struct pipe_context *pipe = ctx->st->pipe; 398 GLuint attr; 399 400 for (attr = 0; attr < vpv->num_inputs; attr++) { 401 const GLuint mesaAttr = vp->index_to_input[attr]; 402 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 403 GLsizei stride = arrays[mesaAttr]->StrideB; 404 405 *userSpace = GL_FALSE; 406 407 if (bufobj && bufobj->Name) { 408 /* Attribute data is in a VBO. 409 * Recall that for VBOs, the gl_client_array->Ptr field is 410 * really an offset from the start of the VBO, not a pointer. 411 */ 412 struct st_buffer_object *stobj = st_buffer_object(bufobj); 413 assert(stobj->buffer); 414 /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ 415 416 vbuffer[attr].buffer = NULL; 417 pipe_buffer_reference(&vbuffer[attr].buffer, stobj->buffer); 418 vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); 419 velements[attr].src_offset = 0; 420 } 421 else { 422 /* attribute data is in user-space memory, not a VBO */ 423 uint bytes; 424 /*printf("user-space array %d stride %d\n", attr, stride);*/ 425 426 *userSpace = GL_TRUE; 427 428 /* wrap user data */ 429 if (arrays[mesaAttr]->Ptr) { 430 /* user's vertex array */ 431 if (arrays[mesaAttr]->StrideB) { 432 bytes = arrays[mesaAttr]->StrideB * (max_index + 1); 433 } 434 else { 435 bytes = arrays[mesaAttr]->Size 436 * _mesa_sizeof_type(arrays[mesaAttr]->Type); 437 } 438 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 439 (void *) arrays[mesaAttr]->Ptr, bytes); 440 } 441 else { 442 /* no array, use ctx->Current.Attrib[] value */ 443 bytes = sizeof(ctx->Current.Attrib[0]); 444 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 445 (void *) ctx->Current.Attrib[mesaAttr], bytes); 446 stride = 0; 447 } 448 449 vbuffer[attr].buffer_offset = 0; 450 velements[attr].src_offset = 0; 451 } 452 453 assert(velements[attr].src_offset <= 2048); /* 11-bit field */ 454 455 /* common-case setup */ 456 vbuffer[attr].stride = stride; /* in bytes */ 457 vbuffer[attr].max_index = max_index; 458 velements[attr].instance_divisor = 0; 459 velements[attr].vertex_buffer_index = attr; 460 velements[attr].nr_components = arrays[mesaAttr]->Size; 461 velements[attr].src_format 462 = st_pipe_vertex_format(arrays[mesaAttr]->Type, 463 arrays[mesaAttr]->Size, 464 arrays[mesaAttr]->Format, 465 arrays[mesaAttr]->Normalized); 466 assert(velements[attr].src_format); 467 } 468} 469 470 471 472/** 473 * Prior to drawing, check that any uniforms referenced by the 474 * current shader have been set. If a uniform has not been set, 475 * issue a warning. 476 */ 477static void 478check_uniforms(GLcontext *ctx) 479{ 480 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 481 if (shProg && shProg->LinkStatus) { 482 GLuint i; 483 for (i = 0; i < shProg->Uniforms->NumUniforms; i++) { 484 const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i]; 485 if (!u->Initialized) { 486 _mesa_warning(ctx, 487 "Using shader with uninitialized uniform: %s", 488 u->Name); 489 } 490 } 491 } 492} 493 494 495static unsigned translate_prim( GLcontext *ctx, 496 unsigned prim ) 497{ 498 /* Avoid quadstrips if it's easy to do so: 499 */ 500 if (prim == GL_QUAD_STRIP && 501 ctx->Light.ShadeModel != GL_FLAT && 502 ctx->Polygon.FrontMode == GL_FILL && 503 ctx->Polygon.BackMode == GL_FILL) 504 prim = GL_TRIANGLE_STRIP; 505 506 return prim; 507} 508 509/** 510 * This function gets plugged into the VBO module and is called when 511 * we have something to render. 512 * Basically, translate the information into the format expected by gallium. 513 */ 514void 515st_draw_vbo(GLcontext *ctx, 516 const struct gl_client_array **arrays, 517 const struct _mesa_prim *prims, 518 GLuint nr_prims, 519 const struct _mesa_index_buffer *ib, 520 GLboolean index_bounds_valid, 521 GLuint min_index, 522 GLuint max_index) 523{ 524 struct pipe_context *pipe = ctx->st->pipe; 525 const struct st_vertex_program *vp; 526 const struct st_vp_varient *vpv; 527 struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; 528 GLuint attr; 529 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; 530 unsigned num_vbuffers, num_velements; 531 GLboolean userSpace = GL_FALSE; 532 GLboolean vertDataEdgeFlags; 533 534 /* Mesa core state should have been validated already */ 535 assert(ctx->NewState == 0x0); 536 537 /* Gallium probably doesn't want this in some cases. */ 538 if (!index_bounds_valid) 539 if (!vbo_all_varyings_in_vbos(arrays)) 540 vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); 541 542 /* sanity check for pointer arithmetic below */ 543 assert(sizeof(arrays[0]->Ptr[0]) == 1); 544 545 vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && 546 arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; 547 if (vertDataEdgeFlags != ctx->st->vertdata_edgeflags) { 548 ctx->st->vertdata_edgeflags = vertDataEdgeFlags; 549 ctx->st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; 550 } 551 552 st_validate_state(ctx->st); 553 554 /* must get these after state validation! */ 555 vp = ctx->st->vp; 556 vpv = ctx->st->vp_varient; 557 558#if 0 559 if (MESA_VERBOSE & VERBOSE_GLSL) { 560 check_uniforms(ctx); 561 } 562#else 563 (void) check_uniforms; 564#endif 565 566 /* 567 * Setup the vbuffer[] and velements[] arrays. 568 */ 569 if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { 570 /*printf("Draw interleaved\n");*/ 571 setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, 572 vbuffer, velements); 573 num_vbuffers = 1; 574 num_velements = vpv->num_inputs; 575 if (num_velements == 0) 576 num_vbuffers = 0; 577 } 578 else { 579 /*printf("Draw non-interleaved\n");*/ 580 setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, 581 &userSpace, vbuffer, velements); 582 num_vbuffers = vpv->num_inputs; 583 num_velements = vpv->num_inputs; 584 } 585 586#if 0 587 { 588 GLuint i; 589 for (i = 0; i < num_vbuffers; i++) { 590 printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); 591 printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); 592 printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); 593 printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); 594 } 595 for (i = 0; i < num_velements; i++) { 596 printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); 597 printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); 598 printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components); 599 printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format)); 600 } 601 } 602#endif 603 604 pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); 605 pipe->set_vertex_elements(pipe, num_velements, velements); 606 607 if (num_vbuffers == 0 || num_velements == 0) 608 return; 609 610 /* do actual drawing */ 611 if (ib) { 612 /* indexed primitive */ 613 struct gl_buffer_object *bufobj = ib->obj; 614 struct pipe_buffer *indexBuf = NULL; 615 unsigned indexSize, indexOffset, i; 616 unsigned prim; 617 618 switch (ib->type) { 619 case GL_UNSIGNED_INT: 620 indexSize = 4; 621 break; 622 case GL_UNSIGNED_SHORT: 623 indexSize = 2; 624 break; 625 case GL_UNSIGNED_BYTE: 626 indexSize = 1; 627 break; 628 default: 629 assert(0); 630 return; 631 } 632 633 /* get/create the index buffer object */ 634 if (bufobj && bufobj->Name) { 635 /* elements/indexes are in a real VBO */ 636 struct st_buffer_object *stobj = st_buffer_object(bufobj); 637 pipe_buffer_reference(&indexBuf, stobj->buffer); 638 indexOffset = pointer_to_offset(ib->ptr) / indexSize; 639 } 640 else { 641 /* element/indicies are in user space memory */ 642 indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr, 643 ib->count * indexSize); 644 indexOffset = 0; 645 } 646 647 /* draw */ 648 if (nr_prims == 1 && pipe->draw_range_elements != NULL) { 649 i = 0; 650 651 /* XXX: exercise temporary path to pass min/max directly 652 * through to driver & draw module. These interfaces still 653 * need a bit of work... 654 */ 655 prim = translate_prim( ctx, prims[i].mode ); 656 657 pipe->draw_range_elements(pipe, indexBuf, indexSize, 658 min_index, 659 max_index, 660 prim, 661 prims[i].start + indexOffset, prims[i].count); 662 } 663 else { 664 for (i = 0; i < nr_prims; i++) { 665 prim = translate_prim( ctx, prims[i].mode ); 666 667 pipe->draw_elements(pipe, indexBuf, indexSize, 668 prim, 669 prims[i].start + indexOffset, prims[i].count); 670 } 671 } 672 673 pipe_buffer_reference(&indexBuf, NULL); 674 } 675 else { 676 /* non-indexed */ 677 GLuint i; 678 GLuint prim; 679 680 for (i = 0; i < nr_prims; i++) { 681 prim = translate_prim( ctx, prims[i].mode ); 682 683 pipe->draw_arrays(pipe, prim, prims[i].start, prims[i].count); 684 } 685 } 686 687 /* unreference buffers (frees wrapped user-space buffer objects) */ 688 for (attr = 0; attr < num_vbuffers; attr++) { 689 pipe_buffer_reference(&vbuffer[attr].buffer, NULL); 690 assert(!vbuffer[attr].buffer); 691 } 692 693 if (userSpace) 694 { 695 pipe->set_vertex_buffers(pipe, 0, NULL); 696 } 697} 698 699 700void st_init_draw( struct st_context *st ) 701{ 702 GLcontext *ctx = st->ctx; 703 704 vbo_set_draw_func(ctx, st_draw_vbo); 705} 706 707 708void st_destroy_draw( struct st_context *st ) 709{ 710} 711 712 713