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