/*
* Mesa 3-D graphics library
- * Version: 6.3
+ * Version: 6.5
*
- * Copyright (C) 1999-2004 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 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.
+ * Texture image-related functions.
*/
#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
}
}
- if (ctx->Extensions.SGIX_depth_texture) {
+ if (ctx->Extensions.SGIX_depth_texture ||
+ ctx->Extensions.ARB_depth_texture) {
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_SGIX:
}
}
+ 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 */
}
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:
}
+/**
+ * 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 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_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 );
}
*
* \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 ||
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;
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 = ctx->Driver.CompressedTextureSize(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) {
}
/* 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))) {
+ (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)");
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;
}
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;
- GLuint dimensions;
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 && is_depth_format(format)) {
+ if (!ctx->Extensions.SGIX_depth_texture &&
+ !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
}
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
}
+ if (!ctx->Extensions.EXT_packed_depth_stencil
+ && is_depthstencil_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ }
+
if (!pixels)
return;
}
/* Make sure the requested image format is compatible with the
- * texture's format.
+ * 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_color_format(texImage->TexFormat->BaseFormat)
+ && !is_index_format(texImage->TexFormat->BaseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
return;
}
return;
}
else if (is_depth_format(format)
- && !is_depth_format(texImage->TexFormat->BaseFormat)) {
+ && !is_depth_format(texImage->TexFormat->BaseFormat)
+ && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
return;
}
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
return;
}
-
- dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
-
- /* XXX - someday the rest of this function should be moved into a
- * fallback routine called via ctx->Driver.GetTexImage()
- */
-
- if (ctx->Pack.BufferObj->Name) {
- /* pack texture image into a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
- texImage->Height, texImage->Depth,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTexImage(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
- return;
- }
- pixels = ADD_POINTERS(buf, pixels);
- }
- else if (!pixels) {
- /* not an error */
+ else if (is_depthstencil_format(format)
+ && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
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( dimensions, &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");
- }
- _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 (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
+
+
+/**
+ * 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,
ASSERT(texImage->TexFormat);
- /* If driver didn't explicitly set this, use the defaults */
- if (!texImage->FetchTexelc)
- texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
- if (!texImage->FetchTexelf)
- texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
- ASSERT(texImage->FetchTexelc);
- ASSERT(texImage->FetchTexelf);
+ 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,
ASSERT(texImage->TexFormat);
- /* If driver didn't explicitly set these, use the defaults */
- if (!texImage->FetchTexelc)
- texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
- if (!texImage->FetchTexelf)
- texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
- ASSERT(texImage->FetchTexelc);
- ASSERT(texImage->FetchTexelf);
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
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,
ASSERT(texImage->TexFormat);
- /* If driver didn't explicitly set these, use the defaults */
- if (!texImage->FetchTexelc)
- texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
- if (!texImage->FetchTexelf)
- texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
- ASSERT(texImage->FetchTexelc);
- ASSERT(texImage->FetchTexelf);
+ 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;
+ 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,
ASSERT(texImage->TexFormat);
- /* If driver didn't explicitly set these, use the defaults */
- if (!texImage->FetchTexelc)
- texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
- if (!texImage->FetchTexelf)
- texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
- ASSERT(texImage->FetchTexelc);
- ASSERT(texImage->FetchTexelf);
+ 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,
ASSERT(texImage->TexFormat);
- /* If driver didn't explicitly set these, use the defaults */
- if (!texImage->FetchTexelc)
- texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
- if (!texImage->FetchTexelf)
- texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
- ASSERT(texImage->FetchTexelc);
- ASSERT(texImage->FetchTexelf);
+ update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->Complete = GL_FALSE;
GLsizei height, GLsizei depth, GLint border,
GLsizei imageSize)
{
- GLint expectedSize, maxLevels = 0, maxTextureSize;
+ GLint /**expectedSize,**/ maxLevels = 0, maxTextureSize;
if (dimensions == 1) {
/* 1D compressed textures not allowed */
* 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;
+#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;
}
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;
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;
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 (is_proxy_target(target)) {
+ if (_mesa_is_proxy_texture(target)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
return;
}
return;
}
- /* XXX - someday the rest of this function should be moved into a
- * fallback routine called via ctx->Driver.GetCompressedTexImage()
- */
-
- if (ctx->Pack.BufferObj->Name) {
- /* pack texture image into a PBO */
- GLubyte *buf;
- if ((const GLubyte *) img + texImage->CompressedSize >
- (const GLubyte *) ctx->Pack.BufferObj->Size) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(PBO is mapped)");
- return;
- }
- img = ADD_POINTERS(buf, img);
- }
- else if (!img) {
- /* not an error */
- return;
- }
-
- /* just memcpy, no pixelstore or pixel transfer */
- MEMCPY(img, texImage->Data, texImage->CompressedSize);
-
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ /* this typically calls _mesa_get_compressed_teximage() */
+ ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
}