varray.c revision 653c83b9b4d922f05767d7f96429863a76996093
1/* $Id: varray.c,v 1.16 1999/11/18 23:56:04 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.1 6 * 7 * Copyright (C) 1999 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27#ifdef PC_HEADER 28#include "all.h" 29#else 30#include "glheader.h" 31#include "context.h" 32#include "cva.h" 33#include "enable.h" 34#include "enums.h" 35#include "dlist.h" 36#include "light.h" 37#include "macros.h" 38#include "mmath.h" 39#include "pipeline.h" 40#include "texstate.h" 41#include "translate.h" 42#include "types.h" 43#include "varray.h" 44#include "vb.h" 45#include "vbfill.h" 46#include "vbrender.h" 47#include "vbindirect.h" 48#include "vbxform.h" 49#include "xform.h" 50#endif 51 52 53 54void 55_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 56{ 57 GET_CURRENT_CONTEXT(ctx); 58 59 if (size<2 || size>4) { 60 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" ); 61 return; 62 } 63 if (stride<0) { 64 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" ); 65 return; 66 } 67 68 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) 69 fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size, 70 gl_lookup_enum_by_nr( type ), 71 stride); 72 73 ctx->Array.Vertex.StrideB = stride; 74 if (!stride) { 75 switch (type) { 76 case GL_SHORT: 77 ctx->Array.Vertex.StrideB = size*sizeof(GLshort); 78 break; 79 case GL_INT: 80 ctx->Array.Vertex.StrideB = size*sizeof(GLint); 81 break; 82 case GL_FLOAT: 83 ctx->Array.Vertex.StrideB = size*sizeof(GLfloat); 84 break; 85 case GL_DOUBLE: 86 ctx->Array.Vertex.StrideB = size*sizeof(GLdouble); 87 break; 88 default: 89 gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" ); 90 return; 91 } 92 } 93 ctx->Array.Vertex.Size = size; 94 ctx->Array.Vertex.Type = type; 95 ctx->Array.Vertex.Stride = stride; 96 ctx->Array.Vertex.Ptr = (void *) ptr; 97 ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)]; 98 ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)]; 99 ctx->Array.NewArrayState |= VERT_OBJ_ANY; 100 ctx->NewState |= NEW_CLIENT_STATE; 101} 102 103 104 105 106void 107_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) 108{ 109 GET_CURRENT_CONTEXT(ctx); 110 111 if (stride<0) { 112 gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" ); 113 return; 114 } 115 116 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) 117 fprintf(stderr, "glNormalPointer( type %s stride %d )\n", 118 gl_lookup_enum_by_nr( type ), 119 stride); 120 121 ctx->Array.Normal.StrideB = stride; 122 if (!stride) { 123 switch (type) { 124 case GL_BYTE: 125 ctx->Array.Normal.StrideB = 3*sizeof(GLbyte); 126 break; 127 case GL_SHORT: 128 ctx->Array.Normal.StrideB = 3*sizeof(GLshort); 129 break; 130 case GL_INT: 131 ctx->Array.Normal.StrideB = 3*sizeof(GLint); 132 break; 133 case GL_FLOAT: 134 ctx->Array.Normal.StrideB = 3*sizeof(GLfloat); 135 break; 136 case GL_DOUBLE: 137 ctx->Array.Normal.StrideB = 3*sizeof(GLdouble); 138 break; 139 default: 140 gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" ); 141 return; 142 } 143 } 144 ctx->Array.Normal.Type = type; 145 ctx->Array.Normal.Stride = stride; 146 ctx->Array.Normal.Ptr = (void *) ptr; 147 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)]; 148 ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)]; 149 ctx->Array.NewArrayState |= VERT_NORM; 150 ctx->NewState |= NEW_CLIENT_STATE; 151} 152 153 154 155void 156_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 157{ 158 GET_CURRENT_CONTEXT(ctx); 159 160 if (size<3 || size>4) { 161 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" ); 162 return; 163 } 164 if (stride<0) { 165 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" ); 166 return; 167 } 168 169 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) 170 fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size, 171 gl_lookup_enum_by_nr( type ), 172 stride); 173 174 ctx->Array.Color.StrideB = stride; 175 if (!stride) { 176 switch (type) { 177 case GL_BYTE: 178 ctx->Array.Color.StrideB = size*sizeof(GLbyte); 179 break; 180 case GL_UNSIGNED_BYTE: 181 ctx->Array.Color.StrideB = size*sizeof(GLubyte); 182 break; 183 case GL_SHORT: 184 ctx->Array.Color.StrideB = size*sizeof(GLshort); 185 break; 186 case GL_UNSIGNED_SHORT: 187 ctx->Array.Color.StrideB = size*sizeof(GLushort); 188 break; 189 case GL_INT: 190 ctx->Array.Color.StrideB = size*sizeof(GLint); 191 break; 192 case GL_UNSIGNED_INT: 193 ctx->Array.Color.StrideB = size*sizeof(GLuint); 194 break; 195 case GL_FLOAT: 196 ctx->Array.Color.StrideB = size*sizeof(GLfloat); 197 break; 198 case GL_DOUBLE: 199 ctx->Array.Color.StrideB = size*sizeof(GLdouble); 200 break; 201 default: 202 gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" ); 203 return; 204 } 205 } 206 ctx->Array.Color.Size = size; 207 ctx->Array.Color.Type = type; 208 ctx->Array.Color.Stride = stride; 209 ctx->Array.Color.Ptr = (void *) ptr; 210 ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)]; 211 ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)]; 212 ctx->Array.NewArrayState |= VERT_RGBA; 213 ctx->NewState |= NEW_CLIENT_STATE; 214} 215 216 217 218void 219_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr) 220{ 221 GET_CURRENT_CONTEXT(ctx); 222 223 if (stride<0) { 224 gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" ); 225 return; 226 } 227 228 ctx->Array.Index.StrideB = stride; 229 if (!stride) { 230 switch (type) { 231 case GL_UNSIGNED_BYTE: 232 ctx->Array.Index.StrideB = sizeof(GLubyte); 233 break; 234 case GL_SHORT: 235 ctx->Array.Index.StrideB = sizeof(GLshort); 236 break; 237 case GL_INT: 238 ctx->Array.Index.StrideB = sizeof(GLint); 239 break; 240 case GL_FLOAT: 241 ctx->Array.Index.StrideB = sizeof(GLfloat); 242 break; 243 case GL_DOUBLE: 244 ctx->Array.Index.StrideB = sizeof(GLdouble); 245 break; 246 default: 247 gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" ); 248 return; 249 } 250 } 251 ctx->Array.Index.Type = type; 252 ctx->Array.Index.Stride = stride; 253 ctx->Array.Index.Ptr = (void *) ptr; 254 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)]; 255 ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)]; 256 ctx->Array.NewArrayState |= VERT_INDEX; 257 ctx->NewState |= NEW_CLIENT_STATE; 258} 259 260 261 262void 263_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 264{ 265 GET_CURRENT_CONTEXT(ctx); 266 GLuint texUnit; 267 268 texUnit = ctx->Array.ActiveTexture; 269 270 if (size<1 || size>4) { 271 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" ); 272 return; 273 } 274 if (stride<0) { 275 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" ); 276 return; 277 } 278 279 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) 280 fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n", 281 texUnit, 282 size, 283 gl_lookup_enum_by_nr( type ), 284 stride); 285 286 ctx->Array.TexCoord[texUnit].StrideB = stride; 287 if (!stride) { 288 switch (type) { 289 case GL_SHORT: 290 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLshort); 291 break; 292 case GL_INT: 293 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLint); 294 break; 295 case GL_FLOAT: 296 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLfloat); 297 break; 298 case GL_DOUBLE: 299 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLdouble); 300 break; 301 default: 302 gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" ); 303 return; 304 } 305 } 306 ctx->Array.TexCoord[texUnit].Size = size; 307 ctx->Array.TexCoord[texUnit].Type = type; 308 ctx->Array.TexCoord[texUnit].Stride = stride; 309 ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr; 310 311 ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)]; 312 ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)]; 313 ctx->Array.NewArrayState |= PIPE_TEX(texUnit); 314 ctx->NewState |= NEW_CLIENT_STATE; 315} 316 317 318 319 320void 321_mesa_EdgeFlagPointer(GLsizei stride, const void *vptr) 322{ 323 GET_CURRENT_CONTEXT(ctx); 324 const GLboolean *ptr = (GLboolean *)vptr; 325 326 if (stride<0) { 327 gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" ); 328 return; 329 } 330 ctx->Array.EdgeFlag.Stride = stride; 331 ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean); 332 ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr; 333 if (stride != sizeof(GLboolean)) { 334 ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)]; 335 } else { 336 ctx->Array.EdgeFlagFunc = 0; 337 } 338 ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)]; 339 ctx->Array.NewArrayState |= VERT_EDGE; 340 ctx->NewState |= NEW_CLIENT_STATE; 341} 342 343 344/* Called only from gl_DrawElements 345 */ 346void gl_CVAEltPointer( GLcontext *ctx, GLenum type, const GLvoid *ptr ) 347{ 348 switch (type) { 349 case GL_UNSIGNED_BYTE: 350 ctx->CVA.Elt.StrideB = sizeof(GLubyte); 351 break; 352 case GL_UNSIGNED_SHORT: 353 ctx->CVA.Elt.StrideB = sizeof(GLushort); 354 break; 355 case GL_UNSIGNED_INT: 356 ctx->CVA.Elt.StrideB = sizeof(GLuint); 357 break; 358 default: 359 gl_error( ctx, GL_INVALID_ENUM, "glEltPointer(type)" ); 360 return; 361 } 362 ctx->CVA.Elt.Type = type; 363 ctx->CVA.Elt.Stride = 0; 364 ctx->CVA.Elt.Ptr = (void *) ptr; 365 ctx->CVA.EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)]; 366 ctx->Array.NewArrayState |= VERT_ELT; /* ??? */ 367} 368 369 370 371/* KW: Batch function to exec all the array elements in the input 372 * buffer prior to transform. Done only the first time a vertex 373 * buffer is executed or compiled. 374 * 375 * KW: Have to do this after each glEnd if cva isn't active. (also 376 * have to do it after each full buffer) 377 */ 378void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM, 379 GLuint start, 380 GLuint count) 381{ 382 GLuint *flags = IM->Flag; 383 GLuint *elts = IM->Elt; 384 GLuint translate = ctx->Array.Flags; 385 GLuint i; 386 387 if (MESA_VERBOSE&VERBOSE_IMMEDIATE) 388 fprintf(stderr, "exec_array_elements %d .. %d\n", start, count); 389 390 if (translate & VERT_OBJ_ANY) 391 (ctx->Array.VertexEltFunc)( IM->Obj, 392 &ctx->Array.Vertex, 393 flags, elts, (VERT_ELT|VERT_OBJ_ANY), 394 start, count); 395 396 if (translate & VERT_NORM) 397 (ctx->Array.NormalEltFunc)( IM->Normal, 398 &ctx->Array.Normal, 399 flags, elts, (VERT_ELT|VERT_NORM), 400 start, count); 401 402 if (translate & VERT_EDGE) 403 (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag, 404 &ctx->Array.EdgeFlag, 405 flags, elts, (VERT_ELT|VERT_EDGE), 406 start, count); 407 408 if (translate & VERT_RGBA) 409 (ctx->Array.ColorEltFunc)( IM->Color, 410 &ctx->Array.Color, 411 flags, elts, (VERT_ELT|VERT_RGBA), 412 start, count); 413 414 if (translate & VERT_INDEX) 415 (ctx->Array.IndexEltFunc)( IM->Index, 416 &ctx->Array.Index, 417 flags, elts, (VERT_ELT|VERT_INDEX), 418 start, count); 419 420 if (translate & VERT_TEX0_ANY) 421 (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0], 422 &ctx->Array.TexCoord[0], 423 flags, elts, (VERT_ELT|VERT_TEX0_ANY), 424 start, count); 425 426 if (translate & VERT_TEX1_ANY) 427 (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1], 428 &ctx->Array.TexCoord[1], 429 flags, elts, (VERT_ELT|VERT_TEX1_ANY), 430 start, count); 431 432 433 for (i = start ; i < count ; i++) 434 if (flags[i] & VERT_ELT) 435 flags[i] |= translate; 436 437} 438 439 440 441/* Enough funny business going on in here it might be quicker to use a 442 * function pointer. 443 */ 444#define ARRAY_ELT( IM, i ) \ 445{ \ 446 GLuint count = IM->Count; \ 447 IM->Elt[count] = i; \ 448 IM->Flag[count] = ((IM->Flag[count] & IM->ArrayAndFlags) | \ 449 VERT_ELT); \ 450 IM->FlushElt |= IM->ArrayEltFlush; \ 451 IM->Count = count += IM->ArrayIncr; \ 452 if (count == VB_MAX) \ 453 IM->maybe_transform_vb( IM ); \ 454} 455 456 457void 458_mesa_ArrayElement( GLint i ) 459{ 460 GET_IMMEDIATE; 461 ARRAY_ELT( IM, i ); 462} 463 464 465void gl_ArrayElement( GLcontext *CC, GLint i ) 466{ 467 struct immediate *im = CC->input; 468 ARRAY_ELT( im, i ); 469} 470 471 472 473void 474_mesa_DrawArrays(GLenum mode, GLint start, GLsizei count) 475{ 476 GET_CURRENT_CONTEXT(ctx); 477 struct vertex_buffer *VB = ctx->VB; 478 GLint i; 479 480 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays"); 481 482 if (count<0) { 483 gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" ); 484 return; 485 } 486 487 if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled) 488 { 489 GLint remaining = count; 490 GLint i; 491 struct gl_client_array *Normal; 492 struct gl_client_array *Color; 493 struct gl_client_array *Index; 494 struct gl_client_array *TexCoord[MAX_TEXTURE_UNITS]; 495 struct gl_client_array *EdgeFlag; 496 struct immediate *IM = VB->IM; 497 struct gl_pipeline *elt = &ctx->CVA.elt; 498 GLboolean relock; 499 GLuint fallback, required; 500 501 if (ctx->NewState) 502 gl_update_state( ctx ); 503 504 /* Just turn off cva on this path. Could be useful for multipass 505 * rendering to keep it turned on. 506 */ 507 relock = ctx->CompileCVAFlag; 508 ctx->CompileCVAFlag = 0; 509 510 if (!elt->pipeline_valid || relock) 511 gl_build_immediate_pipeline( ctx ); 512 513 required = elt->inputs; 514 fallback = (elt->inputs & ~ctx->Array.Summary); 515 516 if (required & VERT_RGBA) 517 { 518 Color = &ctx->Array.Color; 519 if (fallback & VERT_RGBA) { 520 Color = &ctx->Fallback.Color; 521 ctx->Array.ColorFunc = 522 gl_trans_4ub_tab[4][TYPE_IDX(GL_UNSIGNED_BYTE)]; 523 } 524 } 525 526 if (required & VERT_INDEX) 527 { 528 Index = &ctx->Array.Index; 529 if (fallback & VERT_INDEX) { 530 Index = &ctx->Fallback.Index; 531 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(GL_UNSIGNED_INT)]; 532 } 533 } 534 535 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) 536 { 537 GLuint flag = VERT_TEX_ANY(i); 538 539 if (required & flag) { 540 TexCoord[i] = &ctx->Array.TexCoord[i]; 541 542 if (fallback & flag) 543 { 544 TexCoord[i] = &ctx->Fallback.TexCoord[i]; 545 TexCoord[i]->Size = gl_texcoord_size( ctx->Current.Flag, i ); 546 547 ctx->Array.TexCoordFunc[i] = 548 gl_trans_4f_tab[TexCoord[i]->Size][TYPE_IDX(GL_FLOAT)]; 549 } 550 } 551 } 552 553 if (ctx->Array.Flags != ctx->Array.Flag[0]) 554 for (i = 0 ; i < VB_MAX ; i++) 555 ctx->Array.Flag[i] = ctx->Array.Flags; 556 557 558 if (required & VERT_NORM) 559 { 560 Normal = &ctx->Array.Normal; 561 if (fallback & VERT_NORM) { 562 Normal = &ctx->Fallback.Normal; 563 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(GL_FLOAT)]; 564 } 565 } 566 567 if ( required & VERT_EDGE ) 568 { 569 if (mode == GL_TRIANGLES || 570 mode == GL_QUADS || 571 mode == GL_POLYGON) 572 { 573 EdgeFlag = &ctx->Array.EdgeFlag; 574 if (fallback & VERT_EDGE) { 575 EdgeFlag = &ctx->Fallback.EdgeFlag; 576 ctx->Array.EdgeFlagFunc = 577 gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)]; 578 } 579 } 580 else 581 required &= ~VERT_EDGE; 582 } 583 584 VB->Primitive = IM->Primitive; 585 VB->NextPrimitive = IM->NextPrimitive; 586 VB->MaterialMask = IM->MaterialMask; 587 VB->Material = IM->Material; 588 VB->BoundsPtr = 0; 589 590 IM->v.Obj.size = ctx->Array.Vertex.Size; /* added by Andree Borrmann */ 591 592 while (remaining > 0) { 593 GLint vbspace = VB_MAX - VB_START; 594 GLuint count, n; 595 596 if (vbspace >= remaining) { 597 n = remaining; 598 VB->LastPrimitive = VB_START + n; 599 } else { 600 n = vbspace; 601 VB->LastPrimitive = VB_START; 602 } 603 604 VB->CullMode = 0; 605 606 ctx->Array.VertexFunc( IM->Obj + VB_START, 607 &ctx->Array.Vertex, start, n ); 608 609 if (required & VERT_NORM) { 610 ctx->Array.NormalFunc( IM->Normal + VB_START, 611 Normal, start, n ); 612 } 613 614 if (required & VERT_EDGE) { 615 ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START, 616 EdgeFlag, start, n ); 617 } 618 619 if (required & VERT_RGBA) { 620 ctx->Array.ColorFunc( IM->Color + VB_START, 621 Color, start, n ); 622 } 623 624 if (required & VERT_INDEX) { 625 ctx->Array.IndexFunc( IM->Index + VB_START, 626 Index, start, n ); 627 } 628 629 if (required & VERT_TEX0_ANY) { 630 IM->v.TexCoord[0].size = TexCoord[0]->Size; 631 ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START, 632 TexCoord[0], start, n ); 633 } 634 635 if (required & VERT_TEX1_ANY) { 636 IM->v.TexCoord[1].size = TexCoord[1]->Size; 637 ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START, 638 TexCoord[1], start, n ); 639 } 640 641 VB->ObjPtr = &IM->v.Obj; 642 VB->NormalPtr = &IM->v.Normal; 643 VB->ColorPtr = &IM->v.Color; 644 VB->Color[0] = VB->Color[1] = VB->ColorPtr; 645 VB->IndexPtr = &IM->v.Index; 646 VB->EdgeFlagPtr = &IM->v.EdgeFlag; 647 VB->TexCoordPtr[0] = &IM->v.TexCoord[0]; 648 VB->TexCoordPtr[1] = &IM->v.TexCoord[1]; 649 650 VB->Flag = ctx->Array.Flag; 651 VB->OrFlag = ctx->Array.Flags; 652 653 VB->Start = IM->Start = VB_START; 654 count = VB->Count = IM->Count = VB_START + n; 655 656#define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c) 657 658 RESET_VEC(IM->v.Obj, (GLfloat *), VB_START, count); 659 RESET_VEC(IM->v.Normal, (GLfloat *), VB_START, count); 660 RESET_VEC(IM->v.TexCoord[0], (GLfloat *), VB_START, count); 661 RESET_VEC(IM->v.TexCoord[1], (GLfloat *), VB_START, count); 662 RESET_VEC(IM->v.Index, &, VB_START, count); 663 RESET_VEC(IM->v.Elt, &, VB_START, count); 664 RESET_VEC(IM->v.EdgeFlag, &, VB_START, count); 665 RESET_VEC(IM->v.Color, (GLubyte *), VB_START, count); 666 RESET_VEC(VB->Clip, (GLfloat *), VB_START, count); 667 RESET_VEC(VB->Eye, (GLfloat *), VB_START, count); 668 RESET_VEC(VB->Win, (GLfloat *), VB_START, count); 669 RESET_VEC(VB->BColor, (GLubyte *), VB_START, count); 670 RESET_VEC(VB->BIndex, &, VB_START, count); 671 672 VB->NextPrimitive[VB->CopyStart] = VB->Count; 673 VB->Primitive[VB->CopyStart] = mode; 674 675 /* Transform and render. 676 */ 677 gl_run_pipeline( VB ); 678 gl_flush_vb( ctx, "DrawArrays" ); /* added by Andree Borrmann */ 679 gl_reset_vb( VB ); 680 681 ctx->Array.Flag[count] = ctx->Array.Flags; 682 ctx->Array.Flag[VB_START] = ctx->Array.Flags; 683 684 start += n; 685 remaining -= n; 686 } 687 688 ctx->CompileCVAFlag = relock; 689 } 690 else if (ctx->Array.Vertex.Enabled) 691 { 692 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These 693 * could be handled by the above code, but it gets a little 694 * complex. The generated list is still of good quality 695 * this way. 696 */ 697 gl_Begin( ctx, mode ); 698 for (i=0;i<count;i++) { 699 gl_ArrayElement( ctx, start+i ); 700 } 701 gl_End( ctx ); 702 } 703 else 704 { 705 /* The degenerate case where vertices are not enabled - only 706 * need to process the very final array element, as all of the 707 * preceding ones would be overwritten anyway. 708 */ 709 gl_Begin( ctx, mode ); 710 gl_ArrayElement( ctx, start+count ); 711 gl_End( ctx ); 712 } 713} 714 715 716 717/* KW: Exactly fakes the effects of calling glArrayElement multiple times. 718 * Compilation is handled via. the IM->maybe_transform_vb() callback. 719 */ 720#if 1 721#define DRAW_ELT(FUNC, TYPE) \ 722static void FUNC( GLcontext *ctx, GLenum mode, \ 723 TYPE *indices, GLuint count ) \ 724{ \ 725 GLuint i,j; \ 726 \ 727 gl_Begin( ctx, mode ); \ 728 \ 729 for (j = 0 ; j < count ; ) { \ 730 struct immediate *IM = ctx->input; \ 731 GLuint start = IM->Start; \ 732 GLuint nr = MIN2( VB_MAX, count - j + start ); \ 733 GLuint sf = IM->Flag[start]; \ 734 IM->FlushElt |= IM->ArrayEltFlush; \ 735 \ 736 for (i = start ; i < nr ; i++) { \ 737 IM->Elt[i] = (GLuint) *indices++; \ 738 IM->Flag[i] = VERT_ELT; \ 739 } \ 740 \ 741 if (j == 0) IM->Flag[start] |= sf; \ 742 \ 743 IM->Count = nr; \ 744 j += nr - start; \ 745 \ 746 if (j == count) gl_End( ctx ); \ 747 IM->maybe_transform_vb( IM ); \ 748 } \ 749} 750#else 751#define DRAW_ELT(FUNC, TYPE) \ 752static void FUNC( GLcontext *ctx, GLenum mode, \ 753 TYPE *indices, GLuint count ) \ 754{ \ 755 int i; \ 756 glBegin(mode); \ 757 for (i = 0 ; i < count ; i++) \ 758 glArrayElement( indices[i] ); \ 759 glEnd(); \ 760} 761#endif 762 763 764DRAW_ELT( draw_elt_ubyte, GLubyte ) 765DRAW_ELT( draw_elt_ushort, GLushort ) 766DRAW_ELT( draw_elt_uint, GLuint ) 767 768 769static GLuint natural_stride[0x10] = 770{ 771 sizeof(GLbyte), /* 0 */ 772 sizeof(GLubyte), /* 1 */ 773 sizeof(GLshort), /* 2 */ 774 sizeof(GLushort), /* 3 */ 775 sizeof(GLint), /* 4 */ 776 sizeof(GLuint), /* 5 */ 777 sizeof(GLfloat), /* 6 */ 778 2 * sizeof(GLbyte), /* 7 */ 779 3 * sizeof(GLbyte), /* 8 */ 780 4 * sizeof(GLbyte), /* 9 */ 781 sizeof(GLdouble), /* a */ 782 0, /* b */ 783 0, /* c */ 784 0, /* d */ 785 0, /* e */ 786 0 /* f */ 787}; 788 789 790void 791_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) 792{ 793 GET_CURRENT_CONTEXT(ctx); 794 struct gl_cva *cva; 795 796 cva = &ctx->CVA; 797 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements"); 798 799 if (count <= 0) { 800 if (count < 0) 801 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); 802 return; 803 } 804 805 if (mode > GL_POLYGON) { 806 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); 807 return; 808 } 809 810 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT) 811 { 812 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); 813 return; 814 } 815 816 if (ctx->NewState) 817 gl_update_state(ctx); 818 819 if (ctx->CompileCVAFlag) 820 { 821#if defined(MESA_CVA_PROF) 822 force_init_prof(); 823#endif 824 825 /* Treat VERT_ELT like a special client array. 826 */ 827 ctx->Array.NewArrayState |= VERT_ELT; 828 ctx->Array.Summary |= VERT_ELT; 829 ctx->Array.Flags |= VERT_ELT; 830 831 cva->elt_mode = mode; 832 cva->elt_count = count; 833 cva->Elt.Type = type; 834 cva->Elt.Ptr = (void *) indices; 835 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)]; 836 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)]; 837 838 if (!cva->pre.pipeline_valid) 839 gl_build_precalc_pipeline( ctx ); 840 else if (MESA_VERBOSE & VERBOSE_PIPELINE) 841 fprintf(stderr, ": dont rebuild\n"); 842 843 gl_cva_force_precalc( ctx ); 844 845 /* Did we 'precalculate' the render op? 846 */ 847 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) { 848 ctx->Array.NewArrayState |= VERT_ELT; 849 ctx->Array.Summary &= ~VERT_ELT; 850 ctx->Array.Flags &= ~VERT_ELT; 851 return; 852 } 853 854 if ( (MESA_VERBOSE&VERBOSE_VARRAY) ) 855 printf("using immediate\n"); 856 } 857 858 859 /* Otherwise, have to use the immediate path to render. 860 */ 861 switch (type) { 862 case GL_UNSIGNED_BYTE: 863 { 864 GLubyte *ub_indices = (GLubyte *) indices; 865 if (ctx->Array.Summary & VERT_OBJ_ANY) { 866 draw_elt_ubyte( ctx, mode, ub_indices, count ); 867 } else { 868 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] ); 869 } 870 } 871 break; 872 case GL_UNSIGNED_SHORT: 873 { 874 GLushort *us_indices = (GLushort *) indices; 875 if (ctx->Array.Summary & VERT_OBJ_ANY) { 876 draw_elt_ushort( ctx, mode, us_indices, count ); 877 } else { 878 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] ); 879 } 880 } 881 break; 882 case GL_UNSIGNED_INT: 883 { 884 GLuint *ui_indices = (GLuint *) indices; 885 if (ctx->Array.Summary & VERT_OBJ_ANY) { 886 draw_elt_uint( ctx, mode, ui_indices, count ); 887 } else { 888 gl_ArrayElement( ctx, ui_indices[count-1] ); 889 } 890 } 891 break; 892 default: 893 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); 894 break; 895 } 896 897 if (ctx->CompileCVAFlag) { 898 ctx->Array.NewArrayState |= VERT_ELT; 899 ctx->Array.Summary &= ~VERT_ELT; 900 } 901} 902 903 904 905void 906_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) 907{ 908 GET_CURRENT_CONTEXT(ctx); 909 GLboolean tflag, cflag, nflag; /* enable/disable flags */ 910 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */ 911 912 GLenum ctype; /* color type */ 913 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */ 914 GLint defstride; /* default stride */ 915 GLint c, f; 916 GLint coordUnitSave; 917 918 f = sizeof(GLfloat); 919 c = f * ((4*sizeof(GLubyte) + (f-1)) / f); 920 921 if (stride<0) { 922 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" ); 923 return; 924 } 925 926 switch (format) { 927 case GL_V2F: 928 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; 929 tcomps = 0; ccomps = 0; vcomps = 2; 930 voffset = 0; 931 defstride = 2*f; 932 break; 933 case GL_V3F: 934 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; 935 tcomps = 0; ccomps = 0; vcomps = 3; 936 voffset = 0; 937 defstride = 3*f; 938 break; 939 case GL_C4UB_V2F: 940 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; 941 tcomps = 0; ccomps = 4; vcomps = 2; 942 ctype = GL_UNSIGNED_BYTE; 943 coffset = 0; 944 voffset = c; 945 defstride = c + 2*f; 946 break; 947 case GL_C4UB_V3F: 948 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; 949 tcomps = 0; ccomps = 4; vcomps = 3; 950 ctype = GL_UNSIGNED_BYTE; 951 coffset = 0; 952 voffset = c; 953 defstride = c + 3*f; 954 break; 955 case GL_C3F_V3F: 956 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; 957 tcomps = 0; ccomps = 3; vcomps = 3; 958 ctype = GL_FLOAT; 959 coffset = 0; 960 voffset = 3*f; 961 defstride = 6*f; 962 break; 963 case GL_N3F_V3F: 964 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE; 965 tcomps = 0; ccomps = 0; vcomps = 3; 966 noffset = 0; 967 voffset = 3*f; 968 defstride = 6*f; 969 break; 970 case GL_C4F_N3F_V3F: 971 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE; 972 tcomps = 0; ccomps = 4; vcomps = 3; 973 ctype = GL_FLOAT; 974 coffset = 0; 975 noffset = 4*f; 976 voffset = 7*f; 977 defstride = 10*f; 978 break; 979 case GL_T2F_V3F: 980 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; 981 tcomps = 2; ccomps = 0; vcomps = 3; 982 voffset = 2*f; 983 defstride = 5*f; 984 break; 985 case GL_T4F_V4F: 986 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; 987 tcomps = 4; ccomps = 0; vcomps = 4; 988 voffset = 4*f; 989 defstride = 8*f; 990 break; 991 case GL_T2F_C4UB_V3F: 992 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; 993 tcomps = 2; ccomps = 4; vcomps = 3; 994 ctype = GL_UNSIGNED_BYTE; 995 coffset = 2*f; 996 voffset = c+2*f; 997 defstride = c+5*f; 998 break; 999 case GL_T2F_C3F_V3F: 1000 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; 1001 tcomps = 2; ccomps = 3; vcomps = 3; 1002 ctype = GL_FLOAT; 1003 coffset = 2*f; 1004 voffset = 5*f; 1005 defstride = 8*f; 1006 break; 1007 case GL_T2F_N3F_V3F: 1008 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE; 1009 tcomps = 2; ccomps = 0; vcomps = 3; 1010 noffset = 2*f; 1011 voffset = 5*f; 1012 defstride = 8*f; 1013 break; 1014 case GL_T2F_C4F_N3F_V3F: 1015 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; 1016 tcomps = 2; ccomps = 4; vcomps = 3; 1017 ctype = GL_FLOAT; 1018 coffset = 2*f; 1019 noffset = 6*f; 1020 voffset = 9*f; 1021 defstride = 12*f; 1022 break; 1023 case GL_T4F_C4F_N3F_V4F: 1024 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; 1025 tcomps = 4; ccomps = 4; vcomps = 4; 1026 ctype = GL_FLOAT; 1027 coffset = 4*f; 1028 noffset = 8*f; 1029 voffset = 11*f; 1030 defstride = 15*f; 1031 break; 1032 default: 1033 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" ); 1034 return; 1035 } 1036 1037 if (stride==0) { 1038 stride = defstride; 1039 } 1040 1041 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY ); 1042 _mesa_DisableClientState( GL_INDEX_ARRAY ); 1043 1044 /* Texcoords */ 1045 coordUnitSave = ctx->Array.ActiveTexture; 1046 if (tflag) { 1047 GLint i; 1048 GLint factor = ctx->Array.TexCoordInterleaveFactor; 1049 for (i = 0; i < factor; i++) { 1050 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) ); 1051 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY ); 1052 glTexCoordPointer( tcomps, GL_FLOAT, stride, 1053 (GLubyte *) pointer + i * coffset ); 1054 } 1055 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) { 1056 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) ); 1057 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY ); 1058 } 1059 } 1060 else { 1061 GLint i; 1062 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 1063 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) ); 1064 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY ); 1065 } 1066 } 1067 /* Restore texture coordinate unit index */ 1068 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) ); 1069 1070 1071 /* Color */ 1072 if (cflag) { 1073 _mesa_EnableClientState( GL_COLOR_ARRAY ); 1074 glColorPointer( ccomps, ctype, stride, 1075 (GLubyte*) pointer + coffset ); 1076 } 1077 else { 1078 _mesa_DisableClientState( GL_COLOR_ARRAY ); 1079 } 1080 1081 1082 /* Normals */ 1083 if (nflag) { 1084 _mesa_EnableClientState( GL_NORMAL_ARRAY ); 1085 glNormalPointer( GL_FLOAT, stride, 1086 (GLubyte*) pointer + noffset ); 1087 } 1088 else { 1089 _mesa_DisableClientState( GL_NORMAL_ARRAY ); 1090 } 1091 1092 _mesa_EnableClientState( GL_VERTEX_ARRAY ); 1093 glVertexPointer( vcomps, GL_FLOAT, stride, 1094 (GLubyte *) pointer + voffset ); 1095} 1096 1097 1098 1099void 1100_mesa_DrawRangeElements(GLenum mode, GLuint start, 1101 GLuint end, GLsizei count, 1102 GLenum type, const GLvoid *indices) 1103{ 1104 GET_CURRENT_CONTEXT(ctx); 1105 1106 if (end < start) { 1107 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )"); 1108 return; 1109 } 1110 1111 if (!ctx->Array.LockCount && 2*count > (GLint) 3*(end-start)) { 1112 glLockArraysEXT( start, end ); 1113 glDrawElements( mode, count, type, indices ); 1114 glUnlockArraysEXT(); 1115 } else { 1116 glDrawElements( mode, count, type, indices ); 1117 } 1118} 1119 1120 1121 1122void gl_update_client_state( GLcontext *ctx ) 1123{ 1124 static GLuint sz_flags[5] = { 0, 1125 0, 1126 VERT_OBJ_2, 1127 VERT_OBJ_23, 1128 VERT_OBJ_234 }; 1129 1130 static GLuint tc_flags[5] = { 0, 1131 VERT_TEX0_1, 1132 VERT_TEX0_12, 1133 VERT_TEX0_123, 1134 VERT_TEX0_1234 }; 1135 1136 ctx->Array.Flags = 0; 1137 ctx->Array.Summary = 0; 1138 ctx->input->ArrayIncr = 0; 1139 1140 if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM; 1141 if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA; 1142 if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX; 1143 if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE; 1144 if (ctx->Array.Vertex.Enabled) { 1145 ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size]; 1146 ctx->input->ArrayIncr = 1; 1147 } 1148 if (ctx->Array.TexCoord[0].Enabled) { 1149 ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size]; 1150 } 1151 if (ctx->Array.TexCoord[1].Enabled) { 1152 ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS); 1153 } 1154 1155 /* Not really important any more: 1156 */ 1157 ctx->Array.Summary = ctx->Array.Flags & VERT_DATA; 1158 ctx->input->ArrayAndFlags = ~ctx->Array.Flags; 1159 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag); 1160} 1161 1162