📄 teximage.c
字号:
}
/**
* Return pointer to the specified proxy texture image.
* Note that proxy textures are per-context, not per-texture unit.
* \return pointer to texture image or NULL if invalid target, invalid
* level, or out of memory.
*/
struct gl_texture_image *
_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
{
struct gl_texture_image *texImage;
if (level < 0 )
return NULL;
switch (target) {
case GL_PROXY_TEXTURE_1D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
texImage = ctx->Texture.Proxy1D->Image[0][level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.Proxy1D->Image[0][level] = texImage;
/* Set the 'back' pointer */
texImage->TexObject = ctx->Texture.Proxy1D;
}
return texImage;
case GL_PROXY_TEXTURE_2D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
texImage = ctx->Texture.Proxy2D->Image[0][level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.Proxy2D->Image[0][level] = texImage;
/* Set the 'back' pointer */
texImage->TexObject = ctx->Texture.Proxy2D;
}
return texImage;
case GL_PROXY_TEXTURE_3D:
if (level >= ctx->Const.Max3DTextureLevels)
return NULL;
texImage = ctx->Texture.Proxy3D->Image[0][level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.Proxy3D->Image[0][level] = texImage;
/* Set the 'back' pointer */
texImage->TexObject = ctx->Texture.Proxy3D;
}
return texImage;
case GL_PROXY_TEXTURE_CUBE_MAP:
if (level >= ctx->Const.MaxCubeTextureLevels)
return NULL;
texImage = ctx->Texture.ProxyCubeMap->Image[0][level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.ProxyCubeMap->Image[0][level] = texImage;
/* Set the 'back' pointer */
texImage->TexObject = ctx->Texture.ProxyCubeMap;
}
return texImage;
case GL_PROXY_TEXTURE_RECTANGLE_NV:
if (level > 0)
return NULL;
texImage = ctx->Texture.ProxyRect->Image[0][level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.ProxyRect->Image[0][level] = texImage;
/* Set the 'back' pointer */
texImage->TexObject = ctx->Texture.ProxyRect;
}
return texImage;
default:
return NULL;
}
}
/**
* Get the maximum number of allowed mipmap levels.
*
* \param ctx GL context.
* \param target texture target.
*
* \return the maximum number of allowed mipmap levels for the given
* texture target, or zero if passed a bad target.
*
* \sa gl_constants.
*/
GLint
_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
return ctx->Const.MaxTextureLevels;
case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
return ctx->Const.Max3DTextureLevels;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_ARB:
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
return ctx->Const.MaxCubeTextureLevels;
case GL_TEXTURE_RECTANGLE_NV:
case GL_PROXY_TEXTURE_RECTANGLE_NV:
return 1;
default:
return 0; /* bad target */
}
}
#if 000 /* not used anymore */
/*
* glTexImage[123]D can accept a NULL image pointer. In this case we
* create a texture image with unspecified image contents per the OpenGL
* spec.
*/
static GLubyte *
make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
{
const GLint components = _mesa_components_in_format(format);
const GLint numPixels = width * height * depth;
GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
#ifdef DEBUG
/*
* Let's see if anyone finds this. If glTexImage2D() is called with
* a NULL image pointer then load the texture image with something
* interesting instead of leaving it indeterminate.
*/
if (data) {
static const char message[8][32] = {
" X X XXXXX XXX X ",
" XX XX X X X X X ",
" X X X X X X X ",
" X X XXXX XXX XXXXX ",
" X X X X X X ",
" X X X X X X X ",
" X X XXXXX XXX X X ",
" "
};
GLubyte *imgPtr = data;
GLint h, i, j, k;
for (h = 0; h < depth; h++) {
for (i = 0; i < height; i++) {
GLint srcRow = 7 - (i % 8);
for (j = 0; j < width; j++) {
GLint srcCol = j % 32;
GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
for (k = 0; k < components; k++) {
*imgPtr++ = texel;
}
}
}
}
}
#endif
return data;
}
#endif
/**
* Reset the fields of a gl_texture_image struct to zero.
*
* \param img texture image structure.
*
* This is called when a proxy texture test fails, we set all the
* image members (except DriverData) to zero.
* It's also used in glTexImage[123]D as a safeguard to be sure all
* required fields get initialized properly by the Driver.TexImage[123]D
* functions.
*/
static void
clear_teximage_fields(struct gl_texture_image *img)
{
ASSERT(img);
img->Format = 0;
img->IntFormat = 0;
img->Border = 0;
img->Width = 0;
img->Height = 0;
img->Depth = 0;
img->RowStride = 0;
img->Width2 = 0;
img->Height2 = 0;
img->Depth2 = 0;
img->WidthLog2 = 0;
img->HeightLog2 = 0;
img->DepthLog2 = 0;
img->Data = NULL;
img->TexFormat = &_mesa_null_texformat;
img->FetchTexelc = NULL;
img->FetchTexelf = NULL;
img->IsCompressed = 0;
img->CompressedSize = 0;
}
/**
* Initialize basic fields of the gl_texture_image struct.
*
* \param ctx GL context.
* \param target texture target.
* \param img texture image structure to be initialized.
* \param width image width.
* \param height image height.
* \param depth image depth.
* \param border image border.
* \param internalFormat internal format.
*
* Fills in the fields of \p img with the given information.
* Note: width, height and depth include the border.
*/
void
_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
struct gl_texture_image *img,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum internalFormat)
{
ASSERT(img);
img->Format = _mesa_base_tex_format( ctx, internalFormat );
ASSERT(img->Format > 0);
img->IntFormat = internalFormat;
img->Border = border;
img->Width = width;
img->Height = height;
img->Depth = depth;
img->RowStride = width;
img->WidthLog2 = logbase2(width - 2 * border);
if (height == 1) /* 1-D texture */
img->HeightLog2 = 0;
else
img->HeightLog2 = logbase2(height - 2 * border);
if (depth == 1) /* 2-D texture */
img->DepthLog2 = 0;
else
img->DepthLog2 = logbase2(depth - 2 * border);
img->Width2 = width - 2 * border; /*1 << img->WidthLog2;*/
img->Height2 = height - 2 * border; /*1 << img->HeightLog2;*/
img->Depth2 = depth - 2 * border; /*1 << img->DepthLog2;*/
img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
img->IsCompressed = is_compressed_format(ctx, internalFormat);
if (img->IsCompressed)
img->CompressedSize = ctx->Driver.CompressedTextureSize(ctx, width,
height, depth, internalFormat);
else
img->CompressedSize = 0;
if ((width == 1 || _mesa_bitcount(width - 2 * border) == 1) &&
(height == 1 || _mesa_bitcount(height - 2 * border) == 1) &&
(depth == 1 || _mesa_bitcount(depth - 2 * border) == 1))
img->_IsPowerOfTwo = GL_TRUE;
else
img->_IsPowerOfTwo = GL_FALSE;
/* Compute Width/Height/DepthScale for mipmap lod computation */
if (target == GL_TEXTURE_RECTANGLE_NV) {
/* scale = 1.0 since texture coords directly map to texels */
img->WidthScale = 1.0;
img->HeightScale = 1.0;
img->DepthScale = 1.0;
}
else {
img->WidthScale = (GLfloat) img->Width;
img->HeightScale = (GLfloat) img->Height;
img->DepthScale = (GLfloat) img->Depth;
}
}
/**
* This is the fallback for Driver.TestProxyTexImage(). Test the texture
* level, width, height and depth against the ctx->Const limits for textures.
*
* A hardware driver might override this function if, for example, the
* max 3D texture size is 512x512x64 (i.e. not a cube).
*
* \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
* GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
* GL_PROXY_TEXTURE_CUBE_MAP_ARB.
* \param level as passed to glTexImage
* \param internalFormat as passed to glTexImage
* \param format as passed to glTexImage
* \param type as passed to glTexImage
* \param width as passed to glTexImage
* \param height as passed to glTexImage
* \param depth as passed to glTexImage
* \param border as passed to glTexImage
* \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
*/
GLboolean
_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat, GLenum format, GLenum type,
GLint width, GLint height, GLint depth, GLint border)
{
GLint maxSize;
(void) internalFormat;
(void) format;
(void) type;
switch (target) {
case GL_PROXY_TEXTURE_1D:
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
if (width < 2 * border || width > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(width - 2 * border) != 1) ||
level >= ctx->Const.MaxTextureLevels) {
/* bad width or level */
return GL_FALSE;
}
return GL_TRUE;
case GL_PROXY_TEXTURE_2D:
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
if (width < 2 * border || width > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(width - 2 * border) != 1) ||
height < 2 * border || height > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(height - 2 * border) != 1) ||
level >= ctx->Const.MaxTextureLevels) {
/* bad width or height or level */
return GL_FALSE;
}
return GL_TRUE;
case GL_PROXY_TEXTURE_3D:
maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
if (width < 2 * border || width > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(width - 2 * border) != 1) ||
height < 2 * border || height > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(height - 2 * border) != 1) ||
depth < 2 * border || depth > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(depth - 2 * border) != 1) ||
level >= ctx->Const.Max3DTextureLevels) {
/* bad width or height or depth or level */
return GL_FALSE;
}
return GL_TRUE;
case GL_PROXY_TEXTURE_RECTANGLE_NV:
if (width < 1 || width > ctx->Const.MaxTextureRectSize ||
height < 1 || height > ctx->Const.MaxTextureRectSize ||
level != 0) {
/* bad width or height or level */
return GL_FALSE;
}
return GL_TRUE;
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
if (width < 2 * border || width > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(width - 2 * border) != 1) ||
height < 2 * border || height > 2 + maxSize ||
(!ctx->Extensions.ARB_texture_non_power_of_two &&
_mesa_bitcount(height - 2 * border) != 1) ||
level >= ctx->Const.MaxCubeTextureLevels) {
/* bad width or height */
return GL_FALSE;
}
return GL_TRUE;
default:
_mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
return GL_FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -