#include "enums.h"
#include "context.h"
#include "formats.h"
+#include "format_unpack.h"
#include "image.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "pack.h"
+#include "pbo.h"
#include "texcompress.h"
#include "texgetimage.h"
#include "teximage.h"
-#include "texstate.h"
-#if FEATURE_EXT_texture_sRGB
-
-/**
- * Convert a float value from linear space to a
- * non-linear sRGB value in [0, 255].
- * Not terribly efficient.
- */
-static INLINE GLfloat
-linear_to_nonlinear(GLfloat cl)
-{
- /* can't have values outside [0, 1] */
- GLfloat cs;
- if (cl < 0.0031308f) {
- cs = 12.92f * cl;
- }
- else {
- cs = (GLfloat)(1.055 * _mesa_pow(cl, 0.41666) - 0.055);
- }
- return cs;
-}
-
-#endif /* FEATURE_EXT_texture_sRGB */
-
-
/**
* Can the given type represent negative values?
*/
}
-/**
- * glGetTexImage for color index pixels.
- */
-static void
-get_tex_color_index(GLcontext *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- const GLuint indexBits =
- _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT);
- const GLbitfield transferOps = 0x0;
- GLint img, row, col;
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- GLuint indexRow[MAX_WIDTH];
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- assert(dest);
-
- if (indexBits == 8) {
- const GLubyte *src = (const GLubyte *) texImage->Data;
- src += width * (img * texImage->Height + row);
- for (col = 0; col < width; col++) {
- indexRow[col] = src[col];
- }
- }
- else if (indexBits == 16) {
- const GLushort *src = (const GLushort *) texImage->Data;
- src += width * (img * texImage->Height + row);
- for (col = 0; col < width; col++) {
- indexRow[col] = src[col];
- }
- }
- else {
- _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage");
- }
- _mesa_pack_index_span(ctx, width, type, dest,
- indexRow, &ctx->Pack, transferOps);
- }
- }
-}
-
-
/**
* glGetTexImage for depth/Z pixels.
*/
static void
-get_tex_depth(GLcontext *ctx, GLuint dimensions,
+get_tex_depth(struct gl_context *ctx, GLuint dimensions,
GLenum format, GLenum type, GLvoid *pixels,
const struct gl_texture_image *texImage)
{
const GLint width = texImage->Width;
const GLint height = texImage->Height;
const GLint depth = texImage->Depth;
- GLint img, row, col;
+ GLint img, row;
+ GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
+ const GLint texelSize = _mesa_get_format_bytes(texImage->TexFormat);
+
+ if (!depthRow) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+ return;
+ }
for (img = 0; img < depth; img++) {
for (row = 0; row < height; row++) {
- GLfloat depthRow[MAX_WIDTH];
void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
width, height, format, type,
img, row, 0);
- assert(dest);
+ const GLubyte *src = (GLubyte *) texImage->Data +
+ (texImage->ImageOffsets[img] +
+ texImage->RowStride * row) * texelSize;
+
+ _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow);
- 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);
}
}
+
+ free(depthRow);
}
* glGetTexImage for depth/stencil pixels.
*/
static void
-get_tex_depth_stencil(GLcontext *ctx, GLuint dimensions,
+get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
GLenum format, GLenum type, GLvoid *pixels,
const struct gl_texture_image *texImage)
{
const GLint width = texImage->Width;
const GLint height = texImage->Height;
const GLint depth = texImage->Depth;
+ const GLint rowstride = texImage->RowStride;
const GLuint *src = (const GLuint *) texImage->Data;
GLint img, row;
void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
width, height, format, type,
img, row, 0);
- _mesa_memcpy(dest, src, width * sizeof(GLuint));
+ memcpy(dest, src, width * sizeof(GLuint));
if (ctx->Pack.SwapBytes) {
_mesa_swap4((GLuint *) dest, width);
}
- src += width * row + width * height * img;
+ src += rowstride;
}
}
}
* glGetTexImage for YCbCr pixels.
*/
static void
-get_tex_ycbcr(GLcontext *ctx, GLuint dimensions,
+get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
GLenum format, GLenum type, GLvoid *pixels,
const struct gl_texture_image *texImage)
{
void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
width, height, format, type,
img, row, 0);
- _mesa_memcpy(dest, src, width * sizeof(GLushort));
+ memcpy(dest, src, width * sizeof(GLushort));
/* check for byte swapping */
if ((texImage->TexFormat == MESA_FORMAT_YCBCR
/**
- * glGetTexImagefor sRGB pixels;
+ * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
+ * Compressed textures are handled here as well.
*/
static void
-get_tex_srgb(GLcontext *ctx, GLuint dimensions,
+get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
+ struct gl_texture_image *texImage)
{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- const GLbitfield transferOps = 0x0;
- GLint img, row;
+ /* don't want to apply sRGB -> RGB conversion here so override the format */
+ const gl_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat);
+ const GLuint width = texImage->Width;
+ const GLuint height = texImage->Height;
+ const GLuint depth = texImage->Depth;
+ const GLenum dataType = _mesa_get_format_datatype(texFormat);
+ const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
+ /* Normally, no pixel transfer ops are performed during glGetTexImage.
+ * The only possible exception is component clamping to [0,1].
+ */
+ GLbitfield transferOps = 0x0;
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
+ /* In general, clamping does not apply to glGetTexImage, except when
+ * the returned type of the image can't hold negative values.
+ */
+ if (!type_with_negative_values(type)) {
+ /* the returned image type can't have negative values */
+ if (dataType == GL_FLOAT ||
+ dataType == GL_SIGNED_NORMALIZED ||
+ format == GL_LUMINANCE ||
+ format == GL_LUMINANCE_ALPHA) {
+ transferOps |= IMAGE_CLAMP_BIT;
+ }
+ }
- GLfloat rgba[MAX_WIDTH][4];
- GLint col;
+ if (_mesa_is_format_compressed(texFormat)) {
+ /* Decompress into temp buffer, then pack into user buffer */
+ GLfloat *tempImage, *srcRow;
+ GLuint row;
- /* convert row to RGBA format */
- for (col = 0; col < width; col++) {
- texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
- if (texImage->_BaseFormat == GL_LUMINANCE) {
- rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- }
- else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
- rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- }
- else if (texImage->_BaseFormat == GL_RGB ||
- texImage->_BaseFormat == GL_RGBA) {
- rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
- rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
- rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
- }
- }
- _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
- format, type, dest,
- &ctx->Pack, transferOps);
+ tempImage = (GLfloat *) malloc(texImage->Width * texImage->Height *
+ texImage->Depth * 4 * sizeof(GLfloat));
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
+ return;
}
- }
-}
+ _mesa_decompress_image(texFormat, texImage->Width, texImage->Height,
+ texImage->Data, texImage->RowStride, tempImage);
-/**
- * glGetTexImagefor RGBA, Luminance, etc. pixels.
- * This is the slow way since we use texture sampling.
- */
-static void
-get_tex_rgba(GLcontext *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- /* Normally, no pixel transfer ops are performed during glGetTexImage.
- * The only possible exception is component clamping to [0,1].
- */
- GLbitfield transferOps = 0x0;
- GLint img, row;
+ if (baseFormat == GL_LUMINANCE ||
+ baseFormat == GL_LUMINANCE_ALPHA) {
+ /* Set green and blue to zero since the pack function here will
+ * compute L=R+G+B.
+ */
+ GLuint i;
+ for (i = 0; i < width * height; i++) {
+ tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f;
+ }
+ }
- for (img = 0; img < depth; img++) {
+ srcRow = tempImage;
for (row = 0; row < height; row++) {
void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
width, height, format, type,
- img, row, 0);
- GLfloat rgba[MAX_WIDTH][4];
- GLint col;
- GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
+ 0, row, 0);
- /* clamp does not apply to GetTexImage (final conversion)?
- * Looks like we need clamp though when going from format
- * containing negative values to unsigned format.
- */
- if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
- transferOps |= IMAGE_CLAMP_BIT;
- }
- else if (!type_with_negative_values(type) &&
- (dataType == GL_FLOAT ||
- dataType == GL_SIGNED_NORMALIZED)) {
- transferOps |= IMAGE_CLAMP_BIT;
- }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow,
+ format, type, dest, &ctx->Pack, transferOps);
+ srcRow += width * 4;
+ }
+
+ free(tempImage);
+ }
+ else {
+ /* No decompression needed */
+ const GLint texelSize = _mesa_get_format_bytes(texFormat);
+ GLuint img, row;
+ GLfloat (*rgba)[4];
+
+ rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
+ if (!rgba) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
+ return;
+ }
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ const GLubyte *src = (const GLubyte *) texImage->Data +
+ (texImage->ImageOffsets[img] +
+ texImage->RowStride * row) * texelSize;
+
+ _mesa_unpack_rgba_row(texFormat, width, src, rgba);
- for (col = 0; col < width; col++) {
- texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
if (texImage->_BaseFormat == GL_ALPHA) {
- rgba[col][RCOMP] = 0.0F;
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][RCOMP] = 0.0F;
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ }
}
else if (texImage->_BaseFormat == GL_LUMINANCE) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ rgba[col][ACOMP] = 1.0F;
+ }
}
else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ }
}
else if (texImage->_BaseFormat == GL_INTENSITY) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ rgba[col][ACOMP] = 1.0F;
+ }
}
+
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
}
- _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
- format, type, dest,
- &ctx->Pack, transferOps);
}
+
+ free(rgba);
}
}
* \return GL_TRUE if done, GL_FALSE otherwise
*/
static GLboolean
-get_tex_memcpy(GLcontext *ctx, GLenum format, GLenum type, GLvoid *pixels,
+get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels,
const struct gl_texture_object *texObj,
const struct gl_texture_image *texImage)
{
texObj->Target == GL_TEXTURE_RECTANGLE ||
(texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
- if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
+ if ((texImage->TexFormat == MESA_FORMAT_ARGB8888 ||
+ texImage->TexFormat == MESA_FORMAT_SARGB8) &&
format == GL_BGRA &&
- type == GL_UNSIGNED_BYTE &&
+ (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
!ctx->Pack.SwapBytes &&
_mesa_little_endian()) {
memCopy = GL_TRUE;
}
- else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
+ else if ((texImage->TexFormat == MESA_FORMAT_AL88 ||
+ texImage->TexFormat == MESA_FORMAT_SLA8) &&
format == GL_LUMINANCE_ALPHA &&
type == GL_UNSIGNED_BYTE &&
!ctx->Pack.SwapBytes &&
_mesa_little_endian()) {
memCopy = GL_TRUE;
}
- else if (texImage->TexFormat == MESA_FORMAT_L8 &&
+ else if ((texImage->TexFormat == MESA_FORMAT_L8 ||
+ texImage->TexFormat == MESA_FORMAT_SL8) &&
format == GL_LUMINANCE &&
type == GL_UNSIGNED_BYTE) {
memCopy = GL_TRUE;
}
+ else if (texImage->TexFormat == MESA_FORMAT_L16 &&
+ format == GL_LUMINANCE &&
+ type == GL_UNSIGNED_SHORT) {
+ memCopy = GL_TRUE;
+ }
else if (texImage->TexFormat == MESA_FORMAT_A8 &&
format == GL_ALPHA &&
type == GL_UNSIGNED_BYTE) {
memCopy = GL_TRUE;
}
+ else if (texImage->TexFormat == MESA_FORMAT_A16 &&
+ format == GL_ALPHA &&
+ type == GL_UNSIGNED_SHORT) {
+ memCopy = GL_TRUE;
+ }
}
if (memCopy) {
* The texture image must be mapped.
*/
void
-_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+_mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid *pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
* texture data to the PBO if the PBO is in VRAM along with the texture.
*/
GLubyte *buf = (GLubyte *)
- ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
+ ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
+ GL_MAP_WRITE_BIT, ctx->Pack.BufferObj);
if (!buf) {
/* out of memory or other unexpected error */
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) {
/* all done */
}
- else if (format == GL_COLOR_INDEX) {
- get_tex_color_index(ctx, dimensions, format, type, pixels, texImage);
- }
else if (format == GL_DEPTH_COMPONENT) {
get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
}
else if (format == GL_YCBCR_MESA) {
get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
}
- else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) {
- get_tex_srgb(ctx, dimensions, format, type, pixels, texImage);
- }
else {
get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
}
if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
+ ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
}
}
* All error checking will have been done before this routine is called.
*/
void
-_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+_mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level,
GLvoid *img,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
/* pack texture image into a PBO */
GLubyte *buf = (GLubyte *)
- ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
+ ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
+ GL_MAP_WRITE_BIT, ctx->Pack.BufferObj);
if (!buf) {
/* out of memory or other unexpected error */
_mesa_error(ctx, GL_OUT_OF_MEMORY,
texImage->Width,
texImage->Height,
texImage->Depth);
- _mesa_memcpy(img, texImage->Data, size);
+ memcpy(img, texImage->Data, size);
}
else {
GLuint bw, bh;
}
if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
+ ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
}
}
* \return GL_TRUE if any error, GL_FALSE if no errors.
*/
static GLboolean
-getteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid *pixels )
+getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLsizei clientMemSize,
+ GLvoid *pixels )
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
GLenum baseFormat;
if (maxLevels == 0) {
}
if (_mesa_components_in_format(format) <= 0 ||
- format == GL_STENCIL_INDEX) {
+ format == GL_STENCIL_INDEX ||
+ format == GL_COLOR_INDEX) {
_mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
return GL_TRUE;
}
- if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return GL_TRUE;
- }
-
if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
return GL_TRUE;
baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
/* 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.
+ * texture's format.
*/
if (_mesa_is_color_format(format)
- && !_mesa_is_color_format(baseFormat)
- && !_mesa_is_index_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
- else if (_mesa_is_index_format(format)
- && !_mesa_is_index_format(baseFormat)) {
+ && !_mesa_is_color_format(baseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
return GL_TRUE;
}
return GL_TRUE;
}
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- /* packing texture image into a PBO */
- const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
- if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
- texImage->Height, texImage->Depth,
- format, type, pixels)) {
+ if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+ texImage->Height, texImage->Depth,
+ format, type, clientMemSize, pixels)) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTexImage(out of bounds PBO write)");
- return GL_TRUE;
+ "glGetTexImage(out of bounds PBO access)");
+ } else {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetnTexImageARB(out of bounds access:"
+ " bufSize (%d) is too small)", clientMemSize);
}
+ return GL_TRUE;
+ }
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
/* PBO should not be mapped */
if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
* \param level image level.
* \param format pixel data format for returned image.
* \param type pixel data type for returned image.
+ * \param bufSize size of the pixels data buffer.
* \param pixels returned pixel data.
*/
void GLAPIENTRY
-_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
- GLenum type, GLvoid *pixels )
+_mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format,
+ GLenum type, GLsizei bufSize, GLvoid *pixels )
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
+ if (getteximage_error_check(ctx, target, level, format, type,
+ bufSize, pixels)) {
return;
}
}
+void GLAPIENTRY
+_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid *pixels )
+{
+ _mesa_GetnTexImageARB(target, level, format, type, INT_MAX, pixels);
+}
+
/**
* Do error checking for a glGetCompressedTexImage() call.
* \return GL_TRUE if any error, GL_FALSE if no errors.
*/
static GLboolean
-getcompressedteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
- GLvoid *img)
+getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
+ GLint level, GLsizei clientMemSize, GLvoid *img)
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
+ GLuint compressedSize;
if (maxLevels == 0) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
return GL_TRUE;
}
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- GLuint compressedSize;
+ compressedSize = _mesa_format_image_size(texImage->TexFormat,
+ texImage->Width,
+ texImage->Height,
+ texImage->Depth);
- /* make sure PBO is not mapped */
- if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* do bounds checking on writing to client memory */
+ if (clientMemSize < compressedSize) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(PBO is mapped)");
- return GL_TRUE;
+ "glGetnCompressedTexImageARB(out of bounds access:"
+ " bufSize (%d) is too small)", clientMemSize);
}
-
- compressedSize = _mesa_format_image_size(texImage->TexFormat,
- texImage->Width,
- texImage->Height,
- texImage->Depth);
-
+ } else {
/* do bounds checking on PBO write */
if ((const GLubyte *) img + compressedSize >
(const GLubyte *) ctx->Pack.BufferObj->Size) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(out of bounds PBO write)");
+ "glGetCompressedTexImage(out of bounds PBO access)");
+ return GL_TRUE;
+ }
+
+ /* make sure PBO is not mapped */
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(PBO is mapped)");
return GL_TRUE;
}
}
void GLAPIENTRY
-_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
+_mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,
+ GLvoid *img)
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (getcompressedteximage_error_check(ctx, target, level, img)) {
+ if (getcompressedteximage_error_check(ctx, target, level, bufSize, img)) {
return;
}
}
_mesa_unlock_texture(ctx, texObj);
}
+
+void GLAPIENTRY
+_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
+{
+ _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img);
+}