+ if (dimensions_error_check(ctx, texObj, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth, caller)) {
+ return true;
+ }
+
+ if (pbo_error_check(ctx, target, width, height, depth,
+ format, type, bufSize, pixels, caller)) {
+ return true;
+ }
+
+ texImage = select_tex_image(texObj, target, level, zoffset);
+ assert(texImage);
+
+ /*
+ * Format and type checking has been moved up to GetnTexImage and
+ * GetTextureImage so that it happens before getting the texImage object.
+ */
+
+ baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
+
+ /* Make sure the requested image format is compatible with the
+ * texture's format.
+ */
+ if (_mesa_is_color_format(format)
+ && !_mesa_is_color_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(format mismatch)", caller);
+ return true;
+ }
+ else if (_mesa_is_depth_format(format)
+ && !_mesa_is_depth_format(baseFormat)
+ && !_mesa_is_depthstencil_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(format mismatch)", caller);
+ return true;
+ }
+ else if (_mesa_is_stencil_format(format)
+ && !ctx->Extensions.ARB_texture_stencil8) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(format=GL_STENCIL_INDEX)", caller);
+ return true;
+ }
+ else if (_mesa_is_stencil_format(format)
+ && !_mesa_is_depthstencil_format(baseFormat)
+ && !_mesa_is_stencil_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(format mismatch)", caller);
+ return true;
+ }
+ else if (_mesa_is_ycbcr_format(format)
+ && !_mesa_is_ycbcr_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(format mismatch)", caller);
+ return true;
+ }
+ else if (_mesa_is_depthstencil_format(format)
+ && !_mesa_is_depthstencil_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(format mismatch)", caller);
+ return true;
+ }
+ else if (!_mesa_is_stencil_format(format) &&
+ _mesa_is_enum_format_integer(format) !=
+ _mesa_is_format_integer(texImage->TexFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(format mismatch)", caller);
+ return true;
+ }
+
+ return false;
+}
+
+
+/**
+ * Return the width, height and depth of a texture image.
+ * This function must be resilient to bad parameter values since
+ * this is called before full error checking.
+ */
+static void
+get_texture_image_dims(const struct gl_texture_object *texObj,
+ GLenum target, GLint level,
+ GLsizei *width, GLsizei *height, GLsizei *depth)
+{
+ const struct gl_texture_image *texImage = NULL;
+
+ if (level >= 0 && level < MAX_TEXTURE_LEVELS) {
+ texImage = _mesa_select_tex_image(texObj, target, level);
+ }
+
+ if (texImage) {
+ *width = texImage->Width;
+ *height = texImage->Height;
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ *depth = 6;
+ }
+ else {
+ *depth = texImage->Depth;
+ }
+ }
+ else {
+ *width = *height = *depth = 0;
+ }
+}
+
+
+/**
+ * Common code for all (uncompressed) get-texture-image functions.
+ * \param texObj the texture object (should not be null)
+ * \param target user-provided target, or 0 for DSA
+ * \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.
+ * \param caller name of calling function
+ */
+static void
+get_texture_image(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLint depth,
+ GLenum format, GLenum type,
+ GLvoid *pixels, const char *caller)
+{
+ struct gl_texture_image *texImage;
+ unsigned firstFace, numFaces, i;
+ GLint imageStride;
+
+ FLUSH_VERTICES(ctx, 0);
+
+ texImage = select_tex_image(texObj, target, level, zoffset);
+ assert(texImage); /* should have been error checked already */
+
+ if (_mesa_is_zero_size_texture(texImage)) {
+ /* no image data to return */