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