5429 lines
146 KiB
C
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, ©.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
|