NT4/private/windows/opengl/server/soft/so_textu.c
2020-09-30 17:12:29 +02:00

5429 lines
146 KiB
C

/*
** Copyright 1991,1992, 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.
**
*/
#include "precomp.h"
#pragma hdrstop
#include <namesint.h>
#include <math.h>
/*
** Some math routines that are optimized in assembly
*/
#ifndef NT
#ifdef __GL_USEASMCODE
#define __GL_FRAC(f) __glFrac(f)
#else
#define __GL_FRAC(f) ((f) - floorf(f))
#endif
#else
#define __GL_FRAC(f) ((f) - __GL_FLOORF(f))
#endif
#define __GL_M_LN2_INV ((__GLfloat) (1.0 / 0.69314718055994530942))
#define __GL_M_SQRT2 ((__GLfloat) 1.41421356237309504880)
/*
** Return the log based 2 of a number
*/
#ifdef NT
static GLubyte logTab[256] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
static GLint FASTCALL Log2(__GLfloat f)
{
GLuint i = (GLuint) f;
if (i & 0xffff0000) {
if (i & 0xff000000) {
return ((GLint)logTab[i >> 24] + 24);
} else {
return ((GLint)logTab[i >> 16] + 16);
}
} else {
if (i & 0xff00) {
return ((GLint)logTab[i >> 8] + 8);
} else {
return ((GLint)logTab[i]);
}
}
}
#else
static __GLfloat FASTCALL Log2(__GLfloat f)
{
return __GL_LOGF(f) * __GL_M_LN2_INV;
}
#endif
/************************************************************************/
__GLtextureParamState * FASTCALL __glLookUpTextureParams(__GLcontext *gc, GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return &gc->state.texture.texture[2].params;
case GL_TEXTURE_2D:
return &gc->state.texture.texture[3].params;
default:
return 0;
}
}
__GLtextureObjectState * FASTCALL __glLookUpTextureTexobjs(__GLcontext *gc,
GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return &gc->state.texture.texture[2].texobjs;
case GL_TEXTURE_2D:
return &gc->state.texture.texture[3].texobjs;
default:
return 0;
}
}
__GLtexture * FASTCALL __glLookUpTexture(__GLcontext *gc, GLenum target)
{
switch (target) {
case GL_PROXY_TEXTURE_1D:
return &gc->texture.texture[0]->map;
case GL_PROXY_TEXTURE_2D:
return &gc->texture.texture[1]->map;
case GL_TEXTURE_1D:
return &gc->texture.texture[2]->map;
case GL_TEXTURE_2D:
return &gc->texture.texture[3]->map;
default:
return 0;
}
}
__GLtextureObject * FASTCALL __glLookUpTextureObject(__GLcontext *gc, GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return gc->texture.boundTextures[2];
case GL_TEXTURE_2D:
return gc->texture.boundTextures[3];
default:
return 0;
}
}
#define __GL_TEX_TARGET_INDEX_1D 2
#define __GL_TEX_TARGET_INDEX_2D 3
static GLfloat FASTCALL Clampf(GLfloat fval, __GLfloat zero, __GLfloat one)
{
if (fval < zero) return zero;
else if (fval > one) return one;
else return fval;
}
/************************************************************************/
void __glTexPriListRealize(__GLcontext *gc)
{
__GLtextureObject *high, *low;
GLboolean tryUnload = GL_TRUE;
DWORD loadKey;
__GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray);
// Attempt to load as many of the highest priority textures as
// possible. If a lower priority texture is resident and a
// higher priority texture is unable to load, kick it out
// and try again
high = gc->texture.shared->priorityListHighest;
low = gc->texture.shared->priorityListLowest;
while (high != NULL)
{
// We only want to load textures that have image data
// BUGBUG - Should check all mipmap levels?
if (high->loadKey == 0 && high->texture.map.level[0].buffer != NULL)
{
for (;;)
{
// If high == low then there are no longer any
// lower-priority textures to consider for unloading
if (high == low)
{
tryUnload = GL_FALSE;
}
loadKey = __glGenLoadTexture(gc, &high->texture.map);
if (loadKey != 0)
{
high->resident = GL_TRUE;
high->loadKey = loadKey;
break;
}
if (tryUnload)
{
while (low->loadKey == 0 && low != high)
{
low = low->higherPriority;
}
if (low->loadKey != 0)
{
__glGenFreeTexture(gc, &low->texture.map, low->loadKey);
low->loadKey = 0;
low->resident = GL_FALSE;
}
}
else
{
break;
}
}
}
high = high->lowerPriority;
}
}
void __glTexPriListAddToList(__GLcontext *gc, __GLtextureObject *texobj)
{
__GLtextureObject *texobjLower;
__GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray);
// Walk the priority list to find a lower priority texture object
texobjLower = gc->texture.shared->priorityListHighest;
while (texobjLower != NULL &&
texobjLower->texture.map.texobjs.priority >
texobj->texture.map.texobjs.priority)
{
texobjLower = texobjLower->lowerPriority;
}
if (texobjLower == NULL)
{
// Place at end of list
if (gc->texture.shared->priorityListLowest != NULL)
{
gc->texture.shared->priorityListLowest->lowerPriority = texobj;
}
else
{
gc->texture.shared->priorityListHighest = texobj;
}
texobj->higherPriority = gc->texture.shared->priorityListLowest;
gc->texture.shared->priorityListLowest = texobj;
}
else
{
if (texobjLower->higherPriority != NULL)
{
texobjLower->higherPriority->lowerPriority = texobj;
}
else
{
gc->texture.shared->priorityListHighest = texobj;
}
texobj->higherPriority = texobjLower->higherPriority;
texobjLower->higherPriority = texobj;
}
texobj->lowerPriority = texobjLower;
}
void __glTexPriListAdd(__GLcontext *gc, __GLtextureObject *texobj,
GLboolean realize)
{
__glNamesLockArray(gc, gc->texture.shared->namesArray);
__glTexPriListAddToList(gc, texobj);
if (realize)
{
__glTexPriListRealize(gc);
}
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
}
void __glTexPriListRemoveFromList(__GLcontext *gc, __GLtextureObject *texobj)
{
__GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray);
#if DBG
{
__GLtextureObject *t;
for (t = gc->texture.shared->priorityListHighest;
t != NULL; t = t->lowerPriority)
{
if (t == texobj)
{
break;
}
}
ASSERTOPENGL(t != NULL, "Removing an unlisted texobj");
}
#endif
if (texobj->higherPriority != NULL)
{
texobj->higherPriority->lowerPriority = texobj->lowerPriority;
}
else
{
gc->texture.shared->priorityListHighest = texobj->lowerPriority;
}
if (texobj->lowerPriority != NULL)
{
texobj->lowerPriority->higherPriority = texobj->higherPriority;
}
else
{
gc->texture.shared->priorityListLowest = texobj->higherPriority;
}
}
void __glTexPriListRemove(__GLcontext *gc, __GLtextureObject *texobj,
GLboolean realize)
{
__glNamesLockArray(gc, gc->texture.shared->namesArray);
__glTexPriListRemoveFromList(gc, texobj);
__glGenFreeTexture(gc, &texobj->texture.map, texobj->loadKey);
texobj->loadKey = 0;
texobj->resident = GL_FALSE;
if (realize)
{
__glTexPriListRealize(gc);
}
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
}
void __glTexPriListChangePriority(__GLcontext *gc, __GLtextureObject *texobj,
GLboolean realize)
{
__glNamesLockArray(gc, gc->texture.shared->namesArray);
__glTexPriListRemoveFromList(gc, texobj);
__glTexPriListAddToList(gc, texobj);
// If we're re-realizing, don't bother calling the MCD texture-priority
// function:
if (realize) {
__glTexPriListRealize(gc);
} else if (((__GLGENcontext *)gc)->pMcdState && texobj->loadKey) {
GenMcdUpdateTexturePriority((__GLGENcontext *)gc,
&texobj->texture.map, texobj->loadKey);
}
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
}
void __glTexPriListLoadSubImage(__GLcontext *gc, GLenum target, GLint lod,
GLint xoffset, GLint yoffset,
GLsizei w, GLsizei h)
{
__GLtextureObject *pto;
// Always mark things as resident:
pto = __glLookUpTextureObject(gc, target);
pto->resident = GL_TRUE;
__glGenUpdateTexture(gc, &pto->texture.map, pto->loadKey);
// For MCD, send down the full subimage command:
if (((__GLGENcontext *)gc)->pMcdState && pto->loadKey) {
GenMcdUpdateSubTexture((__GLGENcontext *)gc, &pto->texture.map,
pto->texture.map.textureKey, lod,
xoffset, yoffset, w, h);
}
}
void __glTexPriListLoadImage(__GLcontext *gc, GLenum target)
{
__GLtextureObject *pto;
// If we're unaccelerated then always mark things as resident
pto = __glLookUpTextureObject(gc, target);
pto->resident = GL_TRUE;
__glGenUpdateTexture(gc, &pto->texture.map, pto->loadKey);
// For simplicity, we will assume that the texture size or format
// has changed, so delete the texture and re-realize the list.
//
// !!! If this becomes a performance issue, we *could* be smart about
// !!! detecting the cases where the texture size and format remains the
// !!! same. However, modifying a texture should really be done through
// !!! SubImage calls.
if (((__GLGENcontext *)gc)->pMcdState) {
if (pto->loadKey) {
GenMcdDeleteTexture((__GLGENcontext *)gc, pto->loadKey);
pto->loadKey = 0;
}
__glNamesLockArray(gc, gc->texture.shared->namesArray);
__glTexPriListRealize(gc);
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
}
}
void __glTexPriListUnloadAll(__GLcontext *gc)
{
__GLtextureObject *texobj;
__GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray);
texobj = gc->texture.shared->priorityListHighest;
while (texobj != NULL)
{
__glGenFreeTexture(gc, &texobj->texture.map, texobj->loadKey);
texobj->loadKey = 0;
texobj->resident = GL_FALSE;
texobj = texobj->lowerPriority;
}
}
/************************************************************************/
/*
** Initialize everything in a texture object except the textureMachine.
*/
static GLboolean FASTCALL InitTextureObject(__GLcontext *gc, __GLtextureObject *texobj,
GLuint name, GLuint targetIndex)
{
assert(NULL != texobj);
texobj->targetIndex = targetIndex;
texobj->resident = GL_FALSE;
texobj->texture.map.texobjs.name = name;
texobj->texture.map.texobjs.priority = 1.0;
texobj->lowerPriority = NULL;
texobj->higherPriority = NULL;
texobj->loadKey = 0;
#ifdef GL_EXT_paletted_texture
texobj->texture.map.paletteBaseFormat = GL_RGBA;
texobj->texture.map.paletteRequestedFormat = GL_RGBA;
texobj->texture.map.paletteSize = 1;
texobj->texture.map.paletteData =
(*gc->imports.malloc)(gc, sizeof(RGBQUAD));
if (texobj->texture.map.paletteData != NULL)
{
*(DWORD *)&texobj->texture.map.paletteData[0] = 0xffffffff;
return GL_TRUE;
}
else
{
return GL_FALSE;
}
#else
return GL_TRUE;
#endif
}
void __glCleanupTexture(__GLcontext *gc, __GLtexture *tex)
{
GLint level, maxLevel;
if (tex->level != NULL)
{
maxLevel = gc->constants.maxMipMapLevel;
for (level = 0; level < maxLevel; level++)
{
(*gc->imports.free)(gc, tex->level[level].buffer);
}
(*gc->imports.free)(gc, tex->level);
}
#ifdef GL_EXT_paletted_texture
if (tex->paletteData != NULL)
{
(*gc->imports.free)(gc, tex->paletteData);
}
#endif
}
GLvoid FASTCALL __glCleanupTexObj(__GLcontext *gc, void *pData)
{
__GLtextureObject *texobj = (__GLtextureObject *)pData;
// The last context to clean up shared state sets shared to NULL
// so don't depend on it being non-NULL
if (gc->texture.shared != NULL)
{
__glTexPriListRemove(gc, texobj, GL_TRUE);
}
__glCleanupTexture(gc, &texobj->texture.map);
(*gc->imports.free)(gc, texobj);
}
GLvoid WINAPIV __glDisposeTexObj(__GLcontext *gc, void *pData)
{
__GLtextureObject *texobj = (__GLtextureObject *)pData;
#if DBG
if (gc->texture.shared != NULL)
{
__GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray);
}
#endif
texobj->refcount--;
assert(texobj->refcount >= 0);
if (texobj->refcount == 0) {
__glCleanupTexObj(gc, pData);
}
}
static __GLnamesArrayTypeInfo texTypeInfo =
{
NULL, /* ptr to empty data struct */
sizeof(__GLtextureObject), /* dataSize */
__glDisposeTexObj, /* free callback */
NULL /* alloc callback */
};
void FASTCALL __glEarlyInitTextureState(__GLcontext *gc)
{
GLint numTextures, numEnvs;
GLint i,maxMipMapLevel;
__GLtextureObject *texobj;
/* XXX Override device dependent values */
gc->constants.numberOfTextures = 4;
gc->constants.maxTextureSize = 1 << (gc->constants.maxMipMapLevel - 1);
/* Allocate memory based on number of textures supported */
numTextures = gc->constants.numberOfTextures;
numEnvs = gc->constants.numberOfTextureEnvs;
gc->state.texture.texture = (__GLperTextureState*)
(*gc->imports.calloc)(gc, (size_t) numTextures,
sizeof(__GLperTextureState));
gc->texture.texture = (__GLperTextureMachine**)
(*gc->imports.calloc)(gc, (size_t) numTextures,
sizeof(__GLperTextureMachine*));
#ifdef NT
if (gc->texture.texture == NULL)
{
return;
}
#endif
gc->state.texture.env = (__GLtextureEnvState*)
(*gc->imports.calloc)(gc, (size_t) numEnvs,
sizeof(__GLtextureEnvState));
/*
** Init texture object structures.
** The default textures need to be turned into texture objects
** and stored away in the namesArray so they can be retrieved.
** Normally a texture object has only one textureMachine allocated
** with it because it supports only one object. The default texture
** texture object is special in that its textureMachine is an array
** of textureMachines, one for each target.
*/
gc->texture.shared =
(*gc->imports.calloc)(gc, 1, sizeof(__GLsharedTextureState));
if (gc->texture.shared == NULL)
{
return;
}
if (NULL == gc->texture.shared->namesArray) {
gc->texture.shared->namesArray = __glNamesNewArray(gc, &texTypeInfo);
#ifndef NT
assert(NULL != gc->texture.namesArray);
#endif
}
maxMipMapLevel = gc->constants.maxMipMapLevel;
/*
** Set up the dummy texture objects for the default textures.
** Because the default textures are not shared, they should
** not be hung off of the namesArray structure.
*/
gc->texture.defaultTextures = (__GLtextureObject *)(*gc->imports.calloc)
(gc, numTextures, sizeof(__GLtextureObject));
#ifndef NT
assert(NULL != gc->texture.defaultTextures);
#else
if (gc->texture.defaultTextures == NULL)
{
return;
}
#endif
/* allocate the boundTextures array */
gc->texture.boundTextures = (__GLtextureObject **)(*gc->imports.calloc)
(gc, numTextures, sizeof(__GLtextureObject *));
#ifndef NT
assert(NULL != gc->texture.boundTextures);
#else
if (gc->texture.boundTextures == NULL)
{
return;
}
#endif
texobj = gc->texture.defaultTextures;
for (i=0; i < numTextures; i++, texobj++) {
InitTextureObject(gc, texobj, 0/*name*/, i/*targetIndex*/);
assert(texobj->texture.map.texobjs.name == 0);
/*
** The refcount is unused because default textures aren't
** shared.
*/
texobj->refcount = 1;
/*
** Install the default textures into the gc.
*/
gc->texture.texture[i] = &(texobj->texture);
gc->texture.boundTextures[i] = texobj;
/* Allocate memory based on max mipmap level supported */
texobj->texture.map.level = (__GLmipMapLevel*)
(*gc->imports.calloc)(gc, (size_t) maxMipMapLevel,
sizeof(__GLmipMapLevel));
#ifndef NT
assert(NULL != texobj->texture.map.level);
#else
if (texobj->texture.map.level == NULL)
{
return;
}
#endif
__glTexPriListAdd(gc, texobj, GL_TRUE);
}
}
static __GLtextureBuffer * FASTCALL CreateProxyLevel(__GLcontext *gc, __GLtexture *tex,
GLint lod, GLint components,
GLsizei w, GLsizei h, GLint border,
GLint dim);
static __GLtextureBuffer * FASTCALL CreateLevel(__GLcontext *gc, __GLtexture *tex,
GLint lod, GLint components,
GLsizei w, GLsizei h, GLint border,
GLint dim);
/*
** This routine is used to initialize a texture object.
** Texture objects must be initialized exactly the way the default
** textures are initialized at startup of the library.
*/
void FASTCALL InitTextureMachine(__GLcontext *gc, GLuint targetIndex,
__GLperTextureMachine *ptm,
GLboolean allocLevels)
{
GLint level, maxMipMapLevel;
ptm->map.gc = gc;
/*
** Can't copy the params currently in the gc state.texture params,
** because they might not be at init conditions.
*/
ptm->map.params.sWrapMode = GL_REPEAT;
ptm->map.params.tWrapMode = GL_REPEAT;
ptm->map.params.minFilter = GL_NEAREST_MIPMAP_LINEAR;
ptm->map.params.magFilter = GL_LINEAR;
switch (targetIndex) {
case 0:
ptm->map.dim = 1;
ptm->map.createLevel = CreateProxyLevel;
break;
case 1:
ptm->map.dim = 2;
ptm->map.createLevel = CreateProxyLevel;
break;
case 2:
ptm->map.dim = 1;
ptm->map.createLevel = CreateLevel;
break;
case 3:
ptm->map.dim = 2;
ptm->map.createLevel = CreateLevel;
break;
default:
break;
}
maxMipMapLevel = gc->constants.maxMipMapLevel;
if (allocLevels)
{
ptm->map.level = (__GLmipMapLevel*)
(*gc->imports.calloc)(gc, (size_t) maxMipMapLevel,
sizeof(__GLmipMapLevel));
if (ptm->map.level == NULL)
{
return;
}
}
/* Init each texture level */
for (level = 0; level < maxMipMapLevel; level++) {
ptm->map.level[level].requestedFormat = 1;
}
}
void FASTCALL __glInitTextureState(__GLcontext *gc)
{
__GLperTextureState *pts;
__GLtextureEnvState *tes;
__GLperTextureMachine **ptm;
GLint i, numTextures, numEnvs;
numTextures = gc->constants.numberOfTextures;
numEnvs = gc->constants.numberOfTextureEnvs;
gc->state.current.texture.w = __glOne;
/* Init each texture environment state */
tes = &gc->state.texture.env[0];
for (i = 0; i < numEnvs; i++, tes++) {
tes->mode = GL_MODULATE;
}
/* Init each textures state */
pts = &gc->state.texture.texture[0];
ptm = gc->texture.texture;
for (i = 0; i < numTextures; i++, pts++, ptm++) {
/* Init client state */
pts->texobjs.name = 0;
pts->texobjs.priority = 1.0;
/* Init machine state */
InitTextureMachine(gc, i, *ptm, GL_FALSE);
pts->params = (*ptm)->map.params;
}
/* Init rest of texture state */
gc->state.texture.s.mode = GL_EYE_LINEAR;
gc->state.texture.s.eyePlaneEquation.x = __glOne;
gc->state.texture.s.objectPlaneEquation.x = __glOne;
gc->state.texture.t.mode = GL_EYE_LINEAR;
gc->state.texture.t.eyePlaneEquation.y = __glOne;
gc->state.texture.t.objectPlaneEquation.y = __glOne;
gc->state.texture.r.mode = GL_EYE_LINEAR;
gc->state.texture.q.mode = GL_EYE_LINEAR;
}
void __glFreeSharedTextureState(__GLcontext *gc)
{
#ifdef NT
__glNamesLockArray(gc, gc->texture.shared->namesArray);
gc->texture.shared->namesArray->refcount--;
if (gc->texture.shared->namesArray->refcount == 0)
{
__GLsharedTextureState *shared;
__glTexPriListUnloadAll(gc);
// NULL the shared pointer first, preventing its reuse
// after we unlock it. We need to unlock before we free it
// because the critical section will be cleaned up in the
// free
shared = gc->texture.shared;
gc->texture.shared = NULL;
__glNamesFreeArray(gc, shared->namesArray);
(*gc->imports.free)(gc, shared);
}
else
{
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
gc->texture.shared = NULL;
}
#else
gc->texture.namesArray->refcount--;
if (gc->texture.namesArray->refcount == 0)
{
__glNamesFreeArray(gc, gc->texture.namesArray);
}
gc->texture.namesArray = NULL;
#endif
}
void FASTCALL __glFreeTextureState(__GLcontext *gc)
{
__GLperTextureMachine **ptm;
GLint i, level, numTextures;
/*
** Clean up all allocs associated with texture objects.
*/
numTextures = gc->constants.numberOfTextures;
ptm = gc->texture.texture;
for (i = 0; i < numTextures; i++, ptm++)
{
// If the texture selected is a texture object, unbind it
// This protects any shared texture objects plus it selects
// the default texture so it gets cleaned up
if ((*ptm)->map.texobjs.name != 0)
{
__glBindTexture(gc, i, 0, GL_FALSE);
}
ASSERTOPENGL((*ptm)->map.texobjs.name == 0,
"Texture object still bound during cleanup");
// Pull the default texture out of the priority list.
// If we failed partway through initialization we may not
// have added the texture to the list so we need to check
// whether it is appropriate to call remove.
if (gc->texture.defaultTextures[i].texture.map.level != NULL)
{
__glTexPriListRemove(gc, gc->texture.defaultTextures+i, GL_FALSE);
}
__glCleanupTexture(gc, &(*ptm)->map);
}
__glFreeSharedTextureState(gc);
(*gc->imports.free)(gc, gc->texture.texture);
(*gc->imports.free)(gc, gc->texture.boundTextures);
(*gc->imports.free)(gc, gc->texture.defaultTextures);
(*gc->imports.free)(gc, gc->state.texture.texture);
(*gc->imports.free)(gc, gc->state.texture.env);
gc->texture.texture = NULL;
gc->texture.boundTextures = NULL;
gc->texture.defaultTextures = NULL;
gc->state.texture.texture = NULL;
gc->state.texture.env = NULL;
}
/************************************************************************/
void APIPRIVATE __glim_TexGenfv(GLenum coord, GLenum pname, const GLfloat pv[])
{
__GLtextureCoordState *tcs;
__GLfloat v[4];
__GLtransform *tr;
__GL_SETUP_NOT_IN_BEGIN();
switch (coord) {
case GL_S: tcs = &gc->state.texture.s; break;
case GL_T: tcs = &gc->state.texture.t; break;
case GL_R: tcs = &gc->state.texture.r; break;
case GL_Q: tcs = &gc->state.texture.q; break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_GEN_MODE:
switch ((GLenum) pv[0]) {
case GL_EYE_LINEAR:
case GL_OBJECT_LINEAR:
tcs->mode = (GLenum) pv[0];
break;
case GL_SPHERE_MAP:
if ((coord == GL_R) || (coord == GL_Q)) {
__glSetError(GL_INVALID_ENUM);
return;
}
tcs->mode = (GLenum) pv[0];
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
break;
case GL_OBJECT_PLANE:
tcs->objectPlaneEquation.x = pv[0];
tcs->objectPlaneEquation.y = pv[1];
tcs->objectPlaneEquation.z = pv[2];
tcs->objectPlaneEquation.w = pv[3];
break;
case GL_EYE_PLANE:
#ifdef NT
tr = gc->transform.modelView;
if (tr->updateInverse)
__glComputeInverseTranspose(gc, tr);
(*tr->inverseTranspose.xf4)(&tcs->eyePlaneEquation, pv,
&tr->inverseTranspose);
#else
/*XXX transform should not be in generic code */
v[0] = pv[0]; v[1] = pv[1]; v[2] = pv[2]; v[3] = pv[3];
tr = gc->transform.modelView;
if (tr->updateInverse) {
(*gc->procs.computeInverseTranspose)(gc, tr);
}
(*tr->inverseTranspose.xf4)(&tcs->eyePlaneEquation, v,
&tr->inverseTranspose);
#endif
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
__GL_DELAY_VALIDATE(gc);
}
#ifdef NT_DEADCODE_TEXGENF
void APIPRIVATE __glim_TexGenf(GLenum coord, GLenum pname, GLfloat f)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_GEN_MODE:
__glim_TexGenfv(coord, pname, &f);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXGENF
#ifdef NT_DEADCODE_TEXGENDV
void APIPRIVATE __glim_TexGendv(GLenum coord, GLenum pname, const GLdouble pv[])
{
__GLtextureCoordState *tcs;
__GLfloat v[4];
__GLtransform *tr;
__GL_SETUP_NOT_IN_BEGIN();
switch (coord) {
case GL_S: tcs = &gc->state.texture.s; break;
case GL_T: tcs = &gc->state.texture.t; break;
case GL_R: tcs = &gc->state.texture.r; break;
case GL_Q: tcs = &gc->state.texture.q; break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_GEN_MODE:
switch ((GLenum) pv[0]) {
case GL_EYE_LINEAR:
case GL_OBJECT_LINEAR:
tcs->mode = (GLenum) pv[0];
break;
case GL_SPHERE_MAP:
if ((coord == GL_R) || (coord == GL_Q)) {
__glSetError(GL_INVALID_ENUM);
return;
}
tcs->mode = (GLenum) pv[0];
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
break;
case GL_OBJECT_PLANE:
tcs->objectPlaneEquation.x = pv[0];
tcs->objectPlaneEquation.y = pv[1];
tcs->objectPlaneEquation.z = pv[2];
tcs->objectPlaneEquation.w = pv[3];
break;
case GL_EYE_PLANE:
/*XXX transform should not be in generic code */
v[0] = pv[0]; v[1] = pv[1]; v[2] = pv[2]; v[3] = pv[3];
tr = gc->transform.modelView;
if (tr->updateInverse) {
(*gc->procs.computeInverseTranspose)(gc, tr);
}
(*tr->inverseTranspose.xf4)(&tcs->eyePlaneEquation, v,
&tr->inverseTranspose);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
__GL_DELAY_VALIDATE(gc);
}
#endif // NT_DEADCODE_TEXGENDV
#ifdef NT_DEADCODE_TEXGEND
void APIPRIVATE __glim_TexGend(GLenum coord, GLenum pname, GLdouble d)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_GEN_MODE:
__glim_TexGendv(coord, pname, &d);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXGEND
#ifdef NT_DEADCODE_TEXGENIV
void APIPRIVATE __glim_TexGeniv(GLenum coord, GLenum pname, const GLint pv[])
{
__GLtextureCoordState *tcs;
__GLfloat v[4];
__GLtransform *tr;
__GL_SETUP_NOT_IN_BEGIN();
switch (coord) {
case GL_S: tcs = &gc->state.texture.s; break;
case GL_T: tcs = &gc->state.texture.t; break;
case GL_R: tcs = &gc->state.texture.r; break;
case GL_Q: tcs = &gc->state.texture.q; break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_GEN_MODE:
switch ((GLenum) pv[0]) {
case GL_EYE_LINEAR:
case GL_OBJECT_LINEAR:
tcs->mode = (GLenum) pv[0];
break;
case GL_SPHERE_MAP:
if ((coord == GL_R) || (coord == GL_Q)) {
__glSetError(GL_INVALID_ENUM);
return;
}
tcs->mode = (GLenum) pv[0];
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
break;
case GL_OBJECT_PLANE:
tcs->objectPlaneEquation.x = pv[0];
tcs->objectPlaneEquation.y = pv[1];
tcs->objectPlaneEquation.z = pv[2];
tcs->objectPlaneEquation.w = pv[3];
break;
case GL_EYE_PLANE:
/*XXX transform should not be in generic code */
v[0] = pv[0]; v[1] = pv[1]; v[2] = pv[2]; v[3] = pv[3];
tr = gc->transform.modelView;
if (tr->updateInverse) {
(*gc->procs.computeInverseTranspose)(gc, tr);
}
(*tr->inverseTranspose.xf4)(&tcs->eyePlaneEquation, v,
&tr->inverseTranspose);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
__GL_DELAY_VALIDATE(gc);
}
#endif // NT_DEADCODE_TEXGENIV
#ifdef NT_DEADCODE_TEXGENI
void APIPRIVATE __glim_TexGeni(GLenum coord, GLenum pname, GLint i)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_GEN_MODE:
__glim_TexGeniv(coord, pname, &i);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXGENI
#ifdef NT_DEADCODE_SIZE
GLint FASTCALL __glTexGendv_size(GLenum e)
{
switch (e) {
case GL_TEXTURE_GEN_MODE:
return 1;
case GL_OBJECT_PLANE:
case GL_EYE_PLANE:
return 4;
default:
return -1;
}
}
GLint FASTCALL __glTexGenfv_size(GLenum e)
{
return __glTexGendv_size(e);
}
GLint FASTCALL __glTexGeniv_size(GLenum e)
{
return __glTexGendv_size(e);
}
#endif // NT_DEADCODE_SIZE
/************************************************************************/
void APIPRIVATE __glim_TexParameterfv(GLenum target, GLenum pname, const GLfloat pv[])
{
__GLtextureParamState *pts;
GLenum e;
GLboolean bTexState = GL_TRUE;
__GL_SETUP_NOT_IN_BEGIN();
pts = __glLookUpTextureParams(gc, target);
if (!pts) {
bad_enum:
bTexState = GL_FALSE;
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_WRAP_S:
switch (e = (GLenum) pv[0]) {
case GL_REPEAT:
case GL_CLAMP:
pts->sWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_WRAP_T:
switch (e = (GLenum) pv[0]) {
case GL_REPEAT:
case GL_CLAMP:
pts->tWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MIN_FILTER:
switch (e = (GLenum) pv[0]) {
case GL_NEAREST:
case GL_LINEAR:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
pts->minFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MAG_FILTER:
switch (e = (GLenum) pv[0]) {
case GL_NEAREST:
case GL_LINEAR:
pts->magFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_BORDER_COLOR:
__glClampColorf(gc, &pts->borderColor, pv);
break;
case GL_TEXTURE_PRIORITY:
{
__GLtextureObject *texobj;
__GLtextureObjectState *ptos;
ptos = __glLookUpTextureTexobjs(gc, target);
ptos->priority = Clampf(pv[0], __glZero, __glOne);
texobj = __glLookUpTextureObject(gc, target);
texobj->texture.map.texobjs.priority = ptos->priority;
__glTexPriListChangePriority(gc, texobj, GL_TRUE);
}
bTexState = GL_FALSE;
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
#ifdef _MCD_
if (bTexState &&
gc->texture.currentTexture &&
(pts == &gc->texture.currentTexture->params))
{
MCD_STATE_DIRTY(gc, TEXTURE);
}
#endif
}
#ifdef NT_DEADCODE_TEXPARAMETERF
void APIPRIVATE __glim_TexParameterf(GLenum target, GLenum pname, GLfloat f)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_PRIORITY:
__glim_TexParameterfv(target, pname, &f);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXPARAMTERF
void APIPRIVATE __glim_TexParameteriv(GLenum target, GLenum pname, const GLint pv[])
{
__GLtextureParamState *pts;
GLenum e;
GLboolean bTexState = GL_TRUE;
__GL_SETUP_NOT_IN_BEGIN();
pts = __glLookUpTextureParams(gc, target);
if (!pts) {
bad_enum:
bTexState = GL_FALSE;
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_WRAP_S:
switch (e = (GLenum) pv[0]) {
case GL_REPEAT:
case GL_CLAMP:
pts->sWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_WRAP_T:
switch (e = (GLenum) pv[0]) {
case GL_REPEAT:
case GL_CLAMP:
pts->tWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MIN_FILTER:
switch (e = (GLenum) pv[0]) {
case GL_NEAREST:
case GL_LINEAR:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
pts->minFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MAG_FILTER:
switch (e = (GLenum) pv[0]) {
case GL_NEAREST:
case GL_LINEAR:
pts->magFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_BORDER_COLOR:
__glClampColori(gc, &pts->borderColor, pv);
break;
case GL_TEXTURE_PRIORITY:
{
__GLfloat priority;
__GLtextureObjectState *ptos;
__GLtextureObject *texobj;
ptos = __glLookUpTextureTexobjs(gc, target);
priority = Clampf(__GL_I_TO_FLOAT(pv[0]), __glZero, __glOne);
ptos->priority = priority;
texobj = __glLookUpTextureObject(gc, target);
texobj->texture.map.texobjs.priority = priority;
__glTexPriListChangePriority(gc, texobj, GL_TRUE);
}
bTexState = GL_FALSE;
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
#ifdef _MCD_
if (bTexState &&
gc->texture.currentTexture &&
(pts == &gc->texture.currentTexture->params))
{
MCD_STATE_DIRTY(gc, TEXTURE);
}
#endif
}
#ifdef NT_DEADCODE_TEXPARAMETERI
void APIPRIVATE __glim_TexParameteri(GLenum target, GLenum pname, GLint i)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_PRIORITY:
__glim_TexParameteriv(target, pname, &i);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXPARAMTERI
#ifdef NT_DEADCODE_SIZE
GLint FASTCALL __glTexParameterfv_size(GLenum e)
{
switch (e) {
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_PRIORITY:
return 1;
case GL_TEXTURE_BORDER_COLOR:
return 4;
default:
return -1;
}
}
GLint FASTCALL __glTexParameteriv_size(GLenum e)
{
return __glTexParameterfv_size(e);
}
#endif // NT_DEADCODE_SIZE
/************************************************************************/
void APIPRIVATE __glim_TexEnvfv(GLenum target, GLenum pname, const GLfloat pv[])
{
__GLtextureEnvState *tes;
GLenum e;
__GL_SETUP_NOT_IN_BEGIN();
if(target < GL_TEXTURE_ENV) {
__glSetError(GL_INVALID_ENUM);
return;
}
target -= GL_TEXTURE_ENV;
#ifdef NT
// target is unsigned!
if (target >= (GLenum) gc->constants.numberOfTextureEnvs) {
#else
if (target >= gc->constants.numberOfTextureEnvs) {
#endif // NT
bad_enum:
__glSetError(GL_INVALID_ENUM);
return;
}
tes = &gc->state.texture.env[target];
switch (pname) {
case GL_TEXTURE_ENV_MODE:
switch(e = (GLenum) pv[0]) {
case GL_MODULATE:
case GL_DECAL:
case GL_BLEND:
case GL_REPLACE:
tes->mode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_ENV_COLOR:
__glClampAndScaleColorf(gc, &tes->color, pv);
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
}
#ifdef NT_DEADCODE_TEXENVF
void APIPRIVATE __glim_TexEnvf(GLenum target, GLenum pname, GLfloat f)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_ENV_MODE:
__glim_TexEnvfv(target, pname, &f);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXENVF
void APIPRIVATE __glim_TexEnviv(GLenum target, GLenum pname, const GLint pv[])
{
__GLtextureEnvState *tes;
GLenum e;
__GL_SETUP_NOT_IN_BEGIN();
if(target < GL_TEXTURE_ENV) {
__glSetError(GL_INVALID_ENUM);
return;
}
target -= GL_TEXTURE_ENV;
#ifdef NT
// target is unsigned!
if (target >= (GLenum) gc->constants.numberOfTextureEnvs) {
#else
if (target >= gc->constants.numberOfTextureEnvs) {
#endif // NT
bad_enum:
__glSetError(GL_INVALID_ENUM);
return;
}
tes = &gc->state.texture.env[target];
switch (pname) {
case GL_TEXTURE_ENV_MODE:
switch(e = (GLenum) pv[0]) {
case GL_MODULATE:
case GL_DECAL:
case GL_BLEND:
case GL_REPLACE:
tes->mode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_ENV_COLOR:
__glClampAndScaleColori(gc, &tes->color, pv);
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
}
#ifdef NT_DEADCODE_TEXENVI
void APIPRIVATE __glim_TexEnvi(GLenum target, GLenum pname, GLint i)
{
/* Accept only enumerants that correspond to single values */
switch (pname) {
case GL_TEXTURE_ENV_MODE:
__glim_TexEnviv(target, pname, &i);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // NT_DEADCODE_TEXENVI
#ifdef NT_DEADCODE_SIZE
GLint FASTCALL __glTexEnvfv_size(GLenum e)
{
switch (e) {
case GL_TEXTURE_ENV_MODE:
return 1;
case GL_TEXTURE_ENV_COLOR:
return 4;
default:
return -1;
}
}
GLint FASTCALL __glTexEnviv_size(GLenum e)
{
return __glTexEnvfv_size(e);
}
#endif // NT_DEADCODE_SIZE
/************************************************************************/
/*
** Get a texture element out of the one component texture buffer
** with no border.
*/
void FASTCALL __glExtractTexelL(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->luminance = tex->params.borderColor.r;
} else {
image = level->buffer + ((row << level->widthLog2) + col);
result->luminance = image[0];
}
}
/*
** Get a texture element out of the two component texture buffer
** with no border.
*/
void FASTCALL __glExtractTexelLA(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->luminance = tex->params.borderColor.r;
result->alpha = tex->params.borderColor.a;
} else {
image = level->buffer + ((row << level->widthLog2) + col) * 2;
result->luminance = image[0];
result->alpha = image[1];
}
}
/*
** Get a texture element out of the three component texture buffer
** with no border.
*/
void FASTCALL __glExtractTexelRGB(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
} else {
image = level->buffer + ((row << level->widthLog2) + col) * 3;
result->r = image[0];
result->g = image[1];
result->b = image[2];
}
}
/*
** Get a texture element out of the four component texture buffer
** with no border.
*/
void FASTCALL __glExtractTexelRGBA(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
result->alpha = tex->params.borderColor.a;
} else {
image = level->buffer + ((row << level->widthLog2) + col) * 4;
result->r = image[0];
result->g = image[1];
result->b = image[2];
result->alpha = image[3];
}
}
void FASTCALL __glExtractTexelA(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->alpha = tex->params.borderColor.a;
} else {
image = level->buffer + ((row << level->widthLog2) + col);
result->alpha = image[0];
}
}
void FASTCALL __glExtractTexelI(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->intensity = tex->params.borderColor.r;
} else {
image = level->buffer + ((row << level->widthLog2) + col);
result->intensity = image[0];
}
}
void FASTCALL __glExtractTexelBGR8(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
} else {
image = (GLubyte *)level->buffer + ((row << level->widthLog2) + col) * 4;
result->r = __GL_UB_TO_FLOAT(image[2]);
result->g = __GL_UB_TO_FLOAT(image[1]);
result->b = __GL_UB_TO_FLOAT(image[0]);
}
}
void FASTCALL __glExtractTexelBGRA8(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
result->alpha = tex->params.borderColor.a;
} else {
image = (GLubyte *)level->buffer + ((row << level->widthLog2) + col) * 4;
result->r = __GL_UB_TO_FLOAT(image[2]);
result->g = __GL_UB_TO_FLOAT(image[1]);
result->b = __GL_UB_TO_FLOAT(image[0]);
result->alpha = __GL_UB_TO_FLOAT(image[3]);
}
}
#ifdef GL_EXT_paletted_texture
void FASTCALL __glExtractTexelPI8BGRA(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
RGBQUAD *rgb;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
result->alpha = tex->params.borderColor.a;
} else {
image = (GLubyte *)level->buffer + ((row << level->widthLog2) + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
result->alpha = __GL_UB_TO_FLOAT(rgb->rgbReserved);
}
}
void FASTCALL __glExtractTexelPI8BGR(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
RGBQUAD *rgb;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
} else {
image = (GLubyte *)level->buffer + ((row << level->widthLog2) + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
}
}
void FASTCALL __glExtractTexelPI16BGRA(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLushort *image;
RGBQUAD *rgb;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
result->alpha = tex->params.borderColor.a;
} else {
image = (GLushort *)level->buffer + ((row << level->widthLog2) + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
result->alpha = __GL_UB_TO_FLOAT(rgb->rgbReserved);
}
}
void FASTCALL __glExtractTexelPI16BGR(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLushort *image;
RGBQUAD *rgb;
if ((row < 0) || (col < 0) || (row >= level->height2) ||
(col >= level->width2)) {
/*
** Use border color when the texture supplies no border.
*/
result->r = tex->params.borderColor.r;
result->g = tex->params.borderColor.g;
result->b = tex->params.borderColor.b;
} else {
image = (GLushort *)level->buffer + ((row << level->widthLog2) + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
}
}
#endif // GL_EXT_paletted_texture
/*
** Get a texture element out of the one component texture buffer
** with a border.
*/
void FASTCALL __glExtractTexelL_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = level->buffer + (row * level->width + col);
result->luminance = image[0];
}
/*
** Get a texture element out of the two component texture buffer
** with a border.
*/
void FASTCALL __glExtractTexelLA_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = level->buffer + (row * level->width + col) * 2;
result->luminance = image[0];
result->alpha = image[1];
}
/*
** Get a texture element out of the three component texture buffer
** with a border.
*/
void FASTCALL __glExtractTexelRGB_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = level->buffer + (row * level->width + col) * 3;
result->r = image[0];
result->g = image[1];
result->b = image[2];
}
/*
** Get a texture element out of the four component texture buffer
** with a border.
*/
void FASTCALL __glExtractTexelRGBA_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = level->buffer + (row * level->width + col) * 4;
result->r = image[0];
result->g = image[1];
result->b = image[2];
result->alpha = image[3];
}
void FASTCALL __glExtractTexelA_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = level->buffer + (row * level->width + col);
result->alpha = image[0];
}
void FASTCALL __glExtractTexelI_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLtextureBuffer *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = level->buffer + (row * level->width + col);
result->intensity = image[0];
}
void FASTCALL __glExtractTexelBGR8_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = (GLubyte *)level->buffer + (row * level->width + col) * 4;
result->r = __GL_UB_TO_FLOAT(image[2]);
result->g = __GL_UB_TO_FLOAT(image[1]);
result->b = __GL_UB_TO_FLOAT(image[0]);
}
void FASTCALL __glExtractTexelBGRA8_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
#ifdef __GL_LINT
tex = tex;
#endif
row++;
col++;
image = (GLubyte *)level->buffer + (row * level->width + col) * 4;
result->r = __GL_UB_TO_FLOAT(image[2]);
result->g = __GL_UB_TO_FLOAT(image[1]);
result->b = __GL_UB_TO_FLOAT(image[0]);
result->alpha = __GL_UB_TO_FLOAT(image[3]);
}
#ifdef GL_EXT_paletted_texture
void FASTCALL __glExtractTexelPI8BGRA_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
RGBQUAD *rgb;
row++;
col++;
image = (GLubyte *)level->buffer + (row * level->width + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
result->alpha = __GL_UB_TO_FLOAT(rgb->rgbReserved);
}
void FASTCALL __glExtractTexelPI8BGR_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLubyte *image;
RGBQUAD *rgb;
row++;
col++;
image = (GLubyte *)level->buffer + (row * level->width + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
}
void FASTCALL __glExtractTexelPI16BGRA_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLushort *image;
RGBQUAD *rgb;
row++;
col++;
image = (GLushort *)level->buffer + (row * level->width + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
result->alpha = __GL_UB_TO_FLOAT(rgb->rgbReserved);
}
void FASTCALL __glExtractTexelPI16BGR_B(__GLmipMapLevel *level, __GLtexture *tex,
GLint row, GLint col, __GLtexel *result)
{
__GLcontext *gc = tex->gc;
GLushort *image;
RGBQUAD *rgb;
row++;
col++;
image = (GLushort *)level->buffer + (row * level->width + col);
rgb = &tex->paletteData[image[0] & (tex->paletteSize-1)];
result->r = __GL_UB_TO_FLOAT(rgb->rgbRed);
result->g = __GL_UB_TO_FLOAT(rgb->rgbGreen);
result->b = __GL_UB_TO_FLOAT(rgb->rgbBlue);
}
#endif // GL_EXT_paletted_texture
/************************************************************************/
GLboolean FASTCALL __glIsTextureConsistent(__GLcontext *gc, GLenum name)
{
__GLtexture *tex = __glLookUpTexture(gc, name);
__GLtextureParamState *params = __glLookUpTextureParams(gc, name);
GLint i, width, height;
GLint maxLevel;
GLint border;
GLenum baseFormat;
GLenum requestedFormat;
if ((tex->level[0].width == 0) || (tex->level[0].height == 0)) {
return GL_FALSE;
}
border = tex->level[0].border;
width = tex->level[0].width - border*2;
height = tex->level[0].height - border*2;
maxLevel = gc->constants.maxMipMapLevel;
baseFormat = tex->level[0].baseFormat;
requestedFormat = tex->level[0].requestedFormat;
switch(gc->state.texture.env[0].mode) {
case GL_DECAL:
if (baseFormat != GL_RGB && baseFormat != GL_RGBA) {
return GL_FALSE;
}
break;
default:
break;
}
/* If not-mipmapping, we are ok */
switch (params->minFilter) {
case GL_NEAREST:
case GL_LINEAR:
return GL_TRUE;
default:
break;
}
i = 0;
while (++i < maxLevel) {
if (width == 1 && height == 1) break;
width >>= 1;
if (width == 0) width = 1;
height >>= 1;
if (height == 0) height = 1;
if (tex->level[i].border != border ||
(GLenum)tex->level[i].requestedFormat != requestedFormat ||
tex->level[i].width != width + border*2 ||
tex->level[i].height != height + border*2)
{
return GL_FALSE;
}
}
return GL_TRUE;
}
static __GLtexture *CheckTexImageArgs(__GLcontext *gc, GLenum target, GLint lod,
GLint components, GLint border,
GLenum format, GLenum type, GLint dim)
{
__GLtexture *tex = __glLookUpTexture(gc, target);
if (!tex || (tex->dim != dim)) {
bad_enum:
__glSetError(GL_INVALID_ENUM);
return 0;
}
switch (type) {
case GL_BITMAP:
if (format != GL_COLOR_INDEX) goto bad_enum;
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
break;
default:
goto bad_enum;
}
switch (format) {
case GL_COLOR_INDEX: case GL_RED:
case GL_GREEN: case GL_BLUE:
case GL_ALPHA: case GL_RGB:
case GL_RGBA: case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
#ifdef GL_EXT_bgra
case GL_BGRA_EXT:
case GL_BGR_EXT:
#endif
break;
default:
goto bad_enum;
}
if ((lod < 0) || (lod >= gc->constants.maxMipMapLevel)) {
__glSetError(GL_INVALID_VALUE);
return 0;
}
switch (components) {
case GL_LUMINANCE: case 1:
case GL_LUMINANCE4: case GL_LUMINANCE8:
case GL_LUMINANCE12: case GL_LUMINANCE16:
break;
case GL_LUMINANCE_ALPHA: case 2:
case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16:
break;
case GL_RGB: case 3:
case GL_R3_G3_B2: case GL_RGB4:
case GL_RGB5: case GL_RGB8:
case GL_RGB10: case GL_RGB12:
case GL_RGB16:
break;
case GL_RGBA: case 4:
case GL_RGBA2: case GL_RGBA4:
case GL_RGBA8: case GL_RGBA12:
case GL_RGBA16: case GL_RGB5_A1:
case GL_RGB10_A2:
break;
case GL_ALPHA:
case GL_ALPHA4: case GL_ALPHA8:
case GL_ALPHA12: case GL_ALPHA16:
break;
case GL_INTENSITY:
case GL_INTENSITY4: case GL_INTENSITY8:
case GL_INTENSITY12: case GL_INTENSITY16:
break;
#ifdef GL_EXT_paletted_texture
case GL_COLOR_INDEX1_EXT: case GL_COLOR_INDEX2_EXT:
case GL_COLOR_INDEX4_EXT: case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX12_EXT: case GL_COLOR_INDEX16_EXT:
if (format != GL_COLOR_INDEX)
{
__glSetError(GL_INVALID_OPERATION);
return NULL;
}
break;
#endif
default:
goto bad_enum;
}
if ((border < 0) || (border > 1)) {
#ifdef NT
__glSetError(GL_INVALID_VALUE);
return 0;
#else
goto bad_enum;
#endif
}
return tex;
}
#ifdef GL_EXT_paletted_texture
// Attempt to set the extraction function. If no palette is set,
// this can't be done
void __glSetPaletteLevelExtract8(__GLtexture *tex, __GLmipMapLevel *lp,
GLint border)
{
if (tex->paletteBaseFormat == GL_RGB)
{
if (border)
{
lp->extract = __glExtractTexelPI8BGR_B;
}
else
{
lp->extract = __glExtractTexelPI8BGR;
}
}
else if (tex->paletteBaseFormat == GL_RGBA)
{
if (border)
{
lp->extract = __glExtractTexelPI8BGRA_B;
}
else
{
lp->extract = __glExtractTexelPI8BGRA;
}
}
#if DBG
else
{
ASSERTOPENGL(tex->paletteBaseFormat == GL_NONE,
"Unexpected paletteBaseFormat\n");
}
#endif
}
void __glSetPaletteLevelExtract16(__GLtexture *tex, __GLmipMapLevel *lp,
GLint border)
{
if (tex->paletteBaseFormat == GL_RGB)
{
if (border)
{
lp->extract = __glExtractTexelPI16BGR_B;
}
else
{
lp->extract = __glExtractTexelPI16BGR;
}
}
else if (tex->paletteBaseFormat == GL_RGBA)
{
if (border)
{
lp->extract = __glExtractTexelPI16BGRA_B;
}
else
{
lp->extract = __glExtractTexelPI16BGRA;
}
}
#if DBG
else
{
ASSERTOPENGL(tex->paletteBaseFormat == GL_NONE,
"Unexpected paletteBaseFormat\n");
}
#endif
}
#endif // GL_EXT_paletted_texture
static GLint ComputeTexLevelSize(__GLcontext *gc, __GLtexture *tex,
__GLmipMapLevel *lp, GLint lod,
GLint components, GLsizei w, GLsizei h,
GLint border, GLint dim)
{
GLint texelStorageSize;
if ((w - border*2) > gc->constants.maxTextureSize ||
(h - border*2) > gc->constants.maxTextureSize)
{
return -1;
}
lp->requestedFormat = (GLenum) components;
lp->redSize = 0;
lp->greenSize = 0;
lp->blueSize = 0;
lp->alphaSize = 0;
lp->luminanceSize = 0;
lp->intensitySize = 0;
switch (lp->requestedFormat) {
case GL_LUMINANCE: case 1:
case GL_LUMINANCE4: case GL_LUMINANCE8:
case GL_LUMINANCE12: case GL_LUMINANCE16:
lp->baseFormat = GL_LUMINANCE;
lp->internalFormat = GL_LUMINANCE;
lp->luminanceSize = 24;
texelStorageSize = 1 * sizeof(__GLfloat);
if (border) {
lp->extract = __glExtractTexelL_B;
} else {
lp->extract = __glExtractTexelL;
}
break;
case GL_LUMINANCE_ALPHA: case 2:
case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16:
lp->baseFormat = GL_LUMINANCE_ALPHA;
lp->internalFormat = GL_LUMINANCE_ALPHA;
lp->luminanceSize = 24;
lp->alphaSize = 24;
texelStorageSize = 2 * sizeof(__GLfloat);
if (border) {
lp->extract = __glExtractTexelLA_B;
} else {
lp->extract = __glExtractTexelLA;
}
break;
case GL_RGB: case 3:
case GL_R3_G3_B2: case GL_RGB4:
case GL_RGB5: case GL_RGB8:
lp->baseFormat = GL_RGB;
lp->internalFormat = GL_BGR_EXT;
lp->redSize = 8;
lp->greenSize = 8;
lp->blueSize = 8;
// Kept as 32-bit quantities for alignment
texelStorageSize = 4 * sizeof(GLubyte);
if (border) {
lp->extract = __glExtractTexelBGR8_B;
} else {
lp->extract = __glExtractTexelBGR8;
}
break;
case GL_RGB10: case GL_RGB12:
case GL_RGB16:
lp->baseFormat = GL_RGB;
lp->internalFormat = GL_RGB;
lp->redSize = 24;
lp->greenSize = 24;
lp->blueSize = 24;
texelStorageSize = 3 * sizeof(__GLfloat);
if (border) {
lp->extract = __glExtractTexelRGB_B;
} else {
lp->extract = __glExtractTexelRGB;
}
break;
case GL_RGBA: case 4:
case GL_RGBA2: case GL_RGBA4:
case GL_RGBA8: case GL_RGB5_A1:
lp->baseFormat = GL_RGBA;
lp->internalFormat = GL_BGRA_EXT;
lp->redSize = 8;
lp->greenSize = 8;
lp->blueSize = 8;
lp->alphaSize = 8;
texelStorageSize = 4 * sizeof(GLubyte);
if (border) {
lp->extract = __glExtractTexelBGRA8_B;
} else {
lp->extract = __glExtractTexelBGRA8;
}
break;
case GL_RGBA12: case GL_RGBA16:
case GL_RGB10_A2:
lp->baseFormat = GL_RGBA;
lp->internalFormat = GL_RGBA;
lp->redSize = 24;
lp->greenSize = 24;
lp->blueSize = 24;
lp->alphaSize = 24;
texelStorageSize = 4 * sizeof(__GLfloat);
if (border) {
lp->extract = __glExtractTexelRGBA_B;
} else {
lp->extract = __glExtractTexelRGBA;
}
break;
case GL_ALPHA:
case GL_ALPHA4: case GL_ALPHA8:
case GL_ALPHA12: case GL_ALPHA16:
lp->baseFormat = GL_ALPHA;
lp->internalFormat = GL_ALPHA;
lp->alphaSize = 24;
texelStorageSize = 1 * sizeof(__GLfloat);
if (border) {
lp->extract = __glExtractTexelA_B;
} else {
lp->extract = __glExtractTexelA;
}
break;
case GL_INTENSITY:
case GL_INTENSITY4: case GL_INTENSITY8:
case GL_INTENSITY12: case GL_INTENSITY16:
lp->baseFormat = GL_INTENSITY;
lp->internalFormat = GL_INTENSITY;
lp->intensitySize = 24;
texelStorageSize = 1 * sizeof(__GLfloat);
if (border) {
lp->extract = __glExtractTexelI_B;
} else {
lp->extract = __glExtractTexelI;
}
break;
#ifdef GL_EXT_paletted_texture
case GL_COLOR_INDEX1_EXT:
case GL_COLOR_INDEX2_EXT:
case GL_COLOR_INDEX4_EXT:
case GL_COLOR_INDEX8_EXT:
// Inherit the current palette data type
lp->baseFormat = tex->paletteBaseFormat;
lp->internalFormat = GL_COLOR_INDEX8_EXT;
texelStorageSize = sizeof(GLubyte);
__glSetPaletteLevelExtract8(tex, lp, border);
break;
case GL_COLOR_INDEX12_EXT:
case GL_COLOR_INDEX16_EXT:
// Inherit the current palette data type
lp->baseFormat = tex->paletteBaseFormat;
lp->internalFormat = GL_COLOR_INDEX16_EXT;
texelStorageSize = sizeof(GLushort);
__glSetPaletteLevelExtract16(tex, lp, border);
break;
#endif
default:
break;
}
return (w * h * texelStorageSize);
}
static __GLtextureBuffer *FASTCALL CreateProxyLevel(__GLcontext *gc, __GLtexture *tex,
GLint lod, GLint components,
GLsizei w, GLsizei h, GLint border,
GLint dim)
{
__GLmipMapLevel templ, *lp = &tex->level[lod];
GLint size;
size = ComputeTexLevelSize(gc, tex, &templ, lod, components,
w, h, border, dim);
if (size < 0) {
/* Proxy allocation failed */
lp->width = 0;
lp->height = 0;
lp->border = 0;
lp->requestedFormat = 0;
lp->baseFormat = 0;
lp->internalFormat = 0;
lp->redSize = 0;
lp->greenSize = 0;
lp->blueSize = 0;
lp->alphaSize = 0;
lp->luminanceSize = 0;
lp->intensitySize = 0;
lp->extract = __glNopExtract;
} else {
/* Proxy allocation succeeded */
lp->width = w;
lp->height = h;
lp->border = border;
lp->requestedFormat = templ.requestedFormat;
lp->baseFormat = templ.baseFormat;
lp->internalFormat = templ.internalFormat;
lp->redSize = templ.redSize;
lp->greenSize = templ.greenSize;
lp->blueSize = templ.blueSize;
lp->alphaSize = templ.alphaSize;
lp->luminanceSize = templ.luminanceSize;
lp->intensitySize = templ.intensitySize;
lp->extract = templ.extract;
}
return 0;
}
static __GLtextureBuffer *FASTCALL CreateLevel(__GLcontext *gc, __GLtexture *tex,
GLint lod, GLint components,
GLsizei w, GLsizei h, GLint border,
GLint dim)
{
__GLmipMapLevel templ, *lp = &tex->level[lod];
GLint size;
#ifdef NT
__GLtextureBuffer* pbuffer;
#endif
size = ComputeTexLevelSize(gc, tex, &templ, lod, components,
w, h, border, dim);
if (size < 0) {
__glSetError(GL_INVALID_VALUE);
return 0;
}
#ifdef NT
pbuffer = (__GLtextureBuffer*)
(*gc->imports.realloc)(gc, lp->buffer, (size_t)size);
if (!pbuffer && size != 0)
(*gc->imports.free)(gc, lp->buffer);
lp->buffer = pbuffer;
#else
lp->buffer = (__GLtextureBuffer*)
(*gc->imports.realloc)(gc, lp->buffer, (size_t)size);
#endif // NT
if (lp->buffer) {
/* Fill in new level info */
lp->width = w;
lp->height = h;
lp->width2 = w - border*2;
lp->widthLog2 = (GLint)Log2(lp->width2);
lp->height2 = h - border*2;
lp->heightLog2 = (GLint)Log2(lp->height2);
lp->width2f = lp->width2;
lp->height2f = lp->height2;
lp->border = border;
lp->requestedFormat = templ.requestedFormat;
lp->baseFormat = templ.baseFormat;
lp->internalFormat = templ.internalFormat;
lp->redSize = templ.redSize;
lp->greenSize = templ.greenSize;
lp->blueSize = templ.blueSize;
lp->alphaSize = templ.alphaSize;
lp->luminanceSize = templ.luminanceSize;
lp->intensitySize = templ.intensitySize;
lp->extract = templ.extract;
} else {
/* Out of memory or the texture level is being freed */
lp->width = 0;
lp->height = 0;
lp->width2 = 0;
lp->height2 = 0;
lp->widthLog2 = 0;
lp->heightLog2 = 0;
lp->border = 0;
lp->requestedFormat = 0;
lp->baseFormat = 0;
lp->internalFormat = 0;
lp->redSize = 0;
lp->greenSize = 0;
lp->blueSize = 0;
lp->alphaSize = 0;
lp->luminanceSize = 0;
lp->intensitySize = 0;
lp->extract = __glNopExtract;
}
if (lod == 0) {
tex->p = lp->heightLog2;
if (lp->widthLog2 > lp->heightLog2) {
tex->p = lp->widthLog2;
}
}
return lp->buffer;
}
void FASTCALL __glInitTextureStore(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
GLenum internalFormat)
{
spanInfo->dstSkipPixels = 0;
spanInfo->dstSkipLines = 0;
spanInfo->dstSwapBytes = GL_FALSE;
spanInfo->dstLsbFirst = GL_TRUE;
spanInfo->dstLineLength = spanInfo->width;
switch(internalFormat) {
case GL_LUMINANCE:
spanInfo->dstFormat = GL_RED;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_LUMINANCE_ALPHA:
spanInfo->dstFormat = __GL_RED_ALPHA;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_RGB:
spanInfo->dstFormat = GL_RGB;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_RGBA:
spanInfo->dstFormat = GL_RGBA;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_ALPHA:
spanInfo->dstFormat = GL_ALPHA;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_INTENSITY:
spanInfo->dstFormat = GL_RED;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_BGR_EXT:
// Be a little tricky here to pad the data out
// to 32 bits
spanInfo->dstFormat = GL_BGRA_EXT;
spanInfo->dstType = GL_UNSIGNED_BYTE;
spanInfo->dstAlignment = 4;
break;
case GL_BGRA_EXT:
spanInfo->dstFormat = GL_BGRA_EXT;
spanInfo->dstType = GL_UNSIGNED_BYTE;
spanInfo->dstAlignment = 4;
break;
#ifdef GL_EXT_paletted_texture
case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX16_EXT:
spanInfo->dstFormat = GL_COLOR_INDEX;
spanInfo->dstType =
internalFormat == GL_COLOR_INDEX8_EXT ?
GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
spanInfo->dstAlignment = 1;
break;
#endif
}
}
/*
** Used for extraction from textures. "packed" is set to GL_TRUE if this
** image is being pulled out of a display list, and GL_FALSE if it is
** being pulled directly out of an application.
*/
void FASTCALL __glInitTextureUnpack(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
GLint width, GLint height, GLenum format,
GLenum type, const GLvoid *buf,
GLenum internalFormat, GLboolean packed)
{
spanInfo->x = 0;
spanInfo->zoomx = __glOne;
spanInfo->realWidth = spanInfo->width = width;
spanInfo->height = height;
spanInfo->srcFormat = format;
spanInfo->srcType = type;
spanInfo->srcImage = buf;
__glInitTextureStore(gc, spanInfo, internalFormat);
__glLoadUnpackModes(gc, spanInfo, packed);
}
/*
** Return GL_TRUE if the given range (length or width/height) is a legal
** power of 2, taking into account the border. The range is not allowed
** to be negative either.
*/
static GLboolean FASTCALL IsLegalRange(__GLcontext *gc, GLsizei r, GLint border)
{
#ifdef __GL_LINT
gc = gc;
#endif
r -= border * 2;
if ((r < 0) || (r & (r - 1))) {
__glSetError(GL_INVALID_VALUE);
return GL_FALSE;
}
return GL_TRUE;
}
__GLtexture *FASTCALL __glCheckTexImage1DArgs(__GLcontext *gc, GLenum target, GLint lod,
GLint components, GLsizei length,
GLint border, GLenum format, GLenum type)
{
__GLtexture *tex;
/* Check arguments and get the right texture being changed */
tex = CheckTexImageArgs(gc, target, lod, components, border,
format, type, 1);
if (!tex) {
return 0;
}
if (!IsLegalRange(gc, length, border)) {
return 0;
}
return tex;
}
__GLtexture *FASTCALL __glCheckTexImage2DArgs(__GLcontext *gc, GLenum target, GLint lod,
GLint components, GLsizei w, GLsizei h,
GLint border, GLenum format, GLenum type)
{
__GLtexture *tex;
/* Check arguments and get the right texture being changed */
tex = CheckTexImageArgs(gc, target, lod, components, border,
format, type, 2);
if (!tex) {
return 0;
}
if (!IsLegalRange(gc, w, border)) {
return 0;
}
if (!IsLegalRange(gc, h, border)) {
return 0;
}
return tex;
}
#ifdef NT
void APIPRIVATE __glim_TexImage1D(GLenum target, GLint lod,
GLint components, GLsizei length,
GLint border, GLenum format,
GLenum type, const GLvoid *buf, GLboolean _IsDlist)
#else
void APIPRIVATE __glim_TexImage1D(GLenum target, GLint lod,
GLint components, GLsizei length,
GLint border, GLenum format,
GLenum type, const GLvoid *buf)
#endif
{
__GLtexture *tex;
__GLtextureBuffer *dest;
__GLpixelSpanInfo spanInfo;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
/* Check arguments and get the right texture being changed */
tex = __glCheckTexImage1DArgs(gc, target, lod, components, length,
border, format, type);
if (!tex) {
return;
}
/* Allocate memory for the level data */
dest = (*tex->createLevel)(gc, tex, lod, components,
length, 1+border*2, border, 1);
/* Copy image data */
if (buf && dest) {
spanInfo.dstImage = dest;
#ifdef NT
__glInitTextureUnpack(gc, &spanInfo, length, 1, format, type, buf,
tex->level[lod].internalFormat,
(GLboolean) (_IsDlist ? GL_TRUE : GL_FALSE));
#else
__glInitTextureUnpack(gc, &spanInfo, length, 1, format, type, buf,
tex->level[lod].internalFormat, GL_FALSE);
#endif
spanInfo.dstSkipLines += border;
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadImage(gc, GL_TEXTURE_1D);
#endif
}
/* Might have just disabled texturing... */
__GL_DELAY_VALIDATE(gc);
}
#ifndef NT
void __gllei_TexImage1D(__GLcontext *gc, GLenum target, GLint lod,
GLint components, GLsizei length, GLint border,
GLenum format, GLenum type, const GLubyte *image)
{
__GLtexture *tex;
__GLtextureBuffer *dest;
__GLpixelSpanInfo spanInfo;
GLuint beginMode;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
beginMode = gc->beginMode;
if (beginMode != __GL_NOT_IN_BEGIN) {
if (beginMode == __GL_NEED_VALIDATE) {
(*gc->procs.validate)(gc);
gc->beginMode = __GL_NOT_IN_BEGIN;
} else {
__glSetError(GL_INVALID_OPERATION);
return;
}
}
/* Check arguments and get the right texture being changed */
tex = __glCheckTexImage1DArgs(gc, target, lod, components, length,
border, format, type);
if (!tex) {
return;
}
/* Allocate memory for the level data */
dest = (*tex->createLevel)(gc, tex, lod, components,
length, 1+border*2, border, 1);
/* Copy image data */
if (image && dest) {
spanInfo.dstImage = dest;
__glInitTextureUnpack(gc, &spanInfo, length, 1, format, type, image,
tex->level[lod].internalFormat, GL_TRUE);
spanInfo.dstSkipLines += border;
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadImage(gc, GL_TEXTURE_1D);
#endif
}
/* Might have just disabled texturing... */
__GL_DELAY_VALIDATE(gc);
}
#endif // !NT
#ifdef NT_DEADCODE_NOT_USED
GLint FASTCALL __glTexImage1D_size(GLenum format, GLenum type, GLsizei w)
{
GLint elements, esize;
if (w < 0) return -1;
switch (format) {
case GL_COLOR_INDEX:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
elements = 1;
break;
case GL_LUMINANCE_ALPHA:
elements = 2;
break;
case GL_RGB:
#ifdef GL_EXT_bgra
case GL_BGR_EXT:
#endif
elements = 3;
break;
case GL_RGBA:
#ifdef GL_EXT_bgra
case GL_BGRA_EXT:
#endif
elements = 4;
break;
default:
return -1;
}
switch (type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
esize = 1;
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
esize = 2;
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
esize = 4;
break;
default:
return -1;
}
return (elements * esize * w);
}
#endif // NT_DEADCODE_NOT_USED
/************************************************************************/
#ifdef NT
void APIPRIVATE __glim_TexImage2D(GLenum target, GLint lod, GLint components,
GLsizei w, GLsizei h, GLint border, GLenum format,
GLenum type, const GLvoid *buf, GLboolean _IsDlist)
#else
void APIPRIVATE __glim_TexImage2D(GLenum target, GLint lod, GLint components,
GLsizei w, GLsizei h, GLint border, GLenum format,
GLenum type, const GLvoid *buf)
#endif
{
__GLtexture *tex;
__GLtextureBuffer *dest;
__GLpixelSpanInfo spanInfo;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
/* Check arguments and get the right texture being changed */
tex = __glCheckTexImage2DArgs(gc, target, lod, components, w, h,
border, format, type);
if (!tex) {
return;
}
/* Allocate memory for the level data */
dest = (*tex->createLevel)(gc, tex, lod, components, w, h, border, 2);
/* Copy image data */
if (buf && dest) {
spanInfo.dstImage = dest;
#ifdef NT
__glInitTextureUnpack(gc, &spanInfo, w, h, format, type, buf,
(GLenum) tex->level[lod].internalFormat,
(GLboolean) (_IsDlist ? GL_TRUE : GL_FALSE));
#else
__glInitTextureUnpack(gc, &spanInfo, w, h, format, type, buf,
tex->level[lod].internalFormat, GL_FALSE);
#endif
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadImage(gc, GL_TEXTURE_2D);
#endif
}
/* Might have just disabled texturing... */
__GL_DELAY_VALIDATE(gc);
}
#ifndef NT
void __gllei_TexImage2D(__GLcontext *gc, GLenum target, GLint lod,
GLint components, GLsizei w, GLsizei h,
GLint border, GLenum format, GLenum type,
const GLubyte *image)
{
__GLtexture *tex;
__GLtextureBuffer *dest;
__GLpixelSpanInfo spanInfo;
GLuint beginMode;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
beginMode = gc->beginMode;
if (beginMode != __GL_NOT_IN_BEGIN) {
if (beginMode == __GL_NEED_VALIDATE) {
(*gc->procs.validate)(gc);
gc->beginMode = __GL_NOT_IN_BEGIN;
} else {
__glSetError(GL_INVALID_OPERATION);
return;
}
}
/* Check arguments and get the right texture being changed */
tex = __glCheckTexImage2DArgs(gc, target, lod, components, w, h,
border, format, type);
if (!tex) {
return;
}
/* Allocate memory for the level data */
dest = (*tex->createLevel)(gc, tex, lod, components, w, h, border, 2);
/* Copy image data */
if (image && dest) {
spanInfo.dstImage = dest;
__glInitTextureUnpack(gc, &spanInfo, w, h, format, type, image,
tex->level[lod].internalFormat, GL_TRUE);
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadImage(gc, GL_TEXTURE_2D);
#endif
}
/* Might have just disabled texturing... */
__GL_DELAY_VALIDATE(gc);
}
#endif // !NT
#ifdef NT_DEADCODE_NOT_USED
GLint __glTexImage2D_size(GLenum format, GLenum type, GLsizei w, GLsizei h)
{
GLint elements, esize;
if (w < 0) return -1;
if (h < 0) return -1;
switch (format) {
case GL_COLOR_INDEX:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
elements = 1;
break;
case GL_LUMINANCE_ALPHA:
elements = 2;
break;
case GL_RGB:
#ifdef GL_EXT_bgra
case GL_BGR_EXT:
#endif
elements = 3;
break;
case GL_RGBA:
#ifdef GL_EXT_bgra
case GL_BGRA_EXT:
#endif
elements = 4;
break;
default:
return -1;
}
switch (type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
esize = 1;
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
esize = 2;
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
esize = 4;
break;
default:
return -1;
}
return (elements * esize * w * h);
}
#endif // NT_DEADCODE_NOT_USED
/************************************************************************/
// Repeats the given float value in float [0, scale) and converts to
// int. The repeat count is an integer which is a power of two
#define REPEAT_SCALED_VAL(val, scale, repeat) \
(__GL_FLOAT_GEZ(val) ? (FTOL((val) * (scale)) & ((repeat)-1)) : \
((repeat)-1)-(FTOL(-(val) * (scale)) & ((repeat)-1)))
// Clamps the given float value to float [0, scale) and converts to int
#define CLAMP_SCALED_VAL(val, scale) \
(__GL_FLOAT_LEZ(val) ? 0 : \
__GL_FLOAT_COMPARE_PONE(val, >=) ? (scale)-1 : \
FTOL((val) * (scale)))
/*
** Return texel nearest the s coordinate. s is converted to u
** implicitly during this step.
*/
void FASTCALL __glNearestFilter1(__GLcontext *gc, __GLtexture *tex,
__GLmipMapLevel *lp, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLtexel *result)
{
GLint col;
__GLfloat w2f;
CHOP_ROUND_ON();
#ifdef __GL_LINT
gc = gc;
color = color;
t = t;
#endif
/* Find texel index */
w2f = lp->width2f;
if (tex->params.sWrapMode == GL_REPEAT) {
col = REPEAT_SCALED_VAL(s, w2f, lp->width2);
} else {
col = CLAMP_SCALED_VAL(s, w2f);
}
CHOP_ROUND_OFF();
/* Lookup texel */
(*lp->extract)(lp, tex, 0, col, result);
}
/*
** Return texel nearest the s&t coordinates. s&t are converted to u&v
** implicitly during this step.
*/
void FASTCALL __glNearestFilter2(__GLcontext *gc, __GLtexture *tex,
__GLmipMapLevel *lp, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLtexel *result)
{
GLint row, col;
__GLfloat w2f, h2f;
CHOP_ROUND_ON();
#ifdef __GL_LINT
gc = gc;
color = color;
#endif
/* Find texel column address */
w2f = lp->width2f;
if (tex->params.sWrapMode == GL_REPEAT) {
col = REPEAT_SCALED_VAL(s, w2f, lp->width2);
} else {
col = CLAMP_SCALED_VAL(s, w2f);
}
/* Find texel row address */
h2f = lp->height2f;
if (tex->params.tWrapMode == GL_REPEAT) {
row = REPEAT_SCALED_VAL(t, h2f, lp->height2);
} else {
row = CLAMP_SCALED_VAL(t, h2f);
}
CHOP_ROUND_OFF();
/* Lookup texel */
(*lp->extract)(lp, tex, row, col, result);
}
/*
** Return texel which is a linear combination of texels near s.
*/
void FASTCALL __glLinearFilter1(__GLcontext *gc, __GLtexture *tex,
__GLmipMapLevel *lp, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLtexel *result)
{
__GLfloat u, alpha, omalpha;
GLint col0, col1;
__GLtexel t0, t1;
#ifdef __GL_LINT
color = color;
t = t;
#endif
/* Find col0 and col1 */
u = s * lp->width2;
if (tex->params.sWrapMode == GL_REPEAT) {
u -= __glHalf;
col0 = ((GLint) __GL_FLOORF(u)) & (lp->width2 - 1);
col1 = (col0 + 1) & (lp->width2 - 1);
} else {
if (u < __glZero) u = __glZero;
else if (u > lp->width2) u = lp->width2;
u -= __glHalf;
col0 = (GLint) __GL_FLOORF(u);
col1 = col0 + 1;
}
/* Compute alpha and beta */
alpha = __GL_FRAC(u);
/* Calculate the final texel value as a combination of the two texels */
(*lp->extract)(lp, tex, 0, col0, &t0);
(*lp->extract)(lp, tex, 0, col1, &t1);
omalpha = __glOne - alpha;
switch (lp->baseFormat) {
case GL_LUMINANCE_ALPHA:
result->alpha = omalpha * t0.alpha + alpha * t1.alpha;
/* FALLTHROUGH */
case GL_LUMINANCE:
result->luminance = omalpha * t0.luminance + alpha * t1.luminance;
break;
case GL_RGBA:
result->alpha = omalpha * t0.alpha + alpha * t1.alpha;
/* FALLTHROUGH */
case GL_RGB:
result->r = omalpha * t0.r + alpha * t1.r;
result->g = omalpha * t0.g + alpha * t1.g;
result->b = omalpha * t0.b + alpha * t1.b;
break;
case GL_ALPHA:
result->alpha = omalpha * t0.alpha + alpha * t1.alpha;
break;
case GL_INTENSITY:
result->intensity = omalpha * t0.intensity + alpha * t1.intensity;
break;
}
}
/*
** Return texel which is a linear combination of texels near s&t.
*/
void FASTCALL __glLinearFilter2(__GLcontext *gc, __GLtexture *tex,
__GLmipMapLevel *lp, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLtexel *result)
{
__GLfloat u, v, alpha, beta, half, w2f, h2f;
GLint col0, row0, col1, row1;
__GLtexel t00, t01, t10, t11;
__GLfloat omalpha, ombeta, m00, m01, m10, m11;
#ifdef __GL_LINT
color = color;
#endif
/* Find col0, col1 */
w2f = lp->width2f;
u = s * w2f;
half = __glHalf;
if (tex->params.sWrapMode == GL_REPEAT) {
GLint w2mask = lp->width2 - 1;
u -= half;
col0 = ((GLint) __GL_FLOORF(u)) & w2mask;
col1 = (col0 + 1) & w2mask;
} else {
if (u < __glZero) u = __glZero;
else if (u > w2f) u = w2f;
u -= half;
col0 = (GLint) __GL_FLOORF(u);
col1 = col0 + 1;
}
/* Find row0, row1 */
h2f = lp->height2f;
v = t * h2f;
if (tex->params.tWrapMode == GL_REPEAT) {
GLint h2mask = lp->height2 - 1;
v -= half;
row0 = ((GLint) __GL_FLOORF(v)) & h2mask;
row1 = (row0 + 1) & h2mask;
} else {
if (v < __glZero) v = __glZero;
else if (v > h2f) v = h2f;
v -= half;
row0 = (GLint) __GL_FLOORF(v);
row1 = row0 + 1;
}
/* Compute alpha and beta */
alpha = __GL_FRAC(u);
beta = __GL_FRAC(v);
/* Calculate the final texel value as a combination of the square chosen */
(*lp->extract)(lp, tex, row0, col0, &t00);
(*lp->extract)(lp, tex, row0, col1, &t10);
(*lp->extract)(lp, tex, row1, col0, &t01);
(*lp->extract)(lp, tex, row1, col1, &t11);
omalpha = __glOne - alpha;
ombeta = __glOne - beta;
m00 = omalpha * ombeta;
m10 = alpha * ombeta;
m01 = omalpha * beta;
m11 = alpha * beta;
switch (lp->baseFormat) {
case GL_LUMINANCE_ALPHA:
/* FALLTHROUGH */
result->alpha = m00*t00.alpha + m10*t10.alpha + m01*t01.alpha
+ m11*t11.alpha;
case GL_LUMINANCE:
result->luminance = m00*t00.luminance + m10*t10.luminance
+ m01*t01.luminance + m11*t11.luminance;
break;
case GL_RGBA:
/* FALLTHROUGH */
result->alpha = m00*t00.alpha + m10*t10.alpha + m01*t01.alpha
+ m11*t11.alpha;
case GL_RGB:
result->r = m00*t00.r + m10*t10.r + m01*t01.r + m11*t11.r;
result->g = m00*t00.g + m10*t10.g + m01*t01.g + m11*t11.g;
result->b = m00*t00.b + m10*t10.b + m01*t01.b + m11*t11.b;
break;
case GL_ALPHA:
result->alpha = m00*t00.alpha + m10*t10.alpha + m01*t01.alpha
+ m11*t11.alpha;
break;
case GL_INTENSITY:
result->intensity = m00*t00.intensity + m10*t10.intensity
+ m01*t01.intensity + m11*t11.intensity;
break;
}
}
/*
** Linear min/mag filter
*/
void FASTCALL __glLinearFilter(__GLcontext *gc, __GLtexture *tex, __GLfloat lod,
__GLcolor *color, __GLfloat s, __GLfloat t,
__GLtexel *result)
{
#ifdef __GL_LINT
lod = lod;
#endif
(*tex->linear)(gc, tex, &tex->level[0], color, s, t, result);
}
/*
** Nearest min/mag filter
*/
void FASTCALL __glNearestFilter(__GLcontext *gc, __GLtexture *tex, __GLfloat lod,
__GLcolor *color, __GLfloat s, __GLfloat t,
__GLtexel *result)
{
#ifdef __GL_LINT
lod = lod;
#endif
(*tex->nearest)(gc, tex, &tex->level[0], color, s, t, result);
}
/*
** Apply minification rules to find the texel value.
*/
void FASTCALL __glNMNFilter(__GLcontext *gc, __GLtexture *tex, __GLfloat lod,
__GLcolor *color, __GLfloat s, __GLfloat t,
__GLtexel *result)
{
__GLmipMapLevel *lp;
GLint p, d;
if (lod <= ((__GLfloat)0.5)) {
d = 0;
} else {
p = tex->p;
d = (GLint) (lod + ((__GLfloat)0.49995)); /* NOTE: .5 minus epsilon */
if (d > p) {
d = p;
}
}
lp = &tex->level[d];
(*tex->nearest)(gc, tex, lp, color, s, t, result);
}
/*
** Apply minification rules to find the texel value.
*/
void FASTCALL __glLMNFilter(__GLcontext *gc, __GLtexture *tex, __GLfloat lod,
__GLcolor *color, __GLfloat s, __GLfloat t,
__GLtexel *result)
{
__GLmipMapLevel *lp;
GLint p, d;
if (lod <= ((__GLfloat) 0.5)) {
d = 0;
} else {
p = tex->p;
d = (GLint) (lod + ((__GLfloat) 0.49995)); /* NOTE: .5 minus epsilon */
if (d > p) {
d = p;
}
}
lp = &tex->level[d];
(*tex->linear)(gc, tex, lp, color, s, t, result);
}
/*
** Apply minification rules to find the texel value.
*/
void FASTCALL __glNMLFilter(__GLcontext *gc, __GLtexture *tex, __GLfloat lod,
__GLcolor *color, __GLfloat s, __GLfloat t,
__GLtexel *result)
{
__GLmipMapLevel *lp;
GLint p, d;
__GLtexel td, td1;
__GLfloat f, omf;
p = tex->p;
d = ((GLint) lod) + 1;
if (d > p || d < 0) {
/* Clamp d to last available mipmap */
lp = &tex->level[p];
(*tex->nearest)(gc, tex, lp, color, s, t, result);
} else {
(*tex->nearest)(gc, tex, &tex->level[d], color, s, t, &td);
(*tex->nearest)(gc, tex, &tex->level[d-1], color, s, t, &td1);
f = __GL_FRAC(lod);
omf = __glOne - f;
switch (tex->level[0].baseFormat) {
case GL_LUMINANCE_ALPHA:
result->alpha = omf * td1.alpha + f * td.alpha;
/* FALLTHROUGH */
case GL_LUMINANCE:
result->luminance = omf * td1.luminance + f * td.luminance;
break;
case GL_RGBA:
result->alpha = omf * td1.alpha + f * td.alpha;
/* FALLTHROUGH */
case GL_RGB:
result->r = omf * td1.r + f * td.r;
result->g = omf * td1.g + f * td.g;
result->b = omf * td1.b + f * td.b;
break;
case GL_ALPHA:
result->alpha = omf * td1.alpha + f * td.alpha;
break;
case GL_INTENSITY:
result->intensity = omf * td1.intensity + f * td.intensity;
break;
}
}
}
/*
** Apply minification rules to find the texel value.
*/
void FASTCALL __glLMLFilter(__GLcontext *gc, __GLtexture *tex, __GLfloat lod,
__GLcolor *color, __GLfloat s, __GLfloat t,
__GLtexel *result)
{
__GLmipMapLevel *lp;
GLint p, d;
__GLtexel td, td1;
__GLfloat f, omf;
p = tex->p;
d = ((GLint) lod) + 1;
if (d > p || d < 0) {
/* Clamp d to last available mipmap */
lp = &tex->level[p];
(*tex->linear)(gc, tex, lp, color, s, t, result);
} else {
(*tex->linear)(gc, tex, &tex->level[d], color, s, t, &td);
(*tex->linear)(gc, tex, &tex->level[d-1], color, s, t, &td1);
f = __GL_FRAC(lod);
omf = __glOne - f;
switch (tex->level[0].baseFormat) {
case GL_LUMINANCE_ALPHA:
result->alpha = omf * td1.alpha + f * td.alpha;
/* FALLTHROUGH */
case GL_LUMINANCE:
result->luminance = omf * td1.luminance + f * td.luminance;
break;
case GL_RGBA:
result->alpha = omf * td1.alpha + f * td.alpha;
/* FALLTHROUGH */
case GL_RGB:
result->r = omf * td1.r + f * td.r;
result->g = omf * td1.g + f * td.g;
result->b = omf * td1.b + f * td.b;
break;
case GL_ALPHA:
result->alpha = omf * td1.alpha + f * td.alpha;
break;
case GL_INTENSITY:
result->intensity = omf * td1.intensity + f * td.intensity;
break;
}
}
}
/***********************************************************************/
/* 1 Component modulate */
void FASTCALL __glTextureModulateL(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->r = texel->luminance * color->r;
color->g = texel->luminance * color->g;
color->b = texel->luminance * color->b;
}
/* 2 Component modulate */
void FASTCALL __glTextureModulateLA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->r = texel->luminance * color->r;
color->g = texel->luminance * color->g;
color->b = texel->luminance * color->b;
color->a = texel->alpha * color->a;
}
/* 3 Component modulate */
void FASTCALL __glTextureModulateRGB(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->r = texel->r * color->r;
color->g = texel->g * color->g;
color->b = texel->b * color->b;
}
/* 4 Component modulate */
void FASTCALL __glTextureModulateRGBA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->r = texel->r * color->r;
color->g = texel->g * color->g;
color->b = texel->b * color->b;
color->a = texel->alpha * color->a;
}
/* Alpha modulate */
void FASTCALL __glTextureModulateA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->a = texel->alpha * color->a;
}
/* Intensity modulate */
void FASTCALL __glTextureModulateI(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->r = texel->intensity * color->r;
color->g = texel->intensity * color->g;
color->b = texel->intensity * color->b;
color->a = texel->intensity * color->a;
}
/***********************************************************************/
/* 3 Component decal */
void FASTCALL __glTextureDecalRGB(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->r = texel->r * gc->frontBuffer.redScale;
color->g = texel->g * gc->frontBuffer.greenScale;
color->b = texel->b * gc->frontBuffer.blueScale;
}
/* 4 Component decal */
void FASTCALL __glTextureDecalRGBA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
__GLfloat a = texel->alpha;
__GLfloat oma = __glOne - a;
color->r = oma * color->r
+ a * texel->r * gc->frontBuffer.redScale;
color->g = oma * color->g
+ a * texel->g * gc->frontBuffer.greenScale;
color->b = oma * color->b
+ a * texel->b * gc->frontBuffer.blueScale;
}
/***********************************************************************/
/* 1 Component blend */
void FASTCALL __glTextureBlendL(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
__GLfloat l = texel->luminance;
__GLfloat oml = __glOne - l;
__GLcolor *cc = &gc->state.texture.env[0].color;
color->r = oml * color->r + l * cc->r;
color->g = oml * color->g + l * cc->g;
color->b = oml * color->b + l * cc->b;
}
/* 2 Component blend */
void FASTCALL __glTextureBlendLA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
__GLfloat l = texel->luminance;
__GLfloat oml = __glOne - l;
__GLcolor *cc = &gc->state.texture.env[0].color;
color->r = oml * color->r + l * cc->r;
color->g = oml * color->g + l * cc->g;
color->b = oml * color->b + l * cc->b;
color->a = texel->alpha * color->a;
}
/* 3 Component blend */
void FASTCALL __glTextureBlendRGB(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
__GLfloat r = texel->r;
__GLfloat g = texel->g;
__GLfloat b = texel->b;
__GLcolor *cc = &gc->state.texture.env[0].color;
color->r = (__glOne - r) * color->r + r * cc->r;
color->g = (__glOne - g) * color->g + g * cc->g;
color->b = (__glOne - b) * color->b + b * cc->b;
}
/* 4 Component blend */
void FASTCALL __glTextureBlendRGBA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
__GLfloat r = texel->r;
__GLfloat g = texel->g;
__GLfloat b = texel->b;
__GLcolor *cc = &gc->state.texture.env[0].color;
color->r = (__glOne - r) * color->r + r * cc->r;
color->g = (__glOne - g) * color->g + g * cc->g;
color->b = (__glOne - b) * color->b + b * cc->b;
color->a = texel->alpha * color->a;
}
/* Alpha blend */
void FASTCALL __glTextureBlendA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
#ifdef __GL_LINT
gc = gc;
#endif
color->a = texel->alpha * color->a;
}
/* Intensity blend */
void FASTCALL __glTextureBlendI(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
__GLfloat i = texel->intensity;
__GLfloat omi = __glOne - i;
__GLcolor *cc = &gc->state.texture.env[0].color;
color->r = omi * color->r + i * cc->r;
color->g = omi * color->g + i * cc->g;
color->b = omi * color->b + i * cc->b;
color->a = omi * color->a + i * cc->a;
}
/***********************************************************************/
/* 1 Component replace */
void FASTCALL __glTextureReplaceL(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->r = texel->luminance * gc->frontBuffer.redScale;
color->g = texel->luminance * gc->frontBuffer.greenScale;
color->b = texel->luminance * gc->frontBuffer.blueScale;
}
/* 2 Component replace */
void FASTCALL __glTextureReplaceLA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->r = texel->luminance * gc->frontBuffer.redScale;
color->g = texel->luminance * gc->frontBuffer.greenScale;
color->b = texel->luminance * gc->frontBuffer.blueScale;
color->a = texel->alpha * gc->frontBuffer.alphaScale;
}
/* 3 Component replace */
void FASTCALL __glTextureReplaceRGB(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->r = texel->r * gc->frontBuffer.redScale;
color->g = texel->g * gc->frontBuffer.greenScale;
color->b = texel->b * gc->frontBuffer.blueScale;
}
/* 4 Component replace */
void FASTCALL __glTextureReplaceRGBA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->r = texel->r * gc->frontBuffer.redScale;
color->g = texel->g * gc->frontBuffer.greenScale;
color->b = texel->b * gc->frontBuffer.blueScale;
color->a = texel->alpha * gc->frontBuffer.alphaScale;
}
/* Alpha replace */
void FASTCALL __glTextureReplaceA(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->a = texel->alpha * gc->frontBuffer.alphaScale;
}
/* Intensity replace */
void FASTCALL __glTextureReplaceI(__GLcontext *gc, __GLcolor *color, __GLtexel *texel)
{
color->r = texel->intensity * gc->frontBuffer.redScale;
color->g = texel->intensity * gc->frontBuffer.greenScale;
color->b = texel->intensity * gc->frontBuffer.blueScale;
color->a = texel->intensity * gc->frontBuffer.alphaScale;
}
/***********************************************************************/
__GLfloat __glNopPolygonRho(__GLcontext *gc, const __GLshade *sh,
__GLfloat s, __GLfloat t, __GLfloat winv)
{
#ifdef __GL_LINT
gc = gc;
sh = sh;
s = s;
t = t;
winv = winv;
#endif
return __glZero;
}
/*
** Compute the "rho" (level of detail) parameter used by the texturing code.
** Instead of fully computing the derivatives compute nearby texture coordinates
** and discover the derivative. The incoming s & t arguments have not
** been divided by winv yet.
*/
__GLfloat __glComputePolygonRho(__GLcontext *gc, const __GLshade *sh,
__GLfloat s, __GLfloat t, __GLfloat qw)
{
__GLfloat w0, w1, p0, p1;
__GLfloat pupx, pupy, pvpx, pvpy;
__GLfloat px, py, one;
__GLtexture *tex = gc->texture.currentTexture;
if( qw == (__GLfloat) 0.0 ) {
return (__GLfloat) 0.0;
}
/* Compute partial of u with respect to x */
one = __glOne;
w0 = one / (qw - sh->dqwdx);
w1 = one / (qw + sh->dqwdx);
p0 = (s - sh->dsdx) * w0;
p1 = (s + sh->dsdx) * w1;
pupx = (p1 - p0) * tex->level[0].width2f;
/* Compute partial of v with repsect to y */
p0 = (t - sh->dtdx) * w0;
p1 = (t + sh->dtdx) * w1;
pvpx = (p1 - p0) * tex->level[0].height2f;
/* Compute partial of u with respect to y */
w0 = one / (qw - sh->dqwdy);
w1 = one / (qw + sh->dqwdy);
p0 = (s - sh->dsdy) * w0;
p1 = (s + sh->dsdy) * w1;
pupy = (p1 - p0) * tex->level[0].width2f;
/* Figure partial of u&v with repsect to y */
p0 = (t - sh->dtdy) * w0;
p1 = (t + sh->dtdy) * w1;
pvpy = (p1 - p0) * tex->level[0].height2f;
/* Finally, figure sum of squares */
px = pupx * pupx + pvpx * pvpx;
py = pupy * pupy + pvpy * pvpy;
/* Return largest value as the level of detail */
if (px > py) {
return px * ((__GLfloat) 0.25);
} else {
return py * ((__GLfloat) 0.25);
}
}
__GLfloat __glNopLineRho(__GLcontext *gc, __GLfloat s, __GLfloat t,
__GLfloat wInv)
{
#ifdef __GL_LINT
gc = gc;
s = s;
t = t;
wInv = wInv;
#endif
return __glZero;
}
__GLfloat __glComputeLineRho(__GLcontext *gc, __GLfloat s, __GLfloat t,
__GLfloat wInv)
{
__GLfloat pspx, pspy, ptpx, ptpy;
__GLfloat pupx, pupy, pvpx, pvpy;
__GLfloat temp, pu, pv;
__GLfloat magnitude, invMag, invMag2;
__GLfloat dx, dy;
__GLfloat s0w0, s1w1, t0w0, t1w1, w1Inv, w0Inv;
const __GLvertex *v0 = gc->line.options.v0;
const __GLvertex *v1 = gc->line.options.v1;
/* Compute the length of the line (its magnitude) */
dx = v1->window.x - v0->window.x;
dy = v1->window.y - v0->window.y;
magnitude = __GL_SQRTF(dx*dx + dy*dy);
invMag = __glOne / magnitude;
invMag2 = invMag * invMag;
w0Inv = v0->window.w;
w1Inv = v1->window.w;
s0w0 = v0->texture.x * w0Inv;
t0w0 = v0->texture.y * w0Inv;
s1w1 = v1->texture.x * w1Inv;
t1w1 = v1->texture.y * w1Inv;
/* Compute s partials */
temp = ((s1w1 - s0w0) - s * (w1Inv - w0Inv)) / wInv;
pspx = temp * dx * invMag2;
pspy = temp * dy * invMag2;
/* Compute t partials */
temp = ((t1w1 - t0w0) - t * (w1Inv - w0Inv)) / wInv;
ptpx = temp * dx * invMag2;
ptpy = temp * dy * invMag2;
pupx = pspx * gc->texture.currentTexture->level[0].width2;
pupy = pspy * gc->texture.currentTexture->level[0].width2;
pvpx = ptpx * gc->texture.currentTexture->level[0].height2;
pvpy = ptpy * gc->texture.currentTexture->level[0].height2;
/* Now compute rho */
pu = pupx * dx + pupy * dy;
pu = pu * pu;
pv = pvpx * dx + pvpy * dy;
pv = pv * pv;
return (pu + pv) * invMag2;
}
/************************************************************************/
/*
** Fast texture a fragment assumes that rho is noise - this is true
** when no mipmapping is being done and the min and mag filters are
** the same.
*/
void __glFastTextureFragment(__GLcontext *gc, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLfloat rho)
{
__GLtexture *tex = gc->texture.currentTexture;
__GLtexel texel;
#ifdef __GL_LINT
rho = rho;
#endif
(*tex->magnify)(gc, tex, __glZero, color, s, t, &texel);
(*tex->env)(gc, color, &texel);
}
/*
** Non-mipmapping texturing function.
*/
void __glTextureFragment(__GLcontext *gc, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLfloat rho)
{
__GLtexture *tex = gc->texture.currentTexture;
__GLtexel texel;
if (rho <= tex->c) {
(*tex->magnify)(gc, tex, __glZero, color, s, t, &texel);
} else {
(*tex->minnify)(gc, tex, __glZero, color, s, t, &texel);
}
/* Now apply texture environment to get final color */
(*tex->env)(gc, color, &texel);
}
void __glMipMapFragment(__GLcontext *gc, __GLcolor *color,
__GLfloat s, __GLfloat t, __GLfloat rho)
{
__GLtexture *tex = gc->texture.currentTexture;
__GLtexel texel;
/* In the spec c is given in terms of lambda.
** Here c is compared to rho (really rho^2) and adjusted accordingly.
*/
if (rho <= tex->c) {
/* NOTE: rho is ignored by magnify proc */
(*tex->magnify)(gc, tex, rho, color, s, t, &texel);
} else {
if (rho) {
#if 0
__GLfloat oldrho;
#endif
__GLfloat twotolev;
GLuint irho, lev;
/* Convert rho to lambda */
#if 0
oldrho = __GL_LOGF(rho) * (__GL_M_LN2_INV * 0.5);
#endif
/* this is an approximation of log base 2 */
irho = rho;
lev = 0;
while( irho >>= 1 ) lev++;
twotolev = 1<<lev;
rho = (lev + ( (rho-twotolev) / twotolev ) ) * 0.5;
} else {
rho = __glZero;
}
(*tex->minnify)(gc, tex, rho, color, s, t, &texel);
}
/* Now apply texture environment to get final color */
(*tex->env)(gc, color, &texel);
}
/***********************************************************************/
#ifdef NT_DEADCODE_POLYARRAY
static __GLfloat FASTCALL Dot(const __GLcoord *v1, const __GLcoord *v2)
{
return (v1->x * v2->x + v1->y * v2->y + v1->z * v2->z);
}
/*
** Compute the s & t coordinates for a sphere map. The s & t values
** are stored in "result" even if both coordinates are not being
** generated. The caller picks the right values out.
*/
static void FASTCALL SphereGen(__GLcontext *gc, __GLvertex *vx, __GLcoord *result)
{
__GLcoord u, r;
__GLfloat m, ndotu;
/* Get unit vector from origin to the vertex in eye coordinates into u */
(*gc->procs.normalize)(&u.x, &vx->eye.x);
/* Dot the normal with the unit position u */
ndotu = Dot(&vx->normal, &u);
/* Compute r */
r.x = u.x - 2 * vx->normal.x * ndotu;
r.y = u.y - 2 * vx->normal.y * ndotu;
r.z = u.z - 2 * vx->normal.z * ndotu;
/* Compute m */
m = 2 * __GL_SQRTF(r.x*r.x + r.y*r.y + (r.z + 1) * (r.z + 1));
if (m) {
result->x = r.x / m + __glHalf;
result->y = r.y / m + __glHalf;
} else {
result->x = __glHalf;
result->y = __glHalf;
}
}
#endif // NT_DEADCODE_POLYARRAY
#ifdef NT_DEADCODE_POLYARRAY
/*
** Transform or compute the texture coordinates for this vertex.
*/
void FASTCALL __glCalcMixedTexture(__GLcontext *gc, __GLvertex *vx)
{
__GLcoord sphereCoord, gen, *c;
GLboolean didSphereGen = GL_FALSE;
GLuint enables = gc->state.enables.general;
__GLmatrix *m;
/* Generate/copy s coordinate */
if (enables & __GL_TEXTURE_GEN_S_ENABLE) {
switch (gc->state.texture.s.mode) {
case GL_EYE_LINEAR:
c = &gc->state.texture.s.eyePlaneEquation;
gen.x = c->x * vx->eye.x + c->y * vx->eye.y
+ c->z * vx->eye.z + c->w * vx->eye.w;
break;
case GL_OBJECT_LINEAR:
c = &gc->state.texture.s.objectPlaneEquation;
gen.x = c->x * vx->obj.x + c->y * vx->obj.y
+ c->z * vx->obj.z + c->w * vx->obj.w;
break;
case GL_SPHERE_MAP:
SphereGen(gc, vx, &sphereCoord);
gen.x = sphereCoord.x;
didSphereGen = GL_TRUE;
break;
}
} else {
gen.x = vx->texture.x;
}
/* Generate/copy t coordinate */
if (enables & __GL_TEXTURE_GEN_T_ENABLE) {
switch (gc->state.texture.t.mode) {
case GL_EYE_LINEAR:
c = &gc->state.texture.t.eyePlaneEquation;
gen.y = c->x * vx->eye.x + c->y * vx->eye.y
+ c->z * vx->eye.z + c->w * vx->eye.w;
break;
case GL_OBJECT_LINEAR:
c = &gc->state.texture.t.objectPlaneEquation;
gen.y = c->x * vx->obj.x + c->y * vx->obj.y
+ c->z * vx->obj.z + c->w * vx->obj.w;
break;
case GL_SPHERE_MAP:
if (!didSphereGen) {
SphereGen(gc, vx, &sphereCoord);
}
gen.y = sphereCoord.y;
break;
}
} else {
gen.y = vx->texture.y;
}
/* Generate/copy r coordinate */
if (enables & __GL_TEXTURE_GEN_R_ENABLE) {
switch (gc->state.texture.r.mode) {
case GL_EYE_LINEAR:
c = &gc->state.texture.r.eyePlaneEquation;
gen.z = c->x * vx->eye.x + c->y * vx->eye.y
+ c->z * vx->eye.z + c->w * vx->eye.w;
break;
case GL_OBJECT_LINEAR:
c = &gc->state.texture.r.objectPlaneEquation;
gen.z = c->x * vx->obj.x + c->y * vx->obj.y
+ c->z * vx->obj.z + c->w * vx->obj.w;
break;
}
} else {
gen.z = vx->texture.z;
}
/* Generate/copy q coordinate */
if (enables & __GL_TEXTURE_GEN_Q_ENABLE) {
switch (gc->state.texture.q.mode) {
case GL_EYE_LINEAR:
c = &gc->state.texture.q.eyePlaneEquation;
gen.w = c->x * vx->eye.x + c->y * vx->eye.y
+ c->z * vx->eye.z + c->w * vx->eye.w;
break;
case GL_OBJECT_LINEAR:
c = &gc->state.texture.q.objectPlaneEquation;
gen.w = c->x * vx->obj.x + c->y * vx->obj.y
+ c->z * vx->obj.z + c->w * vx->obj.w;
break;
}
} else {
gen.w = vx->texture.w;
}
/* Finally, apply texture matrix */
m = &gc->transform.texture->matrix;
(*m->xf4)(&vx->texture, &gen.x, m);
}
#endif // NT_DEADCODE_POLYARRAY
#ifdef NT_DEADCODE_POLYARRAY
void FASTCALL __glCalcEyeLinear(__GLcontext *gc, __GLvertex *vx)
{
__GLcoord gen, *c;
__GLmatrix *m;
/* Generate texture coordinates from eye coordinates */
c = &gc->state.texture.s.eyePlaneEquation;
gen.x = c->x * vx->eye.x + c->y * vx->eye.y + c->z * vx->eye.z
+ c->w * vx->eye.w;
c = &gc->state.texture.t.eyePlaneEquation;
gen.y = c->x * vx->eye.x + c->y * vx->eye.y + c->z * vx->eye.z
+ c->w * vx->eye.w;
gen.z = vx->texture.z;
gen.w = vx->texture.w;
/* Finally, apply texture matrix */
m = &gc->transform.texture->matrix;
(*m->xf4)(&vx->texture, &gen.x, m);
}
#endif // NT_DEADCODE_POLYARRAY
#ifdef NT_DEADCODE_POLYARRAY
void FASTCALL __glCalcObjectLinear(__GLcontext *gc, __GLvertex *vx)
{
__GLcoord gen, *c;
__GLmatrix *m;
/* Generate texture coordinates from object coordinates */
c = &gc->state.texture.s.objectPlaneEquation;
gen.x = c->x * vx->obj.x + c->y * vx->obj.y + c->z * vx->obj.z
+ c->w * vx->obj.w;
c = &gc->state.texture.t.objectPlaneEquation;
gen.y = c->x * vx->obj.x + c->y * vx->obj.y + c->z * vx->obj.z
+ c->w * vx->obj.w;
gen.z = vx->texture.z;
gen.w = vx->texture.w;
/* Finally, apply texture matrix */
m = &gc->transform.texture->matrix;
(*m->xf4)(&vx->texture, &gen.x, m);
}
#endif // NT_DEADCODE_POLYARRAY
#ifdef NT_DEADCODE_POLYARRAY
void FASTCALL __glCalcSphereMap(__GLcontext *gc, __GLvertex *vx)
{
__GLcoord sphereCoord;
__GLmatrix *m;
SphereGen(gc, vx, &sphereCoord);
sphereCoord.z = vx->texture.z;
sphereCoord.w = vx->texture.w;
/* Finally, apply texture matrix */
m = &gc->transform.texture->matrix;
(*m->xf4)(&vx->texture, &sphereCoord.x, m);
}
#endif // NT_DEADCODE_POLYARRAY
#ifdef NT_DEADCODE_POLYARRAY
void FASTCALL __glCalcTexture(__GLcontext *gc, __GLvertex *vx)
{
__GLcoord copy;
__GLmatrix *m;
copy.x = vx->texture.x;
copy.y = vx->texture.y;
copy.z = vx->texture.z;
copy.w = vx->texture.w;
/* Apply texture matrix */
m = &gc->transform.texture->matrix;
(*m->xf4)(&vx->texture, &copy.x, m);
}
#endif // NT_DEADCODE_POLYARRAY
/************************************************************************/
static __GLtexture *CheckTexSubImageArgs(__GLcontext *gc, GLenum target,
GLint lod, GLenum format,
GLenum type, GLint dim)
{
__GLtexture *tex = __glLookUpTexture(gc, target);
__GLmipMapLevel *lp;
if (!tex || (target == GL_PROXY_TEXTURE_1D) ||
(target == GL_PROXY_TEXTURE_2D))
{
bad_enum:
__glSetError(GL_INVALID_ENUM);
return 0;
}
if (tex->dim != dim) {
goto bad_enum;
}
switch (type) {
case GL_BITMAP:
if (format != GL_COLOR_INDEX) goto bad_enum;
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
break;
default:
goto bad_enum;
}
switch (format) {
case GL_COLOR_INDEX: case GL_RED:
case GL_GREEN: case GL_BLUE:
case GL_ALPHA: case GL_RGB:
case GL_RGBA: case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
#ifdef GL_EXT_bgra
case GL_BGRA_EXT:
case GL_BGR_EXT:
#endif
break;
default:
goto bad_enum;
}
if ((lod < 0) || (lod >= gc->constants.maxMipMapLevel)) {
__glSetError(GL_INVALID_VALUE);
return 0;
}
#ifdef GL_EXT_paletted_texture
lp = &tex->level[lod];
if ((lp->internalFormat == GL_COLOR_INDEX8_EXT ||
lp->internalFormat == GL_COLOR_INDEX16_EXT) &&
format != GL_COLOR_INDEX)
{
goto bad_enum;
}
#endif
return tex;
}
/*
** Used for extraction from textures. "packed" is set to GL_TRUE if this
** image is being pulled out of a display list, and GL_FALSE if it is
** being pulled directly out of an application.
*/
void __glInitTexSubImageUnpack(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
__GLmipMapLevel *lp,
GLsizei xoffset, GLsizei yoffset,
GLint width, GLint height, GLenum format,
GLenum type, const GLvoid *buf, GLboolean packed)
{
spanInfo->x = 0;
spanInfo->zoomx = __glOne;
spanInfo->realWidth = spanInfo->width = width;
spanInfo->height = height;
spanInfo->srcFormat = format;
spanInfo->srcType = type;
spanInfo->srcImage = buf;
__glLoadUnpackModes(gc, spanInfo, packed);
spanInfo->dstImage = lp->buffer;
spanInfo->dstSkipPixels = xoffset + lp->border;
spanInfo->dstSkipLines = yoffset + lp->border;
spanInfo->dstSwapBytes = GL_FALSE;
spanInfo->dstLsbFirst = GL_TRUE;
spanInfo->dstLineLength = lp->width;
switch(lp->internalFormat) {
case GL_LUMINANCE:
spanInfo->dstFormat = GL_RED;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_LUMINANCE_ALPHA:
spanInfo->dstFormat = __GL_RED_ALPHA;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_RGB:
spanInfo->dstFormat = GL_RGB;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_RGBA:
spanInfo->dstFormat = GL_RGBA;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_ALPHA:
spanInfo->dstFormat = GL_ALPHA;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_INTENSITY:
spanInfo->dstFormat = GL_RED;
spanInfo->dstType = GL_FLOAT;
spanInfo->dstAlignment = 4;
break;
case GL_BGR_EXT:
// Be a little tricky here to pad the data out to 32 bits
spanInfo->dstFormat = GL_BGRA_EXT;
spanInfo->dstType = GL_UNSIGNED_BYTE;
spanInfo->dstAlignment = 4;
break;
case GL_BGRA_EXT:
spanInfo->dstFormat = GL_BGRA_EXT;
spanInfo->dstType = GL_UNSIGNED_BYTE;
spanInfo->dstAlignment = 4;
break;
#ifdef GL_EXT_paletted_texture
case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX16_EXT:
spanInfo->dstFormat = GL_COLOR_INDEX;
spanInfo->dstType =
lp->internalFormat == GL_COLOR_INDEX8_EXT ?
GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
spanInfo->dstAlignment = 1;
break;
#endif
}
}
static GLboolean CheckTexSubImageRange(__GLcontext *gc, __GLmipMapLevel *lp,
GLint xoffset, GLint yoffset,
GLsizei w, GLsizei h)
{
#ifdef __GL_LINT
gc = gc;
#endif
if ((w < 0) || (h < 0) ||
(xoffset < -lp->border) || (xoffset+w > lp->width-lp->border) ||
(yoffset < -lp->border) || (yoffset+h > lp->height-lp->border))
{
__glSetError(GL_INVALID_VALUE);
return GL_FALSE;
}
return GL_TRUE;
}
__GLtexture *__glCheckTexSubImage1DArgs(__GLcontext *gc, GLenum target,
GLint lod,
GLint xoffset, GLint length,
GLenum format, GLenum type)
{
__GLtexture *tex;
__GLmipMapLevel *lp;
/* Check arguments and get the right texture being changed */
tex = CheckTexSubImageArgs(gc, target, lod, format, type, 1);
if (!tex) {
return 0;
}
lp = &tex->level[lod];
if (!CheckTexSubImageRange(gc, lp, xoffset, 0, length, 1)) {
return 0;
}
return tex;
}
__GLtexture *__glCheckTexSubImage2DArgs(__GLcontext *gc, GLenum target,
GLint lod,
GLint xoffset, GLint yoffset,
GLsizei w, GLsizei h,
GLenum format, GLenum type)
{
__GLtexture *tex;
__GLmipMapLevel *lp;
/* Check arguments and get the right texture being changed */
tex = CheckTexSubImageArgs(gc, target, lod, format, type, 2);
if (!tex) {
return 0;
}
lp = &tex->level[lod];
if (!CheckTexSubImageRange(gc, lp, xoffset, yoffset, w, h)) {
return 0;
}
return tex;
}
#ifdef NT
void APIPRIVATE __glim_TexSubImage1D(GLenum target, GLint lod,
GLint xoffset, GLint length,
GLenum format, GLenum type, const GLvoid *buf,
GLboolean _IsDlist)
#else
void APIPRIVATE __glim_TexSubImage1D(GLenum target, GLint lod,
GLint xoffset, GLint length,
GLenum format, GLenum type, const GLvoid *buf)
#endif
{
__GLtexture *tex;
__GLmipMapLevel *lp;
__GLpixelSpanInfo spanInfo;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
/* Check arguments and get the right texture level being changed */
tex = __glCheckTexSubImage1DArgs(gc, target, lod, xoffset, length,
format, type);
if (!tex) {
return;
}
lp = &tex->level[lod];
if (lp->buffer == NULL) {
__glSetError(GL_INVALID_OPERATION);
return;
}
/* Copy sub-image data */
#ifdef NT
__glInitTexSubImageUnpack(gc, &spanInfo, lp, xoffset, 0, length, 1,
format, type, buf,
(GLboolean) (_IsDlist ? GL_TRUE : GL_FALSE));
#else
__glInitTexSubImageUnpack(gc, &spanInfo, lp, xoffset, 0, length, 1,
format, type, buf, GL_FALSE);
#endif
spanInfo.dstSkipLines += lp->border;
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadSubImage(gc, GL_TEXTURE_1D, lod, xoffset, 0,
length, 1);
#endif
}
#ifndef NT
void __gllei_TexSubImage1D(__GLcontext *gc, GLenum target, GLint lod,
GLint xoffset, GLint length,
GLenum format, GLenum type, const GLubyte *image)
{
__GLtexture *tex;
__GLmipMapLevel *lp;
__GLpixelSpanInfo spanInfo;
GLuint beginMode;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
beginMode = gc->beginMode;
if (beginMode != __GL_NOT_IN_BEGIN) {
if (beginMode == __GL_NEED_VALIDATE) {
(*gc->procs.validate)(gc);
gc->beginMode = __GL_NOT_IN_BEGIN;
} else {
__glSetError(GL_INVALID_OPERATION);
return;
}
}
/* Check arguments and get the right texture level being changed */
tex = __glCheckTexSubImage1DArgs(gc, target, lod, xoffset, length,
format, type);
if (!tex) {
return;
}
lp = &tex->level[lod];
if (lp->buffer == NULL) {
__glSetError(GL_INVALID_OPERATION);
return;
}
/* Copy sub-image data */
__glInitTexSubImageUnpack(gc, &spanInfo, lp, xoffset, 0, length, 1,
format, type, image, GL_TRUE);
spanInfo.dstSkipLines += lp->border;
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadSubImage(gc, GL_TEXTURE_1D, lod, xoffset, 0,
length, 1);
#endif
}
#endif // !NT
#ifdef NT
void APIPRIVATE __glim_TexSubImage2D(GLenum target, GLint lod,
GLint xoffset, GLint yoffset,
GLsizei w, GLsizei h, GLenum format,
GLenum type, const GLvoid *buf, GLboolean _IsDlist)
#else
void APIPRIVATE __glim_TexSubImage2D(GLenum target, GLint lod,
GLint xoffset, GLint yoffset,
GLsizei w, GLsizei h, GLenum format,
GLenum type, const GLvoid *buf)
#endif
{
__GLtexture *tex;
__GLmipMapLevel *lp;
__GLpixelSpanInfo spanInfo;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
/* Check arguments and get the right texture level being changed */
tex = __glCheckTexSubImage2DArgs(gc, target, lod, xoffset, yoffset, w, h,
format, type);
if (!tex) {
return;
}
lp = &tex->level[lod];
if (lp->buffer == NULL) {
__glSetError(GL_INVALID_OPERATION);
return;
}
/* Copy sub-image data */
#ifdef NT
__glInitTexSubImageUnpack(gc, &spanInfo, lp, xoffset, yoffset, w, h,
format, type, buf,
(GLboolean) (_IsDlist ? GL_TRUE : GL_FALSE));
#else
__glInitTexSubImageUnpack(gc, &spanInfo, lp, xoffset, yoffset, w, h,
format, type, buf, GL_FALSE);
#endif
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadSubImage(gc, GL_TEXTURE_2D, lod, xoffset, yoffset,
w, h);
#endif
}
#ifndef NT
void __gllei_TexSubImage2D(__GLcontext *gc, GLenum target, GLint lod,
GLint xoffset, GLint yoffset,
GLsizei w, GLsizei h, GLenum format, GLenum type,
const GLubyte *image)
{
__GLtexture *tex;
__GLmipMapLevel *lp;
__GLpixelSpanInfo spanInfo;
GLuint beginMode;
/*
** Validate because we use the copyImage proc which may be affected
** by the pickers.
*/
beginMode = gc->beginMode;
if (beginMode != __GL_NOT_IN_BEGIN) {
if (beginMode == __GL_NEED_VALIDATE) {
(*gc->procs.validate)(gc);
gc->beginMode = __GL_NOT_IN_BEGIN;
} else {
__glSetError(GL_INVALID_OPERATION);
return;
}
}
/* Check arguments and get the right texture level being changed */
tex = __glCheckTexSubImage2DArgs(gc, target, lod, xoffset, yoffset, w, h,
format, type);
if (!tex) {
return;
}
lp = &tex->level[lod];
if (lp->buffer == NULL) {
__glSetError(GL_INVALID_OPERATION);
return;
}
/* Copy sub-image data */
__glInitTexSubImageUnpack(gc, &spanInfo, lp, xoffset, yoffset, w, h,
format, type, image, GL_TRUE);
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
#ifdef NT
__glTexPriListLoadSubImage(gc, GL_TEXTURE_2D, lod, xoffset, yoffset,
w, h);
#endif
}
#endif // !NT
/************************************************************************/
// Routine to set up all the correct pixel modes for a straight data
// copy. Preserves state for later shutoff
typedef struct _StraightCopyStorage
{
__GLpixelPackMode pack;
__GLpixelUnpackMode unpack;
__GLpixelTransferMode transfer;
} StraightCopyStorage;
void StartStraightCopy(__GLcontext *gc, StraightCopyStorage *state)
{
state->pack = gc->state.pixel.packModes;
state->unpack = gc->state.pixel.unpackModes;
state->transfer = gc->state.pixel.transferMode;
gc->state.pixel.packModes.swapEndian = GL_FALSE;
gc->state.pixel.packModes.lsbFirst = GL_FALSE;
gc->state.pixel.packModes.lineLength = 0;
gc->state.pixel.packModes.skipLines = 0;
gc->state.pixel.packModes.skipPixels = 0;
gc->state.pixel.packModes.alignment = 4;
gc->state.pixel.unpackModes.swapEndian = GL_FALSE;
gc->state.pixel.unpackModes.lsbFirst = GL_FALSE;
gc->state.pixel.unpackModes.lineLength = 0;
gc->state.pixel.unpackModes.skipLines = 0;
gc->state.pixel.unpackModes.skipPixels = 0;
gc->state.pixel.unpackModes.alignment = 4;
gc->state.pixel.transferMode.r_scale = 1.0f;
gc->state.pixel.transferMode.g_scale = 1.0f;
gc->state.pixel.transferMode.b_scale = 1.0f;
gc->state.pixel.transferMode.a_scale = 1.0f;
gc->state.pixel.transferMode.d_scale = 1.0f;
gc->state.pixel.transferMode.r_bias = 0.0f;
gc->state.pixel.transferMode.g_bias = 0.0f;
gc->state.pixel.transferMode.b_bias = 0.0f;
gc->state.pixel.transferMode.a_bias = 0.0f;
gc->state.pixel.transferMode.d_bias = 0.0f;
gc->state.pixel.transferMode.zoomX = 1.0f;
gc->state.pixel.transferMode.zoomY = 1.0f;
gc->state.pixel.transferMode.indexShift = 0;
gc->state.pixel.transferMode.indexOffset = 0;
gc->state.pixel.transferMode.mapColor = GL_FALSE;
gc->state.pixel.transferMode.mapStencil = GL_FALSE;
// Many states have changed so force a repick
__GL_DELAY_VALIDATE(gc);
}
void EndStraightCopy(__GLcontext *gc, StraightCopyStorage *state)
{
gc->state.pixel.packModes = state->pack;
gc->state.pixel.unpackModes = state->unpack;
gc->state.pixel.transferMode = state->transfer;
// Many states have changed so force a repick
__GL_DELAY_VALIDATE(gc);
}
void APIPRIVATE __glim_CopyTexImage1D(GLenum target, GLint level,
GLenum internalformat, GLint x, GLint y,
GLsizei width, GLint border)
{
GLubyte *pixels;
GLenum format, type;
StraightCopyStorage state;
__GL_SETUP();
if (target != GL_TEXTURE_1D ||
(internalformat >= 1 && internalformat <= 4))
{
__glSetError(GL_INVALID_ENUM);
return;
}
// Use BGRA format because that matches our internal texture format
format = GL_BGRA_EXT;
type = GL_UNSIGNED_BYTE;
// Allocate space for pixel data, read pixels into it from the
// frame buffer and then do a TexImage
pixels = (GLubyte *)(*gc->imports.malloc)(gc, width*4);
if (pixels == NULL)
{
return;
}
StartStraightCopy(gc, &state);
(*gc->srvDispatchTable.ReadPixels)(x, y, width, 1, format, type,
pixels);
(*gc->srvDispatchTable.TexImage1D)(target, level, internalformat,
width, border, format, type,
pixels, GL_FALSE);
EndStraightCopy(gc, &state);
(*gc->imports.free)(gc, pixels);
}
void APIPRIVATE __glim_CopyTexImage2D(GLenum target, GLint level,
GLenum internalformat, GLint x, GLint y,
GLsizei width, GLsizei height, GLint border)
{
GLubyte *pixels;
GLenum format, type;
StraightCopyStorage state;
__GL_SETUP();
if (target != GL_TEXTURE_2D ||
(internalformat >= 1 && internalformat <= 4))
{
__glSetError(GL_INVALID_ENUM);
return;
}
// Use BGRA format because that matches our internal texture format
format = GL_BGRA_EXT;
type = GL_UNSIGNED_BYTE;
// Allocate space for pixel data, read pixels into it from the
// frame buffer and then do a TexImage
pixels = (GLubyte *)(*gc->imports.malloc)(gc, width*height*4);
if (pixels == NULL)
{
return;
}
StartStraightCopy(gc, &state);
(*gc->srvDispatchTable.ReadPixels)(x, y, width, height, format,
type, pixels);
(*gc->srvDispatchTable.TexImage2D)(target, level, internalformat,
width, height, border, format,
type, pixels, GL_FALSE);
EndStraightCopy(gc, &state);
(*gc->imports.free)(gc, pixels);
}
void APIPRIVATE __glim_CopyTexSubImage1D(GLenum target, GLint level, GLint xoffset,
GLint x, GLint y, GLsizei width)
{
GLubyte *pixels;
GLenum format, type;
StraightCopyStorage state;
__GL_SETUP();
if (target != GL_TEXTURE_1D)
{
__glSetError(GL_INVALID_ENUM);
return;
}
// Use BGRA format because that matches our internal texture format
format = GL_BGRA_EXT;
type = GL_UNSIGNED_BYTE;
// Allocate space for pixel data, read pixels into it from the
// frame buffer and then do a TexImage
pixels = (GLubyte *)(*gc->imports.malloc)(gc, width*4);
if (pixels == NULL)
{
return;
}
StartStraightCopy(gc, &state);
(*gc->srvDispatchTable.ReadPixels)(x, y, width, 1, format, type,
pixels);
(*gc->srvDispatchTable.TexSubImage1D)(target, level, xoffset,
width, format, type,
pixels, GL_FALSE);
EndStraightCopy(gc, &state);
(*gc->imports.free)(gc, pixels);
}
void APIPRIVATE __glim_CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset,
GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height)
{
GLubyte *pixels;
GLenum format, type;
StraightCopyStorage state;
__GL_SETUP();
if (target != GL_TEXTURE_2D)
{
__glSetError(GL_INVALID_ENUM);
return;
}
// Use BGRA format because that matches our internal texture format
format = GL_BGRA_EXT;
type = GL_UNSIGNED_BYTE;
// Allocate space for pixel data, read pixels into it from the
// frame buffer and then do a TexImage
pixels = (GLubyte *)(*gc->imports.malloc)(gc, width*height*4);
if (pixels == NULL)
{
return;
}
StartStraightCopy(gc, &state);
(*gc->srvDispatchTable.ReadPixels)(x, y, width, height, format,
type, pixels);
(*gc->srvDispatchTable.TexSubImage2D)(target, level, xoffset,
yoffset, width, height,
format, type, pixels, GL_FALSE);
EndStraightCopy(gc, &state);
(*gc->imports.free)(gc, pixels);
}
/************************************************************************/
/*
** Texture Object extension routines.
*/
/************************************************************************/
#define __GL_CHECK_VALID_N_PARAM(failStatement) \
if (n < 0) { \
__glSetError(GL_INVALID_VALUE); \
} \
if (n == 0) { \
failStatement; \
} \
GLvoid APIPRIVATE __glim_GenTextures(GLsizei n, GLuint* textures)
{
__GL_SETUP_NOT_IN_BEGIN();
__GL_CHECK_VALID_N_PARAM(return);
if (NULL == textures) return;
assert(NULL != gc->texture.shared->namesArray);
__glNamesGenNames(gc, gc->texture.shared->namesArray, n, textures);
}
GLvoid APIPRIVATE __glim_DeleteTextures(GLsizei n, const GLuint* textures)
{
GLuint start, rangeVal, numTextures, targetIndex, i;
__GLnamesArray *array;
__GLtextureObject *texobj, **pBoundTexture;
__GL_SETUP_NOT_IN_BEGIN();
__GL_CHECK_VALID_N_PARAM(return);
array = gc->texture.shared->namesArray;
numTextures = gc->constants.numberOfTextures;
/*
** Send the texture names in ranges to the names module to be
** deleted. Ignore any references to default textures.
** If a texture that is being deleted is currently bound,
** bind the default texture to its target.
** The names routine ignores any names that don't refer to
** textures.
*/
start = rangeVal = textures[0];
for (i=0; i < (GLuint)n; i++, rangeVal++) {
if (0 == textures[i]) { /* skip default textures */
/* delete up to this one */
__glNamesDeleteRange(gc,array,start,rangeVal-start);
/* skip over this one by setting start to the next one */
start = textures[i+1];
rangeVal = start-1; /* because it gets incremented later */
continue;
}
/*
** If the texture is currently bound, bind the defaultTexture
** to its target. The problem here is identifying the target.
** One way is to look up the texobj with the name. Another is
** to look through all of the currently bound textures and
** check each for the name. It has been implemented with the
** assumption that looking through the currently bound textures
** is faster than retrieving the texobj that corresponds to
** the name.
*/
for (targetIndex=0, pBoundTexture = gc->texture.boundTextures;
targetIndex < numTextures; targetIndex++, pBoundTexture++) {
/* Is the texture currently bound? */
if ((*pBoundTexture)->texture.map.texobjs.name == textures[i]) {
__GLperTextureState *pts;
pts = &gc->state.texture.texture[targetIndex];
/* if we don't unlock it, it won't get deleted */
__glNamesUnlockData(gc, *pBoundTexture, __glCleanupTexObj);
/* bind the default texture to this target */
texobj = gc->texture.defaultTextures + targetIndex;
assert(texobj->texture.map.texobjs.name == 0);
gc->texture.texture[targetIndex] = &(texobj->texture);
*pBoundTexture = texobj;
pts->texobjs = texobj->texture.map.texobjs;
pts->params = texobj->texture.map.params;
/* Need to reset the current texture and such. */
__GL_DELAY_VALIDATE(gc);
break;
}
}
if (textures[i] != rangeVal) {
/* delete up to this one */
__glNamesDeleteRange(gc,array,start,rangeVal-start);
start = rangeVal = textures[i];
}
}
__glNamesDeleteRange(gc,array,start,rangeVal-start);
}
/*
** This routine is used by the pick routines to actually perform
** the bind.
*/
void FASTCALL __glBindTexture(__GLcontext *gc, GLuint targetIndex,
GLuint texture, GLboolean callGen)
{
__GLtextureObject *texobj;
assert(NULL != gc->texture.shared->namesArray);
/*
** Retrieve the texture object from the namesArray structure.
*/
if (texture == 0) {
texobj = gc->texture.defaultTextures + targetIndex;
assert(NULL != texobj);
assert(texobj->texture.map.texobjs.name == 0);
}
else {
texobj = (__GLtextureObject *)
__glNamesLockData(gc, gc->texture.shared->namesArray, texture);
}
/*
** Is this the first time this name has been bound?
** If so, create a new texture object and initialize it.
*/
if (NULL == texobj) {
texobj = (__GLtextureObject *)
(*gc->imports.calloc)(gc, 1, sizeof(*texobj));
if (texobj == NULL)
{
return;
}
if (!InitTextureObject(gc, texobj, texture, targetIndex))
{
(*gc->imports.free)(gc, texobj);
return;
}
InitTextureMachine(gc, targetIndex, &(texobj->texture), GL_TRUE);
__glNamesNewData(gc, gc->texture.shared->namesArray, texture, texobj);
/*
** Shortcut way to lock without doing another lookup.
*/
__glNamesLockArray(gc, gc->texture.shared->namesArray);
texobj->refcount++;
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
__glTexPriListAdd(gc, texobj, GL_TRUE);
}
else {
/*
** Retrieved an existing texture object. Do some
** sanity checks.
*/
if (texobj->targetIndex != targetIndex) {
__glSetError(GL_INVALID_OPERATION);
return;
}
assert(texture == texobj->texture.map.texobjs.name);
}
{
__GLperTextureState *pts;
__GLtexture *ptm;
__GLtextureObject *boundTexture;
pts = &(gc->state.texture.texture[targetIndex]);
ptm = &(gc->texture.texture[targetIndex]->map);
boundTexture = gc->texture.boundTextures[targetIndex];
/* Copy the current stackable state into the bound texture. */
ptm->params = pts->params;
ptm->texobjs = pts->texobjs;
if (boundTexture->texture.map.texobjs.name != 0) {
/* Unlock the texture that is being unbound. */
__glNamesUnlockData(gc, boundTexture, __glCleanupTexObj);
}
/*
** Install the new texture into the correct target and save
** its pointer so it can be unlocked easily when it is unbound.
*/
gc->texture.texture[targetIndex] = &(texobj->texture);
gc->texture.boundTextures[targetIndex] = texobj;
/* Copy the new texture's stackable state into the context state. */
pts->params = texobj->texture.map.params;
pts->texobjs = texobj->texture.map.texobjs;
if (callGen)
{
__glGenMakeTextureCurrent(gc, &texobj->texture.map,
texobj->loadKey);
}
}
}
GLvoid APIPRIVATE __glim_BindTexture(GLenum target, GLuint texture)
{
GLuint targetIndex;
/*
** Need to validate in case a new texture was popped into
** the state immediately prior to this call.
*/
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
switch (target) {
case GL_TEXTURE_1D:
targetIndex = 2;
break;
case GL_TEXTURE_2D:
targetIndex = 3;
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
__glBindTexture(gc, targetIndex, texture, GL_TRUE);
/* Need to reset the current texture and such. */
__GL_DELAY_VALIDATE(gc);
}
GLvoid APIPRIVATE __glim_PrioritizeTextures(GLsizei n,
const GLuint* textures,
const GLclampf* priorities)
{
int i;
__GLtextureObject *texobj;
GLuint targetIndex;
__GLtextureObject **pBoundTexture;
GLclampf priority;
__GL_SETUP_NOT_IN_BEGIN();
__GL_CHECK_VALID_N_PARAM(return);
for (i=0; i < n; i++) {
/* silently ignore default texture */
if (0 == textures[i]) continue;
texobj = (__GLtextureObject *)
__glNamesLockData(gc, gc->texture.shared->namesArray, textures[i]);
/* silently ignore non-texture */
if (NULL == texobj) continue;
priority = Clampf(priorities[i], __glZero, __glOne);
texobj->texture.map.texobjs.priority = priority;
// If this texture is currently bound, also update the
// copy of the priority in the gc's state
// BUGBUG - Keeping copies is not a good design. This
// should be fixed
for (targetIndex = 0, pBoundTexture = gc->texture.boundTextures;
targetIndex < (GLuint)gc->constants.numberOfTextures;
targetIndex++, pBoundTexture++)
{
/* Is the texture currently bound? */
if ((*pBoundTexture)->texture.map.texobjs.name == textures[i])
{
gc->state.texture.texture[targetIndex].texobjs.priority =
priority;
break;
}
}
__glTexPriListChangePriority(gc, texobj, GL_FALSE);
__glNamesUnlockData(gc, texobj, __glCleanupTexObj);
}
__glNamesLockArray(gc, gc->texture.shared->namesArray);
__glTexPriListRealize(gc);
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
}
GLboolean APIPRIVATE __glim_AreTexturesResident(GLsizei n,
const GLuint* textures,
GLboolean* residences)
{
int i;
__GLtextureObject *texobj;
GLboolean allResident = GL_TRUE;
GLboolean currentResident;
__GL_SETUP_NOT_IN_BEGIN2();
__GL_CHECK_VALID_N_PARAM(return GL_FALSE);
for (i=0; i < n; i++) {
/* Can't query a default texture. */
if (0 == textures[i]) {
__glSetError(GL_INVALID_VALUE);
return GL_FALSE;
}
texobj = (__GLtextureObject *)
__glNamesLockData(gc, gc->texture.shared->namesArray, textures[i]);
/*
** Ensure that all of the names have corresponding textures.
*/
if (NULL == texobj) {
__glSetError(GL_INVALID_VALUE);
return GL_FALSE;
}
if (((__GLGENcontext *)gc)->pMcdState && texobj->loadKey) {
currentResident = ((GenMcdTextureStatus((__GLGENcontext *)gc, texobj->loadKey) & MCDRV_TEXTURE_RESIDENT) != 0);
} else
currentResident = texobj->resident;
if (!currentResident) {
allResident = GL_FALSE;
}
residences[i] = currentResident;
__glNamesUnlockData(gc, texobj, __glCleanupTexObj);
}
return allResident;
}
GLboolean APIPRIVATE __glim_IsTexture(GLuint texture)
{
__GLtextureObject *texobj;
__GL_SETUP_NOT_IN_BEGIN2();
if (0 == texture) return GL_FALSE;
texobj = (__GLtextureObject *)
__glNamesLockData(gc, gc->texture.shared->namesArray, texture);
if (texobj != NULL)
{
__glNamesUnlockData(gc, texobj, __glCleanupTexObj);
return GL_TRUE;
}
return GL_FALSE;
}
#ifdef NT
GLboolean FASTCALL __glCanShareTextures(__GLcontext *gc, __GLcontext *shareMe)
{
GLboolean canShare = GL_TRUE;
if (gc->texture.shared != NULL)
{
__glNamesLockArray(gc, gc->texture.shared->namesArray);
// Make sure we're not trying to replace a shared object
// The spec also says that it is illegal for the new context
// to have any textures
canShare = gc->texture.shared->namesArray->refcount == 1 &&
gc->texture.shared->namesArray->tree == NULL;
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
}
return canShare;
}
void FASTCALL __glShareTextures(__GLcontext *gc, __GLcontext *shareMe)
{
GLint i, numTextures;
if (gc->texture.shared != NULL)
{
// We know that the names array doesn't have any contents
// so no texture names can be selected as the current texture
// or anything else. Therefore it is safe to simply free
// our array
__glFreeSharedTextureState(gc);
}
__glNamesLockArray(gc, shareMe->texture.shared->namesArray);
gc->texture.shared = shareMe->texture.shared;
gc->texture.shared->namesArray->refcount++;
// Add the new sharer's default textures to the priority list
numTextures = gc->constants.numberOfTextures;
for (i = 0; i < numTextures; i++)
{
__glTexPriListAddToList(gc, gc->texture.defaultTextures+i);
}
// No realization of priority list because these contexts aren't
// current
DBGLEVEL3(LEVEL_INFO, "Sharing textures %p with %p, count %d\n",
gc, shareMe, gc->texture.shared->namesArray->refcount);
__glNamesUnlockArray(gc, shareMe->texture.shared->namesArray);
}
#endif
#ifdef GL_EXT_paletted_texture
GLboolean __glCheckColorTableArgs(__GLcontext *gc, GLenum format, GLenum type)
{
switch (format)
{
case GL_RED:
case GL_GREEN: case GL_BLUE:
case GL_ALPHA: case GL_RGB:
case GL_RGBA:
#ifdef GL_EXT_bgra
case GL_BGRA_EXT:
case GL_BGR_EXT:
#endif
break;
default:
bad_enum:
__glSetError(GL_INVALID_ENUM);
return GL_FALSE;
}
switch (type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
break;
default:
goto bad_enum;
}
return GL_TRUE;
}
void APIPRIVATE __glim_ColorTableEXT(GLenum target,
GLenum internalFormat, GLsizei width,
GLenum format, GLenum type,
const GLvoid *data, GLboolean _IsDlist)
{
__GLtextureObject *pto;
__GLtexture *tex;
GLint level;
__GLpixelSpanInfo spanInfo;
GLenum baseFormat;
RGBQUAD *newData;
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
switch(internalFormat)
{
case GL_RGB: case 3:
case GL_R3_G3_B2: case GL_RGB4:
case GL_RGB5: case GL_RGB8:
case GL_RGB10: case GL_RGB12:
case GL_RGB16:
baseFormat = GL_RGB;
break;
case GL_RGBA: case 4:
case GL_RGBA2: case GL_RGBA4:
case GL_RGBA8: case GL_RGB5_A1:
case GL_RGBA12: case GL_RGBA16:
case GL_RGB10_A2:
baseFormat = GL_RGBA;
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
// width must be a positive power of two greater than zero
if (width <= 0 || (width & (width-1)) != 0)
{
__glSetError(GL_INVALID_VALUE);
return;
}
if (!__glCheckColorTableArgs(gc, format, type))
{
return;
}
if (target == GL_PROXY_TEXTURE_1D ||
target == GL_PROXY_TEXTURE_2D)
{
// BUGBUG - How do MCD's indicate their palette support?
tex = __glLookUpTexture(gc, target);
// We're only in this case if it's a legal proxy target value
// so there's no need to do a real check
ASSERTOPENGL(tex != NULL, "Invalid proxy target");
tex->paletteRequestedFormat = internalFormat;
tex->paletteSize = width;
// Proxies have no data so there's no need to do any more
return;
}
if (data == NULL)
{
return;
}
pto = __glLookUpTextureObject(gc, target);
if (pto == NULL)
{
__glSetError(GL_INVALID_ENUM);
return;
}
tex = &pto->texture.map;
// Allocate palette storage
newData = (*gc->imports.realloc)(gc, tex->paletteData,
sizeof(RGBQUAD)*width);
if (newData == NULL)
{
return;
}
tex->paletteBaseFormat = baseFormat;
tex->paletteRequestedFormat = internalFormat;
tex->paletteSize = width;
tex->paletteData = newData;
// This routine can be called on any kind of texture, not necessarily
// color-indexed ones. If it is a color-index texture then we
// need to set the appropriate baseFormat and extract procs
// according to the palette data
if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT ||
tex->level[0].internalFormat == GL_COLOR_INDEX16_EXT)
{
for (level = 0; level < gc->constants.maxMipMapLevel; level++)
{
tex->level[level].baseFormat = tex->paletteBaseFormat;
// Pick proper extraction proc
if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT)
{
__glSetPaletteLevelExtract8(tex, &tex->level[level],
tex->level[level].border);
}
else
{
ASSERTOPENGL(tex->level[0].internalFormat ==
GL_COLOR_INDEX16_EXT,
"Unexpected internalFormat\n");
__glSetPaletteLevelExtract16(tex, &tex->level[level],
tex->level[level].border);
}
}
// We need to repick the texture procs because the baseFormat
// field has changed
__GL_DELAY_VALIDATE(gc);
}
// Copy user palette data into BGRA form
spanInfo.dstImage = tex->paletteData;
__glInitTextureUnpack(gc, &spanInfo, width, 1, format, type, data,
GL_BGRA_EXT, _IsDlist);
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
// Don't update the optimized palette unless it would actually
// get used
if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT ||
tex->level[0].internalFormat == GL_COLOR_INDEX16_EXT)
{
__glGenUpdateTexturePalette(gc, tex, pto->loadKey,
0, tex->paletteSize);
}
}
void APIPRIVATE __glim_ColorSubTableEXT(GLenum target, GLsizei start,
GLsizei count, GLenum format,
GLenum type, const GLvoid *data,
GLboolean _IsDlist)
{
__GLtextureObject *pto;
__GLtexture *tex;
__GLpixelSpanInfo spanInfo;
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
if (!__glCheckColorTableArgs(gc, format, type))
{
return;
}
pto = __glLookUpTextureObject(gc, target);
if (pto == NULL)
{
__glSetError(GL_INVALID_ENUM);
return;
}
if (data == NULL)
{
return;
}
tex = &pto->texture.map;
// Validate start and count
if (start > tex->paletteSize ||
start+count > tex->paletteSize)
{
__glSetError(GL_INVALID_VALUE);
return;
}
// Copy user palette data into BGRA form
spanInfo.dstImage = tex->paletteData;
__glInitTextureUnpack(gc, &spanInfo, count, 1, format, type, data,
GL_BGRA_EXT, _IsDlist);
spanInfo.dstSkipPixels += start;
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
// Don't update the optimized palette unless it would actually
// get used
if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT ||
tex->level[0].internalFormat == GL_COLOR_INDEX16_EXT)
{
__glGenUpdateTexturePalette(gc, tex, pto->loadKey, start, count);
}
}
void APIPRIVATE __glim_GetColorTableEXT(GLenum target, GLenum format,
GLenum type, GLvoid *data)
{
__GLtextureObject *pto;
__GLtexture *tex;
GLint level;
__GLpixelSpanInfo spanInfo;
GLenum baseFormat;
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
if (!__glCheckColorTableArgs(gc, format, type))
{
return;
}
pto = __glLookUpTextureObject(gc, target);
if (pto == NULL)
{
__glSetError(GL_INVALID_ENUM);
return;
}
tex = &pto->texture.map;
ASSERTOPENGL(tex->paletteData != NULL,
"GetColorTable with no palette data\n");
// Copy BGRA data into user buffer
spanInfo.srcImage = tex->paletteData;
spanInfo.srcFormat = GL_BGRA_EXT;
spanInfo.srcType = GL_UNSIGNED_BYTE;
spanInfo.srcAlignment = 4;
__glInitImagePack(gc, &spanInfo, tex->paletteSize, 1, format, type, data);
__glInitUnpacker(gc, &spanInfo);
__glInitPacker(gc, &spanInfo);
(*gc->procs.copyImage)(gc, &spanInfo, GL_TRUE);
}
void APIPRIVATE __glim_GetColorTableParameterivEXT(GLenum target,
GLenum pname,
GLint *params)
{
__GLtexture *tex;
__GL_SETUP_NOT_IN_BEGIN();
tex = __glLookUpTexture(gc, target);
if (tex == NULL)
{
__glSetError(GL_INVALID_ENUM);
return;
}
switch(pname)
{
case GL_COLOR_TABLE_FORMAT_EXT:
*params = tex->paletteRequestedFormat;
break;
case GL_COLOR_TABLE_WIDTH_EXT:
*params = tex->paletteSize;
break;
case GL_COLOR_TABLE_RED_SIZE_EXT:
case GL_COLOR_TABLE_GREEN_SIZE_EXT:
case GL_COLOR_TABLE_BLUE_SIZE_EXT:
case GL_COLOR_TABLE_ALPHA_SIZE_EXT:
*params = 8;
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
void APIPRIVATE __glim_GetColorTableParameterfvEXT(GLenum target,
GLenum pname,
GLfloat *params)
{
__GLtexture *tex;
__GL_SETUP_NOT_IN_BEGIN();
tex = __glLookUpTexture(gc, target);
if (tex == NULL)
{
__glSetError(GL_INVALID_ENUM);
return;
}
switch(pname)
{
case GL_COLOR_TABLE_FORMAT_EXT:
*params = (GLfloat)tex->paletteRequestedFormat;
break;
case GL_COLOR_TABLE_WIDTH_EXT:
*params = (GLfloat)tex->paletteSize;
break;
case GL_COLOR_TABLE_RED_SIZE_EXT:
case GL_COLOR_TABLE_GREEN_SIZE_EXT:
case GL_COLOR_TABLE_BLUE_SIZE_EXT:
case GL_COLOR_TABLE_ALPHA_SIZE_EXT:
*params = (GLfloat)8;
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
}
#endif // GL_EXT_paletted_texture