/*
* Mesa 3-D graphics library
- * Version: 6.1
+ * Version: 6.3
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
#include "glheader.h"
+#include "bufferobj.h"
#include "context.h"
#include "convolve.h"
#include "image.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)
{
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_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: {
- GLuint face = ((GLuint) target -
- (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
- tObj->Image[face][level] = texImage;
- break;
- }
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ {
+ 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[0][level] = texImage;
}
+/**
+ * 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 );
}
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 */
}
{
const GLboolean isProxy = is_proxy_target(target);
GLboolean sizeOK;
+ GLboolean colorFormat, indexFormat;
/* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
}
/* make sure internal format and format basically agree */
- if ((is_color_format(internalFormat) != is_color_format(format)) ||
- (is_index_format(internalFormat) != is_index_format(format)) ||
+ 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))) {
if (!isProxy)
return;
}
- if (!texImage->Data) {
- /* no image data, not an error */
- return;
- }
-
/* Make sure the requested image format is compatible with the
- * texture's format.
+ * texture's format. We let the colorformat-indexformat go through,
+ * because the texelfetcher will dequantize to full rgba.
*/
if (is_color_format(format)
- && !is_color_format(texImage->TexFormat->BaseFormat)) {
+ && !is_color_format(texImage->TexFormat->BaseFormat)
+ && !is_index_format(texImage->TexFormat->BaseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
return;
}
return;
}
- /*
- * XXX Move this code into a new driver fall-back function
- */
- {
- 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;
- /* Can't use FetchTexel here because that returns RGBA */
- if (texImage->TexFormat->IndexBits == 8) {
- const GLubyte *src = (const GLubyte *) texImage->Data;
- for (col = 0; col < width; col++) {
- indexRow[col] = src[texImage->Width *
- (img * texImage->Height + row) + col];
- }
- }
- else if (texImage->TexFormat->IndexBits == 16) {
- const GLushort *src = (const GLushort *) texImage->Data;
- for (col = 0; col < width; col++) {
- indexRow[col] = src[texImage->Width *
- (img * texImage->Height + row) + col];
- }
- }
- else {
- _mesa_problem(ctx,
- "Color index problem in _mesa_GetTexImage");
- return;
- }
- _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->FetchTexelf)(texImage, col, row, img,
- 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 */
- GLfloat rgba[MAX_WIDTH][4];
- GLint col;
- for (col = 0; col < width; col++) {
- (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
- }
- _mesa_pack_rgba_span_float(ctx, width,
- (const GLfloat (*)[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);
}
}
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, "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,
_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,
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
+ /* non-proxy 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,
_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,
_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,
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;
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);
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);
}