1437 lines
33 KiB
C
1437 lines
33 KiB
C
|
|
/*
|
|
* Mesa 3-D graphics library
|
|
* Version: 3.3
|
|
*
|
|
* Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Author:
|
|
* Keith Whitwell <keith@precisioninsight.com>
|
|
*/
|
|
|
|
|
|
|
|
#include "glheader.h"
|
|
#include "context.h"
|
|
#include "dlist.h"
|
|
#include "enums.h"
|
|
#include "light.h"
|
|
#include "mem.h"
|
|
#include "state.h"
|
|
#include "colormac.h"
|
|
#include "macros.h"
|
|
|
|
#include "t_context.h"
|
|
#include "t_imm_api.h"
|
|
#include "t_imm_elt.h"
|
|
#include "t_imm_exec.h"
|
|
#include "t_imm_dlist.h"
|
|
|
|
|
|
/* A cassette is full or flushed on a statechange.
|
|
*/
|
|
void _tnl_flush_immediate( struct immediate *IM )
|
|
{
|
|
GLcontext *ctx = IM->backref;
|
|
|
|
if (ctx->CompileFlag)
|
|
_tnl_compile_cassette( ctx, IM );
|
|
else
|
|
_tnl_execute_cassette( ctx, IM );
|
|
}
|
|
|
|
|
|
void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
|
|
{
|
|
struct immediate *IM = TNL_CURRENT_IM(ctx);
|
|
|
|
if (IM->Flag[IM->Start])
|
|
if ((flags & FLUSH_UPDATE_CURRENT) || IM->Count > IM->Start)
|
|
_tnl_flush_immediate( IM );
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_begin( GLcontext *ctx, GLenum p )
|
|
{
|
|
struct immediate *IM = TNL_CURRENT_IM(ctx);
|
|
GLuint inflags, state;
|
|
|
|
if (MESA_VERBOSE&VERBOSE_API)
|
|
fprintf(stderr, "glBegin(IM %d) %s\n", IM->id, gl_lookup_enum_by_nr(p));
|
|
|
|
if (ctx->NewState)
|
|
gl_update_state(ctx);
|
|
|
|
/* if only a very few slots left, might as well flush now
|
|
*/
|
|
if (IM->Count > IMM_MAXDATA-8) {
|
|
_tnl_flush_immediate( IM );
|
|
IM = TNL_CURRENT_IM(ctx);
|
|
}
|
|
|
|
/* Check for and flush buffered vertices from internal operations.
|
|
*/
|
|
if (IM->SavedBeginState) {
|
|
_tnl_flush_immediate( IM );
|
|
IM = TNL_CURRENT_IM(ctx);
|
|
IM->BeginState = IM->SavedBeginState;
|
|
IM->SavedBeginState = 0;
|
|
}
|
|
|
|
state = IM->BeginState;
|
|
inflags = state & (VERT_BEGIN_0|VERT_BEGIN_1);
|
|
state |= inflags << 2; /* set error conditions */
|
|
|
|
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
|
|
{
|
|
GLuint count = IM->Count;
|
|
GLuint last = IM->LastPrimitive;
|
|
|
|
ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
|
|
|
|
state |= (VERT_BEGIN_0|VERT_BEGIN_1);
|
|
IM->Flag[count] |= VERT_BEGIN;
|
|
IM->Primitive[IM->LastPrimitive] &= ~PRIM_LAST;
|
|
IM->Primitive[count] = p | PRIM_BEGIN | PRIM_LAST;
|
|
IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive;
|
|
IM->LastPrimitive = count;
|
|
|
|
/* Not quite right. Need to use the fallback '_aa_ArrayElement'
|
|
* when not known to be inside begin/end and arrays are unlocked.
|
|
*/
|
|
if (IM->FlushElt) {
|
|
_tnl_translate_array_elts( ctx, IM, last, count );
|
|
IM->FlushElt = 0;
|
|
}
|
|
}
|
|
|
|
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
|
|
IM->BeginState = state;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
_tnl_Begin( GLenum mode )
|
|
{
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
|
|
if (mode > GL_POLYGON) {
|
|
_mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
|
|
return;
|
|
}
|
|
|
|
_tnl_begin(ctx, mode);
|
|
|
|
/* If compiling update SavePrimitive now.
|
|
*
|
|
* In compile_and_exec mode, exec_primitive will be updated when
|
|
* the cassette is finished.
|
|
*
|
|
* If not compiling, update exec_primitive now.
|
|
*/
|
|
if (ctx->CompileFlag) {
|
|
if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
|
|
ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
|
|
else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
|
|
ctx->Driver.CurrentSavePrimitive = mode;
|
|
}
|
|
else if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
|
|
ctx->Driver.CurrentExecPrimitive = mode;
|
|
}
|
|
|
|
|
|
GLboolean
|
|
_tnl_hard_begin( GLcontext *ctx, GLenum p )
|
|
{
|
|
struct immediate *IM = TNL_CURRENT_IM(ctx);
|
|
GLuint count, last;
|
|
|
|
if (ctx->NewState)
|
|
gl_update_state(ctx);
|
|
|
|
/* If not compiling, treat as a normal begin().
|
|
*/
|
|
if (!ctx->CompileFlag) {
|
|
_tnl_begin( ctx, p );
|
|
|
|
/* Set this for the duration:
|
|
*/
|
|
ctx->Driver.CurrentExecPrimitive = p;
|
|
return GL_TRUE;
|
|
}
|
|
|
|
if (IM->Count > IMM_MAXDATA-8) {
|
|
_tnl_flush_immediate( IM );
|
|
IM = TNL_CURRENT_IM(ctx);
|
|
}
|
|
|
|
switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
|
|
case VERT_BEGIN_0|VERT_BEGIN_1:
|
|
/* This is an immediate known to be inside a begin/end object.
|
|
*/
|
|
IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
|
|
return GL_FALSE;
|
|
|
|
case VERT_BEGIN_0:
|
|
case VERT_BEGIN_1:
|
|
/* This is a display-list immediate in an unknown begin/end
|
|
* state. Assert it is empty and conviert it to a 'hard' one.
|
|
*/
|
|
ASSERT (IM->SavedBeginState == 0);
|
|
|
|
/* ASSERT (ctx->Driver.CurrentSavePrimitive >= GL_POLYGON+1); */
|
|
|
|
/* Push current beginstate, to be restored later. Don't worry
|
|
* about raising errors.
|
|
*/
|
|
IM->SavedBeginState = IM->BeginState;
|
|
|
|
/* FALLTHROUGH */
|
|
case 0:
|
|
/* Unless we have fallen through, this is an immediate known to
|
|
* be outside begin/end objects.
|
|
*/
|
|
|
|
IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
|
|
|
|
|
|
count = IM->Count;
|
|
last = IM->LastPrimitive;
|
|
|
|
ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
|
|
|
|
IM->Flag[count] |= VERT_BEGIN;
|
|
IM->Primitive[last] &= ~PRIM_LAST;
|
|
IM->Primitive[count] = p | PRIM_BEGIN | PRIM_LAST;
|
|
IM->PrimitiveLength[last] = count - last;
|
|
IM->LastPrimitive = count;
|
|
|
|
ASSERT (!IM->FlushElt);
|
|
|
|
/* This is necessary as this immediate will not be flushed in
|
|
* _tnl_end() -- we leave it active, hoping to pick up more
|
|
* vertices before the next state change.
|
|
*/
|
|
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
|
|
|
|
return GL_TRUE;
|
|
|
|
default:
|
|
ASSERT (0);
|
|
return GL_TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Need to do this to get the correct begin/end error behaviour from
|
|
* functions like ColorPointerEXT which are still active in
|
|
* SAVE_AND_EXEC modes.
|
|
*/
|
|
void
|
|
_tnl_save_Begin( GLenum mode )
|
|
{
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
|
|
if (mode > GL_POLYGON) {
|
|
_mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
|
|
return;
|
|
}
|
|
|
|
if (ctx->ExecuteFlag) {
|
|
/* Preserve vtxfmt invarient:
|
|
*/
|
|
if (ctx->NewState)
|
|
gl_update_state( ctx );
|
|
|
|
/* Slot in geomexec: No need to call setdispatch as we know
|
|
* CurrentDispatch is Save.
|
|
*/
|
|
ASSERT(ctx->CurrentDispatch == ctx->Save);
|
|
}
|
|
|
|
_tnl_begin( ctx, mode );
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Note the continuation of a partially completed primitive. For
|
|
* driver t&l fallbacks between begin/end primitives. Has basically
|
|
* the same effects as a primitive wrapping onto a second immediate
|
|
* struct.
|
|
*
|
|
* ==> Can actually call this from _tnl_wakeup_exec, taking mode from
|
|
* ctx->Driver.CurrentExecPrimitive.
|
|
*/
|
|
#if 0
|
|
void _tnl_fallback_begin( GLcontext *ctx, GLenum mode )
|
|
{
|
|
struct immediate *IM = TNL_CURRENT_IM(ctx);
|
|
ASSERT( IM->Count == IM->Start );
|
|
ASSERT( IM->Flag[IM->Start] == 0 );
|
|
ASSERT( mode < GL_POLYGON+1 );
|
|
_tnl_begin( ctx, mode );
|
|
IM->Primitive[IM->Start] &= ~PRIM_BEGIN;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Both streams now outside begin/end.
|
|
*
|
|
* Leave SavedBeginState untouched -- attempt to gather several
|
|
* rects/arrays together in a single immediate struct.
|
|
*/
|
|
void
|
|
_tnl_end( GLcontext *ctx )
|
|
{
|
|
struct immediate *IM = TNL_CURRENT_IM(ctx);
|
|
GLuint state = IM->BeginState;
|
|
GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1);
|
|
|
|
state |= inflags << 2; /* errors */
|
|
|
|
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
|
|
{
|
|
GLuint count = IM->Count;
|
|
GLuint last = IM->LastPrimitive;
|
|
|
|
ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
|
|
|
|
state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */
|
|
IM->Flag[count] |= VERT_END;
|
|
IM->Primitive[last] |= PRIM_END;
|
|
IM->Primitive[last] &= ~PRIM_LAST;
|
|
IM->PrimitiveLength[last] = count - last;
|
|
IM->Primitive[count] = (GL_POLYGON+1) | PRIM_LAST;
|
|
IM->LastPrimitive = count;
|
|
|
|
if (IM->FlushElt) {
|
|
_tnl_translate_array_elts( ctx, IM, last, count );
|
|
IM->FlushElt = 0;
|
|
}
|
|
|
|
/* ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; */
|
|
}
|
|
|
|
IM->BeginState = state;
|
|
|
|
if (!ctx->CompileFlag)
|
|
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
|
|
|
|
|
|
/* You can set this flag to get the old 'flush_vb on glEnd()'
|
|
* behaviour.
|
|
*/
|
|
if ((MESA_DEBUG_FLAGS&DEBUG_ALWAYS_FLUSH))
|
|
_tnl_flush_immediate( IM );
|
|
}
|
|
|
|
static void
|
|
_tnl_End(void)
|
|
{
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
_tnl_end( ctx );
|
|
|
|
/* Need to keep save primitive uptodate in COMPILE and
|
|
* COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
|
|
* otherwise.
|
|
*/
|
|
if (ctx->CompileFlag)
|
|
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
|
|
}
|
|
|
|
|
|
#define COLOR( IM, r, g, b, a ) \
|
|
{ \
|
|
GLuint count = IM->Count; \
|
|
IM->Flag[count] |= VERT_RGBA; \
|
|
IM->Color[count][0] = r; \
|
|
IM->Color[count][1] = g; \
|
|
IM->Color[count][2] = b; \
|
|
IM->Color[count][3] = a; \
|
|
}
|
|
|
|
#define COLORV( IM, v ) \
|
|
{ \
|
|
GLuint count = IM->Count; \
|
|
IM->Flag[count] |= VERT_RGBA; \
|
|
COPY_CHAN4(IM->Color[count], v); \
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GLubyte col[4];
|
|
GET_IMMEDIATE;
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[0], red);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[1], green);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[2], blue);
|
|
col[3] = CHAN_MAX;
|
|
COLORV( IM, col );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UNCLAMPED_FLOAT_TO_CHAN(red),
|
|
UNCLAMPED_FLOAT_TO_CHAN(green),
|
|
UNCLAMPED_FLOAT_TO_CHAN(blue),
|
|
CHAN_MAX);
|
|
#endif
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GET_IMMEDIATE;
|
|
COLOR( IM, red, green, blue, CHAN_MAX );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UBYTE_TO_CHAN(red),
|
|
UBYTE_TO_CHAN(green),
|
|
UBYTE_TO_CHAN(blue),
|
|
CHAN_MAX);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
_tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GLubyte col[4];
|
|
GET_IMMEDIATE;
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[0], red);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[1], green);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[2], blue);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[3], alpha);
|
|
COLORV( IM, col );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UNCLAMPED_FLOAT_TO_CHAN(red),
|
|
UNCLAMPED_FLOAT_TO_CHAN(green),
|
|
UNCLAMPED_FLOAT_TO_CHAN(blue),
|
|
UNCLAMPED_FLOAT_TO_CHAN(alpha));
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GET_IMMEDIATE;
|
|
COLOR( IM, red, green, blue, alpha );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UBYTE_TO_CHAN(red),
|
|
UBYTE_TO_CHAN(green),
|
|
UBYTE_TO_CHAN(blue),
|
|
UBYTE_TO_CHAN(alpha));
|
|
#endif
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_Color3fv( const GLfloat *v )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GLubyte col[4];
|
|
GET_IMMEDIATE;
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[0], v[0]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[1], v[1]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[2], v[2]);
|
|
col[3] = CHAN_MAX;
|
|
COLORV( IM, col );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[0]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[1]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[2]),
|
|
CHAN_MAX);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
_tnl_Color3ubv( const GLubyte *v )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GET_IMMEDIATE;
|
|
COLOR( IM, v[0], v[1], v[2], CHAN_MAX );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UBYTE_TO_CHAN(v[0]),
|
|
UBYTE_TO_CHAN(v[1]),
|
|
UBYTE_TO_CHAN(v[2]),
|
|
CHAN_MAX);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_tnl_Color4fv( const GLfloat *v )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GLubyte col[4];
|
|
GET_IMMEDIATE;
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[0], v[0]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[1], v[1]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[2], v[2]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[3], v[3]);
|
|
COLORV( IM, col );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[0]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[1]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[2]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[3]));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
_tnl_Color4ubv( const GLubyte *v)
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GET_IMMEDIATE;
|
|
COLORV( IM, v );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
COLOR(IM,
|
|
UBYTE_TO_CHAN(v[0]),
|
|
UBYTE_TO_CHAN(v[1]),
|
|
UBYTE_TO_CHAN(v[2]),
|
|
UBYTE_TO_CHAN(v[3]));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SECONDARY_COLOR( IM, r, g, b ) \
|
|
{ \
|
|
GLuint count = IM->Count; \
|
|
IM->Flag[count] |= VERT_SPEC_RGB; \
|
|
IM->SecondaryColor[count][0] = r; \
|
|
IM->SecondaryColor[count][1] = g; \
|
|
IM->SecondaryColor[count][2] = b; \
|
|
}
|
|
|
|
#define SECONDARY_COLORV( IM, v ) \
|
|
{ \
|
|
GLuint count = IM->Count; \
|
|
IM->Flag[count] |= VERT_SPEC_RGB; \
|
|
IM->SecondaryColor[count][0] = v[0]; \
|
|
IM->SecondaryColor[count][1] = v[1]; \
|
|
IM->SecondaryColor[count][2] = v[2]; \
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
_tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GLubyte col[3];
|
|
GET_IMMEDIATE;
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[0], red);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[1], green);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[2], blue);
|
|
SECONDARY_COLORV( IM, col );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
SECONDARY_COLOR(IM,
|
|
UNCLAMPED_FLOAT_TO_CHAN(red),
|
|
UNCLAMPED_FLOAT_TO_CHAN(green),
|
|
UNCLAMPED_FLOAT_TO_CHAN(blue));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
_tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GET_IMMEDIATE;
|
|
SECONDARY_COLOR( IM, red, green, blue );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
SECONDARY_COLOR(IM,
|
|
UBYTE_TO_CHAN(red),
|
|
UBYTE_TO_CHAN(green),
|
|
UBYTE_TO_CHAN(blue));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
_tnl_SecondaryColor3fvEXT( const GLfloat *v )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GLubyte col[3];
|
|
GET_IMMEDIATE;
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[0], v[0]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[1], v[1]);
|
|
UNCLAMPED_FLOAT_TO_UBYTE(col[2], v[2]);
|
|
SECONDARY_COLORV( IM, col );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
SECONDARY_COLOR(IM,
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[0]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[1]),
|
|
UNCLAMPED_FLOAT_TO_CHAN(v[2]));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
_tnl_SecondaryColor3ubvEXT( const GLubyte *v )
|
|
{
|
|
#if CHAN_BITS == 8
|
|
GET_IMMEDIATE;
|
|
SECONDARY_COLOR( IM, v[0], v[1], v[2] );
|
|
#else
|
|
GET_IMMEDIATE;
|
|
SECONDARY_COLOR(IM,
|
|
UBYTE_TO_CHAN(v[0]),
|
|
UBYTE_TO_CHAN(v[1]),
|
|
UBYTE_TO_CHAN(v[2]));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
_tnl_EdgeFlag( GLboolean flag )
|
|
{
|
|
GLuint count;
|
|
GET_IMMEDIATE;
|
|
count = IM->Count;
|
|
IM->EdgeFlag[count] = flag;
|
|
IM->Flag[count] |= VERT_EDGE;
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_EdgeFlagv( const GLboolean *flag )
|
|
{
|
|
GLuint count;
|
|
GET_IMMEDIATE;
|
|
count = IM->Count;
|
|
IM->EdgeFlag[count] = *flag;
|
|
IM->Flag[count] |= VERT_EDGE;
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_FogCoordfEXT( GLfloat f )
|
|
{
|
|
GLuint count;
|
|
GET_IMMEDIATE;
|
|
count = IM->Count;
|
|
IM->FogCoord[count] = f;
|
|
IM->Flag[count] |= VERT_FOG_COORD;
|
|
}
|
|
|
|
static void
|
|
_tnl_FogCoordfvEXT( const GLfloat *v )
|
|
{
|
|
GLuint count;
|
|
GET_IMMEDIATE;
|
|
count = IM->Count;
|
|
IM->FogCoord[count] = v[0];
|
|
IM->Flag[count] |= VERT_FOG_COORD;
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_Indexi( GLint c )
|
|
{
|
|
GLuint count;
|
|
GET_IMMEDIATE;
|
|
count = IM->Count;
|
|
IM->Index[count] = c;
|
|
IM->Flag[count] |= VERT_INDEX;
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_Indexiv( const GLint *c )
|
|
{
|
|
GLuint count;
|
|
GET_IMMEDIATE;
|
|
count = IM->Count;
|
|
IM->Index[count] = *c;
|
|
IM->Flag[count] |= VERT_INDEX;
|
|
}
|
|
|
|
|
|
#define NORMAL( x, y, z ) \
|
|
{ \
|
|
GLuint count; \
|
|
GLfloat *normal; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_NORM; \
|
|
normal = IM->Normal[count]; \
|
|
ASSIGN_3V(normal, x,y,z); \
|
|
}
|
|
|
|
#if defined(USE_IEEE)
|
|
#define NORMALF( x, y, z ) \
|
|
{ \
|
|
GLuint count; \
|
|
GLint *normal; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_NORM; \
|
|
normal = (GLint *)IM->Normal[count]; \
|
|
ASSIGN_3V(normal, *(int*)&(x), *(int*)&(y), *(int*)&(z)); \
|
|
}
|
|
#else
|
|
#define NORMALF NORMAL
|
|
#endif
|
|
|
|
static void
|
|
_tnl_Normal3f( GLfloat nx, GLfloat ny, GLfloat nz )
|
|
{
|
|
NORMALF(nx, ny, nz);
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_Normal3fv( const GLfloat *v )
|
|
{
|
|
NORMALF( v[0], v[1], v[2] );
|
|
}
|
|
|
|
|
|
|
|
#define TEXCOORD1(s) \
|
|
{ \
|
|
GLuint count; \
|
|
GLfloat *tc; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_TEX0; \
|
|
tc = IM->TexCoord0[count]; \
|
|
ASSIGN_4V(tc,s,0,0,1); \
|
|
}
|
|
|
|
#define TEXCOORD2(s,t) \
|
|
{ \
|
|
GLuint count; \
|
|
GLfloat *tc; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_TEX0; \
|
|
tc = IM->TexCoord0[count]; \
|
|
ASSIGN_4V(tc, s,t,0,1); \
|
|
}
|
|
|
|
#define TEXCOORD3(s,t,u) \
|
|
{ \
|
|
GLuint count; \
|
|
GLfloat *tc; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_TEX0; \
|
|
IM->TexSize |= TEX_0_SIZE_3; \
|
|
tc = IM->TexCoord0[count]; \
|
|
ASSIGN_4V(tc, s,t,u,1); \
|
|
}
|
|
|
|
#define TEXCOORD4(s,t,u,v) \
|
|
{ \
|
|
GLuint count; \
|
|
GLfloat *tc; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_TEX0; \
|
|
IM->TexSize |= TEX_0_SIZE_4; \
|
|
tc = IM->TexCoord0[count]; \
|
|
ASSIGN_4V(tc, s,t,u,v); \
|
|
}
|
|
|
|
#if defined(USE_IEEE)
|
|
#define TEXCOORD2F(s,t) \
|
|
{ \
|
|
GLuint count; \
|
|
GLint *tc; \
|
|
GET_IMMEDIATE; \
|
|
count = IM->Count; \
|
|
IM->Flag[count] |= VERT_TEX0; \
|
|
tc = (GLint *)IM->TexCoord0[count]; \
|
|
tc[0] = *(GLint *)&(s); \
|
|
tc[1] = *(GLint *)&(t); \
|
|
tc[2] = 0; \
|
|
tc[3] = IEEE_ONE; \
|
|
}
|
|
#else
|
|
#define TEXCOORD2F TEXCOORD2
|
|
#endif
|
|
|
|
static void
|
|
_tnl_TexCoord1f( GLfloat s )
|
|
{
|
|
TEXCOORD1(s);
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_TexCoord2f( GLfloat s, GLfloat t )
|
|
{
|
|
TEXCOORD2F(s,t);
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
|
|
{
|
|
TEXCOORD3(s,t,r);
|
|
}
|
|
|
|
static void
|
|
_tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
|
|
{
|
|
TEXCOORD4(s,t,r,q)
|
|
}
|
|
|
|
static void
|
|
_tnl_TexCoord1fv( const GLfloat *v )
|
|
{
|
|
TEXCOORD1(v[0]);
|
|
}
|
|
|
|
static void
|
|
_tnl_TexCoord2fv( const GLfloat *v )
|
|
{
|
|
TEXCOORD2F(v[0],v[1]);
|
|
}
|
|
|
|
static void
|
|
_tnl_TexCoord3fv( const GLfloat *v )
|
|
{
|
|
TEXCOORD3(v[0],v[1],v[2]);
|
|
}
|
|
|
|
static void
|
|
_tnl_TexCoord4fv( const GLfloat *v )
|
|
{
|
|
TEXCOORD4(v[0],v[1],v[2],v[3]);
|
|
}
|
|
|
|
|
|
|
|
/* KW: Run into bad problems in vertex copying if we don't fully pad
|
|
* the incoming vertices.
|
|
*/
|
|
#define VERTEX2(IM, x,y) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
GLfloat *dest = IM->Obj[count]; \
|
|
IM->Flag[count] |= VERT_OBJ; \
|
|
ASSIGN_4V(dest, x, y, 0, 1); \
|
|
/* ASSERT(IM->Flag[IM->Count]==0); */\
|
|
if (count == IMM_MAXDATA - 1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
#define VERTEX3(IM,x,y,z) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
GLfloat *dest = IM->Obj[count]; \
|
|
IM->Flag[count] |= VERT_OBJ_23; \
|
|
ASSIGN_4V(dest, x, y, z, 1); \
|
|
/* ASSERT(IM->Flag[IM->Count]==0); */ \
|
|
if (count == IMM_MAXDATA - 1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
#define VERTEX4(IM, x,y,z,w) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
GLfloat *dest = IM->Obj[count]; \
|
|
IM->Flag[count] |= VERT_OBJ_234; \
|
|
ASSIGN_4V(dest, x, y, z, w); \
|
|
if (count == IMM_MAXDATA - 1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
#if defined(USE_IEEE)
|
|
#define VERTEX2F(IM, x, y) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
GLint *dest = (GLint *)IM->Obj[count]; \
|
|
IM->Flag[count] |= VERT_OBJ; \
|
|
dest[0] = *(GLint *)&(x); \
|
|
dest[1] = *(GLint *)&(y); \
|
|
dest[2] = 0; \
|
|
dest[3] = IEEE_ONE; \
|
|
/* ASSERT(IM->Flag[IM->Count]==0); */ \
|
|
if (count == IMM_MAXDATA - 1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
#else
|
|
#define VERTEX2F VERTEX2
|
|
#endif
|
|
|
|
#if defined(USE_IEEE)
|
|
#define VERTEX3F(IM, x, y, z) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
GLint *dest = (GLint *)IM->Obj[count]; \
|
|
IM->Flag[count] |= VERT_OBJ_23; \
|
|
dest[0] = *(GLint *)&(x); \
|
|
dest[1] = *(GLint *)&(y); \
|
|
dest[2] = *(GLint *)&(z); \
|
|
dest[3] = IEEE_ONE; \
|
|
/* ASSERT(IM->Flag[IM->Count]==0); */ \
|
|
if (count == IMM_MAXDATA - 1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
#else
|
|
#define VERTEX3F VERTEX3
|
|
#endif
|
|
|
|
#if defined(USE_IEEE)
|
|
#define VERTEX4F(IM, x, y, z, w) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
GLint *dest = (GLint *)IM->Obj[count]; \
|
|
IM->Flag[count] |= VERT_OBJ_234; \
|
|
dest[0] = *(GLint *)&(x); \
|
|
dest[1] = *(GLint *)&(y); \
|
|
dest[2] = *(GLint *)&(z); \
|
|
dest[3] = *(GLint *)&(w); \
|
|
if (count == IMM_MAXDATA - 1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
#else
|
|
#define VERTEX4F VERTEX4
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
|
_tnl_Vertex2f( GLfloat x, GLfloat y )
|
|
{
|
|
GET_IMMEDIATE;
|
|
VERTEX2F( IM, x, y );
|
|
}
|
|
|
|
static void
|
|
_tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
|
|
{
|
|
GET_IMMEDIATE;
|
|
VERTEX3F( IM, x, y, z );
|
|
}
|
|
static void
|
|
_tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
|
|
{
|
|
GET_IMMEDIATE;
|
|
VERTEX4F( IM, x, y, z, w );
|
|
}
|
|
|
|
static void
|
|
_tnl_Vertex2fv( const GLfloat *v )
|
|
{
|
|
GET_IMMEDIATE;
|
|
VERTEX2F( IM, v[0], v[1] );
|
|
}
|
|
|
|
static void
|
|
_tnl_Vertex3fv( const GLfloat *v )
|
|
{
|
|
GET_IMMEDIATE;
|
|
VERTEX3F( IM, v[0], v[1], v[2] );
|
|
}
|
|
|
|
static void
|
|
_tnl_Vertex4fv( const GLfloat *v )
|
|
{
|
|
GET_IMMEDIATE;
|
|
VERTEX4F( IM, v[0], v[1], v[2], v[3] );
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* GL_ARB_multitexture
|
|
*
|
|
* Note: the multitexture spec says that specifying an invalid target
|
|
* has undefined results and does not have to generate an error. Just
|
|
* don't crash. We no-op on invalid targets.
|
|
*/
|
|
|
|
#define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
|
|
|
|
#define MULTI_TEXCOORD1(target, s) \
|
|
{ \
|
|
GET_IMMEDIATE; \
|
|
GLuint texunit = target - GL_TEXTURE0_ARB; \
|
|
if (texunit < IM->MaxTextureUnits) { \
|
|
GLuint count = IM->Count; \
|
|
GLfloat *tc = IM->TexCoord[texunit][count]; \
|
|
ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
|
|
IM->Flag[count] |= VERT_TEX(texunit); \
|
|
} \
|
|
}
|
|
|
|
#define MULTI_TEXCOORD2(target, s, t) \
|
|
{ \
|
|
GET_IMMEDIATE; \
|
|
GLuint texunit = target - GL_TEXTURE0_ARB; \
|
|
if (texunit < IM->MaxTextureUnits) { \
|
|
GLuint count = IM->Count; \
|
|
GLfloat *tc = IM->TexCoord[texunit][count]; \
|
|
ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
|
|
IM->Flag[count] |= VERT_TEX(texunit); \
|
|
} \
|
|
}
|
|
|
|
#define MULTI_TEXCOORD3(target, s, t, u) \
|
|
{ \
|
|
GET_IMMEDIATE; \
|
|
GLuint texunit = target - GL_TEXTURE0_ARB; \
|
|
if (texunit < IM->MaxTextureUnits) { \
|
|
GLuint count = IM->Count; \
|
|
GLfloat *tc = IM->TexCoord[texunit][count]; \
|
|
ASSIGN_4V(tc, s, t, u, 1.0F); \
|
|
IM->Flag[count] |= VERT_TEX(texunit); \
|
|
IM->TexSize |= TEX_SIZE_3(texunit); \
|
|
} \
|
|
}
|
|
|
|
#define MULTI_TEXCOORD4(target, s, t, u, v) \
|
|
{ \
|
|
GET_IMMEDIATE; \
|
|
GLuint texunit = target - GL_TEXTURE0_ARB; \
|
|
if (texunit < IM->MaxTextureUnits) { \
|
|
GLuint count = IM->Count; \
|
|
GLfloat *tc = IM->TexCoord[texunit][count]; \
|
|
ASSIGN_4V(tc, s, t, u, v); \
|
|
IM->Flag[count] |= VERT_TEX(texunit); \
|
|
IM->TexSize |= TEX_SIZE_4(texunit); \
|
|
} \
|
|
}
|
|
|
|
#if defined(USE_IEEE)
|
|
#define MULTI_TEXCOORD2F(target, s, t) \
|
|
{ \
|
|
GET_IMMEDIATE; \
|
|
GLuint texunit = target - GL_TEXTURE0_ARB; \
|
|
if (texunit < IM->MaxTextureUnits) { \
|
|
GLuint count = IM->Count; \
|
|
GLint *tc = (GLint *)IM->TexCoord[texunit][count]; \
|
|
IM->Flag[count] |= VERT_TEX(texunit); \
|
|
tc[0] = *(int *)&(s); \
|
|
tc[1] = *(int *)&(t); \
|
|
tc[2] = 0; \
|
|
tc[3] = IEEE_ONE; \
|
|
} \
|
|
}
|
|
#else
|
|
#define MULTI_TEXCOORD2F MULTI_TEXCOORD2
|
|
#endif
|
|
|
|
static void
|
|
_tnl_MultiTexCoord1fARB(GLenum target, GLfloat s)
|
|
{
|
|
MULTI_TEXCOORD1( target, s );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord1fvARB(GLenum target, const GLfloat *v)
|
|
{
|
|
MULTI_TEXCOORD1( target, v[0] );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t)
|
|
{
|
|
MULTI_TEXCOORD2F( target, s, t );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord2fvARB(GLenum target, const GLfloat *v)
|
|
{
|
|
MULTI_TEXCOORD2F( target, v[0], v[1] );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r)
|
|
{
|
|
MULTI_TEXCOORD3( target, s, t, r );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord3fvARB(GLenum target, const GLfloat *v)
|
|
{
|
|
MULTI_TEXCOORD3( target, v[0], v[1], v[2] );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
|
|
{
|
|
MULTI_TEXCOORD4( target, s, t, r, q );
|
|
}
|
|
|
|
static void
|
|
_tnl_MultiTexCoord4fvARB(GLenum target, const GLfloat *v)
|
|
{
|
|
MULTI_TEXCOORD4( target, v[0], v[1], v[2], v[3] );
|
|
}
|
|
|
|
|
|
|
|
/* KW: Because the eval values don't become 'current', fixup will flow
|
|
* through these vertices, and then evaluation will write on top
|
|
* of the fixup results.
|
|
*
|
|
* Note: using Obj to hold eval coord data.
|
|
*/
|
|
#define EVALCOORD1(IM, x) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
IM->Flag[count] |= VERT_EVAL_C1; \
|
|
ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
|
|
if (count == IMM_MAXDATA-1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
#define EVALCOORD2(IM, x, y) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
IM->Flag[count] |= VERT_EVAL_C2; \
|
|
ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
|
|
if (count == IMM_MAXDATA-1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
#define EVALPOINT1(IM, x) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
IM->Flag[count] |= VERT_EVAL_P1; \
|
|
ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
|
|
if (count == IMM_MAXDATA-1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
#define EVALPOINT2(IM, x, y) \
|
|
{ \
|
|
GLuint count = IM->Count++; \
|
|
IM->Flag[count] |= VERT_EVAL_P2; \
|
|
ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
|
|
if (count == IMM_MAXDATA-1) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
static void
|
|
_tnl_EvalCoord1f( GLfloat u )
|
|
{
|
|
GET_IMMEDIATE;
|
|
EVALCOORD1( IM, u );
|
|
}
|
|
|
|
static void
|
|
_tnl_EvalCoord1fv( const GLfloat *u )
|
|
{
|
|
GET_IMMEDIATE;
|
|
EVALCOORD1( IM, (GLfloat) *u );
|
|
}
|
|
|
|
static void
|
|
_tnl_EvalCoord2f( GLfloat u, GLfloat v )
|
|
{
|
|
GET_IMMEDIATE;
|
|
EVALCOORD2( IM, u, v );
|
|
}
|
|
|
|
static void
|
|
_tnl_EvalCoord2fv( const GLfloat *u )
|
|
{
|
|
GET_IMMEDIATE;
|
|
EVALCOORD2( IM, u[0], u[1] );
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_EvalPoint1( GLint i )
|
|
{
|
|
GET_IMMEDIATE;
|
|
EVALPOINT1( IM, i );
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_EvalPoint2( GLint i, GLint j )
|
|
{
|
|
GET_IMMEDIATE;
|
|
EVALPOINT2( IM, i, j );
|
|
}
|
|
|
|
|
|
/* Need to use the default array-elt outside begin/end for strict
|
|
* conformance.
|
|
*/
|
|
#define ARRAY_ELT( IM, i ) \
|
|
{ \
|
|
GLuint count = IM->Count; \
|
|
IM->Elt[count] = i; \
|
|
IM->Flag[count] &= IM->ArrayEltFlags; \
|
|
IM->Flag[count] |= VERT_ELT; \
|
|
IM->FlushElt |= IM->ArrayEltFlush; \
|
|
IM->Count += IM->ArrayEltIncr; \
|
|
if (IM->Count == IMM_MAXDATA) \
|
|
_tnl_flush_immediate( IM ); \
|
|
}
|
|
|
|
|
|
static void
|
|
_tnl_ArrayElement( GLint i )
|
|
{
|
|
GET_IMMEDIATE;
|
|
ARRAY_ELT( IM, i );
|
|
}
|
|
|
|
|
|
/* Internal functions. These are safe to use providing either:
|
|
*
|
|
* - It is determined that a display list is not being compiled, or
|
|
* if so that these commands won't be compiled into the list (see
|
|
* t_eval.c for an example).
|
|
*
|
|
* - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
|
|
* for a GL_TRUE return value. See _tnl_Rectf, below.
|
|
*/
|
|
void
|
|
_tnl_eval_coord1f( GLcontext *CC, GLfloat u )
|
|
{
|
|
struct immediate *i = TNL_CURRENT_IM(CC);
|
|
EVALCOORD1( i, u );
|
|
}
|
|
|
|
void
|
|
_tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v )
|
|
{
|
|
struct immediate *i = TNL_CURRENT_IM(CC);
|
|
EVALCOORD2( i, u, v );
|
|
}
|
|
|
|
void
|
|
_tnl_array_element( GLcontext *CC, GLint i )
|
|
{
|
|
struct immediate *im = TNL_CURRENT_IM(CC);
|
|
ARRAY_ELT( im, i );
|
|
}
|
|
|
|
void
|
|
_tnl_vertex2f( GLcontext *ctx, GLfloat x, GLfloat y )
|
|
{
|
|
struct immediate *im = TNL_CURRENT_IM(ctx);
|
|
VERTEX2( im, x, y );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Execute a glRectf() function. _tnl_hard_begin() ensures the check
|
|
* on outside_begin_end is executed even in compiled lists. These
|
|
* vertices can now participate in the same VB as regular ones, even
|
|
* in most display lists.
|
|
*/
|
|
static void
|
|
_tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
|
|
{
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
|
|
if (_tnl_hard_begin( ctx, GL_QUADS )) {
|
|
_tnl_vertex2f( ctx, x1, y1 );
|
|
_tnl_vertex2f( ctx, x2, y1 );
|
|
_tnl_vertex2f( ctx, x2, y2 );
|
|
_tnl_vertex2f( ctx, x1, y2 );
|
|
_tnl_end( ctx );
|
|
}
|
|
}
|
|
|
|
static void
|
|
_tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
|
|
{
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
struct immediate *IM = TNL_CURRENT_IM(ctx);
|
|
GLuint count = IM->Count;
|
|
struct gl_material *mat;
|
|
GLuint bitmask = gl_material_bitmask( ctx, face, pname, ~0, "Materialfv" );
|
|
|
|
if (bitmask == 0)
|
|
return;
|
|
|
|
if (!IM->Material) {
|
|
IM->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
|
|
IMM_SIZE * 2 );
|
|
IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
|
|
}
|
|
|
|
if (!(IM->Flag[count] & VERT_MATERIAL)) {
|
|
IM->Flag[count] |= VERT_MATERIAL;
|
|
IM->MaterialMask[count] = 0;
|
|
}
|
|
|
|
IM->MaterialMask[count] |= bitmask;
|
|
mat = IM->Material[count];
|
|
|
|
if (bitmask & FRONT_AMBIENT_BIT) {
|
|
COPY_4FV( mat[0].Ambient, params );
|
|
}
|
|
if (bitmask & BACK_AMBIENT_BIT) {
|
|
COPY_4FV( mat[1].Ambient, params );
|
|
}
|
|
if (bitmask & FRONT_DIFFUSE_BIT) {
|
|
COPY_4FV( mat[0].Diffuse, params );
|
|
}
|
|
if (bitmask & BACK_DIFFUSE_BIT) {
|
|
COPY_4FV( mat[1].Diffuse, params );
|
|
}
|
|
if (bitmask & FRONT_SPECULAR_BIT) {
|
|
COPY_4FV( mat[0].Specular, params );
|
|
}
|
|
if (bitmask & BACK_SPECULAR_BIT) {
|
|
COPY_4FV( mat[1].Specular, params );
|
|
}
|
|
if (bitmask & FRONT_EMISSION_BIT) {
|
|
COPY_4FV( mat[0].Emission, params );
|
|
}
|
|
if (bitmask & BACK_EMISSION_BIT) {
|
|
COPY_4FV( mat[1].Emission, params );
|
|
}
|
|
if (bitmask & FRONT_SHININESS_BIT) {
|
|
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
|
|
mat[0].Shininess = shininess;
|
|
}
|
|
if (bitmask & BACK_SHININESS_BIT) {
|
|
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
|
|
mat[1].Shininess = shininess;
|
|
}
|
|
if (bitmask & FRONT_INDEXES_BIT) {
|
|
mat[0].AmbientIndex = params[0];
|
|
mat[0].DiffuseIndex = params[1];
|
|
mat[0].SpecularIndex = params[2];
|
|
}
|
|
if (bitmask & BACK_INDEXES_BIT) {
|
|
mat[1].AmbientIndex = params[0];
|
|
mat[1].DiffuseIndex = params[1];
|
|
mat[1].SpecularIndex = params[2];
|
|
}
|
|
}
|
|
|
|
void _tnl_imm_vtxfmt_init( GLcontext *ctx )
|
|
{
|
|
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
|
|
|
|
/* All begin/end operations are handled by this vertex format:
|
|
*/
|
|
vfmt->ArrayElement = _tnl_ArrayElement;
|
|
vfmt->Begin = _tnl_Begin;
|
|
vfmt->Color3f = _tnl_Color3f;
|
|
vfmt->Color3fv = _tnl_Color3fv;
|
|
vfmt->Color3ub = _tnl_Color3ub;
|
|
vfmt->Color3ubv = _tnl_Color3ubv;
|
|
vfmt->Color4f = _tnl_Color4f;
|
|
vfmt->Color4fv = _tnl_Color4fv;
|
|
vfmt->Color4ub = _tnl_Color4ub;
|
|
vfmt->Color4ubv = _tnl_Color4ubv;
|
|
vfmt->EdgeFlag = _tnl_EdgeFlag;
|
|
vfmt->EdgeFlagv = _tnl_EdgeFlagv;
|
|
vfmt->End = _tnl_End;
|
|
vfmt->EvalCoord1f = _tnl_EvalCoord1f;
|
|
vfmt->EvalCoord1fv = _tnl_EvalCoord1fv;
|
|
vfmt->EvalCoord2f = _tnl_EvalCoord2f;
|
|
vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
|
|
vfmt->EvalPoint1 = _tnl_EvalPoint1;
|
|
vfmt->EvalPoint2 = _tnl_EvalPoint2;
|
|
vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
|
|
vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
|
|
vfmt->Indexi = _tnl_Indexi;
|
|
vfmt->Indexiv = _tnl_Indexiv;
|
|
vfmt->Materialfv = _tnl_Materialfv;
|
|
vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1fARB;
|
|
vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fvARB;
|
|
vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2fARB;
|
|
vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fvARB;
|
|
vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3fARB;
|
|
vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fvARB;
|
|
vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4fARB;
|
|
vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fvARB;
|
|
vfmt->Normal3f = _tnl_Normal3f;
|
|
vfmt->Normal3fv = _tnl_Normal3fv;
|
|
vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
|
|
vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
|
|
vfmt->SecondaryColor3ubEXT = _tnl_SecondaryColor3ubEXT;
|
|
vfmt->SecondaryColor3ubvEXT = _tnl_SecondaryColor3ubvEXT;
|
|
vfmt->TexCoord1f = _tnl_TexCoord1f;
|
|
vfmt->TexCoord1fv = _tnl_TexCoord1fv;
|
|
vfmt->TexCoord2f = _tnl_TexCoord2f;
|
|
vfmt->TexCoord2fv = _tnl_TexCoord2fv;
|
|
vfmt->TexCoord3f = _tnl_TexCoord3f;
|
|
vfmt->TexCoord3fv = _tnl_TexCoord3fv;
|
|
vfmt->TexCoord4f = _tnl_TexCoord4f;
|
|
vfmt->TexCoord4fv = _tnl_TexCoord4fv;
|
|
vfmt->Vertex2f = _tnl_Vertex2f;
|
|
vfmt->Vertex2fv = _tnl_Vertex2fv;
|
|
vfmt->Vertex3f = _tnl_Vertex3f;
|
|
vfmt->Vertex3fv = _tnl_Vertex3fv;
|
|
vfmt->Vertex4f = _tnl_Vertex4f;
|
|
vfmt->Vertex4fv = _tnl_Vertex4fv;
|
|
|
|
/* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
|
|
*/
|
|
vfmt->Rectf = _tnl_Rectf;
|
|
|
|
/* Just use the core function:
|
|
*/
|
|
vfmt->CallList = _mesa_CallList;
|
|
|
|
vfmt->prefer_float_colors = GL_FALSE;
|
|
}
|