st_draw.c revision a673dee4553b6f1649d4cc31f7f7849058411c49
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#include "util/u_format.h" 60#include "cso_cache/cso_context.h" 61 62 63static GLuint double_types[4] = { 64 PIPE_FORMAT_R64_FLOAT, 65 PIPE_FORMAT_R64G64_FLOAT, 66 PIPE_FORMAT_R64G64B64_FLOAT, 67 PIPE_FORMAT_R64G64B64A64_FLOAT 68}; 69 70static GLuint float_types[4] = { 71 PIPE_FORMAT_R32_FLOAT, 72 PIPE_FORMAT_R32G32_FLOAT, 73 PIPE_FORMAT_R32G32B32_FLOAT, 74 PIPE_FORMAT_R32G32B32A32_FLOAT 75}; 76 77static GLuint uint_types_norm[4] = { 78 PIPE_FORMAT_R32_UNORM, 79 PIPE_FORMAT_R32G32_UNORM, 80 PIPE_FORMAT_R32G32B32_UNORM, 81 PIPE_FORMAT_R32G32B32A32_UNORM 82}; 83 84static GLuint uint_types_scale[4] = { 85 PIPE_FORMAT_R32_USCALED, 86 PIPE_FORMAT_R32G32_USCALED, 87 PIPE_FORMAT_R32G32B32_USCALED, 88 PIPE_FORMAT_R32G32B32A32_USCALED 89}; 90 91static GLuint int_types_norm[4] = { 92 PIPE_FORMAT_R32_SNORM, 93 PIPE_FORMAT_R32G32_SNORM, 94 PIPE_FORMAT_R32G32B32_SNORM, 95 PIPE_FORMAT_R32G32B32A32_SNORM 96}; 97 98static GLuint int_types_scale[4] = { 99 PIPE_FORMAT_R32_SSCALED, 100 PIPE_FORMAT_R32G32_SSCALED, 101 PIPE_FORMAT_R32G32B32_SSCALED, 102 PIPE_FORMAT_R32G32B32A32_SSCALED 103}; 104 105static GLuint ushort_types_norm[4] = { 106 PIPE_FORMAT_R16_UNORM, 107 PIPE_FORMAT_R16G16_UNORM, 108 PIPE_FORMAT_R16G16B16_UNORM, 109 PIPE_FORMAT_R16G16B16A16_UNORM 110}; 111 112static GLuint ushort_types_scale[4] = { 113 PIPE_FORMAT_R16_USCALED, 114 PIPE_FORMAT_R16G16_USCALED, 115 PIPE_FORMAT_R16G16B16_USCALED, 116 PIPE_FORMAT_R16G16B16A16_USCALED 117}; 118 119static GLuint short_types_norm[4] = { 120 PIPE_FORMAT_R16_SNORM, 121 PIPE_FORMAT_R16G16_SNORM, 122 PIPE_FORMAT_R16G16B16_SNORM, 123 PIPE_FORMAT_R16G16B16A16_SNORM 124}; 125 126static GLuint short_types_scale[4] = { 127 PIPE_FORMAT_R16_SSCALED, 128 PIPE_FORMAT_R16G16_SSCALED, 129 PIPE_FORMAT_R16G16B16_SSCALED, 130 PIPE_FORMAT_R16G16B16A16_SSCALED 131}; 132 133static GLuint ubyte_types_norm[4] = { 134 PIPE_FORMAT_R8_UNORM, 135 PIPE_FORMAT_R8G8_UNORM, 136 PIPE_FORMAT_R8G8B8_UNORM, 137 PIPE_FORMAT_R8G8B8A8_UNORM 138}; 139 140static GLuint ubyte_types_scale[4] = { 141 PIPE_FORMAT_R8_USCALED, 142 PIPE_FORMAT_R8G8_USCALED, 143 PIPE_FORMAT_R8G8B8_USCALED, 144 PIPE_FORMAT_R8G8B8A8_USCALED 145}; 146 147static GLuint byte_types_norm[4] = { 148 PIPE_FORMAT_R8_SNORM, 149 PIPE_FORMAT_R8G8_SNORM, 150 PIPE_FORMAT_R8G8B8_SNORM, 151 PIPE_FORMAT_R8G8B8A8_SNORM 152}; 153 154static GLuint byte_types_scale[4] = { 155 PIPE_FORMAT_R8_SSCALED, 156 PIPE_FORMAT_R8G8_SSCALED, 157 PIPE_FORMAT_R8G8B8_SSCALED, 158 PIPE_FORMAT_R8G8B8A8_SSCALED 159}; 160 161static GLuint fixed_types[4] = { 162 PIPE_FORMAT_R32_FIXED, 163 PIPE_FORMAT_R32G32_FIXED, 164 PIPE_FORMAT_R32G32B32_FIXED, 165 PIPE_FORMAT_R32G32B32A32_FIXED 166}; 167 168 169 170/** 171 * Return a PIPE_FORMAT_x for the given GL datatype and size. 172 */ 173GLuint 174st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, 175 GLboolean normalized) 176{ 177 assert((type >= GL_BYTE && type <= GL_DOUBLE) || 178 type == GL_FIXED); 179 assert(size >= 1); 180 assert(size <= 4); 181 assert(format == GL_RGBA || format == GL_BGRA); 182 183 if (format == GL_BGRA) { 184 /* this is an odd-ball case */ 185 assert(type == GL_UNSIGNED_BYTE); 186 assert(normalized); 187 return PIPE_FORMAT_A8R8G8B8_UNORM; 188 } 189 190 if (normalized) { 191 switch (type) { 192 case GL_DOUBLE: return double_types[size-1]; 193 case GL_FLOAT: return float_types[size-1]; 194 case GL_INT: return int_types_norm[size-1]; 195 case GL_SHORT: return short_types_norm[size-1]; 196 case GL_BYTE: return byte_types_norm[size-1]; 197 case GL_UNSIGNED_INT: return uint_types_norm[size-1]; 198 case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; 199 case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; 200 case GL_FIXED: return fixed_types[size-1]; 201 default: assert(0); return 0; 202 } 203 } 204 else { 205 switch (type) { 206 case GL_DOUBLE: return double_types[size-1]; 207 case GL_FLOAT: return float_types[size-1]; 208 case GL_INT: return int_types_scale[size-1]; 209 case GL_SHORT: return short_types_scale[size-1]; 210 case GL_BYTE: return byte_types_scale[size-1]; 211 case GL_UNSIGNED_INT: return uint_types_scale[size-1]; 212 case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; 213 case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; 214 case GL_FIXED: return fixed_types[size-1]; 215 default: assert(0); return 0; 216 } 217 } 218 return 0; /* silence compiler warning */ 219} 220 221 222 223 224 225/** 226 * Examine the active arrays to determine if we have interleaved 227 * vertex arrays all living in one VBO, or all living in user space. 228 * \param userSpace returns whether the arrays are in user space. 229 */ 230static GLboolean 231is_interleaved_arrays(const struct st_vertex_program *vp, 232 const struct st_vp_varient *vpv, 233 const struct gl_client_array **arrays, 234 GLboolean *userSpace) 235{ 236 GLuint attr; 237 const struct gl_buffer_object *firstBufObj = NULL; 238 GLint firstStride = -1; 239 GLuint num_client_arrays = 0; 240 const GLubyte *client_addr = NULL; 241 242 for (attr = 0; attr < vpv->num_inputs; attr++) { 243 const GLuint mesaAttr = vp->index_to_input[attr]; 244 const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj; 245 const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */ 246 247 if (firstStride < 0) { 248 firstStride = stride; 249 } 250 else if (firstStride != stride) { 251 return GL_FALSE; 252 } 253 254 if (!bufObj || !bufObj->Name) { 255 num_client_arrays++; 256 /* Try to detect if the client-space arrays are 257 * "close" to each other. 258 */ 259 if (!client_addr) { 260 client_addr = arrays[mesaAttr]->Ptr; 261 } 262 else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) { 263 /* arrays start too far apart */ 264 return GL_FALSE; 265 } 266 } 267 else if (!firstBufObj) { 268 firstBufObj = bufObj; 269 } 270 else if (bufObj != firstBufObj) { 271 return GL_FALSE; 272 } 273 } 274 275 *userSpace = (num_client_arrays == vpv->num_inputs); 276 /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */ 277 278 return GL_TRUE; 279} 280 281 282/** 283 * Compute the memory range occupied by the arrays. 284 */ 285static void 286get_arrays_bounds(const struct st_vertex_program *vp, 287 const struct st_vp_varient *vpv, 288 const struct gl_client_array **arrays, 289 GLuint max_index, 290 const GLubyte **low, const GLubyte **high) 291{ 292 const GLubyte *low_addr = NULL; 293 const GLubyte *high_addr = NULL; 294 GLuint attr; 295 296 for (attr = 0; attr < vpv->num_inputs; attr++) { 297 const GLuint mesaAttr = vp->index_to_input[attr]; 298 const GLint stride = arrays[mesaAttr]->StrideB; 299 const GLubyte *start = arrays[mesaAttr]->Ptr; 300 const unsigned sz = (arrays[mesaAttr]->Size * 301 _mesa_sizeof_type(arrays[mesaAttr]->Type)); 302 const GLubyte *end = start + (max_index * stride) + sz; 303 304 if (attr == 0) { 305 low_addr = start; 306 high_addr = end; 307 } 308 else { 309 low_addr = MIN2(low_addr, start); 310 high_addr = MAX2(high_addr, end); 311 } 312 } 313 314 *low = low_addr; 315 *high = high_addr; 316} 317 318 319/** 320 * Set up for drawing interleaved arrays that all live in one VBO 321 * or all live in user space. 322 * \param vbuffer returns vertex buffer info 323 * \param velements returns vertex element info 324 */ 325static void 326setup_interleaved_attribs(GLcontext *ctx, 327 const struct st_vertex_program *vp, 328 const struct st_vp_varient *vpv, 329 const struct gl_client_array **arrays, 330 GLuint max_index, 331 GLboolean userSpace, 332 struct pipe_vertex_buffer *vbuffer, 333 struct pipe_vertex_element velements[]) 334{ 335 struct pipe_context *pipe = ctx->st->pipe; 336 GLuint attr; 337 const GLubyte *offset0 = NULL; 338 339 for (attr = 0; attr < vpv->num_inputs; attr++) { 340 const GLuint mesaAttr = vp->index_to_input[attr]; 341 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 342 struct st_buffer_object *stobj = st_buffer_object(bufobj); 343 GLsizei stride = arrays[mesaAttr]->StrideB; 344 345 /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ 346 347 if (attr == 0) { 348 const GLubyte *low, *high; 349 350 get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); 351 /*printf("buffer range: %p %p %d\n", low, high, high-low);*/ 352 353 offset0 = low; 354 if (userSpace) { 355 vbuffer->buffer = 356 pipe_user_buffer_create(pipe->screen, (void *) low, high - low); 357 vbuffer->buffer_offset = 0; 358 } 359 else { 360 vbuffer->buffer = NULL; 361 pipe_buffer_reference(&vbuffer->buffer, stobj->buffer); 362 vbuffer->buffer_offset = pointer_to_offset(low); 363 } 364 vbuffer->stride = stride; /* in bytes */ 365 vbuffer->max_index = max_index; 366 } 367 368 velements[attr].src_offset = 369 (unsigned) (arrays[mesaAttr]->Ptr - offset0); 370 velements[attr].instance_divisor = 0; 371 velements[attr].vertex_buffer_index = 0; 372 velements[attr].src_format = 373 st_pipe_vertex_format(arrays[mesaAttr]->Type, 374 arrays[mesaAttr]->Size, 375 arrays[mesaAttr]->Format, 376 arrays[mesaAttr]->Normalized); 377 assert(velements[attr].src_format); 378 } 379} 380 381 382/** 383 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each 384 * vertex attribute. 385 * \param vbuffer returns vertex buffer info 386 * \param velements returns vertex element info 387 */ 388static void 389setup_non_interleaved_attribs(GLcontext *ctx, 390 const struct st_vertex_program *vp, 391 const struct st_vp_varient *vpv, 392 const struct gl_client_array **arrays, 393 GLuint max_index, 394 GLboolean *userSpace, 395 struct pipe_vertex_buffer vbuffer[], 396 struct pipe_vertex_element velements[]) 397{ 398 struct pipe_context *pipe = ctx->st->pipe; 399 GLuint attr; 400 401 for (attr = 0; attr < vpv->num_inputs; attr++) { 402 const GLuint mesaAttr = vp->index_to_input[attr]; 403 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 404 GLsizei stride = arrays[mesaAttr]->StrideB; 405 406 *userSpace = GL_FALSE; 407 408 if (bufobj && bufobj->Name) { 409 /* Attribute data is in a VBO. 410 * Recall that for VBOs, the gl_client_array->Ptr field is 411 * really an offset from the start of the VBO, not a pointer. 412 */ 413 struct st_buffer_object *stobj = st_buffer_object(bufobj); 414 assert(stobj->buffer); 415 /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ 416 417 vbuffer[attr].buffer = NULL; 418 pipe_buffer_reference(&vbuffer[attr].buffer, stobj->buffer); 419 vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); 420 velements[attr].src_offset = 0; 421 } 422 else { 423 /* attribute data is in user-space memory, not a VBO */ 424 uint bytes; 425 /*printf("user-space array %d stride %d\n", attr, stride);*/ 426 427 *userSpace = GL_TRUE; 428 429 /* wrap user data */ 430 if (arrays[mesaAttr]->Ptr) { 431 /* user's vertex array */ 432 if (arrays[mesaAttr]->StrideB) { 433 bytes = arrays[mesaAttr]->StrideB * (max_index + 1); 434 } 435 else { 436 bytes = arrays[mesaAttr]->Size 437 * _mesa_sizeof_type(arrays[mesaAttr]->Type); 438 } 439 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 440 (void *) arrays[mesaAttr]->Ptr, bytes); 441 } 442 else { 443 /* no array, use ctx->Current.Attrib[] value */ 444 bytes = sizeof(ctx->Current.Attrib[0]); 445 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 446 (void *) ctx->Current.Attrib[mesaAttr], bytes); 447 stride = 0; 448 } 449 450 vbuffer[attr].buffer_offset = 0; 451 velements[attr].src_offset = 0; 452 } 453 454 assert(velements[attr].src_offset <= 2048); /* 11-bit field */ 455 456 /* common-case setup */ 457 vbuffer[attr].stride = stride; /* in bytes */ 458 vbuffer[attr].max_index = max_index; 459 velements[attr].instance_divisor = 0; 460 velements[attr].vertex_buffer_index = attr; 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 memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); 567 /* 568 * Setup the vbuffer[] and velements[] arrays. 569 */ 570 if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { 571 /*printf("Draw interleaved\n");*/ 572 setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, 573 vbuffer, velements); 574 num_vbuffers = 1; 575 num_velements = vpv->num_inputs; 576 if (num_velements == 0) 577 num_vbuffers = 0; 578 } 579 else { 580 /*printf("Draw non-interleaved\n");*/ 581 setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, 582 &userSpace, vbuffer, velements); 583 num_vbuffers = vpv->num_inputs; 584 num_velements = vpv->num_inputs; 585 } 586 587#if 0 588 { 589 GLuint i; 590 for (i = 0; i < num_vbuffers; i++) { 591 printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); 592 printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); 593 printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); 594 printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); 595 } 596 for (i = 0; i < num_velements; i++) { 597 printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); 598 printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); 599 printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format)); 600 } 601 } 602#endif 603 604 pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); 605 cso_set_vertex_elements(ctx->st->cso_context, 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 (pipe->draw_range_elements && min_index != ~0 && max_index != ~0) { 649 /* XXX: exercise temporary path to pass min/max directly 650 * through to driver & draw module. These interfaces still 651 * need a bit of work... 652 */ 653 for (i = 0; i < nr_prims; i++) { 654 prim = translate_prim( ctx, prims[i].mode ); 655 656 pipe->draw_range_elements(pipe, indexBuf, indexSize, 657 min_index, max_index, prim, 658 prims[i].start + indexOffset, prims[i].count); 659 } 660 } 661 else { 662 for (i = 0; i < nr_prims; i++) { 663 prim = translate_prim( ctx, prims[i].mode ); 664 665 pipe->draw_elements(pipe, indexBuf, indexSize, 666 prim, 667 prims[i].start + indexOffset, prims[i].count); 668 } 669 } 670 671 pipe_buffer_reference(&indexBuf, NULL); 672 } 673 else { 674 /* non-indexed */ 675 GLuint i; 676 GLuint prim; 677 678 for (i = 0; i < nr_prims; i++) { 679 prim = translate_prim( ctx, prims[i].mode ); 680 681 pipe->draw_arrays(pipe, prim, prims[i].start, prims[i].count); 682 } 683 } 684 685 /* unreference buffers (frees wrapped user-space buffer objects) */ 686 for (attr = 0; attr < num_vbuffers; attr++) { 687 pipe_buffer_reference(&vbuffer[attr].buffer, NULL); 688 assert(!vbuffer[attr].buffer); 689 } 690 691 if (userSpace) 692 { 693 pipe->set_vertex_buffers(pipe, 0, NULL); 694 } 695} 696 697 698void st_init_draw( struct st_context *st ) 699{ 700 GLcontext *ctx = st->ctx; 701 702 vbo_set_draw_func(ctx, st_draw_vbo); 703} 704 705 706void st_destroy_draw( struct st_context *st ) 707{ 708} 709 710 711