st_draw.c revision 4dcdf3b9c67f1481d46c1decba84c9c55698db4c
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 * If edge flags are needed, setup an bitvector of flags and call 222 * pipe->set_edgeflags(). 223 * XXX memleak: need to free the returned pointer at some point 224 */ 225static void * 226setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count, 227 const struct gl_client_array *array) 228{ 229 struct pipe_context *pipe = ctx->st->pipe; 230 231 if ((primMode == GL_TRIANGLES || 232 primMode == GL_QUADS || 233 primMode == GL_POLYGON) && 234 (ctx->Polygon.FrontMode != GL_FILL || 235 ctx->Polygon.BackMode != GL_FILL)) { 236 /* need edge flags */ 237 GLint i; 238 unsigned *vec; 239 struct st_buffer_object *stobj = st_buffer_object(array->BufferObj); 240 ubyte *map; 241 242 if (!stobj || stobj->Base.Name == 0) { 243 /* edge flags are not in a VBO */ 244 return NULL; 245 } 246 247 vec = (unsigned *) _mesa_calloc(sizeof(unsigned) * ((count + 31) / 32)); 248 if (!vec) 249 return NULL; 250 251 map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ); 252 map = ADD_POINTERS(map, array->Ptr); 253 254 for (i = 0; i < count; i++) { 255 if (*((float *) map)) 256 vec[i/32] |= 1 << (i % 32); 257 258 map += array->StrideB; 259 } 260 261 pipe_buffer_unmap(pipe->screen, stobj->buffer); 262 263 pipe->set_edgeflags(pipe, vec); 264 265 return vec; 266 } 267 else { 268 /* edge flags not needed */ 269 pipe->set_edgeflags(pipe, NULL); 270 return NULL; 271 } 272} 273 274 275/** 276 * Examine the active arrays to determine if we have interleaved 277 * vertex arrays all living in one VBO, or all living in user space. 278 * \param userSpace returns whether the arrays are in user space. 279 */ 280static GLboolean 281is_interleaved_arrays(const struct st_vertex_program *vp, 282 const struct gl_client_array **arrays, 283 GLboolean *userSpace) 284{ 285 GLuint attr; 286 const struct gl_buffer_object *firstBufObj = NULL; 287 GLint firstStride = -1; 288 GLuint num_client_arrays = 0; 289 const GLubyte *client_addr = NULL; 290 291 for (attr = 0; attr < vp->num_inputs; attr++) { 292 const GLuint mesaAttr = vp->index_to_input[attr]; 293 const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj; 294 const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */ 295 296 if (firstStride < 0) { 297 firstStride = stride; 298 } 299 else if (firstStride != stride) { 300 return GL_FALSE; 301 } 302 303 if (!bufObj || !bufObj->Name) { 304 num_client_arrays++; 305 /* Try to detect if the client-space arrays are 306 * "close" to each other. 307 */ 308 if (!client_addr) { 309 client_addr = arrays[mesaAttr]->Ptr; 310 } 311 else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) { 312 /* arrays start too far apart */ 313 return GL_FALSE; 314 } 315 } 316 else if (!firstBufObj) { 317 firstBufObj = bufObj; 318 } 319 else if (bufObj != firstBufObj) { 320 return GL_FALSE; 321 } 322 } 323 324 *userSpace = (num_client_arrays == vp->num_inputs); 325 /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */ 326 327 return GL_TRUE; 328} 329 330 331/** 332 * Compute the memory range occupied by the arrays. 333 */ 334static void 335get_arrays_bounds(const struct st_vertex_program *vp, 336 const struct gl_client_array **arrays, 337 GLuint max_index, 338 const GLubyte **low, const GLubyte **high) 339{ 340 const GLubyte *low_addr = NULL; 341 const GLubyte *high_addr = NULL; 342 GLuint attr; 343 344 for (attr = 0; attr < vp->num_inputs; attr++) { 345 const GLuint mesaAttr = vp->index_to_input[attr]; 346 const GLint stride = arrays[mesaAttr]->StrideB; 347 const GLubyte *start = arrays[mesaAttr]->Ptr; 348 const unsigned sz = (arrays[mesaAttr]->Size * 349 _mesa_sizeof_type(arrays[mesaAttr]->Type)); 350 const GLubyte *end = start + (max_index * stride) + sz; 351 352 if (attr == 0) { 353 low_addr = start; 354 high_addr = end; 355 } 356 else { 357 low_addr = MIN2(low_addr, start); 358 high_addr = MAX2(high_addr, end); 359 } 360 } 361 362 *low = low_addr; 363 *high = high_addr; 364} 365 366 367/** 368 * Set up for drawing interleaved arrays that all live in one VBO 369 * or all live in user space. 370 * \param vbuffer returns vertex buffer info 371 * \param velements returns vertex element info 372 */ 373static void 374setup_interleaved_attribs(GLcontext *ctx, 375 const struct st_vertex_program *vp, 376 const struct gl_client_array **arrays, 377 GLuint max_index, 378 GLboolean userSpace, 379 struct pipe_vertex_buffer *vbuffer, 380 struct pipe_vertex_element velements[]) 381{ 382 struct pipe_context *pipe = ctx->st->pipe; 383 GLuint attr; 384 const GLubyte *offset0; 385 386 for (attr = 0; attr < vp->num_inputs; attr++) { 387 const GLuint mesaAttr = vp->index_to_input[attr]; 388 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 389 struct st_buffer_object *stobj = st_buffer_object(bufobj); 390 GLsizei stride = arrays[mesaAttr]->StrideB; 391 392 /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ 393 394 if (attr == 0) { 395 const GLubyte *low, *high; 396 397 get_arrays_bounds(vp, arrays, max_index, &low, &high); 398 /*printf("buffer range: %p %p %d\n", low, high, high-low);*/ 399 400 offset0 = low; 401 if (userSpace) { 402 vbuffer->buffer = 403 pipe_user_buffer_create(pipe->screen, (void *) low, high - low); 404 vbuffer->buffer_offset = 0; 405 } 406 else { 407 vbuffer->buffer = NULL; 408 pipe_buffer_reference(&vbuffer->buffer, stobj->buffer); 409 vbuffer->buffer_offset = pointer_to_offset(low); 410 } 411 vbuffer->stride = stride; /* in bytes */ 412 vbuffer->max_index = max_index; 413 } 414 415 velements[attr].src_offset = 416 (unsigned) (arrays[mesaAttr]->Ptr - offset0); 417 velements[attr].vertex_buffer_index = 0; 418 velements[attr].nr_components = arrays[mesaAttr]->Size; 419 velements[attr].src_format = 420 st_pipe_vertex_format(arrays[mesaAttr]->Type, 421 arrays[mesaAttr]->Size, 422 arrays[mesaAttr]->Format, 423 arrays[mesaAttr]->Normalized); 424 assert(velements[attr].src_format); 425 } 426} 427 428 429/** 430 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each 431 * vertex attribute. 432 * \param vbuffer returns vertex buffer info 433 * \param velements returns vertex element info 434 */ 435static void 436setup_non_interleaved_attribs(GLcontext *ctx, 437 const struct st_vertex_program *vp, 438 const struct gl_client_array **arrays, 439 GLuint max_index, 440 GLboolean *userSpace, 441 struct pipe_vertex_buffer vbuffer[], 442 struct pipe_vertex_element velements[]) 443{ 444 struct pipe_context *pipe = ctx->st->pipe; 445 GLuint attr; 446 447 for (attr = 0; attr < vp->num_inputs; attr++) { 448 const GLuint mesaAttr = vp->index_to_input[attr]; 449 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; 450 GLsizei stride = arrays[mesaAttr]->StrideB; 451 452 *userSpace = GL_FALSE; 453 454 if (bufobj && bufobj->Name) { 455 /* Attribute data is in a VBO. 456 * Recall that for VBOs, the gl_client_array->Ptr field is 457 * really an offset from the start of the VBO, not a pointer. 458 */ 459 struct st_buffer_object *stobj = st_buffer_object(bufobj); 460 assert(stobj->buffer); 461 /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ 462 463 vbuffer[attr].buffer = NULL; 464 pipe_buffer_reference(&vbuffer[attr].buffer, stobj->buffer); 465 vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); 466 velements[attr].src_offset = 0; 467 } 468 else { 469 /* attribute data is in user-space memory, not a VBO */ 470 uint bytes; 471 /*printf("user-space array %d stride %d\n", attr, stride);*/ 472 473 *userSpace = GL_TRUE; 474 475 /* wrap user data */ 476 if (arrays[mesaAttr]->Ptr) { 477 /* user's vertex array */ 478 if (arrays[mesaAttr]->StrideB) { 479 bytes = arrays[mesaAttr]->StrideB * (max_index + 1); 480 } 481 else { 482 bytes = arrays[mesaAttr]->Size 483 * _mesa_sizeof_type(arrays[mesaAttr]->Type); 484 } 485 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 486 (void *) arrays[mesaAttr]->Ptr, bytes); 487 } 488 else { 489 /* no array, use ctx->Current.Attrib[] value */ 490 bytes = sizeof(ctx->Current.Attrib[0]); 491 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, 492 (void *) ctx->Current.Attrib[mesaAttr], bytes); 493 stride = 0; 494 } 495 496 vbuffer[attr].buffer_offset = 0; 497 velements[attr].src_offset = 0; 498 } 499 500 assert(velements[attr].src_offset <= 2048); /* 11-bit field */ 501 502 /* common-case setup */ 503 vbuffer[attr].stride = stride; /* in bytes */ 504 vbuffer[attr].max_index = max_index; 505 velements[attr].vertex_buffer_index = attr; 506 velements[attr].nr_components = arrays[mesaAttr]->Size; 507 velements[attr].src_format 508 = st_pipe_vertex_format(arrays[mesaAttr]->Type, 509 arrays[mesaAttr]->Size, 510 arrays[mesaAttr]->Format, 511 arrays[mesaAttr]->Normalized); 512 assert(velements[attr].src_format); 513 } 514} 515 516 517 518/** 519 * Prior to drawing, check that any uniforms referenced by the 520 * current shader have been set. If a uniform has not been set, 521 * issue a warning. 522 */ 523static void 524check_uniforms(GLcontext *ctx) 525{ 526 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 527 if (shProg && shProg->LinkStatus) { 528 GLuint i; 529 for (i = 0; i < shProg->Uniforms->NumUniforms; i++) { 530 const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i]; 531 if (!u->Initialized) { 532 _mesa_warning(ctx, 533 "Using shader with uninitialized uniform: %s", 534 u->Name); 535 } 536 } 537 } 538} 539 540 541/** 542 * This function gets plugged into the VBO module and is called when 543 * we have something to render. 544 * Basically, translate the information into the format expected by gallium. 545 */ 546void 547st_draw_vbo(GLcontext *ctx, 548 const struct gl_client_array **arrays, 549 const struct _mesa_prim *prims, 550 GLuint nr_prims, 551 const struct _mesa_index_buffer *ib, 552 GLboolean index_bounds_valid, 553 GLuint min_index, 554 GLuint max_index) 555{ 556 struct pipe_context *pipe = ctx->st->pipe; 557 const struct st_vertex_program *vp; 558 const struct pipe_shader_state *vs; 559 struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; 560 GLuint attr; 561 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; 562 unsigned num_vbuffers, num_velements; 563 GLboolean userSpace; 564 565 /* Gallium probably doesn't want this in some cases. */ 566 if (!index_bounds_valid) 567 vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); 568 569 /* sanity check for pointer arithmetic below */ 570 assert(sizeof(arrays[0]->Ptr[0]) == 1); 571 572 st_validate_state(ctx->st); 573 574 /* must get these after state validation! */ 575 vp = ctx->st->vp; 576 vs = &ctx->st->vp_varient->state; 577 578#if 0 579 if (MESA_VERBOSE & VERBOSE_GLSL) { 580 check_uniforms(ctx); 581 } 582#else 583 (void) check_uniforms; 584#endif 585 586 /* 587 * Setup the vbuffer[] and velements[] arrays. 588 */ 589 if (is_interleaved_arrays(vp, arrays, &userSpace)) { 590 /*printf("Draw interleaved\n");*/ 591 setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace, 592 vbuffer, velements); 593 num_vbuffers = 1; 594 num_velements = vp->num_inputs; 595 if (num_velements == 0) 596 num_vbuffers = 0; 597 } 598 else { 599 /*printf("Draw non-interleaved\n");*/ 600 setup_non_interleaved_attribs(ctx, vp, arrays, max_index, 601 &userSpace, vbuffer, velements); 602 num_vbuffers = vp->num_inputs; 603 num_velements = vp->num_inputs; 604 } 605 606#if 0 607 { 608 GLuint i; 609 for (i = 0; i < num_vbuffers; i++) { 610 printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); 611 printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); 612 printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); 613 printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); 614 } 615 for (i = 0; i < num_velements; i++) { 616 printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); 617 printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); 618 printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components); 619 printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format)); 620 } 621 } 622#endif 623 624 pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); 625 pipe->set_vertex_elements(pipe, num_velements, velements); 626 627 if (num_vbuffers == 0 || num_velements == 0) 628 return; 629 630 /* do actual drawing */ 631 if (ib) { 632 /* indexed primitive */ 633 struct gl_buffer_object *bufobj = ib->obj; 634 struct pipe_buffer *indexBuf = NULL; 635 unsigned indexSize, indexOffset, i; 636 637 switch (ib->type) { 638 case GL_UNSIGNED_INT: 639 indexSize = 4; 640 break; 641 case GL_UNSIGNED_SHORT: 642 indexSize = 2; 643 break; 644 case GL_UNSIGNED_BYTE: 645 indexSize = 1; 646 break; 647 default: 648 assert(0); 649 return; 650 } 651 652 /* get/create the index buffer object */ 653 if (bufobj && bufobj->Name) { 654 /* elements/indexes are in a real VBO */ 655 struct st_buffer_object *stobj = st_buffer_object(bufobj); 656 pipe_buffer_reference(&indexBuf, stobj->buffer); 657 indexOffset = pointer_to_offset(ib->ptr) / indexSize; 658 } 659 else { 660 /* element/indicies are in user space memory */ 661 indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr, 662 ib->count * indexSize); 663 indexOffset = 0; 664 } 665 666 /* draw */ 667 if (nr_prims == 1 && pipe->draw_range_elements != NULL) { 668 i = 0; 669 670 /* XXX: exercise temporary path to pass min/max directly 671 * through to driver & draw module. These interfaces still 672 * need a bit of work... 673 */ 674 setup_edgeflags(ctx, prims[i].mode, 675 prims[i].start + indexOffset, prims[i].count, 676 arrays[VERT_ATTRIB_EDGEFLAG]); 677 678 pipe->draw_range_elements(pipe, indexBuf, indexSize, 679 min_index, 680 max_index, 681 prims[i].mode, 682 prims[i].start + indexOffset, prims[i].count); 683 } 684 else { 685 for (i = 0; i < nr_prims; i++) { 686 setup_edgeflags(ctx, prims[i].mode, 687 prims[i].start + indexOffset, prims[i].count, 688 arrays[VERT_ATTRIB_EDGEFLAG]); 689 690 pipe->draw_elements(pipe, indexBuf, indexSize, 691 prims[i].mode, 692 prims[i].start + indexOffset, prims[i].count); 693 } 694 } 695 696 pipe_buffer_reference(&indexBuf, NULL); 697 } 698 else { 699 /* non-indexed */ 700 GLuint i; 701 for (i = 0; i < nr_prims; i++) { 702 setup_edgeflags(ctx, prims[i].mode, 703 prims[i].start, prims[i].count, 704 arrays[VERT_ATTRIB_EDGEFLAG]); 705 706 pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count); 707 } 708 } 709 710 /* unreference buffers (frees wrapped user-space buffer objects) */ 711 for (attr = 0; attr < num_vbuffers; attr++) { 712 pipe_buffer_reference(&vbuffer[attr].buffer, NULL); 713 assert(!vbuffer[attr].buffer); 714 } 715 716 if (userSpace) 717 { 718 pipe->set_vertex_buffers(pipe, 0, NULL); 719 } 720} 721 722 723void st_init_draw( struct st_context *st ) 724{ 725 GLcontext *ctx = st->ctx; 726 727 vbo_set_draw_func(ctx, st_draw_vbo); 728} 729 730 731void st_destroy_draw( struct st_context *st ) 732{ 733} 734 735 736