/******************************Module*Header*******************************\ * Module Name: glcltgs.c * * Routines to batch function calls and primitives * * Copyright (c) 1993-1996 Microsoft Corporation \**************************************************************************/ /* ** Copyright 1991-1993, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. */ /* * AUTOMATICALLY UPDATED OR GENERATED BY SGI: DO NOT EDIT * IF YOU MUST MODIFY THIS FILE, PLEASE CONTACT ptar@sgi.com 415-390-1483 */ #include "precomp.h" #pragma hdrstop /* Generic OpenGL Client using subbatching. */ #include #include "imports.h" #include "types.h" #include "glsbmsg.h" #include "glsbmsgh.h" #include "glsrvspt.h" #include "subbatch.h" #include "batchinf.h" #include "glteb.h" #include "glsbcltu.h" #include "glclt.h" #include "compsize.h" #include "context.h" #include "global.h" #include "parray.h" #include "glarray.h" #include "lighting.h" #include "imfuncs.h" #include "..\dlist\dlistopt.h" // // extension apis these are not exported // void APIENTRY glAddSwapHintRectWIN(IN GLint x, IN GLint y, IN GLint width, IN GLint height) { PLRC plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL || plrc->dhrc != 0) { // this api should only be called if there is a generic rc // currently selected. return; } GLCLIENT_BEGIN( AddSwapHintRectWIN, ADDSWAPHINTRECTWIN ) pMsg->xs = x; pMsg->ys = y; pMsg->xe = x + width; pMsg->ye = y + height; return; GLCLIENT_END } #ifdef PRIMITIVE_TRACK static ULONG prim_entries; static ULONG prim_total = 0; static ULONG prim_count = 0; #endif // Polyarray begin flags. Reset line stipple for new line loop, // line strip, and polygon. // Assume that all vertices have the same color. GLuint aPolyArrayBeginFlags[] = { POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_POINTS POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_LINES POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA | POLYARRAY_RESET_STIPPLE, // GL_LINE_LOOP POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA | POLYARRAY_RESET_STIPPLE, // GL_LINE_STRIP POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_TRIANGLES POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_TRIANGLE_STRIP POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_TRIANGLE_FAN POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_QUADS POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA, // GL_QUAD_STRIP POLYARRAY_IN_BEGIN | POLYARRAY_SAME_COLOR_DATA | POLYARRAY_RESET_STIPPLE // GL_POLYGON }; // If you modify this function, you need to also modify VA_DrawElementsBegin. void APIENTRY glcltBegin ( IN GLenum mode ) { POLYARRAY *pa; POLYDATA *pd0, *pdFlush; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; // The invalid functions within begin/end are detected in glsbAttention. pa = GLTEB_CLTPOLYARRAY(); // The vertex buffer is used as follows. The first entry contains the // POLYARRAY structure. The incoming vertices will be saved beginning // at a following entry. As an optimization, the POLYARRAY structure is // kept in the TEB. When glEnd is called, it will be copied to the // vertex buffer. #ifndef _WIN95_ ASSERTOPENGL(sizeof(POLYARRAY) <= sizeof(NtCurrentTeb()->glReserved1), "POLYARRAY and TEB sizes mismatch!"); #endif ASSERTOPENGL(sizeof(POLYDATA) == sizeof(__GLvertex), "POLYDATA and __GLvertex sizes mismatch!"); ASSERTOPENGL(sizeof(POLYARRAY) <= sizeof(POLYDATA), "POLYARRAY and POLYDATA sizes mismatch!"); // Keep vertex structure a multiple of 4 bytes (or 8 bytes). // The vertex buffer must be 4-byte aligned. ASSERTOPENGL(!(sizeof(POLYDATA) & 0x3), "bad POLYDATA size!"); ASSERTOPENGL(!((ULONG)pa->pdBuffer0 & 0x3), "POLYDATA should be aligned!\n"); // If we are already in the begin/end bracket, return an error. if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } if ((GLuint) mode > GL_POLYGON) { GLSETERROR(GL_INVALID_ENUM); return; } // Flush the command buffer if the vertex buffer is nearly full. // Otherwise, just continue with the next available vertex buffer entry. if (pa->pdBufferNext > pa->pdBufferMax - MIN_POLYDATA_BATCH_SIZE) { #ifdef PRIMITIVE_TRACK DbgPrint("* Min-not-present flush\n"); #endif glsbAttention(); // it resets pdBufferNext pointer too ASSERTOPENGL(pa->nextMsgOffset == -1, "bad nextMsgOffset\n"); } // Batch POLYARRAY command in the command buffer. // We want to leave enough room to accomodate at least one invalid command // that may be batched in the begin/end bracket. When glsbAttention, // glsbAttentionAlt, or glcltEnd is called, we will remove these invalid // commands. // // Combine adjacent DrawPolyArray commands into one command. // request DRAWPOLYARRAY_LARGE structure to make room for invalid commands GLCLIENT_BEGIN(DrawPolyArray, DRAWPOLYARRAY_LARGE) // need msg pointer to update pa later pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) pMsg; if (pa->nextMsgOffset == CurrentOffset) { // rewind command buffer pointer pMsgBatchInfo->NextOffset = CurrentOffset; ((BYTE *) pMsgDrawPolyArray) -= GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY)); // chain adjacent DrawPolyArray commands ((POLYARRAY *) pMsgDrawPolyArray->paLast)->paNext = (POLYARRAY *) pa->pdBufferNext; ((POLYARRAY *) pMsgDrawPolyArray->paLast) = (POLYARRAY *) pa->pdBufferNext; } else { // resize the msg to the real size pMsgBatchInfo->NextOffset = CurrentOffset + GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY)); // remember the end of the primitive command pa->nextMsgOffset = pMsgBatchInfo->NextOffset; // start of a new chain pMsgDrawPolyArray->pa0 = pMsgDrawPolyArray->paLast = (PVOID) pa->pdBufferNext; } GLCLIENT_END // Compute the start of the primitive. A new primitive always begins with a // POLYARRAY entry immediately followed by vertex entries. pd0 = pa->pdBufferNext + 1; // Initialize first polydata. pd0->flags = 0; ASSERTOPENGL(pd0->color == &pd0->colors[__GL_FRONTFACE], "bad color pointer!\n"); // Initialize the polyarray structure in the TEB. pa->flags = aPolyArrayBeginFlags[mode]; pa->pdNextVertex = pa->pdCurColor = pa->pdCurNormal = pa->pdCurTexture = pa->pdCurEdgeFlag = pa->pd0 = pd0; pa->primType = mode; pa->paNext = NULL; pa->nIndices = 0; pa->aIndices = NULL; // identity mapping // Compute the flush vertex for this primitive. When the flush vertex is // reached, we will have accumulated enough vertices to render a partially // composed primitive. pdFlush = pa->pdBufferMax; switch (mode) { case GL_POINTS: case GL_LINE_STRIP: case GL_TRIANGLE_FAN: break; case GL_LINE_LOOP: // Line loop reserves an additional end vertex to close the loop. pdFlush--; break; case GL_POLYGON: // The polygon decomposer can only handle up to // __GL_MAX_POLYGON_CLIP_SIZE vertices. if (pdFlush > pd0 + __GL_MAX_POLYGON_CLIP_SIZE - 1); pdFlush = pd0 + __GL_MAX_POLYGON_CLIP_SIZE - 1; break; case GL_LINES: case GL_TRIANGLE_STRIP: case GL_QUAD_STRIP: // number of vertices must be a multiple of 2 if ((pdFlush - pd0 + 1) % 2) pdFlush--; break; case GL_TRIANGLES: // number of vertices must be a multiple of 3 switch ((pdFlush - pd0 + 1) % 3) { case 2: pdFlush--; // fall through case 1: pdFlush--; } break; case GL_QUADS: // number of vertices must be a multiple of 4 switch ((pdFlush - pd0 + 1) % 4) { case 3: pdFlush--; // fall through case 2: pdFlush--; // fall through case 1: pdFlush--; } break; } pa->pdFlush = pdFlush; #ifdef PRIMITIVE_TRACK DbgPrint("glcltBegin with %3d space left\n", pdFlush-pd0+1); prim_entries = 0; #endif } // Special version of Begin for DrawElements. // If you modify this function, you need to also modify glcltBegin. void FASTCALL VA_DrawElementsBegin(POLYARRAY *pa, GLenum mode, GLsizei count) { POLYDATA *pd0; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; GLint maxVertexCount; // The vertex buffer is used as follows. The first entry contains the // POLYARRAY structure. The incoming vertices will be saved beginning // at a following entry. As an optimization, the POLYARRAY structure is // kept in the TEB. When VA_DrawElementsEnd is called, it will be copied // to the vertex buffer. // We don't handle Points, Line Loop, and Polygon here. They should // have been sent to Begin/End. ASSERTOPENGL(mode != GL_POINTS && mode != GL_LINE_LOOP && mode != GL_POLYGON, "Primitive type not handled\n"); // Flush the command buffer if the vertex buffer will overflow. // Otherwise, just continue with the next available vertex buffer entry. // Maximum number of vertex entries that we will handle in next batch maxVertexCount = min(count,VA_DRAWELEM_MAP_SIZE) // Add maximum number of entries used for index map + (VA_DRAWELEM_INDEX_SIZE + sizeof(POLYDATA) - 1) / sizeof(POLYDATA) // Reserve an extra vertex entry to prevent calling // PolyArrayFlushPartialPrimitive in the Vertex routines. // It should call VA_DrawElementsFlushPartialPrimitive instead. + 1 // Add an entry for POLYARRAY + 1 // Add a few more entries to be safe + 4; if (pa->pdBufferNext > pa->pdBufferMax - maxVertexCount + 1) { #ifdef PRIMITIVE_TRACK DbgPrint("* Min-not-present flush\n"); #endif glsbAttention(); // it resets pdBufferNext pointer too ASSERTOPENGL(pa->nextMsgOffset == -1, "bad nextMsgOffset\n"); } // The vertex buffer must have at least maxVertexCount (currently <= 277) // entries. ASSERTOPENGL(maxVertexCount <= pa->pdBufferMax - pa->pdBuffer0 + 1, "vertex buffer is too small!\n"); // Batch POLYARRAY command in the command buffer. // Combine adjacent DrawPolyArray commands into one command. GLCLIENT_BEGIN(DrawPolyArray, DRAWPOLYARRAY) // need msg pointer to update pa later pMsgDrawPolyArray = pMsg; if (pa->nextMsgOffset == CurrentOffset) { // rewind command buffer pointer pMsgBatchInfo->NextOffset = CurrentOffset; ((BYTE *) pMsgDrawPolyArray) -= GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY)); // chain adjacent DrawPolyArray commands ((POLYARRAY *) pMsgDrawPolyArray->paLast)->paNext = (POLYARRAY *) pa->pdBufferNext; ((POLYARRAY *) pMsgDrawPolyArray->paLast) = (POLYARRAY *) pa->pdBufferNext; } else { // remember the end of the primitive command pa->nextMsgOffset = pMsgBatchInfo->NextOffset; // start of a new chain pMsgDrawPolyArray->pa0 = pMsgDrawPolyArray->paLast = (PVOID) pa->pdBufferNext; } GLCLIENT_END // Compute the start of the primitive. A new primitive always begins with a // POLYARRAY entry immediately followed by vertex entries. pd0 = pa->pdBufferNext + 1; // Initialize first polydata. pd0->flags = 0; ASSERTOPENGL(pd0->color == &pd0->colors[__GL_FRONTFACE], "bad color pointer!\n"); // Initialize the polyarray structure in the TEB. pa->flags = aPolyArrayBeginFlags[mode] | POLYARRAY_SAME_POLYDATA_TYPE; pa->pdNextVertex = pa->pdCurColor = pa->pdCurNormal = pa->pdCurTexture = pa->pdCurEdgeFlag = pa->pd0 = pd0; pa->primType = mode; pa->paNext = NULL; pa->nIndices = 0; pa->aIndices = (GLubyte *) -1; // this is updated in End // The flush vertex for this primitive should never be reached. We have // reserved enough room for a vertex batch. Set it to maximum and assert // that we never reach the vertex in PolyArrayFlushPartialPrimitive! pa->pdFlush = pa->pdBufferMax; #ifdef PRIMITIVE_TRACK DbgPrint("VA_DrawElementsBegin with %3d space left\n", pa->pdBufferMax-pd0+1); #endif return; } void APIENTRY glcltEnd ( void ) { POLYARRAY *pa; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; pa = GLTEB_CLTPOLYARRAY(); // Flush invalid commands accumulated in the command buffer if there is any. glsbAttention(); // If we are not in the begin/end bracket, return an error. if (!(pa->flags & POLYARRAY_IN_BEGIN)) { GLSETERROR(GL_INVALID_OPERATION); return; } // Clear the POLYARRAY_IN_BEGIN flag in the TEB. We are now out of // the begin/end bracket. pa->flags &= ~POLYARRAY_IN_BEGIN; // Clear POLYARRAY_SAME_COLOR_DATA flag if the primitive uses more than // one color. Also clear the flag if an evaluator is used. We cannot // tell if an evaluator modifies the color on the client side. if ((pa->pdCurColor != pa->pd0) || ((pa->pd0->flags & POLYDATA_COLOR_VALID) && (pa->flags & POLYARRAY_PARTIAL_BEGIN)) || (pa->flags & (POLYARRAY_EVALCOORD1 | POLYARRAY_EVALCOORD2 | POLYARRAY_EVALPOINT1 | POLYARRAY_EVALPOINT2))) pa->flags &= ~POLYARRAY_SAME_COLOR_DATA; // Compute nIndices. It is the final number of vertices passed to the low // level render routines and is different from the number of polydata's // accumulated. The final number includes the reserved vertices and the // accumulated vertices. pa->nIndices += pa->pdNextVertex - pa->pd0; if (pa->primType == GL_LINE_LOOP) pa->nIndices++; // add one extra vertex when a line loop is closed. // It's okay not to advance pdBufferNext since we // don't need attributes after they've been // processed. // Save the POLYARRAY structure in the batch. pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pa->pMsgBatchInfo + pa->nextMsgOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); *(POLYARRAY *) pMsgDrawPolyArray->paLast = *pa; #ifdef PRIMITIVE_TRACK prim_entries += pa->pdNextVertex-pa->pd0; prim_total += prim_entries; prim_count++; DbgPrint("glcltEnd with %3d polydata entries, %3d now, avg %d\n", prim_entries, pa->pdNextVertex-pa->pd0, prim_total/prim_count); #endif // Advance polyarray batch pointer. // Skip a vertex because it may contain attributes for the current batch. pa->pdBufferNext = pa->pdNextVertex + 1; } void FASTCALL VA_DrawElementsEnd(POLYARRAY *pa) { GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; ASSERTOPENGL(pa->flags & POLYARRAY_IN_BEGIN, "not in begin\n"); ASSERTOPENGL(pa->aIndices && pa->aIndices != (GLubyte *) -1, "no output index array!\n"); // Clear the POLYARRAY_IN_BEGIN flag in the TEB. We are now out of // the begin/end bracket. pa->flags &= ~POLYARRAY_IN_BEGIN; // Clear POLYARRAY_SAME_COLOR_DATA flag if the primitive uses more than // one color. if (pa->pdCurColor != pa->pd0) pa->flags &= ~POLYARRAY_SAME_COLOR_DATA; // Save the POLYARRAY structure in the batch. pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pa->pMsgBatchInfo + pa->nextMsgOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); *(POLYARRAY *) pMsgDrawPolyArray->paLast = *pa; #ifdef PRIMITIVE_TRACK prim_count++; DbgPrint("VA_DrawElementsEnd called\n"); #endif // Advance polyarray batch pointer. pa->pdBufferNext = (POLYDATA *) (pa->aIndices + (pa->nIndices + sizeof(POLYDATA) - 1) / sizeof(POLYDATA) * sizeof(POLYDATA)); } // Number of reserved vertices for partial Begin. GLint nReservedIndicesPartialBegin[] = { 0, // GL_POINTS 0, // GL_LINES 1, // GL_LINE_LOOP 1, // GL_LINE_STRIP 0, // GL_TRIANGLES 2, // GL_TRIANGLE_STRIP 2, // GL_TRIANGLE_FAN 0, // GL_QUADS 2, // GL_QUAD_STRIP 3 // GL_POLYGON }; // If you modify this function, you need to also modify // VA_DrawElementsFlushPartialPrimitive. void FASTCALL PolyArrayFlushPartialPrimitive() { POLYARRAY *pa; POLYDATA *pd0, *pdFlush; GLenum mode; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; GLuint paFlags; __GL_SETUP(); pa = gc->paTeb; #ifdef PRIMITIVE_TRACK prim_entries += pa->pdNextVertex-pa->pd0; DbgPrint("* Flush partial primitive with %d polydata entries\n", pa->pdNextVertex-pa->pd0); #endif ASSERTOPENGL(pa->flags & POLYARRAY_IN_BEGIN, "not in begin\n"); ASSERTOPENGL(!pa->aIndices, "Flushing DrawElements unexpected!\n"); // Flush invalid commands accumulated in the command buffer if there is any. glsbAttention(); // Clear the POLYARRAY_IN_BEGIN flag in the TEB. We are now out of // the begin/end bracket temporarily. glsbAttention does not flush // unless the flag is clear. pa->flags &= ~POLYARRAY_IN_BEGIN; // Mark it as a partially completed primitive batch. pa->flags |= POLYARRAY_PARTIAL_END; // Clear POLYARRAY_SAME_COLOR_DATA flag if the primitive uses more than // one color. Also clear the flag if an evaluator is used. We cannot // tell if an evaluator modifies the color on the client side. if ((pa->pdCurColor != pa->pd0) || ((pa->pd0->flags & POLYDATA_COLOR_VALID) && (pa->flags & POLYARRAY_PARTIAL_BEGIN)) || (pa->flags & (POLYARRAY_EVALCOORD1 | POLYARRAY_EVALCOORD2 | POLYARRAY_EVALPOINT1 | POLYARRAY_EVALPOINT2))) pa->flags &= ~POLYARRAY_SAME_COLOR_DATA; // Save some pa flags for next partial primitive. // Need to preserve POLYARRAY_CLAMP_COLOR flag in dlist playback. paFlags = pa->flags & (POLYARRAY_SAME_POLYDATA_TYPE | POLYARRAY_SAME_COLOR_DATA | POLYARRAY_CLAMP_COLOR); // Compute nIndices. It is the final number of vertices passed to the low // level render routines and is different from the number of polydata's // accumulated. The final number includes the reserved vertices and the // accumulated vertices. pa->nIndices += pa->pdNextVertex - pa->pd0; // Save the POLYARRAY structure in the batch. pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pa->pMsgBatchInfo + pa->nextMsgOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); *(POLYARRAY *) pMsgDrawPolyArray->paLast = *pa; // Save states before flushing the batch. mode = pa->primType; // Flush the command buffer and reset pointer for the next batch. // If we are compiling poly array primitive in dlist, record the last poly // data record. if (gc->dlist.beginRec) { // Record the poly data. __glDlistCompilePolyData(gc, GL_FALSE); // We just recorded this vertex, don't record it in the compile // code again! gc->dlist.skipPolyData = GL_TRUE; if (gc->dlist.mode == GL_COMPILE_AND_EXECUTE) glsbAttention(); // reset pdBufferNext pointer too! else glsbResetBuffers(TRUE); // reset pointers but no execution } else { glsbAttention(); // reset pdBufferNext pointer too! } ASSERTOPENGL(pa->nextMsgOffset == -1, "bad nextMsgOffset\n"); // Batch new POLYARRAY command in the command buffer. GLCLIENT_BEGIN(DrawPolyArray, DRAWPOLYARRAY) // need msg pointer to update pa later pMsgDrawPolyArray = pMsg; // start of a new chain pMsgDrawPolyArray->pa0 = pMsgDrawPolyArray->paLast = (PVOID) pa->pdBufferNext; // remember the end of the primitive command pa->nextMsgOffset = pMsgBatchInfo->NextOffset; GLCLIENT_END // Compute the start of the PARTIAL primitive. A partial primitive begins // with a POLYARRAY entry followed by vertex entries. We need to // reserve additional vertex entries at the beginning for connectivity // between decomposed primitives. pd0 = pa->pdBufferNext + 1 + nReservedIndicesPartialBegin[mode]; // Initialize first polydata. pd0->flags = 0; ASSERTOPENGL(pd0->color == &pd0->colors[__GL_FRONTFACE], "bad color pointer!\n"); // Initialize the polyarray structure in the TEB. pa->flags = POLYARRAY_IN_BEGIN | POLYARRAY_PARTIAL_BEGIN | paFlags; pa->pdNextVertex = pa->pdCurColor = pa->pdCurNormal = pa->pdCurTexture = pa->pdCurEdgeFlag = pa->pd0 = pd0; pa->primType = mode; pa->paNext = NULL; pa->nIndices = nReservedIndicesPartialBegin[mode]; pa->aIndices = NULL; // identity mapping // Compute the flush vertex for this primitive. When the flush vertex is // reached, we will have accumulated enough vertices to render a partially // composed primitive. pdFlush = pa->pdBufferMax; switch (mode) { case GL_POINTS: case GL_LINE_STRIP: case GL_TRIANGLE_FAN: break; case GL_LINE_LOOP: // Line loop reserves an additional end vertex to close the loop. pdFlush--; break; case GL_POLYGON: // The polygon decomposer can only handle up to // __GL_MAX_POLYGON_CLIP_SIZE vertices. We also need to give // allowance for 3 vertices in the decomposed polygons. if (pdFlush > (pd0 - 3) + __GL_MAX_POLYGON_CLIP_SIZE - 1) pdFlush = (pd0 - 3) + __GL_MAX_POLYGON_CLIP_SIZE - 1; ASSERTOPENGL(nReservedIndicesPartialBegin[GL_POLYGON] == 3, "bad reserved size!\n"); break; case GL_LINES: case GL_TRIANGLE_STRIP: case GL_QUAD_STRIP: // number of vertices must be a multiple of 2 if ((pdFlush - pd0 + 1) % 2) pdFlush--; break; case GL_TRIANGLES: // number of vertices must be a multiple of 3 switch ((pdFlush - pd0 + 1) % 3) { case 2: pdFlush--; // fall through case 1: pdFlush--; } break; case GL_QUADS: // number of vertices must be a multiple of 4 switch ((pdFlush - pd0 + 1) % 4) { case 3: pdFlush--; // fall through case 2: pdFlush--; // fall through case 1: pdFlush--; } break; } pa->pdFlush = pdFlush; } // Special version of Flush for DrawElements. // If you modify this function, you need to also modify // PolyArrayFlushPartialPrimitive. void FASTCALL VA_DrawElementsFlushPartialPrimitive(POLYARRAY *pa, GLenum mode) { POLYDATA *pd0; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; GLuint paFlags; __GL_SETUP(); #ifdef PRIMITIVE_TRACK DbgPrint("VA_DrawElementsFlushPartialPrimitive called\n"); #endif // We don't handle Points, Line Loop, and Polygon here. They should // have been sent to Begin/End. ASSERTOPENGL(mode != GL_POINTS && mode != GL_LINE_LOOP && mode != GL_POLYGON, "Primitive type not handled\n"); ASSERTOPENGL(pa->flags & POLYARRAY_IN_BEGIN, "not in begin\n"); ASSERTOPENGL(pa->aIndices && pa->aIndices != (GLubyte *) -1, "no output index array!\n"); // Clear the POLYARRAY_IN_BEGIN flag in the TEB. We are now out of // the begin/end bracket temporarily. glsbAttention does not flush // unless the flag is clear. pa->flags &= ~POLYARRAY_IN_BEGIN; // Mark it as a partially completed primitive batch. pa->flags |= POLYARRAY_PARTIAL_END; // Clear POLYARRAY_SAME_COLOR_DATA flag if the primitive uses more than // one color. if (pa->pdCurColor != pa->pd0) pa->flags &= ~POLYARRAY_SAME_COLOR_DATA; // Save some pa flags for next partial primitive. paFlags = pa->flags & POLYARRAY_SAME_COLOR_DATA; // Save the POLYARRAY structure in the batch. pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pa->pMsgBatchInfo + pa->nextMsgOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); *(POLYARRAY *) pMsgDrawPolyArray->paLast = *pa; // Flush the command buffer and reset pointer for the next batch. ASSERTOPENGL(!gc->dlist.beginRec || gc->dlist.mode == GL_COMPILE_AND_EXECUTE, "dlist complilation unexpected!\n"); glsbAttention(); // reset pdBufferNext pointer too! ASSERTOPENGL(pa->nextMsgOffset == -1, "bad nextMsgOffset\n"); // Batch new POLYARRAY command in the command buffer. GLCLIENT_BEGIN(DrawPolyArray, DRAWPOLYARRAY) // need msg pointer to update pa later pMsgDrawPolyArray = pMsg; // start of a new chain pMsgDrawPolyArray->pa0 = pMsgDrawPolyArray->paLast = (PVOID) pa->pdBufferNext; // remember the end of the primitive command pa->nextMsgOffset = pMsgBatchInfo->NextOffset; GLCLIENT_END // Compute the start of the PARTIAL primitive. A partial primitive begins // with a POLYARRAY entry followed by vertex entries. We need to // reserve additional vertex entries at the beginning for connectivity // between decomposed primitives. pd0 = pa->pdBufferNext + 1 + nReservedIndicesPartialBegin[mode]; // Initialize first polydata. pd0->flags = 0; ASSERTOPENGL(pd0->color == &pd0->colors[__GL_FRONTFACE], "bad color pointer!\n"); // Initialize the polyarray structure in the TEB. pa->flags = POLYARRAY_IN_BEGIN | POLYARRAY_PARTIAL_BEGIN | POLYARRAY_SAME_POLYDATA_TYPE | paFlags; pa->pdNextVertex = pa->pdCurColor = pa->pdCurNormal = pa->pdCurTexture = pa->pdCurEdgeFlag = pa->pd0 = pd0; pa->primType = mode; pa->paNext = NULL; pa->nIndices = nReservedIndicesPartialBegin[mode]; pa->aIndices = (GLubyte *) -1; // this is updated in End // The flush vertex for this primitive should never be reached. The call // to glsbAttention in this function has left enough room for a vertex batch. // Set it to maximum and assert that we never reach the vertex in // PolyArrayFlushPartialPrimitive! pa->pdFlush = pa->pdBufferMax; } // The vertex functions are called in begin/end only. #define PA_VERTEX2(x1,y1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_VERTEX2; \ \ pd = pa->pdNextVertex++; \ pd->flags |= POLYDATA_VERTEX2; \ pd->obj.x = x1; \ pd->obj.y = y1; \ pd->obj.z = __glZero; \ pd->obj.w = __glOne; \ \ pd[1].flags = 0; \ \ if (pd >= pa->pdFlush) \ PolyArrayFlushPartialPrimitive(); \ } #define PA_VERTEX3(x1,y1,z1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_VERTEX3; \ \ pd = pa->pdNextVertex++; \ pd->flags |= POLYDATA_VERTEX3; \ pd->obj.x = x1; \ pd->obj.y = y1; \ pd->obj.z = z1; \ pd->obj.w = __glOne; \ \ pd[1].flags = 0; \ \ if (pd >= pa->pdFlush) \ PolyArrayFlushPartialPrimitive(); \ } #define PA_VERTEX4(x1,y1,z1,w1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_VERTEX4; \ \ pd = pa->pdNextVertex++; \ pd->flags |= POLYDATA_VERTEX4; \ pd->obj.x = x1; \ pd->obj.y = y1; \ pd->obj.z = z1; \ pd->obj.w = w1; \ \ pd[1].flags = 0; \ \ if (pd >= pa->pdFlush) \ PolyArrayFlushPartialPrimitive(); \ } #define PA_COLOR_IN_RGBA_NO_CLAMP1(red,green,blue) \ POLYARRAY *pa; \ POLYDATA *pd; \ __GL_SETUP(); \ \ pa = gc->paTeb; \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurColor = pd; \ \ __GL_SCALE_R(pd->colors[0].r, gc, red); \ __GL_SCALE_G(pd->colors[0].g, gc, green); \ __GL_SCALE_B(pd->colors[0].b, gc, blue); \ pd->colors[0].a = gc->alphaVertexScale; \ \ pd->flags |= POLYDATA_COLOR_VALID; \ } \ else \ { \ glcltColor4f_InRGBA_NotInBegin(gc, pa, \ POLYDATA_COLOR_VALID, red, green, blue, __glOne); \ } #define PA_COLOR_IN_RGBA_NO_CLAMP(red,green,blue,alpha) \ POLYARRAY *pa; \ POLYDATA *pd; \ __GL_SETUP(); \ \ pa = gc->paTeb; \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurColor = pd; \ \ __GL_SCALE_R(pd->colors[0].r, gc, red); \ __GL_SCALE_G(pd->colors[0].g, gc, green); \ __GL_SCALE_B(pd->colors[0].b, gc, blue); \ __GL_SCALE_A(pd->colors[0].a, gc, alpha); \ \ pd->flags |= POLYDATA_COLOR_VALID | POLYDATA_DLIST_COLOR_4; \ } \ else \ { \ glcltColor4f_InRGBA_NotInBegin(gc, pa, \ POLYDATA_COLOR_VALID | POLYDATA_DLIST_COLOR_4, red, green, blue, alpha);\ } #define PA_COLOR_IN_RGB1(red,green,blue) \ POLYARRAY *pa; \ POLYDATA *pd; \ __GL_SETUP(); \ \ pa = gc->paTeb; \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurColor = pd; \ \ __GL_SCALE_AND_CHECK_CLAMP_R(pd->colors[0].r, gc, pa->flags, red); \ __GL_SCALE_AND_CHECK_CLAMP_G(pd->colors[0].g, gc, pa->flags, green);\ __GL_SCALE_AND_CHECK_CLAMP_B(pd->colors[0].b, gc, pa->flags, blue); \ pd->colors[0].a = gc->alphaVertexScale; \ \ pd->flags |= POLYDATA_COLOR_VALID; \ } \ else \ { \ glcltColor4f_InRGBA_NotInBegin(gc, pa, \ POLYDATA_COLOR_VALID, red, green, blue, __glOne); \ } #define PA_COLOR_IN_RGBA(red,green,blue,alpha) \ POLYARRAY *pa; \ POLYDATA *pd; \ __GL_SETUP(); \ \ pa = gc->paTeb; \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurColor = pd; \ \ __GL_SCALE_AND_CHECK_CLAMP_R(pd->colors[0].r, gc, pa->flags, red); \ __GL_SCALE_AND_CHECK_CLAMP_G(pd->colors[0].g, gc, pa->flags, green);\ __GL_SCALE_AND_CHECK_CLAMP_B(pd->colors[0].b, gc, pa->flags, blue); \ __GL_SCALE_AND_CHECK_CLAMP_A(pd->colors[0].a, gc, pa->flags, alpha);\ \ pd->flags |= POLYDATA_COLOR_VALID | POLYDATA_DLIST_COLOR_4; \ } \ else \ { \ glcltColor4f_InRGBA_NotInBegin(gc, pa, \ POLYDATA_COLOR_VALID | POLYDATA_DLIST_COLOR_4, red, green, blue, alpha);\ } #define PA_COLOR_IN_CI(red,green,blue,alpha) \ \ POLYARRAY *pa; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_OTHER_COLOR; \ /* need only record the latest values */ \ /* otherColor in the TEB may not be aligned at 16-byte boundary */ \ pa->otherColor.r = red; \ pa->otherColor.g = green; \ pa->otherColor.b = blue; \ pa->otherColor.a = alpha; \ } \ else \ { \ glcltColor4f_NotInBegin(red, green, blue, alpha); \ } void FASTCALL glcltColor4f_NotInBegin(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { GLCLIENT_BEGIN( Color4fv, COLOR4FV ) pMsg->v[0] = red; pMsg->v[1] = green; pMsg->v[2] = blue; pMsg->v[3] = alpha; GLCLIENT_END } void FASTCALL glcltColor4f_InRGBA_NotInBegin(__GLcontext *gc, POLYARRAY *pa, GLuint pdFlags, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { POLYDATA *pd; GLMSGBATCHINFO *pMsgBatchInfo; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo; // If the last command is DrawPolyArray, add it to the command. // This allows us to chain primitives separated by the attribute. if (pMsgBatchInfo->NextOffset == pa->nextMsgOffset) { pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pMsgBatchInfo + pMsgBatchInfo->NextOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); pa = (POLYARRAY *) pMsgDrawPolyArray->paLast; pd = pa->pdNextVertex; pa->pdCurColor = pd; __GL_SCALE_AND_CHECK_CLAMP_R(pd->colors[0].r, gc, pa->flags, red); __GL_SCALE_AND_CHECK_CLAMP_G(pd->colors[0].g, gc, pa->flags, green); __GL_SCALE_AND_CHECK_CLAMP_B(pd->colors[0].b, gc, pa->flags, blue); __GL_SCALE_AND_CHECK_CLAMP_A(pd->colors[0].a, gc, pa->flags, alpha); pd->flags |= pdFlags; } else { glcltColor4f_NotInBegin(red, green, blue, alpha); } } #define PA_INDEX_IN_RGBA(i) \ \ POLYARRAY *pa; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_OTHER_COLOR; \ /* need only record the latest value */ \ pa->otherColor.r = i; \ } \ else \ { \ glcltIndexf_NotInBegin(i); \ } #define PA_INDEX_IN_CI(i) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ __GL_SETUP(); \ \ pa = gc->paTeb; \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurColor = pd; \ __GL_CHECK_CLAMP_CI(pd->colors[0].r, gc, pa->flags, i); \ pd->flags |= POLYDATA_COLOR_VALID; \ } \ else \ { \ glcltIndexf_InCI_NotInBegin(gc, pa, i); \ } void FASTCALL glcltIndexf_NotInBegin(GLfloat c) { GLCLIENT_BEGIN( Indexf, INDEXF ) pMsg->c = c; GLCLIENT_END } void FASTCALL glcltIndexf_InCI_NotInBegin(__GLcontext *gc, POLYARRAY *pa, GLfloat c) { POLYDATA *pd; GLMSGBATCHINFO *pMsgBatchInfo; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo; // If the last command is DrawPolyArray, add it to the command. // This allows us to chain primitives separated by the attribute. if (pMsgBatchInfo->NextOffset == pa->nextMsgOffset) { pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pMsgBatchInfo + pMsgBatchInfo->NextOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); pa = (POLYARRAY *) pMsgDrawPolyArray->paLast; pd = pa->pdNextVertex; pa->pdCurColor = pd; __GL_CHECK_CLAMP_CI(pd->colors[0].r, gc, pa->flags, c); pd->flags |= POLYDATA_COLOR_VALID; } else { glcltIndexf_NotInBegin(c); } } #define PA_TEXTURE1(s1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_TEXTURE1; \ \ pd = pa->pdNextVertex; \ pa->pdCurTexture = pd; \ pd->flags |= POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE1; \ pd->texture.x = s1; \ pd->texture.y = __glZero; \ pd->texture.z = __glZero; \ pd->texture.w = __glOne; \ } \ else \ { \ glcltTexCoord4f_NotInBegin(pa, POLYARRAY_TEXTURE1, \ s1, __glZero, __glZero, __glOne); \ } #define PA_TEXTURE2(s1,t1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_TEXTURE2; \ \ pd = pa->pdNextVertex; \ pa->pdCurTexture = pd; \ pd->flags |= POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE2; \ pd->texture.x = s1; \ pd->texture.y = t1; \ pd->texture.z = __glZero; \ pd->texture.w = __glOne; \ } \ else \ { \ glcltTexCoord4f_NotInBegin(pa, POLYARRAY_TEXTURE2, \ s1, t1, __glZero, __glOne); \ } #define PA_TEXTURE3(s1,t1,r1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_TEXTURE3; \ \ pd = pa->pdNextVertex; \ pa->pdCurTexture = pd; \ pd->flags |= POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE3; \ pd->texture.x = s1; \ pd->texture.y = t1; \ pd->texture.z = r1; \ pd->texture.w = __glOne; \ } \ else \ { \ glcltTexCoord4f_NotInBegin(pa, POLYARRAY_TEXTURE3, \ s1, t1, r1, __glOne); \ } #define PA_TEXTURE4(s1,t1,r1,q1) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pa->flags |= POLYARRAY_TEXTURE4; \ \ pd = pa->pdNextVertex; \ pa->pdCurTexture = pd; \ pd->flags |= POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE4; \ pd->texture.x = s1; \ pd->texture.y = t1; \ pd->texture.z = r1; \ pd->texture.w = q1; \ } \ else \ { \ glcltTexCoord4f_NotInBegin(pa, POLYARRAY_TEXTURE4, \ s1, t1, r1, q1); \ } void FASTCALL glcltTexCoord4f_NotInBegin(POLYARRAY *pa, GLuint paFlags, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { POLYDATA *pd; GLMSGBATCHINFO *pMsgBatchInfo; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo; // If the last command is DrawPolyArray, add it to the command. // This allows us to chain primitives separated by the attribute. if (pMsgBatchInfo->NextOffset == pa->nextMsgOffset) { pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pMsgBatchInfo + pMsgBatchInfo->NextOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); pa = (POLYARRAY *) pMsgDrawPolyArray->paLast; pa->flags |= paFlags; pd = pa->pdNextVertex; pa->pdCurTexture = pd; pd->flags |= POLYDATA_TEXTURE_VALID | paFlags; pd->texture.x = s; pd->texture.y = t; pd->texture.z = r; pd->texture.w = q; } else { GLCLIENT_BEGIN( TexCoord4fv, TEXCOORD4FV ) pMsg->v[0] = s; pMsg->v[1] = t; pMsg->v[2] = r; pMsg->v[3] = q; GLCLIENT_END } } #define PA_NORMAL(nx,ny,nz) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurNormal = pd; \ pd->flags |= POLYDATA_NORMAL_VALID; \ pd->normal.x = nx; \ pd->normal.y = ny; \ pd->normal.z = nz; \ } \ else \ { \ glcltNormal3f_NotInBegin(pa, nx, ny, nz); \ } void FASTCALL glcltNormal3f_NotInBegin(POLYARRAY *pa, GLfloat nx, GLfloat ny, GLfloat nz) { POLYDATA *pd; GLMSGBATCHINFO *pMsgBatchInfo; GLMSG_DRAWPOLYARRAY *pMsgDrawPolyArray; pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo; // If the last command is DrawPolyArray, add it to the command. // This allows us to chain primitives separated by the attribute. if (pMsgBatchInfo->NextOffset == pa->nextMsgOffset) { pMsgDrawPolyArray = (GLMSG_DRAWPOLYARRAY *) ((BYTE *) pMsgBatchInfo + pMsgBatchInfo->NextOffset - GLMSG_ALIGN(sizeof(GLMSG_DRAWPOLYARRAY))); pa = (POLYARRAY *) pMsgDrawPolyArray->paLast; pd = pa->pdNextVertex; pa->pdCurNormal = pd; pd->flags |= POLYDATA_NORMAL_VALID; pd->normal.x = nx; pd->normal.y = ny; pd->normal.z = nz; } else { GLCLIENT_BEGIN( Normal3fv, NORMAL3FV ) pMsg->v[ 0] = nx; pMsg->v[ 1] = ny; pMsg->v[ 2] = nz; GLCLIENT_END } } #define PA_EDGEFLAG(edgeflag) \ \ POLYARRAY *pa; \ POLYDATA *pd; \ \ pa = GLTEB_CLTPOLYARRAY(); \ \ if (pa->flags & POLYARRAY_IN_BEGIN) \ { \ pd = pa->pdNextVertex; \ pa->pdCurEdgeFlag = pd; \ if (edgeflag) \ pd->flags |= POLYDATA_EDGEFLAG_VALID|POLYDATA_EDGEFLAG_BOUNDARY;\ else \ { \ /* must clear POLYDATA_EDGEFLAG_BOUNDARY flag here since */ \ /* there may have been a previous edge flag for this same */ \ /* vertex! */ \ pd->flags &= ~POLYDATA_EDGEFLAG_BOUNDARY; \ pd->flags |= POLYDATA_EDGEFLAG_VALID; \ } \ } \ else \ { \ glcltEdgeFlag_NotInBegin(edgeflag); \ } void FASTCALL glcltEdgeFlag_NotInBegin(GLboolean flag) { GLCLIENT_BEGIN( EdgeFlag, EDGEFLAG ) pMsg->flag = flag; GLCLIENT_END } void APIENTRY glcltColor3b_InRGBA ( IN GLbyte red, IN GLbyte green, IN GLbyte blue ) { PA_COLOR_IN_RGB1(__GL_B_TO_FLOAT(red), __GL_B_TO_FLOAT(green), __GL_B_TO_FLOAT(blue)); } void APIENTRY glcltColor3bv_InRGBA ( IN const GLbyte v[3] ) { PA_COLOR_IN_RGB1(__GL_B_TO_FLOAT(v[0]), __GL_B_TO_FLOAT(v[1]), __GL_B_TO_FLOAT(v[2])); } void APIENTRY glcltColor3d_InRGBA ( IN GLdouble red, IN GLdouble green, IN GLdouble blue ) { PA_COLOR_IN_RGB1((GLfloat) red, (GLfloat) green, (GLfloat) blue); } void APIENTRY glcltColor3dv_InRGBA ( IN const GLdouble v[3] ) { PA_COLOR_IN_RGB1((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } void APIENTRY glcltColor3f_InRGBA ( IN GLfloat red, IN GLfloat green, IN GLfloat blue ) { #if _X86NOT_ // This is currently disable since I don't see any improvements in the // timings! // Need rewrite if used. POLYARRAY *pa; __GL_SETUP(); pa = gc->paTeb; __asm{ mov eax, pa mov ebx, [OFFSET(POLYARRAY.flags)][eax] test ebx, POLYARRAY_IN_BEGIN jne in_begin } glcltColor4f_InRGBA_NotInBegin(gc, pa, POLYARRAY_COLOR3F, red, green, blue, __glOne); return; __asm{ in_begin: mov edi, [OFFSET(POLYARRAY.pdNextVertex)][eax] or ebx, POLYARRAY_COLOR3F mov ecx, gc mov [OFFSET(POLYARRAY.flags)][eax], ebx mov edx, [OFFSET(POLYDATA.flags)][edi] mov [OFFSET(POLYARRAY.pdCurColor)][eax], edi or edx, POLYDATA_COLOR_VALID | POLYARRAY_COLOR3F mov [OFFSET(POLYDATA.flags)][edi], edx fld DWORD PTR red mov eax, [OFFSET(__GLcontext.redClampTable)][ecx] fmul DWORD PTR [OFFSET(__GLcontext.redVertexScale)][ecx] mov edx, 0x3f800000 shr eax, 31 sub edx, [OFFSET(__GLcontext.redClampTable)][ecx] shr edx, 31 fstp [OFFSET(__GLcontext.redClampTable)][ecx] lea eax, [edx + 2*eax] fld DWORD PTR green mov ebx, [OFFSET(__GLcontext.greenClampTable)][ecx] fmul DWORD PTR [OFFSET(__GLcontext.greenVertexScale)][ecx] mov edx, 0x3f800000 shr ebx, 31 sub edx, [OFFSET(__GLcontext.greenClampTable)][ecx] shr edx, 31 fstp [OFFSET(__GLcontext.redClampTable)][ecx] lea ebx, [edx + 2*ebx] mov edx, [OFFSET(__GLcontext.redClampTable)][ecx][eax] mov DWORD PTR [OFFSET(POLYDATA.colors)][edi], edx mov eax, [OFFSET(__GLcontext.redClampTable)][ecx][ebx] mov DWORD PTR [OFFSET(POLYDATA.colors) + 4][edi], eax fld DWORD PTR blue mov eax, [OFFSET(__GLcontext.blueClampTable)][ecx] fmul DWORD PTR [OFFSET(__GLcontext.blueVertexScale)][ecx] mov edx, 0x3f800000 shr eax, 31 sub edx, [OFFSET(__GLcontext.blueClampTable)][ecx] shr edx, 31 fstp [OFFSET(__GLcontext.blueClampTable)][ecx] lea eax, [edx + 2*eax] mov ebx, [OFFSET(__GLcontext.alphaVertexScale)][ecx] mov DWORD PTR [OFFSET(POLYDATA.colors) + 12][edi], ebx mov edx, [OFFSET(__GLcontext.blueClampTable)][ecx][eax] mov DWORD PTR [OFFSET(POLYDATA.colors) + 8][edi], edx } #else PA_COLOR_IN_RGB1(red, green, blue); #endif } void APIENTRY glcltColor3fv_InRGBA ( IN const GLfloat v[3] ) { PA_COLOR_IN_RGB1(v[0], v[1], v[2]); } void APIENTRY glcltColor3i_InRGBA ( IN GLint red, IN GLint green, IN GLint blue ) { PA_COLOR_IN_RGB1(__GL_I_TO_FLOAT(red), __GL_I_TO_FLOAT(green), __GL_I_TO_FLOAT(blue)); } void APIENTRY glcltColor3iv_InRGBA ( IN const GLint v[3] ) { PA_COLOR_IN_RGB1(__GL_I_TO_FLOAT(v[0]), __GL_I_TO_FLOAT(v[1]), __GL_I_TO_FLOAT(v[2])); } void APIENTRY glcltColor3s_InRGBA ( IN GLshort red, IN GLshort green, IN GLshort blue ) { PA_COLOR_IN_RGB1(__GL_S_TO_FLOAT(red), __GL_S_TO_FLOAT(green), __GL_S_TO_FLOAT(blue)); } void APIENTRY glcltColor3sv_InRGBA ( IN const GLshort v[3] ) { PA_COLOR_IN_RGB1(__GL_S_TO_FLOAT(v[0]), __GL_S_TO_FLOAT(v[1]), __GL_S_TO_FLOAT(v[2])); } void APIENTRY glcltColor3ub_InRGBA ( IN GLubyte red, IN GLubyte green, IN GLubyte blue ) { PA_COLOR_IN_RGBA_NO_CLAMP1(__GL_UB_TO_FLOAT(red), __GL_UB_TO_FLOAT(green), __GL_UB_TO_FLOAT(blue)); } void APIENTRY glcltColor3ubv_InRGBA ( IN const GLubyte v[3] ) { PA_COLOR_IN_RGBA_NO_CLAMP1(__GL_UB_TO_FLOAT(v[0]), __GL_UB_TO_FLOAT(v[1]), __GL_UB_TO_FLOAT(v[2])); } void APIENTRY glcltColor3ui_InRGBA ( IN GLuint red, IN GLuint green, IN GLuint blue ) { PA_COLOR_IN_RGB1(__GL_UI_TO_FLOAT(red), __GL_UI_TO_FLOAT(green), __GL_UI_TO_FLOAT(blue)); } void APIENTRY glcltColor3uiv_InRGBA ( IN const GLuint v[3] ) { PA_COLOR_IN_RGB1(__GL_UI_TO_FLOAT(v[0]), __GL_UI_TO_FLOAT(v[1]), __GL_UI_TO_FLOAT(v[2])); } void APIENTRY glcltColor3us_InRGBA ( IN GLushort red, IN GLushort green, IN GLushort blue ) { PA_COLOR_IN_RGBA_NO_CLAMP1(__GL_US_TO_FLOAT(red), __GL_US_TO_FLOAT(green), __GL_US_TO_FLOAT(blue)); } void APIENTRY glcltColor3usv_InRGBA ( IN const GLushort v[3] ) { PA_COLOR_IN_RGBA_NO_CLAMP1(__GL_US_TO_FLOAT(v[0]), __GL_US_TO_FLOAT(v[1]), __GL_US_TO_FLOAT(v[2])); } void APIENTRY glcltColor4b_InRGBA ( IN GLbyte red, IN GLbyte green, IN GLbyte blue, IN GLbyte alpha ) { PA_COLOR_IN_RGBA(__GL_B_TO_FLOAT(red), __GL_B_TO_FLOAT(green), __GL_B_TO_FLOAT(blue), __GL_B_TO_FLOAT(alpha)); } void APIENTRY glcltColor4bv_InRGBA ( IN const GLbyte v[4] ) { PA_COLOR_IN_RGBA(__GL_B_TO_FLOAT(v[0]), __GL_B_TO_FLOAT(v[1]), __GL_B_TO_FLOAT(v[2]), __GL_B_TO_FLOAT(v[3])); } void APIENTRY glcltColor4d_InRGBA ( IN GLdouble red, IN GLdouble green, IN GLdouble blue, IN GLdouble alpha ) { PA_COLOR_IN_RGBA((GLfloat) red, (GLfloat) green, (GLfloat) blue, (GLfloat) alpha); } void APIENTRY glcltColor4dv_InRGBA ( IN const GLdouble v[4] ) { PA_COLOR_IN_RGBA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltColor4f_InRGBA ( IN GLfloat red, IN GLfloat green, IN GLfloat blue, IN GLfloat alpha ) { PA_COLOR_IN_RGBA(red, green, blue, alpha); } void APIENTRY glcltColor4fv_InRGBA ( IN const GLfloat v[4] ) { PA_COLOR_IN_RGBA(v[0], v[1], v[2], v[3]); } void APIENTRY glcltColor4i_InRGBA ( IN GLint red, IN GLint green, IN GLint blue, IN GLint alpha ) { PA_COLOR_IN_RGBA(__GL_I_TO_FLOAT(red), __GL_I_TO_FLOAT(green), __GL_I_TO_FLOAT(blue), __GL_I_TO_FLOAT(alpha)); } void APIENTRY glcltColor4iv_InRGBA ( IN const GLint v[4] ) { PA_COLOR_IN_RGBA(__GL_I_TO_FLOAT(v[0]), __GL_I_TO_FLOAT(v[1]), __GL_I_TO_FLOAT(v[2]), __GL_I_TO_FLOAT(v[3])); } void APIENTRY glcltColor4s_InRGBA ( IN GLshort red, IN GLshort green, IN GLshort blue, IN GLshort alpha ) { PA_COLOR_IN_RGBA(__GL_S_TO_FLOAT(red), __GL_S_TO_FLOAT(green), __GL_S_TO_FLOAT(blue), __GL_S_TO_FLOAT(alpha)); } void APIENTRY glcltColor4sv_InRGBA ( IN const GLshort v[4] ) { PA_COLOR_IN_RGBA(__GL_S_TO_FLOAT(v[0]), __GL_S_TO_FLOAT(v[1]), __GL_S_TO_FLOAT(v[2]), __GL_S_TO_FLOAT(v[3])); } void APIENTRY glcltColor4ub_InRGBA ( IN GLubyte red, IN GLubyte green, IN GLubyte blue, IN GLubyte alpha ) { PA_COLOR_IN_RGBA_NO_CLAMP(__GL_UB_TO_FLOAT(red), __GL_UB_TO_FLOAT(green), __GL_UB_TO_FLOAT(blue), __GL_UB_TO_FLOAT(alpha)); } void APIENTRY glcltColor4ubv_InRGBA ( IN const GLubyte v[4] ) { PA_COLOR_IN_RGBA_NO_CLAMP(__GL_UB_TO_FLOAT(v[0]), __GL_UB_TO_FLOAT(v[1]), __GL_UB_TO_FLOAT(v[2]), __GL_UB_TO_FLOAT(v[3])); } void APIENTRY glcltColor4ui_InRGBA ( IN GLuint red, IN GLuint green, IN GLuint blue, IN GLuint alpha ) { PA_COLOR_IN_RGBA(__GL_UI_TO_FLOAT(red), __GL_UI_TO_FLOAT(green), __GL_UI_TO_FLOAT(blue), __GL_UI_TO_FLOAT(alpha)); } void APIENTRY glcltColor4uiv_InRGBA ( IN const GLuint v[4] ) { PA_COLOR_IN_RGBA(__GL_UI_TO_FLOAT(v[0]), __GL_UI_TO_FLOAT(v[1]), __GL_UI_TO_FLOAT(v[2]), __GL_UI_TO_FLOAT(v[3])); } void APIENTRY glcltColor4us_InRGBA ( IN GLushort red, IN GLushort green, IN GLushort blue, IN GLushort alpha ) { PA_COLOR_IN_RGBA_NO_CLAMP(__GL_US_TO_FLOAT(red), __GL_US_TO_FLOAT(green), __GL_US_TO_FLOAT(blue), __GL_US_TO_FLOAT(alpha)); } void APIENTRY glcltColor4usv_InRGBA ( IN const GLushort v[4] ) { PA_COLOR_IN_RGBA_NO_CLAMP(__GL_US_TO_FLOAT(v[0]), __GL_US_TO_FLOAT(v[1]), __GL_US_TO_FLOAT(v[2]), __GL_US_TO_FLOAT(v[3])); } void APIENTRY glcltColor3b_InCI ( IN GLbyte red, IN GLbyte green, IN GLbyte blue ) { PA_COLOR_IN_CI(__GL_B_TO_FLOAT(red), __GL_B_TO_FLOAT(green), __GL_B_TO_FLOAT(blue), __glOne); } void APIENTRY glcltColor3bv_InCI ( IN const GLbyte v[3] ) { PA_COLOR_IN_CI(__GL_B_TO_FLOAT(v[0]), __GL_B_TO_FLOAT(v[1]), __GL_B_TO_FLOAT(v[2]), __glOne); } void APIENTRY glcltColor3d_InCI ( IN GLdouble red, IN GLdouble green, IN GLdouble blue ) { PA_COLOR_IN_CI((GLfloat) red, (GLfloat) green, (GLfloat) blue, __glOne); } void APIENTRY glcltColor3dv_InCI ( IN const GLdouble v[3] ) { PA_COLOR_IN_CI((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], __glOne); } void APIENTRY glcltColor3f_InCI ( IN GLfloat red, IN GLfloat green, IN GLfloat blue ) { PA_COLOR_IN_CI(red, green, blue, __glOne); } void APIENTRY glcltColor3fv_InCI ( IN const GLfloat v[3] ) { PA_COLOR_IN_CI(v[0], v[1], v[2], __glOne); } void APIENTRY glcltColor3i_InCI ( IN GLint red, IN GLint green, IN GLint blue ) { PA_COLOR_IN_CI(__GL_I_TO_FLOAT(red), __GL_I_TO_FLOAT(green), __GL_I_TO_FLOAT(blue), __glOne); } void APIENTRY glcltColor3iv_InCI ( IN const GLint v[3] ) { PA_COLOR_IN_CI(__GL_I_TO_FLOAT(v[0]), __GL_I_TO_FLOAT(v[1]), __GL_I_TO_FLOAT(v[2]), __glOne); } void APIENTRY glcltColor3s_InCI ( IN GLshort red, IN GLshort green, IN GLshort blue ) { PA_COLOR_IN_CI(__GL_S_TO_FLOAT(red), __GL_S_TO_FLOAT(green), __GL_S_TO_FLOAT(blue), __glOne); } void APIENTRY glcltColor3sv_InCI ( IN const GLshort v[3] ) { PA_COLOR_IN_CI(__GL_S_TO_FLOAT(v[0]), __GL_S_TO_FLOAT(v[1]), __GL_S_TO_FLOAT(v[2]), __glOne); } void APIENTRY glcltColor3ub_InCI ( IN GLubyte red, IN GLubyte green, IN GLubyte blue ) { PA_COLOR_IN_CI(__GL_UB_TO_FLOAT(red), __GL_UB_TO_FLOAT(green), __GL_UB_TO_FLOAT(blue), __glOne); } void APIENTRY glcltColor3ubv_InCI ( IN const GLubyte v[3] ) { PA_COLOR_IN_CI(__GL_UB_TO_FLOAT(v[0]), __GL_UB_TO_FLOAT(v[1]), __GL_UB_TO_FLOAT(v[2]), __glOne); } void APIENTRY glcltColor3ui_InCI ( IN GLuint red, IN GLuint green, IN GLuint blue ) { PA_COLOR_IN_CI(__GL_UI_TO_FLOAT(red), __GL_UI_TO_FLOAT(green), __GL_UI_TO_FLOAT(blue), __glOne); } void APIENTRY glcltColor3uiv_InCI ( IN const GLuint v[3] ) { PA_COLOR_IN_CI(__GL_UI_TO_FLOAT(v[0]), __GL_UI_TO_FLOAT(v[1]), __GL_UI_TO_FLOAT(v[2]), __glOne); } void APIENTRY glcltColor3us_InCI ( IN GLushort red, IN GLushort green, IN GLushort blue ) { PA_COLOR_IN_CI(__GL_US_TO_FLOAT(red), __GL_US_TO_FLOAT(green), __GL_US_TO_FLOAT(blue), __glOne); } void APIENTRY glcltColor3usv_InCI ( IN const GLushort v[3] ) { PA_COLOR_IN_CI(__GL_US_TO_FLOAT(v[0]), __GL_US_TO_FLOAT(v[1]), __GL_US_TO_FLOAT(v[2]), __glOne); } void APIENTRY glcltColor4b_InCI ( IN GLbyte red, IN GLbyte green, IN GLbyte blue, IN GLbyte alpha ) { PA_COLOR_IN_CI(__GL_B_TO_FLOAT(red), __GL_B_TO_FLOAT(green), __GL_B_TO_FLOAT(blue), __GL_B_TO_FLOAT(alpha)); } void APIENTRY glcltColor4bv_InCI ( IN const GLbyte v[4] ) { PA_COLOR_IN_CI(__GL_B_TO_FLOAT(v[0]), __GL_B_TO_FLOAT(v[1]), __GL_B_TO_FLOAT(v[2]), __GL_B_TO_FLOAT(v[3])); } void APIENTRY glcltColor4d_InCI ( IN GLdouble red, IN GLdouble green, IN GLdouble blue, IN GLdouble alpha ) { PA_COLOR_IN_CI((GLfloat) red, (GLfloat) green, (GLfloat) blue, (GLfloat) alpha); } void APIENTRY glcltColor4dv_InCI ( IN const GLdouble v[4] ) { PA_COLOR_IN_CI((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltColor4f_InCI ( IN GLfloat red, IN GLfloat green, IN GLfloat blue, IN GLfloat alpha ) { PA_COLOR_IN_CI(red, green, blue, alpha); } void APIENTRY glcltColor4fv_InCI ( IN const GLfloat v[4] ) { PA_COLOR_IN_CI(v[0], v[1], v[2], v[3]); } void APIENTRY glcltColor4i_InCI ( IN GLint red, IN GLint green, IN GLint blue, IN GLint alpha ) { PA_COLOR_IN_CI(__GL_I_TO_FLOAT(red), __GL_I_TO_FLOAT(green), __GL_I_TO_FLOAT(blue), __GL_I_TO_FLOAT(alpha)); } void APIENTRY glcltColor4iv_InCI ( IN const GLint v[4] ) { PA_COLOR_IN_CI(__GL_I_TO_FLOAT(v[0]), __GL_I_TO_FLOAT(v[1]), __GL_I_TO_FLOAT(v[2]), __GL_I_TO_FLOAT(v[3])); } void APIENTRY glcltColor4s_InCI ( IN GLshort red, IN GLshort green, IN GLshort blue, IN GLshort alpha ) { PA_COLOR_IN_CI(__GL_S_TO_FLOAT(red), __GL_S_TO_FLOAT(green), __GL_S_TO_FLOAT(blue), __GL_S_TO_FLOAT(alpha)); } void APIENTRY glcltColor4sv_InCI ( IN const GLshort v[4] ) { PA_COLOR_IN_CI(__GL_S_TO_FLOAT(v[0]), __GL_S_TO_FLOAT(v[1]), __GL_S_TO_FLOAT(v[2]), __GL_S_TO_FLOAT(v[3])); } void APIENTRY glcltColor4ub_InCI ( IN GLubyte red, IN GLubyte green, IN GLubyte blue, IN GLubyte alpha ) { PA_COLOR_IN_CI(__GL_UB_TO_FLOAT(red), __GL_UB_TO_FLOAT(green), __GL_UB_TO_FLOAT(blue), __GL_UB_TO_FLOAT(alpha)); } void APIENTRY glcltColor4ubv_InCI ( IN const GLubyte v[4] ) { PA_COLOR_IN_CI(__GL_UB_TO_FLOAT(v[0]), __GL_UB_TO_FLOAT(v[1]), __GL_UB_TO_FLOAT(v[2]), __GL_UB_TO_FLOAT(v[3])); } void APIENTRY glcltColor4ui_InCI ( IN GLuint red, IN GLuint green, IN GLuint blue, IN GLuint alpha ) { PA_COLOR_IN_CI(__GL_UI_TO_FLOAT(red), __GL_UI_TO_FLOAT(green), __GL_UI_TO_FLOAT(blue), __GL_UI_TO_FLOAT(alpha)); } void APIENTRY glcltColor4uiv_InCI ( IN const GLuint v[4] ) { PA_COLOR_IN_CI(__GL_UI_TO_FLOAT(v[0]), __GL_UI_TO_FLOAT(v[1]), __GL_UI_TO_FLOAT(v[2]), __GL_UI_TO_FLOAT(v[3])); } void APIENTRY glcltColor4us_InCI ( IN GLushort red, IN GLushort green, IN GLushort blue, IN GLushort alpha ) { PA_COLOR_IN_CI(__GL_US_TO_FLOAT(red), __GL_US_TO_FLOAT(green), __GL_US_TO_FLOAT(blue), __GL_US_TO_FLOAT(alpha)); } void APIENTRY glcltColor4usv_InCI ( IN const GLushort v[4] ) { PA_COLOR_IN_CI(__GL_US_TO_FLOAT(v[0]), __GL_US_TO_FLOAT(v[1]), __GL_US_TO_FLOAT(v[2]), __GL_US_TO_FLOAT(v[3])); } // Allocate a __GLmatChange structure. // // The POLYMATERIAL structure contains pointers to __GLmatChange arrays. // These __GLmatChange structures are used to record material changes to // vertices in the vertex buffer. // // To reduce memory requirement, the POLYMATERIAL structure keeps an array // of pointers to __GLmatChange arrays. Each __GLmatChange array is // allocated as needed. // // An iMat index is used to keep track of the next free __GLmatChange // entry. When the poly array buffer is flushed in glsbAttention, iMat // is reset to 0. // // The POLYMATERIAL structure and its __GLmatChange arrays are part of // a thread local storage and are freed when the thread exits. __GLmatChange * FASTCALL PAMatAlloc() { POLYMATERIAL *pm; GLuint iArray, iMat; #if DBG __GL_SETUP(); #endif pm = GLTEB_CLTPOLYMATERIAL(); // Allocate a POLYMATERIAL structure for this thread if one does not exist. if (!pm) { GLuint nv, aMatSize; __GL_SETUP(); nv = gc->vertex.pdBufSize; aMatSize = nv * 2 / POLYMATERIAL_ARRAY_SIZE + 1; if (!(pm = (POLYMATERIAL *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, // Base size sizeof(POLYMATERIAL) - sizeof(__GLmatChange *) + // array of pointers to __GLmatChange arrays aMatSize * sizeof(__GLmatChange *) + // the PDMATERIAL array nv * sizeof(PDMATERIAL)))) { GLSETERROR(GL_OUT_OF_MEMORY); return NULL; } pm->aMatSize = aMatSize; // Initialize pointer to the PDMATERIAL array pm->pdMaterial0 = (PDMATERIAL *) &pm->aMat[aMatSize]; GLTEB_SET_CLTPOLYMATERIAL(pm); } // Sanity check that pdBufSize has not changed. ASSERTOPENGL ( pm->aMatSize == gc->vertex.pdBufSize * 2 / POLYMATERIAL_ARRAY_SIZE + 1, "vertex buffer size has changed!\n" ); // Find the material array from which to allocate the material change structure. iMat = pm->iMat; iArray = iMat / POLYMATERIAL_ARRAY_SIZE; iMat = iMat % POLYMATERIAL_ARRAY_SIZE; ASSERTOPENGL(iArray < pm->aMatSize, "iArray exceeds range!\n"); // Allocate the material array if it has not been allocated. if (!(pm->aMat[iArray])) { if (!(pm->aMat[iArray] = (__GLmatChange *) LocalAlloc(LMEM_FIXED, sizeof(__GLmatChange) * POLYMATERIAL_ARRAY_SIZE))) { GLSETERROR(GL_OUT_OF_MEMORY); return NULL; } } // Advance next available material pointer. pm->iMat++; ASSERTOPENGL(pm->iMat <= gc->vertex.pdBufSize * 2, "too many material changes!\n"); // Return the material change. return (&pm->aMat[iArray][iMat]); } // Free polymaterial for current thread. void FASTCALL FreePolyMaterial(void) { POLYMATERIAL *pm = GLTEB_CLTPOLYMATERIAL(); GLuint i; if (pm) { for (i = 0; i < pm->aMatSize && pm->aMat[i]; i++) { if (LocalFree((PVOID) pm->aMat[i])) RIP("LocalFree failed\n"); } if (LocalFree((PVOID) pm)) RIP("LocalFree failed\n"); GLTEB_SET_CLTPOLYMATERIAL(NULL); } } #if !((POLYARRAY_MATERIAL_FRONT == POLYDATA_MATERIAL_FRONT) \ && (POLYARRAY_MATERIAL_BACK == POLYDATA_MATERIAL_BACK)) #error "bad material mask\n" #endif void APIENTRY glcltMaterialfv ( IN GLenum face, IN GLenum pname, IN const GLfloat params[] ) { POLYARRAY *pa; POLYDATA *pd; GLuint i, pdFlags, dirtyBits, matMask; POLYMATERIAL *pm; pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { switch (pname) { case GL_SHININESS: if (params[0] < (GLfloat) 0 || params[0] > (GLfloat) 128) { GLSETERROR(GL_INVALID_VALUE); return; } dirtyBits = __GL_MATERIAL_SHININESS; break; case GL_EMISSION: dirtyBits = __GL_MATERIAL_EMISSIVE; break; case GL_AMBIENT: dirtyBits = __GL_MATERIAL_AMBIENT; break; case GL_DIFFUSE: dirtyBits = __GL_MATERIAL_DIFFUSE; break; case GL_SPECULAR: dirtyBits = __GL_MATERIAL_SPECULAR; break; case GL_AMBIENT_AND_DIFFUSE: dirtyBits = __GL_MATERIAL_AMBIENT | __GL_MATERIAL_DIFFUSE; break; case GL_COLOR_INDEXES: dirtyBits = __GL_MATERIAL_COLORINDEXES; break; default: GLSETERROR(GL_INVALID_ENUM); return; } switch (face) { case GL_FRONT: pdFlags = POLYDATA_MATERIAL_FRONT; break; case GL_BACK: pdFlags = POLYDATA_MATERIAL_BACK; break; case GL_FRONT_AND_BACK: pdFlags = POLYDATA_MATERIAL_FRONT | POLYDATA_MATERIAL_BACK; break; default: GLSETERROR(GL_INVALID_ENUM); return; } // Update pa flags POLYARRAY_MATERIAL_FRONT and POLYARRAY_MATERIAL_BACK. pa->flags |= pdFlags; // Do front and back material for this vertex // Overwrite the previous material changes for this vertex if they exist since // only the last material changes matter. pd = pa->pdNextVertex; for (i = 0, matMask = POLYDATA_MATERIAL_FRONT; i < 2; i++, matMask = POLYDATA_MATERIAL_BACK) { __GLmatChange *pdMat; if (!(pdFlags & matMask)) continue; // allocate __GLmatChange structure if this vertex hasn't got one if (!(pd->flags & matMask)) { if (!(pdMat = PAMatAlloc())) return; // Get POLYMATERIAL pointer after PAMatAlloc! pm = GLTEB_CLTPOLYMATERIAL(); if (matMask == POLYDATA_MATERIAL_FRONT) pm->pdMaterial0[pd - pa->pdBuffer0].front = pdMat; else pm->pdMaterial0[pd - pa->pdBuffer0].back = pdMat; pdMat->dirtyBits = dirtyBits; } else { pm = GLTEB_CLTPOLYMATERIAL(); if (matMask == POLYDATA_MATERIAL_FRONT) pdMat = pm->pdMaterial0[pd - pa->pdBuffer0].front; else pdMat = pm->pdMaterial0[pd - pa->pdBuffer0].back; pdMat->dirtyBits |= dirtyBits; } if (dirtyBits & __GL_MATERIAL_SHININESS) { pdMat->shininess = params[0]; } else if (dirtyBits & __GL_MATERIAL_COLORINDEXES) { pdMat->cmapa = params[0]; pdMat->cmapd = params[1]; pdMat->cmaps = params[2]; } else if (dirtyBits & __GL_MATERIAL_EMISSIVE) { pdMat->emissive.r = params[0]; pdMat->emissive.g = params[1]; pdMat->emissive.b = params[2]; pdMat->emissive.a = params[3]; } else if (dirtyBits & __GL_MATERIAL_SPECULAR) { pdMat->specular.r = params[0]; pdMat->specular.g = params[1]; pdMat->specular.b = params[2]; pdMat->specular.a = params[3]; } else { // ambient and/or diffuse if (dirtyBits & __GL_MATERIAL_AMBIENT) { pdMat->ambient.r = params[0]; pdMat->ambient.g = params[1]; pdMat->ambient.b = params[2]; pdMat->ambient.a = params[3]; } if (dirtyBits & __GL_MATERIAL_DIFFUSE) { pdMat->diffuse.r = params[0]; pdMat->diffuse.g = params[1]; pdMat->diffuse.b = params[2]; pdMat->diffuse.a = params[3]; } } } // Finally, update pd flags pd->flags |= pdFlags; } else { int cArgs; switch (pname) { case GL_SHININESS: if (params[0] < (GLfloat) 0 || params[0] > (GLfloat) 128) { GLSETERROR(GL_INVALID_VALUE); return; } cArgs = 1; break; case GL_EMISSION: case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: case GL_AMBIENT_AND_DIFFUSE: cArgs = 4; break; case GL_COLOR_INDEXES: cArgs = 3; break; default: GLSETERROR(GL_INVALID_ENUM); return; } switch (face) { case GL_FRONT: case GL_BACK: case GL_FRONT_AND_BACK: break; default: GLSETERROR(GL_INVALID_ENUM); return; } GLCLIENT_BEGIN( Materialfv, MATERIALFV ) pMsg->face = face; pMsg->pname = pname; while (--cArgs >= 0) pMsg->params[cArgs] = params[cArgs]; GLCLIENT_END } } void APIENTRY glcltMaterialf ( IN GLenum face, IN GLenum pname, IN GLfloat param ) { if (pname != GL_SHININESS) { GLSETERROR(GL_INVALID_ENUM); return; } glcltMaterialfv(face, pname, ¶m); } void APIENTRY glcltMateriali ( IN GLenum face, IN GLenum pname, IN GLint param ) { GLfloat fParams[1]; if (pname != GL_SHININESS) { GLSETERROR(GL_INVALID_ENUM); return; } fParams[0] = (GLfloat) param; glcltMaterialfv(face, pname, fParams); } void APIENTRY glcltMaterialiv ( IN GLenum face, IN GLenum pname, IN const GLint params[] ) { GLfloat fParams[4]; switch (pname) { case GL_EMISSION: case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: case GL_AMBIENT_AND_DIFFUSE: fParams[0] = __GL_I_TO_FLOAT(params[0]); fParams[1] = __GL_I_TO_FLOAT(params[1]); fParams[2] = __GL_I_TO_FLOAT(params[2]); fParams[3] = __GL_I_TO_FLOAT(params[3]); break; case GL_COLOR_INDEXES: fParams[2] = (GLfloat) params[2]; fParams[1] = (GLfloat) params[1]; case GL_SHININESS: fParams[0] = (GLfloat) params[0]; break; } glcltMaterialfv(face, pname, fParams); } void APIENTRY glcltEdgeFlag ( IN GLboolean flag ) { PA_EDGEFLAG(flag); } void APIENTRY glcltEdgeFlagv ( IN const GLboolean flag[1] ) { PA_EDGEFLAG(flag[0]); } void APIENTRY glcltIndexd_InCI ( IN GLdouble c ) { PA_INDEX_IN_CI((GLfloat) c); } void APIENTRY glcltIndexdv_InCI ( IN const GLdouble c[1] ) { PA_INDEX_IN_CI((GLfloat) c[0]); } void APIENTRY glcltIndexf_InCI ( IN GLfloat c ) { PA_INDEX_IN_CI((GLfloat) c); } void APIENTRY glcltIndexfv_InCI ( IN const GLfloat c[1] ) { PA_INDEX_IN_CI((GLfloat) c[0]); } void APIENTRY glcltIndexi_InCI ( IN GLint c ) { PA_INDEX_IN_CI((GLfloat) c); } void APIENTRY glcltIndexiv_InCI ( IN const GLint c[1] ) { PA_INDEX_IN_CI((GLfloat) c[0]); } void APIENTRY glcltIndexs_InCI ( IN GLshort c ) { PA_INDEX_IN_CI((GLfloat) c); } void APIENTRY glcltIndexsv_InCI ( IN const GLshort c[1] ) { PA_INDEX_IN_CI((GLfloat) c[0]); } void APIENTRY glcltIndexub_InCI ( IN GLubyte c ) { PA_INDEX_IN_CI((GLfloat) c); } void APIENTRY glcltIndexubv_InCI ( IN const GLubyte c[1] ) { PA_INDEX_IN_CI((GLfloat) c[0]); } void APIENTRY glcltIndexd_InRGBA ( IN GLdouble c ) { PA_INDEX_IN_RGBA((GLfloat) c); } void APIENTRY glcltIndexdv_InRGBA ( IN const GLdouble c[1] ) { PA_INDEX_IN_RGBA((GLfloat) c[0]); } void APIENTRY glcltIndexf_InRGBA ( IN GLfloat c ) { PA_INDEX_IN_RGBA((GLfloat) c); } void APIENTRY glcltIndexfv_InRGBA ( IN const GLfloat c[1] ) { PA_INDEX_IN_RGBA((GLfloat) c[0]); } void APIENTRY glcltIndexi_InRGBA ( IN GLint c ) { PA_INDEX_IN_RGBA((GLfloat) c); } void APIENTRY glcltIndexiv_InRGBA ( IN const GLint c[1] ) { PA_INDEX_IN_RGBA((GLfloat) c[0]); } void APIENTRY glcltIndexs_InRGBA ( IN GLshort c ) { PA_INDEX_IN_RGBA((GLfloat) c); } void APIENTRY glcltIndexsv_InRGBA ( IN const GLshort c[1] ) { PA_INDEX_IN_RGBA((GLfloat) c[0]); } void APIENTRY glcltIndexub_InRGBA ( IN GLubyte c ) { PA_INDEX_IN_RGBA((GLfloat) c); } void APIENTRY glcltIndexubv_InRGBA ( IN const GLubyte c[1] ) { PA_INDEX_IN_RGBA((GLfloat) c[0]); } /******************************************************************/ void APIENTRY glcltNormal3b ( IN GLbyte nx, IN GLbyte ny, IN GLbyte nz ) { PA_NORMAL(__GL_B_TO_FLOAT(nx), __GL_B_TO_FLOAT(ny), __GL_B_TO_FLOAT(nz)); } void APIENTRY glcltNormal3bv ( IN const GLbyte v[3] ) { PA_NORMAL(__GL_B_TO_FLOAT(v[0]), __GL_B_TO_FLOAT(v[1]), __GL_B_TO_FLOAT(v[2])); } void APIENTRY glcltNormal3d ( IN GLdouble nx, IN GLdouble ny, IN GLdouble nz ) { PA_NORMAL((GLfloat) nx, (GLfloat) ny, (GLfloat) nz); } void APIENTRY glcltNormal3dv ( IN const GLdouble v[3] ) { PA_NORMAL((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } #ifndef _X86_ void APIENTRY glcltNormal3f ( IN GLfloat nx, IN GLfloat ny, IN GLfloat nz ) { PA_NORMAL(nx, ny, nz); } void APIENTRY glcltNormal3fv ( IN const GLfloat v[3] ) { PA_NORMAL(v[0], v[1], v[2]); } #endif void APIENTRY glcltNormal3i ( IN GLint nx, IN GLint ny, IN GLint nz ) { PA_NORMAL(__GL_I_TO_FLOAT(nx), __GL_I_TO_FLOAT(ny), __GL_I_TO_FLOAT(nz)); } void APIENTRY glcltNormal3iv ( IN const GLint v[3] ) { PA_NORMAL(__GL_I_TO_FLOAT(v[0]), __GL_I_TO_FLOAT(v[1]), __GL_I_TO_FLOAT(v[2])); } void APIENTRY glcltNormal3s ( IN GLshort nx, IN GLshort ny, IN GLshort nz ) { PA_NORMAL(__GL_S_TO_FLOAT(nx), __GL_S_TO_FLOAT(ny), __GL_S_TO_FLOAT(nz)); } void APIENTRY glcltNormal3sv ( IN const GLshort v[3] ) { PA_NORMAL(__GL_S_TO_FLOAT(v[0]), __GL_S_TO_FLOAT(v[1]), __GL_S_TO_FLOAT(v[2])); } void APIENTRY glcltRasterPos2d ( IN GLdouble x, IN GLdouble y ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2dv ( IN const GLdouble v[2] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2f ( IN GLfloat x, IN GLfloat y ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2fv ( IN const GLfloat v[2] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2i ( IN GLint x, IN GLint y ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2iv ( IN const GLint v[2] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2s ( IN GLshort x, IN GLshort y ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos2sv ( IN const GLshort v[2] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) 0.0, (GLfloat) 1.0); } void APIENTRY glcltRasterPos3d ( IN GLdouble x, IN GLdouble y, IN GLdouble z ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) 1.0); } void APIENTRY glcltRasterPos3dv ( IN const GLdouble v[3] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) 1.0); } void APIENTRY glcltRasterPos3f ( IN GLfloat x, IN GLfloat y, IN GLfloat z ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) 1.0); } void APIENTRY glcltRasterPos3fv ( IN const GLfloat v[3] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) 1.0); } void APIENTRY glcltRasterPos3i ( IN GLint x, IN GLint y, IN GLint z ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) 1.0); } void APIENTRY glcltRasterPos3iv ( IN const GLint v[3] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) 1.0); } void APIENTRY glcltRasterPos3s ( IN GLshort x, IN GLshort y, IN GLshort z ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) 1.0); } void APIENTRY glcltRasterPos3sv ( IN const GLshort v[3] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) 1.0); } void APIENTRY glcltRasterPos4d ( IN GLdouble x, IN GLdouble y, IN GLdouble z, IN GLdouble w ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltRasterPos4dv ( IN const GLdouble v[4] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltRasterPos4f ( IN GLfloat x, IN GLfloat y, IN GLfloat z, IN GLfloat w ) { GLCLIENT_BEGIN( RasterPos4fv, RASTERPOS4FV ) pMsg->v[0] = x; pMsg->v[1] = y; pMsg->v[2] = z; pMsg->v[3] = w; return; GLCLIENT_END } void APIENTRY glcltRasterPos4fv ( IN const GLfloat v[4] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltRasterPos4i ( IN GLint x, IN GLint y, IN GLint z, IN GLint w ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltRasterPos4iv ( IN const GLint v[4] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltRasterPos4s ( IN GLshort x, IN GLshort y, IN GLshort z, IN GLshort w ) { glcltRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltRasterPos4sv ( IN const GLshort v[4] ) { glcltRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltRectd ( IN GLdouble x1, IN GLdouble y1, IN GLdouble x2, IN GLdouble y2 ) { glcltRectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); } void APIENTRY glcltRectdv ( IN const GLdouble v1[2], IN const GLdouble v2[2] ) { glcltRectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } void APIENTRY glcltRectf ( IN GLfloat x1, IN GLfloat y1, IN GLfloat x2, IN GLfloat y2 ) { POLYARRAY *pa; // Not allowed in begin/end. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } // Call Begin/End to do polyarray correctly. Note that by calling these // functions, we allow poly array to be batched correctly. // Note also that we use quad strip instead of quad to force edge flag to be on. //!!! Conformance fails if we use QUAD_STRIP! //glcltBegin(GL_QUAD_STRIP); glcltBegin(GL_QUADS); pa->flags |= POLYARRAY_SAME_POLYDATA_TYPE; glcltVertex2f(x1, y1); glcltVertex2f(x2, y1); glcltVertex2f(x2, y2); glcltVertex2f(x1, y2); glcltEnd(); } void APIENTRY glcltRectfv ( IN const GLfloat v1[2], IN const GLfloat v2[2] ) { glcltRectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } void APIENTRY glcltRecti ( IN GLint x1, IN GLint y1, IN GLint x2, IN GLint y2 ) { glcltRectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); } void APIENTRY glcltRectiv ( IN const GLint v1[2], IN const GLint v2[2] ) { glcltRectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } void APIENTRY glcltRects ( IN GLshort x1, IN GLshort y1, IN GLshort x2, IN GLshort y2 ) { glcltRectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); } void APIENTRY glcltRectsv ( IN const GLshort v1[2], IN const GLshort v2[2] ) { glcltRectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } void APIENTRY glcltTexCoord1d ( IN GLdouble s ) { PA_TEXTURE1((GLfloat) s); } void APIENTRY glcltTexCoord1dv ( IN const GLdouble v[1] ) { PA_TEXTURE1((GLfloat) v[0]); } void APIENTRY glcltTexCoord1f ( IN GLfloat s ) { PA_TEXTURE1((GLfloat) s); } void APIENTRY glcltTexCoord1fv ( IN const GLfloat v[1] ) { PA_TEXTURE1((GLfloat) v[0]); } void APIENTRY glcltTexCoord1i ( IN GLint s ) { PA_TEXTURE1((GLfloat) s); } void APIENTRY glcltTexCoord1iv ( IN const GLint v[1] ) { PA_TEXTURE1((GLfloat) v[0]); } void APIENTRY glcltTexCoord1s ( IN GLshort s ) { PA_TEXTURE1((GLfloat) s); } void APIENTRY glcltTexCoord1sv ( IN const GLshort v[1] ) { PA_TEXTURE1((GLfloat) v[0]); } void APIENTRY glcltTexCoord2d ( IN GLdouble s, IN GLdouble t ) { PA_TEXTURE2((GLfloat) s, (GLfloat) t); } void APIENTRY glcltTexCoord2dv ( IN const GLdouble v[2] ) { PA_TEXTURE2((GLfloat) v[0], (GLfloat) v[1]); } #ifndef _X86_ void APIENTRY glcltTexCoord2f ( IN GLfloat s, IN GLfloat t ) { PA_TEXTURE2((GLfloat) s, (GLfloat) t); } void APIENTRY glcltTexCoord2fv ( IN const GLfloat v[2] ) { PA_TEXTURE2((GLfloat) v[0], (GLfloat) v[1]); } #endif void APIENTRY glcltTexCoord2i ( IN GLint s, IN GLint t ) { PA_TEXTURE2((GLfloat) s, (GLfloat) t); } void APIENTRY glcltTexCoord2iv ( IN const GLint v[2] ) { PA_TEXTURE2((GLfloat) v[0], (GLfloat) v[1]); } void APIENTRY glcltTexCoord2s ( IN GLshort s, IN GLshort t ) { PA_TEXTURE2((GLfloat) s, (GLfloat) t); } void APIENTRY glcltTexCoord2sv ( IN const GLshort v[2] ) { PA_TEXTURE2((GLfloat) v[0], (GLfloat) v[1]); } void APIENTRY glcltTexCoord3d ( IN GLdouble s, IN GLdouble t, IN GLdouble r ) { PA_TEXTURE3((GLfloat) s, (GLfloat) t, (GLfloat) r); } void APIENTRY glcltTexCoord3dv ( IN const GLdouble v[3] ) { PA_TEXTURE3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } #ifndef _X86_ void APIENTRY glcltTexCoord3f ( IN GLfloat s, IN GLfloat t, IN GLfloat r ) { PA_TEXTURE3((GLfloat) s, (GLfloat) t, (GLfloat) r); } void APIENTRY glcltTexCoord3fv ( IN const GLfloat v[3] ) { PA_TEXTURE3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } #endif void APIENTRY glcltTexCoord3i ( IN GLint s, IN GLint t, IN GLint r ) { PA_TEXTURE3((GLfloat) s, (GLfloat) t, (GLfloat) r); } void APIENTRY glcltTexCoord3iv ( IN const GLint v[3] ) { PA_TEXTURE3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } void APIENTRY glcltTexCoord3s ( IN GLshort s, IN GLshort t, IN GLshort r ) { PA_TEXTURE3((GLfloat) s, (GLfloat) t, (GLfloat) r); } void APIENTRY glcltTexCoord3sv ( IN const GLshort v[3] ) { PA_TEXTURE3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } void APIENTRY glcltTexCoord4d ( IN GLdouble s, IN GLdouble t, IN GLdouble r, IN GLdouble q ) { PA_TEXTURE4((GLfloat) s, (GLfloat) t, (GLfloat) r, (GLfloat) q); } void APIENTRY glcltTexCoord4dv ( IN const GLdouble v[4] ) { PA_TEXTURE4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltTexCoord4f ( IN GLfloat s, IN GLfloat t, IN GLfloat r, IN GLfloat q ) { PA_TEXTURE4((GLfloat) s, (GLfloat) t, (GLfloat) r, (GLfloat) q); } void APIENTRY glcltTexCoord4fv ( IN const GLfloat v[4] ) { PA_TEXTURE4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltTexCoord4i ( IN GLint s, IN GLint t, IN GLint r, IN GLint q ) { PA_TEXTURE4((GLfloat) s, (GLfloat) t, (GLfloat) r, (GLfloat) q); } void APIENTRY glcltTexCoord4iv ( IN const GLint v[4] ) { PA_TEXTURE4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltTexCoord4s ( IN GLshort s, IN GLshort t, IN GLshort r, IN GLshort q ) { PA_TEXTURE4((GLfloat) s, (GLfloat) t, (GLfloat) r, (GLfloat) q); } void APIENTRY glcltTexCoord4sv ( IN const GLshort v[4] ) { PA_TEXTURE4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltVertex2d ( IN GLdouble x, IN GLdouble y ) { PA_VERTEX2((GLfloat) x, (GLfloat) y); } void APIENTRY glcltVertex2dv ( IN const GLdouble v[2] ) { PA_VERTEX2((GLfloat) v[0], (GLfloat) v[1]); } #ifndef _X86_ void APIENTRY glcltVertex2f ( IN GLfloat x, IN GLfloat y ) { PA_VERTEX2((GLfloat) x, (GLfloat) y); } void APIENTRY glcltVertex2fv ( IN const GLfloat v[2] ) { PA_VERTEX2((GLfloat) v[0], (GLfloat) v[1]); } #endif void APIENTRY glcltVertex2i ( IN GLint x, IN GLint y ) { PA_VERTEX2((GLfloat) x, (GLfloat) y); } void APIENTRY glcltVertex2iv ( IN const GLint v[2] ) { PA_VERTEX2((GLfloat) v[0], (GLfloat) v[1]); } void APIENTRY glcltVertex2s ( IN GLshort x, IN GLshort y ) { PA_VERTEX2((GLfloat) x, (GLfloat) y); } void APIENTRY glcltVertex2sv ( IN const GLshort v[2] ) { PA_VERTEX2((GLfloat) v[0], (GLfloat) v[1]); } void APIENTRY glcltVertex3d ( IN GLdouble x, IN GLdouble y, IN GLdouble z ) { PA_VERTEX3((GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltVertex3dv ( IN const GLdouble v[3] ) { PA_VERTEX3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } #ifndef _X86_ void APIENTRY glcltVertex3f ( IN GLfloat x, IN GLfloat y, IN GLfloat z ) { PA_VERTEX3((GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltVertex3fv ( IN const GLfloat v[3] ) { PA_VERTEX3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } #endif void APIENTRY glcltVertex3i ( IN GLint x, IN GLint y, IN GLint z ) { PA_VERTEX3((GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltVertex3iv ( IN const GLint v[3] ) { PA_VERTEX3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } void APIENTRY glcltVertex3s ( IN GLshort x, IN GLshort y, IN GLshort z ) { PA_VERTEX3((GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltVertex3sv ( IN const GLshort v[3] ) { PA_VERTEX3((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); } void APIENTRY glcltVertex4d ( IN GLdouble x, IN GLdouble y, IN GLdouble z, IN GLdouble w ) { PA_VERTEX4((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltVertex4dv ( IN const GLdouble v[4] ) { PA_VERTEX4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltVertex4f ( IN GLfloat x, IN GLfloat y, IN GLfloat z, IN GLfloat w ) { PA_VERTEX4((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltVertex4fv ( IN const GLfloat v[4] ) { PA_VERTEX4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltVertex4i ( IN GLint x, IN GLint y, IN GLint z, IN GLint w ) { PA_VERTEX4((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltVertex4iv ( IN const GLint v[4] ) { PA_VERTEX4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltVertex4s ( IN GLshort x, IN GLshort y, IN GLshort z, IN GLshort w ) { PA_VERTEX4((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); } void APIENTRY glcltVertex4sv ( IN const GLshort v[4] ) { PA_VERTEX4((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); } void APIENTRY glcltClipPlane ( IN GLenum plane, IN const GLdouble equation[4] ) { GLCLIENT_BEGIN( ClipPlane, CLIPPLANE ) pMsg->plane = plane ; pMsg->equation[ 0] = equation[ 0]; pMsg->equation[ 1] = equation[ 1]; pMsg->equation[ 2] = equation[ 2]; pMsg->equation[ 3] = equation[ 3]; return; GLCLIENT_END } void APIENTRY glcltColorMaterial ( IN GLenum face, IN GLenum mode ) { GLCLIENT_BEGIN( ColorMaterial, COLORMATERIAL ) pMsg->face = face ; pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltCullFace ( IN GLenum mode ) { GLCLIENT_BEGIN( CullFace, CULLFACE ) pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltFrontFace ( IN GLenum mode ) { GLCLIENT_BEGIN( FrontFace, FRONTFACE ) pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltHint ( IN GLenum target, IN GLenum mode ) { GLCLIENT_BEGIN( Hint, HINT ) pMsg->target = target ; pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltLineStipple ( IN GLint factor, IN GLushort pattern ) { GLCLIENT_BEGIN( LineStipple, LINESTIPPLE ) pMsg->factor = factor ; pMsg->pattern = pattern ; return; GLCLIENT_END } void APIENTRY glcltLineWidth ( IN GLfloat width ) { GLCLIENT_BEGIN( LineWidth, LINEWIDTH ) pMsg->width = width ; return; GLCLIENT_END } void APIENTRY glcltPointSize ( IN GLfloat size ) { GLCLIENT_BEGIN( PointSize, POINTSIZE ) pMsg->size = size ; return; GLCLIENT_END } void APIENTRY glcltPolygonMode ( IN GLenum face, IN GLenum mode ) { GLCLIENT_BEGIN( PolygonMode, POLYGONMODE ) pMsg->face = face ; pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltScissor ( IN GLint x, IN GLint y, IN GLsizei width, IN GLsizei height ) { GLCLIENT_BEGIN( Scissor, SCISSOR ) pMsg->x = x ; pMsg->y = y ; pMsg->width = width ; pMsg->height = height ; return; GLCLIENT_END } void APIENTRY glcltShadeModel ( IN GLenum mode ) { GLCLIENT_BEGIN( ShadeModel, SHADEMODEL ) pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltInitNames ( void ) { GLCLIENT_BEGIN( InitNames, INITNAMES ) return; GLCLIENT_END } void APIENTRY glcltLoadName ( IN GLuint name ) { GLCLIENT_BEGIN( LoadName, LOADNAME ) pMsg->name = name ; return; GLCLIENT_END } void APIENTRY glcltPassThrough ( IN GLfloat token ) { GLCLIENT_BEGIN( PassThrough, PASSTHROUGH ) pMsg->token = token ; return; GLCLIENT_END } void APIENTRY glcltPopName ( void ) { GLCLIENT_BEGIN( PopName, POPNAME ) return; GLCLIENT_END } void APIENTRY glcltPushName ( IN GLuint name ) { GLCLIENT_BEGIN( PushName, PUSHNAME ) pMsg->name = name ; return; GLCLIENT_END } void APIENTRY glcltDrawBuffer ( IN GLenum mode ) { // We're doing something special here. By doing a glsbAttention after // putting a glDrawBuffer in the batch, we are guaranteeing that all // drawing done in the batch is in the same drawing mode and that the // drawing mode cannot change until the end of the batch. This allows // the server to sample the current drawing mode at the beginning of // batch and to assume that it is constant for the entire batch. // // The server might be able to take advantage of the fact, for example, // that all drawing in a batch is only to the back buffer. GLCLIENT_BEGIN( DrawBuffer, DRAWBUFFER ) pMsg->mode = mode ; glsbAttention(); return; GLCLIENT_END } void APIENTRY glcltClear ( IN GLbitfield mask ) { GLCLIENT_BEGIN( Clear, CLEAR ) pMsg->mask = mask ; return; GLCLIENT_END } void APIENTRY glcltClearAccum ( IN GLfloat red, IN GLfloat green, IN GLfloat blue, IN GLfloat alpha ) { GLCLIENT_BEGIN( ClearAccum, CLEARACCUM ) pMsg->red = red ; pMsg->green = green ; pMsg->blue = blue ; pMsg->alpha = alpha ; return; GLCLIENT_END } void APIENTRY glcltClearIndex ( IN GLfloat c ) { GLCLIENT_BEGIN( ClearIndex, CLEARINDEX ) pMsg->c = c ; return; GLCLIENT_END } void APIENTRY glcltClearColor ( IN GLclampf red, IN GLclampf green, IN GLclampf blue, IN GLclampf alpha ) { GLCLIENT_BEGIN( ClearColor, CLEARCOLOR ) pMsg->red = red ; pMsg->green = green ; pMsg->blue = blue ; pMsg->alpha = alpha ; return; GLCLIENT_END } void APIENTRY glcltClearStencil ( IN GLint s ) { GLCLIENT_BEGIN( ClearStencil, CLEARSTENCIL ) pMsg->s = s ; return; GLCLIENT_END } void APIENTRY glcltClearDepth ( IN GLclampd depth ) { GLCLIENT_BEGIN( ClearDepth, CLEARDEPTH ) pMsg->depth = depth ; return; GLCLIENT_END } void APIENTRY glcltStencilMask ( IN GLuint mask ) { GLCLIENT_BEGIN( StencilMask, STENCILMASK ) pMsg->mask = mask ; return; GLCLIENT_END } void APIENTRY glcltColorMask ( IN GLboolean red, IN GLboolean green, IN GLboolean blue, IN GLboolean alpha ) { GLCLIENT_BEGIN( ColorMask, COLORMASK ) pMsg->red = red ; pMsg->green = green ; pMsg->blue = blue ; pMsg->alpha = alpha ; return; GLCLIENT_END } void APIENTRY glcltDepthMask ( IN GLboolean flag ) { GLCLIENT_BEGIN( DepthMask, DEPTHMASK ) pMsg->flag = flag ; return; GLCLIENT_END } void APIENTRY glcltIndexMask ( IN GLuint mask ) { GLCLIENT_BEGIN( IndexMask, INDEXMASK ) pMsg->mask = mask ; return; GLCLIENT_END } void APIENTRY glcltAccum ( IN GLenum op, IN GLfloat value ) { GLCLIENT_BEGIN( Accum, ACCUM ) pMsg->op = op ; pMsg->value = value ; return; GLCLIENT_END } void APIENTRY glcltDisable ( IN GLenum cap ) { GLCLIENT_BEGIN( Disable, DISABLE ) pMsg->cap = cap ; return; GLCLIENT_END } void APIENTRY glcltEnable ( IN GLenum cap ) { GLCLIENT_BEGIN( Enable, ENABLE ) pMsg->cap = cap ; return; GLCLIENT_END } void APIENTRY glcltFinish ( void ) { // This function is invalid between glBegin and glEnd. // This is detected in glsbAttention. glsbAttention(); } void APIENTRY glcltFlush ( void ) { // This function is invalid between glBegin and glEnd. // This is detected in glsbAttention. glsbAttention(); } void APIENTRY glcltPopAttrib ( void ) { GLCLIENT_BEGIN( PopAttrib, POPATTRIB ) return; GLCLIENT_END } void APIENTRY glcltPushAttrib ( IN GLbitfield mask ) { GLCLIENT_BEGIN( PushAttrib, PUSHATTRIB ) pMsg->mask = mask ; return; GLCLIENT_END } void APIENTRY glcltMapGrid1d ( IN GLint un, IN GLdouble u1, IN GLdouble u2 ) { glcltMapGrid1f(un, (GLfloat) u1, (GLfloat) u2); } void APIENTRY glcltMapGrid1f ( IN GLint un, IN GLfloat u1, IN GLfloat u2 ) { GLCLIENT_BEGIN( MapGrid1f, MAPGRID1F ) pMsg->un = un ; pMsg->u1 = u1 ; pMsg->u2 = u2 ; return; GLCLIENT_END } void APIENTRY glcltMapGrid2d ( IN GLint un, IN GLdouble u1, IN GLdouble u2, IN GLint vn, IN GLdouble v1, IN GLdouble v2 ) { glcltMapGrid2f(un, (GLfloat) u1, (GLfloat) u2, vn, (GLfloat) v1, (GLfloat) v2); } void APIENTRY glcltMapGrid2f ( IN GLint un, IN GLfloat u1, IN GLfloat u2, IN GLint vn, IN GLfloat v1, IN GLfloat v2 ) { GLCLIENT_BEGIN( MapGrid2f, MAPGRID2F ) pMsg->un = un ; pMsg->u1 = u1 ; pMsg->u2 = u2 ; pMsg->vn = vn ; pMsg->v1 = v1 ; pMsg->v2 = v2 ; return; GLCLIENT_END } void APIENTRY glcltEvalCoord1f ( IN GLfloat u ) { POLYARRAY *pa; POLYDATA *pd; // This call has no effect outside begin/end (unless it is being compiled). // We cannot evaluate the map on the client side since we do not have access // to the latest gc states (e.g. map definitions, enables) without flushing // the batch. Instead, we will insert a record into poly array for evaluation // on the server side. // This code is similar to glcltVertex. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { pa->flags |= POLYARRAY_EVALCOORD1; pd = pa->pdNextVertex++; pd->flags |= POLYDATA_EVALCOORD1; pd->obj.x = u; pd[1].flags = 0; if (pd >= pa->pdFlush) PolyArrayFlushPartialPrimitive(); } } void APIENTRY glcltEvalCoord1d ( IN GLdouble u ) { glcltEvalCoord1f((GLfloat) u); } void APIENTRY glcltEvalCoord1dv ( IN const GLdouble u[1] ) { glcltEvalCoord1f((GLfloat) u[0]); } void APIENTRY glcltEvalCoord1fv ( IN const GLfloat u[1] ) { glcltEvalCoord1f((GLfloat) u[0]); } void APIENTRY glcltEvalCoord2f ( IN GLfloat u, IN GLfloat v ) { POLYARRAY *pa; POLYDATA *pd; // This call has no effect outside begin/end (unless it is being compiled). // We cannot evaluate the map on the client side since we do not have access // to the latest gc states (e.g. map definitions, enables) without flushing // the batch. Instead, we will insert a record into poly array for evaluation // on the server side. // This code is similar to glcltVertex. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { pa->flags |= POLYARRAY_EVALCOORD2; pd = pa->pdNextVertex++; pd->flags |= POLYDATA_EVALCOORD2; pd->obj.x = u; pd->obj.y = v; pd[1].flags = 0; if (pd >= pa->pdFlush) PolyArrayFlushPartialPrimitive(); } } void APIENTRY glcltEvalCoord2d ( IN GLdouble u, IN GLdouble v ) { glcltEvalCoord2f((GLfloat) u, (GLfloat) v); } void APIENTRY glcltEvalCoord2dv ( IN const GLdouble u[2] ) { glcltEvalCoord2f((GLfloat) u[0], (GLfloat) u[1]); } void APIENTRY glcltEvalCoord2fv ( IN const GLfloat u[2] ) { glcltEvalCoord2f((GLfloat) u[0], (GLfloat) u[1]); } void APIENTRY glcltEvalPoint1 ( IN GLint i ) { POLYARRAY *pa; POLYDATA *pd; GLint *pi; // This call has no effect outside begin/end (unless it is being compiled). // We cannot evaluate the map on the client side since we do not have access // to the latest gc states (e.g. map definitions, enables) without flushing // the batch. Instead, we will insert a record into poly array for evaluation // on the server side. // This code is similar to glcltVertex. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { pa->flags |= POLYARRAY_EVALPOINT1; pd = pa->pdNextVertex++; pd->flags |= POLYDATA_EVALPOINT1; pi = (GLint *) &pd->obj; pi[0] = i; pd[1].flags = 0; if (pd >= pa->pdFlush) PolyArrayFlushPartialPrimitive(); } } void APIENTRY glcltEvalPoint2 ( IN GLint i, IN GLint j ) { POLYARRAY *pa; POLYDATA *pd; GLint *pi; // This call has no effect outside begin/end (unless it is being compiled). // We cannot evaluate the map on the client side since we do not have access // to the latest gc states (e.g. map definitions, enables) without flushing // the batch. Instead, we will insert a record into poly array for evaluation // on the server side. // This code is similar to glcltVertex. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { pa->flags |= POLYARRAY_EVALPOINT2; pd = pa->pdNextVertex++; pd->flags |= POLYDATA_EVALPOINT2; pi = (GLint *) &pd->obj; pi[0] = i; pi[1] = j; pd[1].flags = 0; if (pd >= pa->pdFlush) PolyArrayFlushPartialPrimitive(); } } void APIENTRY glcltEvalMesh1 ( IN GLenum mode, IN GLint u1, IN GLint u2 ) { POLYARRAY *pa; GLenum primType; GLint i; // Not allowed in begin/end. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } switch(mode) { case GL_LINE: primType = GL_LINE_STRIP; break; case GL_POINT: primType = GL_POINTS; break; default: GLSETERROR(GL_INVALID_ENUM); return; } // Call Begin/End to do polyarray correctly. Note that by calling these // functions, we allow poly array to be batched correctly. glcltBegin(primType); pa->flags |= POLYARRAY_SAME_POLYDATA_TYPE; for (i = u1; i <= u2; i++) glcltEvalPoint1(i); glcltEnd(); } #define MV_VERTEX3 0x0001 #define MV_VERTEX4 0x0002 #define MV_NORMAL 0x0004 #define MV_COLOR 0x0008 #define MV_INDEX 0x0010 // Assumption: U is moving, left to right. V is moving top to bottom #define MV_TOP 0x0001 #define MV_LEFT 0x0002 typedef struct { __GLcoord vertex; __GLcoord normal; __GLcoord texture; __GLcolor color; } MESHVERTEX; #define MAX_MESH_VERTICES MAX_U_SIZE*MAX_V_SIZE #define MAX_U_SIZE 16 #define MAX_V_SIZE 16 GLubyte *dBufFill; //fill only GLuint totFillPts; GLubyte *dBufTopLeft; //for mv_left GLuint totTopLeftPts; GLubyte *dBufTopRight; //for non mv_left GLuint totTopRightPts; int FASTCALL genMeshElts (GLenum mode, GLuint sides, GLint nu, GLint nv, GLubyte *buff) { GLint start; GLint i, j, k; // Compute the DrawElements Indices switch(mode) { case GL_LINE : // Draw lines along U direction start = 1; k = 0; if (sides & MV_TOP) start = 0 ; for (i=start; ivertex = polyData.obj; mv->normal = polyData.normal; mv->texture = polyData.texture; mv->color = polyData.colors[0]; mv++; } } if ((nv != MAX_V_SIZE) || (nu != MAX_U_SIZE)) { disBuf = dBufSmall; totalPts = genMeshElts (mode, sides, nu, nv, disBuf); } else { if (mode == GL_FILL) { disBuf = dBufFill; totalPts = totFillPts; } else switch (sides) { case (MV_TOP | MV_LEFT): disBuf = dBufTopLeft; totalPts = totTopLeftPts; break; case (MV_TOP): disBuf = dBufTopRight; totalPts = totTopRightPts; break; case (MV_LEFT): disBuf = &dBufTopLeft [(MAX_U_SIZE - 1) * 2]; totalPts = totTopLeftPts - (MAX_U_SIZE - 1) * 2; break; default : //NONE disBuf = &dBufTopRight [(MAX_V_SIZE - 1) * 2]; totalPts = totTopRightPts - (MAX_V_SIZE - 1) * 2; break; } } // Compute mesh valid flags. mflags = 0; if (polyData.flags & POLYDATA_VERTEX3) mflags |= MV_VERTEX3; else { ASSERTOPENGL(polyData.flags & POLYDATA_VERTEX4, "bad vertex flag!\n"); mflags |= MV_VERTEX4; } if (polyData.flags & POLYDATA_NORMAL_VALID) mflags |= MV_NORMAL; if (polyData.flags & POLYDATA_COLOR_VALID) { if (gc->modes.colorIndexMode) mflags |= MV_INDEX; else mflags |= MV_COLOR; } if (polyArray.flags & POLYARRAY_TEXTURE1) texSize = 1; else if (polyArray.flags & POLYARRAY_TEXTURE2) texSize = 2; else if (polyArray.flags & POLYARRAY_TEXTURE3) texSize = 3; else if (polyArray.flags & POLYARRAY_TEXTURE4) texSize = 4; // Save current values. if (mflags & MV_NORMAL) currentNormal = gc->state.current.normal; if (mflags & MV_INDEX) currentColor.r = gc->state.current.userColorIndex; else if (mflags & MV_COLOR) currentColor = gc->state.current.userColor; if (texSize) currentTexture = gc->state.current.texture; // Always force edge flag on in GL_FILL mode. The spec uses QUAD_STRIP // which implies that edge flag is on for the evaluated mesh. currentEdgeFlag = gc->state.current.edgeTag; gc->state.current.edgeTag = GL_TRUE; currentVertexInfo = gc->vertexArray; //Enable the appropriate arrays // Disable the arrays followed by enabling each individual array. gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY; gc->vertexArray.mask &= ~(VAMASK_VERTEX_ENABLE_MASK | VAMASK_NORMAL_ENABLE_MASK | VAMASK_COLOR_ENABLE_MASK | VAMASK_INDEX_ENABLE_MASK | VAMASK_TEXCOORD_ENABLE_MASK | VAMASK_EDGEFLAG_ENABLE_MASK); stride = sizeof(MESHVERTEX); if (mflags & MV_NORMAL) { gc->vertexArray.mask |= VAMASK_NORMAL_ENABLE_MASK; glcltNormalPointer(GL_FLOAT, stride, &(mvBuf[0].normal.x)); } if (mflags & MV_INDEX) { gc->vertexArray.mask |= VAMASK_INDEX_ENABLE_MASK; glcltIndexPointer(GL_FLOAT, stride, &(mvBuf[0].color.r)); } else if (mflags & MV_COLOR) { gc->vertexArray.mask |= VAMASK_COLOR_ENABLE_MASK; glcltColorPointer(3, GL_FLOAT, stride, &(mvBuf[0].color.r)); } if (texSize) { glcltTexCoordPointer(texSize, GL_FLOAT, stride, &(mvBuf[0].texture.x)); gc->vertexArray.mask |= VAMASK_TEXCOORD_ENABLE_MASK; } if (mflags & MV_VERTEX3) glcltVertexPointer(3, GL_FLOAT, stride, &(mvBuf[0].vertex.x)); else glcltVertexPointer(4, GL_FLOAT, stride, &(mvBuf[0].vertex.x)); gc->vertexArray.mask |= VAMASK_VERTEX_ENABLE_MASK; if (mode == GL_FILL) glcltDrawElements(GL_QUADS, totalPts, GL_UNSIGNED_BYTE, disBuf); else glcltDrawElements(GL_LINES, totalPts, GL_UNSIGNED_BYTE, disBuf); // Execute the command now. Otherwise, the current states will be messed up. glsbAttention(); // Restore current values. if (mflags & MV_NORMAL) __glim_Normal3fv(¤tNormal.x); if (mflags & MV_INDEX) __glim_Indexf(currentColor.r); else if (mflags & MV_COLOR) __glim_Color4fv(¤tColor.r); if (texSize) __glim_TexCoord4fv(¤tTexture.x); gc->state.current.edgeTag = currentEdgeFlag; gc->vertexArray = currentVertexInfo ; } void APIENTRY glcltEvalMesh2 ( IN GLenum mode, IN GLint u1, IN GLint u2, IN GLint v1, IN GLint v2 ) { POLYARRAY *pa; GLint i, j, meshSize; __GL_SETUP(); GLboolean done_v, done_u; GLint v_beg, v_end, u_beg, u_end, u_len; GLuint sides; // Flush the command buffer before we start. We need to access the // latest evaluator states in this function. glsbAttention(); // Not allowed in begin/end. pa = gc->paTeb; if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } // If vertex map is not enabled, this is a noop. if (!(gc->state.enables.eval2 & (__GL_MAP2_VERTEX_4_ENABLE | __GL_MAP2_VERTEX_3_ENABLE))) return; // Make sure that the mesh is not empty. if (u1 > u2 || v1 > v2) return; // Call Begin/End to do polyarray correctly. Note that by calling these // functions, we allow poly array to be batched correctly. // In fill or line modes, we use vertex array for best performance. if (mode == GL_FILL && dBufFill == NULL) { if (!(dBufFill = (GLubyte *) LocalAlloc (LMEM_FIXED, 4 * MAX_U_SIZE * MAX_V_SIZE * sizeof (GLubyte)))) { GLSETERROR(GL_OUT_OF_MEMORY); return; } totFillPts = genMeshElts (GL_FILL, MV_TOP | MV_LEFT, MAX_U_SIZE, MAX_V_SIZE, dBufFill); } if (mode == GL_LINE && dBufTopLeft == NULL) { if (!(dBufTopLeft = (GLubyte *) LocalAlloc (LMEM_FIXED, 2 * 4 * MAX_U_SIZE * MAX_V_SIZE * sizeof (GLubyte)))) { GLSETERROR(GL_OUT_OF_MEMORY); return; } dBufTopRight = &dBufTopLeft[4 * MAX_U_SIZE * MAX_V_SIZE]; totTopLeftPts = genMeshElts (GL_LINE, MV_TOP | MV_LEFT, MAX_U_SIZE, MAX_V_SIZE, dBufTopLeft); totTopRightPts = genMeshElts (GL_LINE, MV_TOP, MAX_U_SIZE, MAX_V_SIZE, dBufTopRight); } switch(mode) { case GL_POINT: glcltBegin(GL_POINTS); pa->flags |= POLYARRAY_SAME_POLYDATA_TYPE; for (i = v1; i <= v2; i++) for (j = u1; j <= u2; j++) glcltEvalPoint2(j, i); glcltEnd(); break ; case GL_LINE: case GL_FILL: // the sides argument in the fastcall is ignored meshSize = (u2 - u1 + 1)*(v2 - v1 + 1); if (meshSize <= MAX_MESH_VERTICES) PA_EvalMesh2Fast(gc, u1, u2, v1, v2, meshSize, mode, (GLubyte) 15); else { u_beg = u1; u_end = u_beg + MAX_U_SIZE - 1; done_u = GL_FALSE; while (!done_u) { //Along U side if(u_end >= u2) { u_end = u2; done_u = GL_TRUE; } u_len = u_end - u_beg + 1; v_beg = v1; v_end = v_beg + MAX_V_SIZE - 1; done_v = GL_FALSE; while(!done_v) { //Along V side if(v_end >= v2) { v_end = v2; done_v = GL_TRUE; } meshSize = u_len*(v_end - v_beg + 1); sides = 0; if (u_beg == u1) sides |= MV_LEFT; if (v_beg == v1) sides |= MV_TOP; PA_EvalMesh2Fast(gc, u_beg, u_end, v_beg, v_end, meshSize, mode, sides); v_beg = v_end; v_end = v_beg+MAX_V_SIZE-1; } u_beg = u_end; u_end = u_beg + MAX_U_SIZE - 1; } } break ; default: GLSETERROR(GL_INVALID_ENUM); return; } } void APIENTRY glcltAlphaFunc ( IN GLenum func, IN GLclampf ref ) { GLCLIENT_BEGIN( AlphaFunc, ALPHAFUNC ) pMsg->func = func ; pMsg->ref = ref ; return; GLCLIENT_END } void APIENTRY glcltBlendFunc ( IN GLenum sfactor, IN GLenum dfactor ) { GLCLIENT_BEGIN( BlendFunc, BLENDFUNC ) pMsg->sfactor = sfactor ; pMsg->dfactor = dfactor ; return; GLCLIENT_END } void APIENTRY glcltLogicOp ( IN GLenum opcode ) { GLCLIENT_BEGIN( LogicOp, LOGICOP ) pMsg->opcode = opcode ; return; GLCLIENT_END } void APIENTRY glcltStencilFunc ( IN GLenum func, IN GLint ref, IN GLuint mask ) { GLCLIENT_BEGIN( StencilFunc, STENCILFUNC ) pMsg->func = func ; pMsg->ref = ref ; pMsg->mask = mask ; return; GLCLIENT_END } void APIENTRY glcltStencilOp ( IN GLenum fail, IN GLenum zfail, IN GLenum zpass ) { GLCLIENT_BEGIN( StencilOp, STENCILOP ) pMsg->fail = fail ; pMsg->zfail = zfail ; pMsg->zpass = zpass ; return; GLCLIENT_END } void APIENTRY glcltDepthFunc ( IN GLenum func ) { GLCLIENT_BEGIN( DepthFunc, DEPTHFUNC ) pMsg->func = func ; return; GLCLIENT_END } void APIENTRY glcltPixelZoom ( IN GLfloat xfactor, IN GLfloat yfactor ) { GLCLIENT_BEGIN( PixelZoom, PIXELZOOM ) pMsg->xfactor = xfactor ; pMsg->yfactor = yfactor ; return; GLCLIENT_END } void APIENTRY glcltPixelTransferf ( IN GLenum pname, IN GLfloat param ) { GLCLIENT_BEGIN( PixelTransferf, PIXELTRANSFERF ) pMsg->pname = pname ; pMsg->param = param ; return; GLCLIENT_END } void APIENTRY glcltPixelTransferi ( IN GLenum pname, IN GLint param ) { GLCLIENT_BEGIN( PixelTransferi, PIXELTRANSFERI ) pMsg->pname = pname ; pMsg->param = param ; return; GLCLIENT_END } void APIENTRY glcltPixelStoref ( IN GLenum pname, IN GLfloat param ) { GLCLIENT_BEGIN( PixelStoref, PIXELSTOREF ) pMsg->pname = pname ; pMsg->param = param ; return; GLCLIENT_END } void APIENTRY glcltPixelStorei ( IN GLenum pname, IN GLint param ) { GLCLIENT_BEGIN( PixelStorei, PIXELSTOREI ) pMsg->pname = pname ; pMsg->param = param ; return; GLCLIENT_END } void APIENTRY glcltPixelMapfv ( IN GLenum map, IN GLint mapsize, IN const GLfloat values[] ) { GLCLIENT_BEGIN_LARGE_SET( PixelMapfv, PIXELMAPFV, values, ulSize, valuesOff ) pMsg->map = map ; pMsg->mapsize = mapsize ; GLCLIENT_END_LARGE_SET return; } void APIENTRY glcltPixelMapuiv ( IN GLenum map, IN GLint mapsize, IN const GLuint values[] ) { GLCLIENT_BEGIN_LARGE_SET( PixelMapuiv, PIXELMAPUIV, values, ulSize, valuesOff ) pMsg->map = map ; pMsg->mapsize = mapsize ; GLCLIENT_END_LARGE_SET return; } void APIENTRY glcltPixelMapusv ( IN GLenum map, IN GLint mapsize, IN const GLushort values[] ) { GLCLIENT_BEGIN_LARGE_SET( PixelMapusv, PIXELMAPUSV, values, ulSize, valuesOff ) pMsg->map = map ; pMsg->mapsize = mapsize ; GLCLIENT_END_LARGE_SET return; } void APIENTRY glcltReadBuffer ( IN GLenum mode ) { GLCLIENT_BEGIN( ReadBuffer, READBUFFER ) pMsg->mode = mode ; glsbAttention(); return; GLCLIENT_END } void APIENTRY glcltCopyPixels ( IN GLint x, IN GLint y, IN GLsizei width, IN GLsizei height, IN GLenum type ) { GLCLIENT_BEGIN( CopyPixels, COPYPIXELS ) pMsg->x = x ; pMsg->y = y ; pMsg->width = width ; pMsg->height = height ; pMsg->type = type ; return; GLCLIENT_END } void APIENTRY glcltGetClipPlane ( IN GLenum plane, OUT GLdouble equation[4] ) { GLCLIENT_BEGIN( GetClipPlane, GETCLIPPLANE ) pMsg->plane = plane ; pMsg->equation = equation; glsbAttention(); return; GLCLIENT_END } GLenum APIENTRY glcltGetError ( void ) { GLCLIENT_BEGIN( GetError, GETERROR ) GLTEB_RETURNVALUE() = GL_INVALID_OPERATION; // assume error glsbAttention(); return((GLenum)GLTEB_RETURNVALUE()); GLCLIENT_END } void APIENTRY glcltGetMapdv ( IN GLenum target, IN GLenum query, OUT GLdouble v[] ) { GLCLIENT_BEGIN_LARGE_GET( GetMapdv, GETMAPDV, v, ulSize, vOff ) pMsg->target = target ; pMsg->query = query ; GLCLIENT_END_LARGE_GET return; } void APIENTRY glcltGetMapfv ( IN GLenum target, IN GLenum query, OUT GLfloat v[] ) { GLCLIENT_BEGIN_LARGE_GET( GetMapfv, GETMAPFV, v, ulSize, vOff ) pMsg->target = target ; pMsg->query = query ; GLCLIENT_END_LARGE_GET return; } void APIENTRY glcltGetMapiv ( IN GLenum target, IN GLenum query, OUT GLint v[] ) { GLCLIENT_BEGIN_LARGE_GET( GetMapiv, GETMAPIV, v, ulSize, vOff ) pMsg->target = target ; pMsg->query = query ; GLCLIENT_END_LARGE_GET return; } void APIENTRY glcltGetPixelMapfv ( IN GLenum map, OUT GLfloat values[] ) { GLCLIENT_BEGIN_LARGE_GET( GetPixelMapfv, GETPIXELMAPFV, values, ulSize, valuesOff ) pMsg->map = map ; GLCLIENT_END_LARGE_GET return; } void APIENTRY glcltGetPixelMapuiv ( IN GLenum map, OUT GLuint values[] ) { GLCLIENT_BEGIN_LARGE_GET( GetPixelMapuiv, GETPIXELMAPUIV, values, ulSize, valuesOff ) pMsg->map = map ; GLCLIENT_END_LARGE_GET return; } void APIENTRY glcltGetPixelMapusv ( IN GLenum map, OUT GLushort values[] ) { GLCLIENT_BEGIN_LARGE_GET( GetPixelMapusv, GETPIXELMAPUSV, values, ulSize, valuesOff ) pMsg->map = map ; GLCLIENT_END_LARGE_GET return; } GLboolean APIENTRY glcltIsEnabled ( IN GLenum cap ) { GLCLIENT_BEGIN( IsEnabled, ISENABLED ) pMsg->cap = cap ; GLTEB_RETURNVALUE() = 0; // assume error glsbAttention(); return((GLboolean)GLTEB_RETURNVALUE()); GLCLIENT_END } void APIENTRY glcltDepthRange ( IN GLclampd zNear, IN GLclampd zFar ) { GLCLIENT_BEGIN( DepthRange, DEPTHRANGE ) pMsg->zNear = zNear ; pMsg->zFar = zFar ; return; GLCLIENT_END } void APIENTRY glcltFrustum ( IN GLdouble left, IN GLdouble right, IN GLdouble bottom, IN GLdouble top, IN GLdouble zNear, IN GLdouble zFar ) { GLCLIENT_BEGIN( Frustum, FRUSTUM ) pMsg->left = left ; pMsg->right = right ; pMsg->bottom = bottom ; pMsg->top = top ; pMsg->zNear = zNear ; pMsg->zFar = zFar ; return; GLCLIENT_END } void APIENTRY glcltLoadIdentity ( void ) { GLCLIENT_BEGIN( LoadIdentity, LOADIDENTITY ) return; GLCLIENT_END } void APIENTRY glcltLoadMatrixf ( IN const GLfloat m[16] ) { GLCLIENT_BEGIN( LoadMatrixf, LOADMATRIXF ) pMsg->m[ 0] = m[ 0]; pMsg->m[ 1] = m[ 1]; pMsg->m[ 2] = m[ 2]; pMsg->m[ 3] = m[ 3]; pMsg->m[ 4] = m[ 4]; pMsg->m[ 5] = m[ 5]; pMsg->m[ 6] = m[ 6]; pMsg->m[ 7] = m[ 7]; pMsg->m[ 8] = m[ 8]; pMsg->m[ 9] = m[ 9]; pMsg->m[10] = m[10]; pMsg->m[11] = m[11]; pMsg->m[12] = m[12]; pMsg->m[13] = m[13]; pMsg->m[14] = m[14]; pMsg->m[15] = m[15]; return; GLCLIENT_END } void APIENTRY glcltLoadMatrixd ( IN const GLdouble m[16] ) { // Call LoadMatrixf instead GLCLIENT_BEGIN( LoadMatrixf, LOADMATRIXF ) pMsg->m[ 0] = (GLfloat) m[ 0]; pMsg->m[ 1] = (GLfloat) m[ 1]; pMsg->m[ 2] = (GLfloat) m[ 2]; pMsg->m[ 3] = (GLfloat) m[ 3]; pMsg->m[ 4] = (GLfloat) m[ 4]; pMsg->m[ 5] = (GLfloat) m[ 5]; pMsg->m[ 6] = (GLfloat) m[ 6]; pMsg->m[ 7] = (GLfloat) m[ 7]; pMsg->m[ 8] = (GLfloat) m[ 8]; pMsg->m[ 9] = (GLfloat) m[ 9]; pMsg->m[10] = (GLfloat) m[10]; pMsg->m[11] = (GLfloat) m[11]; pMsg->m[12] = (GLfloat) m[12]; pMsg->m[13] = (GLfloat) m[13]; pMsg->m[14] = (GLfloat) m[14]; pMsg->m[15] = (GLfloat) m[15]; return; GLCLIENT_END } void APIENTRY glcltMatrixMode ( IN GLenum mode ) { GLCLIENT_BEGIN( MatrixMode, MATRIXMODE ) pMsg->mode = mode ; return; GLCLIENT_END } void APIENTRY glcltMultMatrixf ( IN const GLfloat m[16] ) { GLCLIENT_BEGIN( MultMatrixf, MULTMATRIXF ) pMsg->m[ 0] = m[ 0]; pMsg->m[ 1] = m[ 1]; pMsg->m[ 2] = m[ 2]; pMsg->m[ 3] = m[ 3]; pMsg->m[ 4] = m[ 4]; pMsg->m[ 5] = m[ 5]; pMsg->m[ 6] = m[ 6]; pMsg->m[ 7] = m[ 7]; pMsg->m[ 8] = m[ 8]; pMsg->m[ 9] = m[ 9]; pMsg->m[10] = m[10]; pMsg->m[11] = m[11]; pMsg->m[12] = m[12]; pMsg->m[13] = m[13]; pMsg->m[14] = m[14]; pMsg->m[15] = m[15]; return; GLCLIENT_END } void APIENTRY glcltMultMatrixd ( IN const GLdouble m[16] ) { // Call MultMatrixf instead GLCLIENT_BEGIN( MultMatrixf, MULTMATRIXF ) pMsg->m[ 0] = (GLfloat) m[ 0]; pMsg->m[ 1] = (GLfloat) m[ 1]; pMsg->m[ 2] = (GLfloat) m[ 2]; pMsg->m[ 3] = (GLfloat) m[ 3]; pMsg->m[ 4] = (GLfloat) m[ 4]; pMsg->m[ 5] = (GLfloat) m[ 5]; pMsg->m[ 6] = (GLfloat) m[ 6]; pMsg->m[ 7] = (GLfloat) m[ 7]; pMsg->m[ 8] = (GLfloat) m[ 8]; pMsg->m[ 9] = (GLfloat) m[ 9]; pMsg->m[10] = (GLfloat) m[10]; pMsg->m[11] = (GLfloat) m[11]; pMsg->m[12] = (GLfloat) m[12]; pMsg->m[13] = (GLfloat) m[13]; pMsg->m[14] = (GLfloat) m[14]; pMsg->m[15] = (GLfloat) m[15]; return; GLCLIENT_END } void APIENTRY glcltOrtho ( IN GLdouble left, IN GLdouble right, IN GLdouble bottom, IN GLdouble top, IN GLdouble zNear, IN GLdouble zFar ) { GLCLIENT_BEGIN( Ortho, ORTHO ) pMsg->left = left ; pMsg->right = right ; pMsg->bottom = bottom ; pMsg->top = top ; pMsg->zNear = zNear ; pMsg->zFar = zFar ; return; GLCLIENT_END } void APIENTRY glcltPopMatrix ( void ) { GLCLIENT_BEGIN( PopMatrix, POPMATRIX ) return; GLCLIENT_END } void APIENTRY glcltPushMatrix ( void ) { GLCLIENT_BEGIN( PushMatrix, PUSHMATRIX ) return; GLCLIENT_END } void APIENTRY glcltRotated ( IN GLdouble angle, IN GLdouble x, IN GLdouble y, IN GLdouble z ) { // Call Rotatef instead glcltRotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltRotatef ( IN GLfloat angle, IN GLfloat x, IN GLfloat y, IN GLfloat z ) { GLCLIENT_BEGIN( Rotatef, ROTATEF ) pMsg->angle = angle ; pMsg->x = x ; pMsg->y = y ; pMsg->z = z ; return; GLCLIENT_END } void APIENTRY glcltScaled ( IN GLdouble x, IN GLdouble y, IN GLdouble z ) { // Call Scalef instead glcltScalef((GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltScalef ( IN GLfloat x, IN GLfloat y, IN GLfloat z ) { GLCLIENT_BEGIN( Scalef, SCALEF ) pMsg->x = x ; pMsg->y = y ; pMsg->z = z ; return; GLCLIENT_END } void APIENTRY glcltTranslated ( IN GLdouble x, IN GLdouble y, IN GLdouble z ) { // Call Translatef instead glcltTranslatef((GLfloat) x, (GLfloat) y, (GLfloat) z); } void APIENTRY glcltTranslatef ( IN GLfloat x, IN GLfloat y, IN GLfloat z ) { GLCLIENT_BEGIN( Translatef, TRANSLATEF ) pMsg->x = x ; pMsg->y = y ; pMsg->z = z ; return; GLCLIENT_END } void APIENTRY glcltViewport ( IN GLint x, IN GLint y, IN GLsizei width, IN GLsizei height ) { GLCLIENT_BEGIN( Viewport, VIEWPORT ) pMsg->x = x ; pMsg->y = y ; pMsg->width = width ; pMsg->height = height ; return; GLCLIENT_END }