|
|
/*
** 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 <glmath.h>
#include <devlock.h>
/************************************************************************/ /*
** Texture Object 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;
ASSERTOPENGL(NULL != gc->texture.shared->namesArray, "No texture names array\n");
__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 != &gc->texture.ddtex.texobj && (*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; ASSERTOPENGL(texobj->texture.map.texobjs.name == 0, "Non-default texture\n"); 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); }
// These macros used for comparing properties of 2 textures
#define _DIFFERENT_TEX_PARAMS( tex1, tex2 ) \
( ! RtlEqualMemory( &(tex1)->params, &(tex2)->params, sizeof(__GLtextureParamState)) )
#define _DIFFERENT_TEXDATA_FORMATS( tex1, tex2 ) \
( (tex1)->level[0].internalFormat != (tex2)->level[0].internalFormat )
/*
** 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;
ASSERTOPENGL(NULL != gc->texture.shared->namesArray, "No texture names array\n");
// Check if this texture is the currently bound one
if( (targetIndex != __GL_TEX_TARGET_INDEX_DDRAW && gc->texture.boundTextures[targetIndex] != &gc->texture.ddtex.texobj && texture == gc->texture.boundTextures[targetIndex]-> texture.map.texobjs.name) || (targetIndex == __GL_TEX_TARGET_INDEX_DDRAW && gc->texture.boundTextures[__GL_TEX_TARGET_INDEX_2D] == &gc->texture.ddtex.texobj)) { return; }
/*
** Retrieve the texture object from the namesArray structure. */ if (targetIndex == __GL_TEX_TARGET_INDEX_DDRAW) { targetIndex = __GL_TEX_TARGET_INDEX_2D; texobj = &gc->texture.ddtex.texobj; } else if (texture == 0) { texobj = gc->texture.defaultTextures + targetIndex; ASSERTOPENGL(NULL != texobj, "No default texture\n"); ASSERTOPENGL(texobj->texture.map.texobjs.name == 0, "Non-default texture\n"); } 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 *)GCALLOCZ(gc, sizeof(*texobj)); if (texobj == NULL) { return; } if (!__glInitTextureObject(gc, texobj, texture, targetIndex)) { GCFREE(gc, texobj); return; } __glInitTextureMachine(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; } ASSERTOPENGL(texture == texobj->texture.map.texobjs.name, "Texture name mismatch\n"); }
{ __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 the DDraw texture is currently bound, release its
// resources
if (boundTexture == &gc->texture.ddtex.texobj) { glsrvUnbindDirectDrawTexture(gc); } else 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); }
__GL_DELAY_VALIDATE_MASK( gc, __GL_DIRTY_TEXTURE );
// We can avoid dirtying generic if the new texture has same
// properties as the old one...
if( !( gc->dirtyMask & __GL_DIRTY_GENERIC ) ) { // GL_DIRTY_GENERIC has not yet been set
__GLtexture *newTex = &texobj->texture.map; __GLtexture *oldTex = &boundTexture->texture.map;
if( (_DIFFERENT_TEX_PARAMS( newTex, oldTex )) || (_DIFFERENT_TEXDATA_FORMATS( newTex, oldTex )) || (texobj->targetIndex != boundTexture->targetIndex) ) { __GL_DELAY_VALIDATE( gc ); // dirty generic
} } } }
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); }
#ifdef GL_WIN_multiple_textures
void APIPRIVATE __glim_BindNthTextureWIN(GLuint index, GLenum target, GLuint texture) { } #endif // GL_WIN_multiple_textures
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 = __glClampf(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
// Keeping copies is not a good design. This
// should be improved
for (targetIndex = 0, pBoundTexture = gc->texture.boundTextures; targetIndex < (GLuint)gc->constants.numberOfTextures; targetIndex++, pBoundTexture++) { /* Is the texture currently bound? */ if (*pBoundTexture != &gc->texture.ddtex.texobj && (*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
/******************************Public*Routine******************************\
* * glsrvBindDirectDrawTexture * * Make the DirectDraw texture data in gc->texture the current 2D texture * * History: * Wed Sep 04 11:35:59 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL APIENTRY glsrvBindDirectDrawTexture(__GLcontext *gc, int levels, LPDIRECTDRAWSURFACE *apdds, DDSURFACEDESC *pddsd, ULONG flags) { __GLmipMapLevel *lev; __GLtexture *tex; GLint levIndex; GLint width, height; GLint wlog2, hlog2; __GLddrawTexture *pddtex;
ASSERTOPENGL(levels <= gc->constants.maxMipMapLevel, "Too many levels in DDraw texture\n");
// Bind the fake DDraw texture.
__glBindTexture(gc, __GL_TEX_TARGET_INDEX_DDRAW, __GL_TEX_DDRAW, GL_FALSE);
pddtex = &gc->texture.ddtex; tex = &pddtex->texobj.texture.map;
pddtex->levels = levels; memcpy(gc->texture.ddtex.pdds, apdds, levels*sizeof(LPDIRECTDRAWSURFACE)); pddtex->gdds.pdds = apdds[0]; pddtex->gdds.ddsd = *pddsd; pddtex->gdds.dwBitDepth = DdPixDepthToCount(pddsd->ddpfPixelFormat.dwRGBBitCount); pddtex->flags = flags;
// Fill out the DirectDraw texture data
width = (GLint)pddtex->gdds.ddsd.dwWidth; wlog2 = __glIntLog2(width); height = (GLint)pddtex->gdds.ddsd.dwHeight; hlog2 = __glIntLog2(height);
if (wlog2 > hlog2) { tex->p = wlog2; } else { tex->p = hlog2; }
lev = tex->level; for (levIndex = 0; levIndex < gc->texture.ddtex.levels; levIndex++) { // Buffer pointer is filled in at attention time.
// If we're going to pass this texture to the MCD then we
// fill in the surface handles at this time so they're
// given to the driver at create time.
if (flags & DDTEX_VIDEO_MEMORY) { lev->buffer = (__GLtextureBuffer *) ((LPDDRAWI_DDRAWSURFACE_INT)apdds[levIndex])-> lpLcl->hDDSurface; } else { lev->buffer = NULL; }
lev->width = width; lev->height = height; lev->width2 = width; lev->height2 = height; lev->width2f = (__GLfloat)width; lev->height2f = (__GLfloat)height; lev->widthLog2 = wlog2; lev->heightLog2 = hlog2; lev->border = 0;
lev->luminanceSize = 0; lev->intensitySize = 0;
if (pddtex->gdds.ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { lev->requestedFormat = tex->paletteRequestedFormat; lev->baseFormat = tex->paletteBaseFormat; lev->internalFormat = GL_COLOR_INDEX8_EXT;
__glSetPaletteLevelExtract8(tex, lev, 0);
lev->redSize = 0; lev->greenSize = 0; lev->blueSize = 0; lev->alphaSize = 0; } else { if (pddtex->gdds.ddsd.ddsCaps.dwCaps & DDSCAPS_ALPHA) { lev->requestedFormat = GL_RGBA; lev->baseFormat = GL_RGBA; } else { lev->requestedFormat = GL_RGB; lev->baseFormat = GL_RGB; } lev->internalFormat = GL_BGRA_EXT;
lev->extract = __glExtractTexelBGRA8;
lev->redSize = 8; lev->greenSize = 8; lev->blueSize = 8; lev->alphaSize = 8; }
if (width != 1) { width >>= 1; wlog2--; } if (height != 1) { height >>= 1; hlog2--; }
lev++; }
// If the texture is in VRAM then attempt to create an MCD handle for it.
// This must be done before palette operations so that
// the loadKey is set.
if (flags & DDTEX_VIDEO_MEMORY) { pddtex->texobj.loadKey = __glGenLoadTexture(gc, tex, MCDTEXTURE_DIRECTDRAW_SURFACES);
// Remove handles that were set earlier.
lev = tex->level; for (levIndex = 0; levIndex < gc->texture.ddtex.levels; levIndex++) { lev->buffer = NULL; lev++; } } else { pddtex->texobj.loadKey = 0; }
// Pick up palette for paletted surface
if (pddtex->gdds.ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { LPDIRECTDRAWPALETTE pddp; HRESULT hr;
hr = pddtex->gdds.pdds->lpVtbl-> GetPalette(pddtex->gdds.pdds, &pddp); if (hr == DD_OK && pddp != NULL) { PALETTEENTRY pe[256];
if (pddp->lpVtbl->GetEntries(pddp, 0, 0, 256, pe) == DD_OK) { __glim_ColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256, GL_RGBA, GL_UNSIGNED_BYTE, pe, GL_FALSE); }
pddp->lpVtbl->Release(pddp); } }
// If we have a loadKey, make the texture current
if (pddtex->texobj.loadKey != 0) { __glGenMakeTextureCurrent(gc, tex, pddtex->texobj.loadKey); }
__GL_DELAY_VALIDATE(gc);
return TRUE; }
/******************************Public*Routine******************************\
* * glsrvUnbindDirectDrawTexture * * Cleans up DirectDraw texture data * * History: * Wed Sep 04 13:45:08 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void APIENTRY glsrvUnbindDirectDrawTexture(__GLcontext *gc) { GLint i; __GLddrawTexture *pddtex; __GLGENcontext *gengc = (__GLGENcontext *)gc;
pddtex = &gc->texture.ddtex;
// Make sure a texture is bound
if (pddtex->levels <= 0) { return; }
// Delete any MCD information
if (pddtex->texobj.loadKey != 0) { __glGenFreeTexture(gc, &pddtex->texobj.texture.map, pddtex->texobj.loadKey); pddtex->texobj.loadKey = 0; }
for (i = 0; i < pddtex->levels; i++) { // If we're currently in an attention then we locked the texture
// surfaces and need to unlock them before we release them.
//
// Since there's no way to bind new DD textures in a batch, we
// are guaranteed to have had the texture active at the beginning
// of the batch and therefore we're guaranteed to have the texture
// locks.
if (gengc->fsLocks & LOCKFLAG_DD_TEXTURE) { DDSUNLOCK(pddtex->pdds[i], pddtex->texobj.texture.map.level[i].buffer); #if DBG
pddtex->texobj.texture.map.level[i].buffer = NULL; #endif
}
pddtex->pdds[i]->lpVtbl-> Release(pddtex->pdds[i]); #if DBG
pddtex->pdds[i] = NULL; #endif
}
#if DBG
memset(&pddtex->gdds, 0, sizeof(pddtex->gdds)); #endif
pddtex->levels = 0; if (gengc->fsGenLocks & LOCKFLAG_DD_TEXTURE) { gengc->fsGenLocks &= ~LOCKFLAG_DD_TEXTURE; gengc->fsLocks &= ~LOCKFLAG_DD_TEXTURE; }
__GL_DELAY_VALIDATE(gc); }
|