-/**
- * \file teximage.c
- * Texture images manipulation functions.
- *
- * \note Mesa's native texture data type is GLchan. Native formats are
- * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, and
- * GL_COLOR_INDEX.
- *
- * \note Device drivers are free to implement any internal format they want.
- */
-
/*
* Mesa 3-D graphics library
- * Version: 5.1
+ * Version: 6.5
*
- * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*/
+/**
+ * \file teximage.c
+ * Texture image-related functions.
+ */
+
+
#include "glheader.h"
+#include "bufferobj.h"
#include "context.h"
#include "convolve.h"
+#include "fbobject.h"
+#include "framebuffer.h"
#include "image.h"
#include "imports.h"
#include "macros.h"
#include "mtypes.h"
+/**
+ * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
+ * elsewhere.
+ */
+void *
+_mesa_alloc_texmemory(GLsizei bytes)
+{
+ return _mesa_align_malloc(bytes, 512);
+}
+
+
+/**
+ * Free texture memory allocated with _mesa_alloc_texmemory()
+ */
+void
+_mesa_free_texmemory(void *m)
+{
+ _mesa_align_free(m);
+}
+
+
+
+
#if 0
static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
{
_mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
data += (img->RowStride - img->Width) * c;
}
+ /* XXX use img->ImageStride here */
_mesa_printf("\n");
}
#endif
/**
- * Get base internal format.
+ * Return the simple base format for a given internal texture format.
+ * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
*
* \param ctx GL context.
- * \param format internal texture format enum or 1, 2, 3, 4.
+ * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
*
* \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
* GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
* texture format and env mode determine the arithmetic used.
*/
GLint
-_mesa_base_tex_format( GLcontext *ctx, GLint format )
+_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
{
- /*
- * Ask the driver for the base format, if it doesn't
- * know, it will return -1;
- */
- switch (format) {
+ switch (internalFormat) {
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_RGBA12:
case GL_RGBA16:
return GL_RGBA;
- case GL_COLOR_INDEX:
- 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 (ctx->Extensions.EXT_paletted_texture)
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.EXT_paletted_texture) {
+ switch (internalFormat) {
+ case GL_COLOR_INDEX:
+ 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:
return GL_COLOR_INDEX;
- else
- return -1;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_SGIX:
- case GL_DEPTH_COMPONENT24_SGIX:
- case GL_DEPTH_COMPONENT32_SGIX:
- if (ctx->Extensions.SGIX_depth_texture)
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.SGIX_depth_texture ||
+ ctx->Extensions.ARB_depth_texture) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16_SGIX:
+ case GL_DEPTH_COMPONENT24_SGIX:
+ case GL_DEPTH_COMPONENT32_SGIX:
return GL_DEPTH_COMPONENT;
- else
- return -1;
+ default:
+ ; /* fallthrough */
+ }
+ }
- /* GL_ARB_texture_compression */
- case GL_COMPRESSED_ALPHA:
- if (ctx->Extensions.ARB_texture_compression)
+ if (ctx->Extensions.ARB_texture_compression) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA:
return GL_ALPHA;
- else
- return -1;
- case GL_COMPRESSED_LUMINANCE:
- if (ctx->Extensions.ARB_texture_compression)
+ case GL_COMPRESSED_LUMINANCE:
return GL_LUMINANCE;
- else
- return -1;
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- if (ctx->Extensions.ARB_texture_compression)
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
return GL_LUMINANCE_ALPHA;
- else
- return -1;
- case GL_COMPRESSED_INTENSITY:
- if (ctx->Extensions.ARB_texture_compression)
+ case GL_COMPRESSED_INTENSITY:
return GL_INTENSITY;
- else
- return -1;
- case GL_COMPRESSED_RGB:
- if (ctx->Extensions.ARB_texture_compression)
+ case GL_COMPRESSED_RGB:
return GL_RGB;
- else
- return -1;
- case GL_COMPRESSED_RGBA:
- if (ctx->Extensions.ARB_texture_compression)
+ case GL_COMPRESSED_RGBA:
return GL_RGBA;
- else
- return -1;
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
return GL_RGB;
- else
- return -1;
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
- if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
return GL_RGBA;
- else
- return -1;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- if (ctx->Extensions.EXT_texture_compression_s3tc)
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return GL_RGB;
- else
- return -1;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- if (ctx->Extensions.EXT_texture_compression_s3tc)
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return GL_RGBA;
- else
- return -1;
+ default:
+ ; /* fallthrough */
+ }
+ }
- case GL_YCBCR_MESA:
- if (ctx->Extensions.MESA_ycbcr_texture)
- return GL_YCBCR_MESA;
- else
- return -1;
+ if (ctx->Extensions.S3_s3tc) {
+ switch (internalFormat) {
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ return GL_RGB;
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
- default:
- return -1; /* error */
+ if (ctx->Extensions.MESA_ycbcr_texture) {
+ if (internalFormat == GL_YCBCR_MESA)
+ return GL_YCBCR_MESA;
}
+
+ if (ctx->Extensions.ARB_texture_float) {
+ switch (internalFormat) {
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ return GL_ALPHA;
+ case GL_RGBA16F_ARB:
+ case GL_RGBA32F_ARB:
+ return GL_RGBA;
+ case GL_RGB16F_ARB:
+ case GL_RGB32F_ARB:
+ return GL_RGB;
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ return GL_INTENSITY;
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return GL_LUMINANCE_ALPHA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_packed_depth_stencil) {
+ switch (internalFormat) {
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return GL_DEPTH_STENCIL_EXT;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ return -1; /* error */
}
/**
- * Test if the given image format is a color/RGBA format, i.e., not
- * color index, depth, stencil, etc.
+ * Test if the given image format is a color/RGBA format (i.e., not color
+ * index, depth, stencil, etc).
+ * \param format the image format value (may by an internal texture format)
+ * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
*/
static GLboolean
is_color_format(GLenum format)
{
switch (format) {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_INTENSITY16:
case 3:
case GL_RGB:
+ case GL_BGR:
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
case GL_RGB12:
case GL_RGB16:
case 4:
+ case GL_ABGR_EXT:
case GL_RGBA:
+ case GL_BGRA:
case GL_RGBA2:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
+ /* float texture formats */
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ case GL_RGB16F_ARB:
+ case GL_RGB32F_ARB:
+ case GL_RGBA16F_ARB:
+ case GL_RGBA32F_ARB:
+ /* compressed formats */
+ case GL_COMPRESSED_ALPHA:
+ case GL_COMPRESSED_LUMINANCE:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ case GL_COMPRESSED_INTENSITY:
+ case GL_COMPRESSED_RGB:
+ case GL_COMPRESSED_RGBA:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
return GL_TRUE;
case GL_YCBCR_MESA: /* not considered to be RGB */
default:
}
+/**
+ * Test if the given image format is a depth component format.
+ */
+static GLboolean
+is_depth_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT16_ARB:
+ case GL_DEPTH_COMPONENT24_ARB:
+ case GL_DEPTH_COMPONENT32_ARB:
+ case GL_DEPTH_COMPONENT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a YCbCr format.
+ */
+static GLboolean
+is_ycbcr_format(GLenum format)
+{
+ switch (format) {
+ case GL_YCBCR_MESA:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a Depth/Stencil format.
+ */
+static GLboolean
+is_depthstencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH24_STENCIL8_EXT:
+ case GL_DEPTH_STENCIL_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+
/**
* Test if it is a supported compressed format.
*
static GLboolean
is_compressed_format(GLcontext *ctx, GLenum internalFormat)
{
+ (void) ctx;
switch (internalFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
case GL_COMPRESSED_RGBA_FXT1_3DFX:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
return GL_TRUE;
default:
- if (ctx->Driver.IsCompressedFormat) {
- return ctx->Driver.IsCompressedFormat(ctx, internalFormat);
- }
return GL_FALSE;
}
}
+static GLuint
+texture_face(GLenum target)
+{
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
+ return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ else
+ return 0;
+}
+
+
+
/**
* Store a gl_texture_image pointer in a gl_texture_object structure
* according to the target and level parameters.
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
- tObj->Image[level] = texImage;
- return;
+ tObj->Image[0][level] = texImage;
+ break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- tObj->Image[level] = texImage;
- return;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- tObj->NegX[level] = texImage;
- return;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- tObj->PosY[level] = texImage;
- return;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- tObj->NegY[level] = texImage;
- return;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- tObj->PosZ[level] = texImage;
- return;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- tObj->NegZ[level] = texImage;
- return;
+ {
+ GLuint face = ((GLuint) target -
+ (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
+ tObj->Image[face][level] = texImage;
+ }
+ break;
case GL_TEXTURE_RECTANGLE_NV:
ASSERT(level == 0);
- tObj->Image[level] = texImage;
- return;
+ tObj->Image[0][level] = texImage;
+ break;
default:
_mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
return;
}
+ /* Set the 'back' pointer */
+ texImage->TexObject = tObj;
}
}
+/**
+ * Free texture image data.
+ * This function is a fallback called via ctx->Driver.FreeTexImageData().
+ *
+ * \param teximage texture image.
+ *
+ * Free the texture image data if it's not marked as client data.
+ */
+void
+_mesa_free_texture_image_data(GLcontext *ctx,
+ struct gl_texture_image *texImage)
+{
+ if (texImage->Data && !texImage->IsClientData) {
+ /* free the old texture data */
+ _mesa_free_texmemory(texImage->Data);
+ }
+
+ texImage->Data = NULL;
+}
+
+
/**
* Free texture image.
*
* \param teximage texture image.
*
- * Free the texture image structure and the associated image data if it's not
- * marked as client data.
+ * Free the texture image structure and the associated image data.
*/
void
-_mesa_delete_texture_image( struct gl_texture_image *teximage )
+_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
{
- if (teximage->Data && !teximage->IsClientData) {
- MESA_PBUFFER_FREE( teximage->Data );
- teximage->Data = NULL;
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- FREE( teximage );
+ ASSERT(texImage->Data == NULL);
+ FREE( texImage );
}
*
* \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
*/
-static GLboolean
-is_proxy_target(GLenum target)
+GLboolean
+_mesa_is_proxy_texture(GLenum target)
{
return (target == GL_PROXY_TEXTURE_1D ||
target == GL_PROXY_TEXTURE_2D ||
ASSERT(level < MAX_TEXTURE_LEVELS);
switch (target) {
case GL_TEXTURE_1D:
- return texUnit->Current1D->Image[level];
+ return texUnit->Current1D->Image[0][level];
case GL_PROXY_TEXTURE_1D:
- return ctx->Texture.Proxy1D->Image[level];
+ return ctx->Texture.Proxy1D->Image[0][level];
case GL_TEXTURE_2D:
- return texUnit->Current2D->Image[level];
+ return texUnit->Current2D->Image[0][level];
case GL_PROXY_TEXTURE_2D:
- return ctx->Texture.Proxy2D->Image[level];
+ return ctx->Texture.Proxy2D->Image[0][level];
case GL_TEXTURE_3D:
- return texUnit->Current3D->Image[level];
+ return texUnit->Current3D->Image[0][level];
case GL_PROXY_TEXTURE_3D:
- return ctx->Texture.Proxy3D->Image[level];
+ return ctx->Texture.Proxy3D->Image[0][level];
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texUnit->CurrentCubeMap->Image[level];
- else
- return NULL;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texUnit->CurrentCubeMap->NegX[level];
- else
- return NULL;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texUnit->CurrentCubeMap->PosY[level];
- else
- return NULL;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texUnit->CurrentCubeMap->NegY[level];
- else
- return NULL;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texUnit->CurrentCubeMap->PosZ[level];
- else
- return NULL;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texUnit->CurrentCubeMap->NegZ[level];
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ GLuint face = ((GLuint) target -
+ (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
+ return texUnit->CurrentCubeMap->Image[face][level];
+ }
else
return NULL;
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
if (ctx->Extensions.ARB_texture_cube_map)
- return ctx->Texture.ProxyCubeMap->Image[level];
+ return ctx->Texture.ProxyCubeMap->Image[0][level];
else
return NULL;
case GL_TEXTURE_RECTANGLE_NV:
if (ctx->Extensions.NV_texture_rectangle) {
ASSERT(level == 0);
- return texUnit->CurrentRect->Image[level];
+ return texUnit->CurrentRect->Image[0][level];
}
else {
return NULL;
case GL_PROXY_TEXTURE_RECTANGLE_NV:
if (ctx->Extensions.NV_texture_rectangle) {
ASSERT(level == 0);
- return ctx->Texture.ProxyRect->Image[level];
+ return ctx->Texture.ProxyRect->Image[0][level];
}
else {
return NULL;
case GL_PROXY_TEXTURE_1D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
- texImage = ctx->Texture.Proxy1D->Image[level];
+ 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[level] = texImage;
+ 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[level];
+ 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[level] = texImage;
+ 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[level];
+ 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[level] = texImage;
+ 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[level];
+ 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[level] = texImage;
+ 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[level];
+ 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[level] = texImage;
+ ctx->Texture.ProxyRect->Image[0][level] = texImage;
+ /* Set the 'back' pointer */
+ texImage->TexObject = ctx->Texture.ProxyRect;
}
return texImage;
default:
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;
- break;
case GL_TEXTURE_RECTANGLE_NV:
case GL_PROXY_TEXTURE_RECTANGLE_NV:
return 1;
- break;
default:
return 0; /* bad target */
}
clear_teximage_fields(struct gl_texture_image *img)
{
ASSERT(img);
- img->Format = 0;
- img->IntFormat = 0;
+ img->_BaseFormat = 0;
+ img->InternalFormat = 0;
img->Border = 0;
img->Width = 0;
img->Height = 0;
img->Depth = 0;
img->RowStride = 0;
+ img->ImageStride = 0;
img->Width2 = 0;
img->Height2 = 0;
img->Depth2 = 0;
img->DepthLog2 = 0;
img->Data = NULL;
img->TexFormat = &_mesa_null_texformat;
- img->FetchTexel = NULL;
+ img->FetchTexelc = NULL;
+ img->FetchTexelf = NULL;
img->IsCompressed = 0;
img->CompressedSize = 0;
}
GLint border, GLenum internalFormat)
{
ASSERT(img);
- img->Format = _mesa_base_tex_format( ctx, internalFormat );
- ASSERT(img->Format > 0);
- img->IntFormat = internalFormat;
+ img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
+ ASSERT(img->_BaseFormat > 0);
+ img->InternalFormat = internalFormat;
img->Border = border;
img->Width = width;
img->Height = height;
img->Depth = depth;
img->RowStride = width;
- img->WidthLog2 = logbase2(width - 2 * border);
+ img->ImageStride = width * height;
+ 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->WidthLog2 = logbase2(img->Width2);
if (height == 1) /* 1-D texture */
img->HeightLog2 = 0;
else
- img->HeightLog2 = logbase2(height - 2 * border);
+ img->HeightLog2 = logbase2(img->Height2);
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->DepthLog2 = logbase2(img->Depth2);
img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
- img->IsCompressed = is_compressed_format(ctx, internalFormat);
- if (img->IsCompressed)
- img->CompressedSize = _mesa_compressed_texture_size(ctx, width, height,
- depth, internalFormat);
- else
- img->CompressedSize = 0;
+ img->IsCompressed = GL_FALSE;
+ 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))
+ if ((width == 1 || _mesa_bitcount(img->Width2) == 1) &&
+ (height == 1 || _mesa_bitcount(img->Height2) == 1) &&
+ (depth == 1 || _mesa_bitcount(img->Depth2) == 1))
img->_IsPowerOfTwo = GL_TRUE;
else
img->_IsPowerOfTwo = GL_FALSE;
GLint width, GLint height,
GLint depth, GLint border )
{
- const GLboolean isProxy = is_proxy_target(target);
+ const GLboolean isProxy = _mesa_is_proxy_texture(target);
GLboolean sizeOK;
+ GLboolean colorFormat, indexFormat;
/* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
}
/* Check incoming image format and type */
- if (!_mesa_is_legal_format_and_type(format, type)) {
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
/* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
* is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
*/
return GL_TRUE;
}
- if (format == GL_YCBCR_MESA || internalFormat == GL_YCBCR_MESA) {
+ /* make sure internal format and format basically agree */
+ colorFormat = is_color_format(format);
+ indexFormat = is_index_format(format);
+ if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
+ (is_index_format(internalFormat) && !indexFormat) ||
+ (is_depth_format(internalFormat) != is_depth_format(format)) ||
+ (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
+ (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage(internalFormat/format)");
+ return GL_TRUE;
+ }
+
+ /* additional checks for ycbcr textures */
+ if (internalFormat == GL_YCBCR_MESA) {
ASSERT(ctx->Extensions.MESA_ycbcr_texture);
- if (format != GL_YCBCR_MESA ||
- internalFormat != GL_YCBCR_MESA ||
- (type != GL_UNSIGNED_SHORT_8_8_MESA &&
- type != GL_UNSIGNED_SHORT_8_8_REV_MESA)) {
+ if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
+ type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
char message[100];
_mesa_sprintf(message,
- "glTexImage%d(format/type/internalFormat YCBCR mismatch",
- dimensions);
+ "glTexImage%d(format/type YCBCR mismatch", dimensions);
_mesa_error(ctx, GL_INVALID_ENUM, message);
return GL_TRUE; /* error */
}
}
}
+ /* additional checks for depth textures */
+ if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
+ /* Only 1D and 2D textures supported */
+ if (target != GL_TEXTURE_1D &&
+ target != GL_PROXY_TEXTURE_1D &&
+ target != GL_TEXTURE_2D &&
+ target != GL_PROXY_TEXTURE_2D) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage(target/internalFormat)");
+ return GL_TRUE;
+ }
+ }
+
+ /* additional checks for compressed textures */
if (is_compressed_format(ctx, internalFormat)) {
if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
/* OK */
}
}
- if (!_mesa_is_legal_format_and_type(format, type)) {
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glTexSubImage%dD(format or type)", dimensions);
return GL_TRUE;
GLenum target, GLint level, GLint internalFormat,
GLint width, GLint height, GLint border )
{
- GLenum format, type;
+ GLenum type;
GLboolean sizeOK;
+ GLint format;
/* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ /* Check that the source buffer is complete */
+ if (ctx->ReadBuffer->Name) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyTexImage%dD(invalid readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
_mesa_error(ctx, GL_INVALID_VALUE,
"glCopyTexImage%dD(level=%d)", dimensions, level);
return GL_TRUE;
return GL_TRUE;
}
- /* The format and type aren't really significant here, but we need to pass
- * something to TestProxyTexImage().
- */
format = _mesa_base_tex_format(ctx, internalFormat);
+ if (format < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage%dD(internalFormat)", dimensions);
+ return GL_TRUE;
+ }
+
+ /* NOTE: the format and type aren't really significant for
+ * TestProxyTexImage(). Only the internalformat really matters.
+ if (!_mesa_source_buffer_exists(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(missing readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+
+ */
type = GL_FLOAT;
/* Check target and call ctx->Driver.TestProxyTexImage() to check the
return GL_TRUE;
}
- if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage%dD(internalFormat)", dimensions);
- return GL_TRUE;
- }
-
if (is_compressed_format(ctx, internalFormat)) {
if (target != GL_TEXTURE_2D) {
_mesa_error(ctx, GL_INVALID_ENUM,
return GL_TRUE;
}
}
+ else if (is_depth_format(internalFormat)) {
+ /* make sure we have depth/stencil buffers */
+ if (!ctx->ReadBuffer->_DepthBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%D(no depth)", dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (is_depthstencil_format(internalFormat)) {
+ /* make sure we have depth/stencil buffers */
+ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
/* if we get here, the parameters are OK */
return GL_FALSE;
/**
- * Test glCopyTexImage[12]D() parameters for errors.
+ * Test glCopyTexSubImage[12]D() parameters for errors.
*
* \param ctx GL context.
* \param dimensions texture image dimensions (must be 1, 2 or 3).
struct gl_texture_image *teximage;
/* Check target */
+ /* Check that the source buffer is complete */
+ if (ctx->ReadBuffer->Name) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyTexImage%dD(invalid readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
if (dimensions == 1) {
if (target != GL_TEXTURE_1D) {
_mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
}
if (teximage->IsCompressed) {
+ if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(missing readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+
if (target != GL_TEXTURE_2D) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glCopyTexSubImage%d(target)", dimensions);
}
}
- if (teximage->IntFormat == GL_YCBCR_MESA) {
+ if (teximage->InternalFormat == GL_YCBCR_MESA) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
return GL_TRUE;
}
+ if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
+ if (!ctx->ReadBuffer->_DepthBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%D(no depth buffer)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%D(no depth/stencil buffer)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+
/* if we get here, the parameters are OK */
return GL_FALSE;
}
/**
- * Get texture image.
+ * Get texture image. Called by glGetTexImage.
*
* \param target texture target.
* \param level image level.
- * \param format pixel data format.
- * \param type pixel data type.
- * \param pixels pixel data.
+ * \param format pixel data format for returned image.
+ * \param type pixel data type for returned image.
+ * \param pixels returned pixel data.
*/
void GLAPIENTRY
_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
GLenum type, GLvoid *pixels )
{
const struct gl_texture_unit *texUnit;
- const struct gl_texture_object *texObj;
- const struct gl_texture_image *texImage;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
GLint maxLevels = 0;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
- if (!texObj || is_proxy_target(target)) {
+ if (!texObj || _mesa_is_proxy_texture(target)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
return;
}
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
}
- if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) {
+ if (!ctx->Extensions.SGIX_depth_texture &&
+ !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
}
- if (!ctx->Extensions.MESA_ycbcr_texture && format == GL_YCBCR_MESA) {
+ if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
}
- /* XXX what if format/type doesn't match texture format/type? */
+ if (!ctx->Extensions.EXT_packed_depth_stencil
+ && is_depthstencil_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ }
if (!pixels)
return;
return;
}
- if (!texImage->Data) {
- /* no image data, not an error */
+ /* Make sure the requested image format is compatible with the
+ * texture's format. Note that a color index texture can be converted
+ * to RGBA so that combo is allowed.
+ */
+ if (is_color_format(format)
+ && !is_color_format(texImage->TexFormat->BaseFormat)
+ && !is_index_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return;
+ }
+ else if (is_index_format(format)
+ && !is_index_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return;
+ }
+ else if (is_depth_format(format)
+ && !is_depth_format(texImage->TexFormat->BaseFormat)
+ && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return;
+ }
+ else if (is_ycbcr_format(format)
+ && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return;
+ }
+ else if (is_depthstencil_format(format)
+ && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
return;
}
- {
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- GLint img, row;
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- /* compute destination address in client memory */
- GLvoid *dest = _mesa_image_address( &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- assert(dest);
-
- if (format == GL_COLOR_INDEX) {
- GLuint indexRow[MAX_WIDTH];
- GLint col;
- for (col = 0; col < width; col++) {
- (*texImage->FetchTexel)(texImage, col, row, img,
- (GLvoid *) &indexRow[col]);
- }
- _mesa_pack_index_span(ctx, width, type, dest,
- indexRow, &ctx->Pack,
- 0 /* no image transfer */);
- }
- else if (format == GL_DEPTH_COMPONENT) {
- GLfloat depthRow[MAX_WIDTH];
- GLint col;
- for (col = 0; col < width; col++) {
- (*texImage->FetchTexel)(texImage, col, row, img,
- (GLvoid *) &depthRow[col]);
- }
- _mesa_pack_depth_span(ctx, width, dest, type,
- depthRow, &ctx->Pack);
- }
- else if (format == GL_YCBCR_MESA) {
- /* No pixel transfer */
- const GLint rowstride = texImage->RowStride;
- MEMCPY(dest,
- (const GLushort *) texImage->Data + row * rowstride,
- width * sizeof(GLushort));
- /* check for byte swapping */
- if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
- && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
- (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
- && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
- if (!ctx->Pack.SwapBytes)
- _mesa_swap2((GLushort *) dest, width);
- }
- else if (ctx->Pack.SwapBytes) {
- _mesa_swap2((GLushort *) dest, width);
- }
- }
- else {
- /* general case: convert row to RGBA format */
- GLchan rgba[MAX_WIDTH][4];
- GLint col;
- for (col = 0; col < width; col++) {
- (*texImage->FetchTexel)(texImage, col, row, img,
- (GLvoid *) rgba[col]);
- }
- _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba,
- format, type, dest, &ctx->Pack,
- 0 /* no image transfer */);
- } /* format */
- } /* row */
- } /* img */
+ /* typically, this will call _mesa_get_teximage() */
+ ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+}
+
+
+
+/**
+ * Check if the given texture image is bound to any framebuffer objects
+ * and update/invalidate them.
+ * XXX We're only checking the currently bound framebuffer object for now.
+ * In the future, perhaps struct gl_texture_image should have a pointer (or
+ * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
+ */
+static void
+update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLuint face, GLuint level)
+{
+ if (ctx->DrawBuffer->Name) {
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att =
+ ctx->DrawBuffer->Attachment + i;
+ if (att->Type == GL_TEXTURE &&
+ att->Texture == texObj &&
+ att->TextureLevel == level &&
+ att->CubeMapFace == face) {
+ ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
+ /* Tell driver about the new renderbuffer texture */
+ ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
+ }
+ }
}
}
}
if (target == GL_TEXTURE_1D) {
+ /* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
+ const GLuint face = texture_face(target);
if (texture_error_check(ctx, target, level, internalFormat,
format, type, 1, postConvWidth, 1, 1, border)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- /* free the old texture data */
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
clear_teximage_fields(texImage); /* not really needed, but helpful */
_mesa_init_teximage_fields(ctx, target, texImage,
postConvWidth, 1, 1,
&ctx->Unpack, texObj, texImage);
ASSERT(texImage->TexFormat);
- if (!texImage->FetchTexel) {
- /* If driver didn't explicitly set this, use the default */
- texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
- }
- ASSERT(texImage->FetchTexel);
+
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
+ const GLuint face = texture_face(target);
if (texture_error_check(ctx, target, level, internalFormat,
format, type, 2, postConvWidth, postConvHeight,
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- /* free the old texture data */
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
clear_teximage_fields(texImage); /* not really needed, but helpful */
_mesa_init_teximage_fields(ctx, target, texImage,
postConvWidth, postConvHeight, 1,
&ctx->Unpack, texObj, texImage);
ASSERT(texImage->TexFormat);
- if (!texImage->FetchTexel) {
- /* If driver didn't explicitly set this, use the default */
- texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
- }
- ASSERT(texImage->FetchTexel);
+
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
1, border)) {
/* when error, clear all proxy texture image parameters */
if (texImage)
- clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
+ clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]);
}
else {
/* no error, set the tex image parameters */
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (target == GL_TEXTURE_3D) {
+ /* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
+ const GLuint face = texture_face(target);
if (texture_error_check(ctx, target, level, (GLint) internalFormat,
format, type, 3, width, height, depth, border)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
clear_teximage_fields(texImage); /* not really needed, but helpful */
_mesa_init_teximage_fields(ctx, target, texImage,
width, height, depth,
pixels, &ctx->Unpack, texObj, texImage);
ASSERT(texImage->TexFormat);
- if (!texImage->FetchTexel) {
- /* If driver didn't explicitly set this, use the default */
- texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
- }
- ASSERT(texImage->FetchTexel);
+
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
assert(texImage);
- if (width == 0 || !pixels)
+ if (width == 0)
return; /* no-op, not an error */
/* If we have a border, xoffset=-1 is legal. Bias by border width */
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
assert(texImage);
- if (width == 0 || height == 0 || !pixels)
+ if (width == 0 || height == 0)
return; /* no-op, not an error */
/* If we have a border, xoffset=-1 is legal. Bias by border width */
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
assert(texImage);
- if (width == 0 || height == 0 || height == 0 || !pixels)
+ if (width == 0 || height == 0 || height == 0)
return; /* no-op, not an error */
/* If we have a border, xoffset=-1 is legal. Bias by border width */
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLsizei postConvWidth = width;
+ const GLuint face = texture_face(target);
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- /* free the old texture data */
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
clear_teximage_fields(texImage); /* not really needed, but helpful */
_mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
x, y, width, border);
ASSERT(texImage->TexFormat);
- if (!texImage->FetchTexel) {
- /* If driver didn't explicitly set this, use the default */
- texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
- }
- ASSERT(texImage->FetchTexel);
+
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLsizei postConvWidth = width, postConvHeight = height;
+ const GLuint face = texture_face(target);
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- /* free the old texture data */
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
clear_teximage_fields(texImage); /* not really needed, but helpful */
_mesa_init_teximage_fields(ctx, target, texImage,
x, y, width, height, border);
ASSERT(texImage->TexFormat);
- if (!texImage->FetchTexel) {
- /* If driver didn't explicitly set this, use the default */
- texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
- }
- ASSERT(texImage->FetchTexel);
+
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
GLint xoffset, GLint x, GLint y, GLsizei width )
{
struct gl_texture_unit *texUnit;
- struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLsizei postConvWidth = width;
GET_CURRENT_CONTEXT(ctx);
return;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit;
- struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLsizei postConvWidth = width, postConvHeight = height;
GET_CURRENT_CONTEXT(ctx);
return;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit;
- struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLsizei postConvWidth = width, postConvHeight = height;
GET_CURRENT_CONTEXT(ctx);
return;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
GLsizei height, GLsizei depth, GLint border,
GLsizei imageSize)
{
- GLboolean isProxy = GL_FALSE;
- GLint expectedSize, maxLevels = 0, maxTextureSize;
+ GLint /**expectedSize,**/ maxLevels = 0, maxTextureSize;
if (dimensions == 1) {
/* 1D compressed textures not allowed */
else if (dimensions == 2) {
if (target == GL_PROXY_TEXTURE_2D) {
maxLevels = ctx->Const.MaxTextureLevels;
- isProxy = GL_TRUE;
}
else if (target == GL_TEXTURE_2D) {
maxLevels = ctx->Const.MaxTextureLevels;
if (!ctx->Extensions.ARB_texture_cube_map)
return GL_INVALID_ENUM; /*target*/
maxLevels = ctx->Const.MaxCubeTextureLevels;
- isProxy = GL_TRUE;
}
else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
if (!is_compressed_format(ctx, internalFormat))
return GL_INVALID_ENUM;
+ if (_mesa_base_tex_format(ctx, internalFormat) < 0)
+ return GL_INVALID_ENUM;
+
if (border != 0)
return GL_INVALID_VALUE;
* XXX We should probably use the proxy texture error check function here.
*/
if (width < 1 || width > maxTextureSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two && logbase2(width) < 0))
+ (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1))
return GL_INVALID_VALUE;
if ((height < 1 || height > maxTextureSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two && logbase2(height) < 0))
+ (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1))
&& dimensions > 1)
return GL_INVALID_VALUE;
if ((depth < 1 || depth > maxTextureSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two && logbase2(depth) < 0))
+ (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1))
&& dimensions > 2)
return GL_INVALID_VALUE;
if (level < 0 || level >= maxLevels)
return GL_INVALID_VALUE;
- expectedSize = _mesa_compressed_texture_size(ctx, width, height, depth,
- internalFormat);
+#if 0
+ /* XXX need to renable this code someday! */
+ expectedSize = ctx->Driver.CompressedTextureSize(ctx, width, height, depth,
+ internalFormat);
if (expectedSize != imageSize)
return GL_INVALID_VALUE;
+#endif
return GL_NO_ERROR;
}
/**
* Error checking for glCompressedTexSubImage[123]D().
+ * \warning There are some bad assumptions here about the size of compressed
+ * texture tiles (multiple of 4) used to test the validity of the
+ * offset and size parameters.
* \return error code or GL_NO_ERROR.
*/
static GLenum
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize)
{
- GLboolean isProxy = GL_FALSE;
GLint expectedSize, maxLevels = 0, maxTextureSize;
+ (void) zoffset;
if (dimensions == 1) {
/* 1D compressed textures not allowed */
else if (dimensions == 2) {
if (target == GL_PROXY_TEXTURE_2D) {
maxLevels = ctx->Const.MaxTextureLevels;
- isProxy = GL_TRUE;
}
else if (target == GL_TEXTURE_2D) {
maxLevels = ctx->Const.MaxTextureLevels;
if (!ctx->Extensions.ARB_texture_cube_map)
return GL_INVALID_ENUM; /*target*/
maxLevels = ctx->Const.MaxCubeTextureLevels;
- isProxy = GL_TRUE;
}
else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
if (level < 0 || level >= maxLevels)
return GL_INVALID_VALUE;
+ /* XXX these tests are specific to the compressed format.
+ * this code should be generalized in some way.
+ */
if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
return GL_INVALID_VALUE;
if ((height & 3) != 0 && height != 2 && height != 1)
return GL_INVALID_VALUE;
- expectedSize = _mesa_compressed_texture_size(ctx, width, height, depth,
- format);
+ expectedSize = ctx->Driver.CompressedTextureSize(ctx, width, height, depth,
+ format);
if (expectedSize != imageSize)
return GL_INVALID_VALUE;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (target == GL_TEXTURE_1D) {
+ /* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
_mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
border, internalFormat);
(ctx->Extensions.ARB_texture_cube_map &&
target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
+ /* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
_mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
border, internalFormat);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (target == GL_TEXTURE_3D) {
+ /* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
return;
}
- else if (texImage->Data && !texImage->IsClientData) {
- MESA_PBUFFER_FREE(texImage->Data);
+ else if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
}
- texImage->Data = NULL;
+ ASSERT(texImage->Data == NULL);
_mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
border, internalFormat);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
assert(texImage);
- if ((GLint) format != texImage->IntFormat) {
+ if ((GLint) format != texImage->InternalFormat) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCompressedTexSubImage1D(format)");
return;
return;
}
- if (width == 0 || !data)
+ if (width == 0)
return; /* no-op, not an error */
if (ctx->Driver.CompressedTexSubImage1D) {
error = compressed_subtexture_error_check(ctx, 2, target, level,
xoffset, yoffset, 0, width, height, 1, format, imageSize);
if (error) {
+ /* XXX proxy target? */
_mesa_error(ctx, error, "glCompressedTexSubImage2D");
return;
}
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
assert(texImage);
- if ((GLint) format != texImage->IntFormat) {
+ if ((GLint) format != texImage->InternalFormat) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCompressedTexSubImage2D(format)");
return;
return;
}
- if (width == 0 || height == 0 || !data)
+ if (width == 0 || height == 0)
return; /* no-op, not an error */
if (ctx->Driver.CompressedTexSubImage2D) {
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
assert(texImage);
- if ((GLint) format != texImage->IntFormat) {
+ if ((GLint) format != texImage->InternalFormat) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCompressedTexSubImage3D(format)");
return;
return;
}
- if (width == 0 || height == 0 || depth == 0 || !data)
+ if (width == 0 || height == 0 || depth == 0)
return; /* no-op, not an error */
if (ctx->Driver.CompressedTexSubImage3D) {
return;
}
- if (is_proxy_target(target)) {
+ if (_mesa_is_proxy_texture(target)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
return;
}
return;
}
- if (!img)
- return;
-
- /* just memcpy, no pixelstore or pixel transfer */
- MEMCPY(img, texImage->Data, texImage->CompressedSize);
+ /* this typically calls _mesa_get_compressed_teximage() */
+ ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
}