void GLAPIENTRY _mesa_GetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params ) { const struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; const struct gl_texture_image *img = NULL; GLuint dimensions; GLboolean isProxy; GLint maxLevels; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexLevelParameteriv(current unit)"); return; } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; /* this will catch bad target values */ dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */ if (dimensions == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)"); return; } maxLevels = _mesa_max_texture_levels(ctx, target); if (maxLevels == 0) { /* should not happen since <target> was just checked above */ _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter"); return; } if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" ); return; } texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); img = _mesa_select_tex_image(ctx, texObj, target, level); if (!img || !img->TexFormat) { /* undefined texture image */ if (pname == GL_TEXTURE_COMPONENTS) *params = 1; else *params = 0; goto out; } isProxy = _mesa_is_proxy_texture(target); switch (pname) { case GL_TEXTURE_WIDTH: *params = img->Width; break; case GL_TEXTURE_HEIGHT: *params = img->Height; break; case GL_TEXTURE_DEPTH: *params = img->Depth; break; case GL_TEXTURE_INTERNAL_FORMAT: *params = img->InternalFormat; break; case GL_TEXTURE_BORDER: *params = img->Border; break; case GL_TEXTURE_RED_SIZE: if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA) *params = img->TexFormat->RedBits; else *params = 0; break; case GL_TEXTURE_GREEN_SIZE: if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA) *params = img->TexFormat->GreenBits; else *params = 0; break; case GL_TEXTURE_BLUE_SIZE: if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA) *params = img->TexFormat->BlueBits; else *params = 0; break; case GL_TEXTURE_ALPHA_SIZE: if (img->_BaseFormat == GL_ALPHA || img->_BaseFormat == GL_LUMINANCE_ALPHA || img->_BaseFormat == GL_RGBA) *params = img->TexFormat->AlphaBits; else *params = 0; break; case GL_TEXTURE_INTENSITY_SIZE: if (img->_BaseFormat != GL_INTENSITY) *params = 0; else if (img->TexFormat->IntensityBits > 0) *params = img->TexFormat->IntensityBits; else /* intensity probably stored as rgb texture */ *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits); break; case GL_TEXTURE_LUMINANCE_SIZE: if (img->_BaseFormat != GL_LUMINANCE && img->_BaseFormat != GL_LUMINANCE_ALPHA) *params = 0; else if (img->TexFormat->LuminanceBits > 0) *params = img->TexFormat->LuminanceBits; else /* luminance probably stored as rgb texture */ *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits); break; case GL_TEXTURE_INDEX_SIZE_EXT: if (img->_BaseFormat == GL_COLOR_INDEX) *params = img->TexFormat->IndexBits; else *params = 0; break; case GL_TEXTURE_DEPTH_SIZE_ARB: if (ctx->Extensions.ARB_depth_texture) *params = img->TexFormat->DepthBits; else _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); break; case GL_TEXTURE_STENCIL_SIZE_EXT: if (ctx->Extensions.EXT_packed_depth_stencil) { *params = img->TexFormat->StencilBits; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; /* GL_ARB_texture_compression */ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: if (ctx->Extensions.ARB_texture_compression) { if (img->IsCompressed && !isProxy) { /* Don't use ctx->Driver.CompressedTextureSize() since that * may returned a padded hardware size. */ *params = _mesa_compressed_texture_size(ctx, img->Width, img->Height, img->Depth, img->TexFormat->MesaFormat); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexLevelParameter[if]v(pname)"); } } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_COMPRESSED: if (ctx->Extensions.ARB_texture_compression) { *params = (GLint) img->IsCompressed; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; /* GL_ARB_texture_float */ case GL_TEXTURE_RED_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_GREEN_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_BLUE_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_ALPHA_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_LUMINANCE_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_INTENSITY_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_DEPTH_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname)"); } out: _mesa_unlock_texture(ctx, texObj); }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, struct gl_texture_object *texObj, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool dsa) { const char* suffix = dsa ? "ture" : ""; /* Legal format checking has been moved to texstorage and texturestorage in * order to allow meta functions to use legacy formats. */ /* size check */ if (!_mesa_valid_tex_storage_dim(width, height, depth)) { _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(width, height or depth < 1)", suffix, dims); return GL_TRUE; } if (_mesa_is_compressed_format(ctx, internalformat)) { GLenum err; if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) { _mesa_error(ctx, err, "glTex%sStorage%dD(internalformat = %s)", suffix, dims, _mesa_enum_to_string(internalformat)); return GL_TRUE; } } /* levels check */ if (levels < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)", suffix, dims); return GL_TRUE; } /* check levels against maximum (note different error than above) */ if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(levels too large)", suffix, dims); return GL_TRUE; } /* check levels against width/height/depth */ if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(too many levels" " for max texture dimension)", suffix, dims); return GL_TRUE; } /* non-default texture object check */ if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(texture object 0)", suffix, dims); return GL_TRUE; } /* Check if texObj->Immutable is set */ if (!_mesa_is_proxy_texture(target) && texObj->Immutable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)", suffix, dims); return GL_TRUE; } /* additional checks for depth textures */ if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)", suffix, dims); return GL_TRUE; } return GL_FALSE; }
void GLAPIENTRY _mesa_GetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params ) { const struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; const struct gl_texture_image *img = NULL; GLint maxLevels; gl_format texFormat; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexLevelParameteriv(current unit)"); return; } texUnit = _mesa_get_current_tex_unit(ctx); /* this will catch bad target values */ maxLevels = _mesa_max_texture_levels(ctx, target); if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target=0x%x)", target); return; } if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" ); return; } texObj = _mesa_select_tex_object(ctx, texUnit, target); img = _mesa_select_tex_image(ctx, texObj, target, level); if (!img || !img->TexFormat) { /* undefined texture image */ if (pname == GL_TEXTURE_COMPONENTS) *params = 1; else *params = 0; return; } texFormat = img->TexFormat; switch (pname) { case GL_TEXTURE_WIDTH: *params = img->Width; break; case GL_TEXTURE_HEIGHT: *params = img->Height; break; case GL_TEXTURE_DEPTH: *params = img->Depth; break; case GL_TEXTURE_INTERNAL_FORMAT: if (_mesa_is_format_compressed(texFormat)) { /* need to return the actual compressed format */ *params = _mesa_compressed_format_to_glenum(ctx, texFormat); } else { /* If the true internal format is not compressed but the user * requested a generic compressed format, we have to return the * generic base format that matches. * * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec: * * "If no specific compressed format is available, * internalformat is instead replaced by the corresponding base * internal format." * * Otherwise just return the user's requested internal format */ const GLenum f = _mesa_gl_compressed_format_base_format(img->InternalFormat); *params = (f != 0) ? f : img->InternalFormat; } break; case GL_TEXTURE_BORDER: *params = img->Border; break; case GL_TEXTURE_RED_SIZE: if (img->_BaseFormat == GL_RED) { *params = _mesa_get_format_bits(texFormat, pname); break; } /* FALLTHROUGH */ case GL_TEXTURE_GREEN_SIZE: if (img->_BaseFormat == GL_RG) { *params = _mesa_get_format_bits(texFormat, pname); break; } /* FALLTHROUGH */ case GL_TEXTURE_BLUE_SIZE: if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA) *params = _mesa_get_format_bits(texFormat, pname); else *params = 0; break; case GL_TEXTURE_ALPHA_SIZE: if (img->_BaseFormat == GL_ALPHA || img->_BaseFormat == GL_LUMINANCE_ALPHA || img->_BaseFormat == GL_RGBA) *params = _mesa_get_format_bits(texFormat, pname); else *params = 0; break; case GL_TEXTURE_INTENSITY_SIZE: if (img->_BaseFormat != GL_INTENSITY) *params = 0; else { *params = _mesa_get_format_bits(texFormat, pname); if (*params == 0) { /* intensity probably stored as rgb texture */ *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE), _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE)); } } break; case GL_TEXTURE_LUMINANCE_SIZE: if (img->_BaseFormat != GL_LUMINANCE && img->_BaseFormat != GL_LUMINANCE_ALPHA) *params = 0; else { *params = _mesa_get_format_bits(texFormat, pname); if (*params == 0) { /* luminance probably stored as rgb texture */ *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE), _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE)); } } break; case GL_TEXTURE_INDEX_SIZE_EXT: if (img->_BaseFormat == GL_COLOR_INDEX) *params = _mesa_get_format_bits(texFormat, pname); else *params = 0; break; case GL_TEXTURE_DEPTH_SIZE_ARB: if (ctx->Extensions.ARB_depth_texture) *params = _mesa_get_format_bits(texFormat, pname); else goto invalid_pname; break; case GL_TEXTURE_STENCIL_SIZE_EXT: if (ctx->Extensions.EXT_packed_depth_stencil || ctx->Extensions.ARB_framebuffer_object) { *params = _mesa_get_format_bits(texFormat, pname); } else { goto invalid_pname; } break; case GL_TEXTURE_SHARED_SIZE: if (ctx->VersionMajor >= 3 || ctx->Extensions.EXT_texture_shared_exponent) { *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0; } else { goto invalid_pname; } break; /* GL_ARB_texture_compression */ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: if (_mesa_is_format_compressed(texFormat) && !_mesa_is_proxy_texture(target)) { *params = _mesa_format_image_size(texFormat, img->Width, img->Height, img->Depth); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexLevelParameter[if]v(pname)"); } break; case GL_TEXTURE_COMPRESSED: *params = (GLint) _mesa_is_format_compressed(texFormat); break; /* GL_ARB_texture_float */ case GL_TEXTURE_RED_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; case GL_TEXTURE_GREEN_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; case GL_TEXTURE_BLUE_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_BLUE_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; case GL_TEXTURE_ALPHA_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_ALPHA_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; case GL_TEXTURE_LUMINANCE_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_LUMINANCE_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; case GL_TEXTURE_INTENSITY_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_INTENSITY_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; case GL_TEXTURE_DEPTH_TYPE_ARB: if (ctx->Extensions.ARB_texture_float) { *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_DEPTH_SIZE) ? _mesa_get_format_datatype(texFormat) : GL_NONE; } else { goto invalid_pname; } break; default: goto invalid_pname; } /* no error if we get here */ return; invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname=%s)", _mesa_lookup_enum_by_nr(pname)); }
void GLAPIENTRY _mesa_GetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params ) { struct gl_texture_object *texObj; const struct gl_texture_image *img = NULL; GLint maxLevels; gl_format texFormat; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); /* this will catch bad target values */ maxLevels = _mesa_max_texture_levels(ctx, target); if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target=0x%x)", target); return; } if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" ); return; } texObj = _mesa_select_tex_object(ctx, target); img = _mesa_select_tex_image(ctx, texObj, target, level); if (!img || img->TexFormat == MESA_FORMAT_NONE) { /* undefined texture image */ if (pname == GL_TEXTURE_COMPONENTS) *params = 1; else *params = 0; return; } texFormat = img->TexFormat; switch (pname) { case GL_TEXTURE_WIDTH: *params = img->Width; break; case GL_TEXTURE_HEIGHT: *params = img->Height; break; case GL_TEXTURE_DEPTH: *params = img->Depth; break; case GL_TEXTURE_INTERNAL_FORMAT: *params = img->InternalFormat; break; case GL_TEXTURE_BORDER: *params = img->Border; break; case GL_TEXTURE_RED_SIZE: case GL_TEXTURE_GREEN_SIZE: case GL_TEXTURE_BLUE_SIZE: case GL_TEXTURE_ALPHA_SIZE: if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) *params = _mesa_get_format_bits(texFormat, pname); else *params = 0; break; case GL_TEXTURE_INTENSITY_SIZE: case GL_TEXTURE_LUMINANCE_SIZE: if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) { *params = _mesa_get_format_bits(texFormat, pname); if (*params == 0) { /* intensity or luminance is probably stored as RGB[A] */ *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE), _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE)); } } else { *params = 0; } break; /* GL_ARB_texture_float */ case GL_TEXTURE_RED_TYPE_ARB: case GL_TEXTURE_GREEN_TYPE_ARB: case GL_TEXTURE_BLUE_TYPE_ARB: case GL_TEXTURE_ALPHA_TYPE_ARB: case GL_TEXTURE_LUMINANCE_TYPE_ARB: case GL_TEXTURE_INTENSITY_TYPE_ARB: case GL_TEXTURE_DEPTH_TYPE_ARB: if (!ctx->Extensions.ARB_texture_float) goto invalid_pname; if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) *params = _mesa_get_format_datatype(texFormat); else *params = GL_NONE; break; default: goto invalid_pname; } /* no error if we get here */ return; invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(pname=%s)", _mesa_lookup_enum_by_nr(pname)); }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; GLboolean legalFormat; /* check internal format - note that only sized formats are allowed */ switch (internalformat) { case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RED: case GL_RG: case GL_RGB: case GL_RGBA: case GL_BGRA: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: case GL_COMPRESSED_ALPHA: case GL_COMPRESSED_LUMINANCE_ALPHA: case GL_COMPRESSED_LUMINANCE: case GL_COMPRESSED_INTENSITY: case GL_COMPRESSED_RGB: case GL_COMPRESSED_RGBA: case GL_COMPRESSED_SRGB: case GL_COMPRESSED_SRGB_ALPHA: case GL_COMPRESSED_SLUMINANCE: case GL_COMPRESSED_SLUMINANCE_ALPHA: case GL_RED_INTEGER: case GL_GREEN_INTEGER: case GL_BLUE_INTEGER: case GL_ALPHA_INTEGER: case GL_RGB_INTEGER: case GL_RGBA_INTEGER: case GL_BGR_INTEGER: case GL_BGRA_INTEGER: case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: /* these unsized formats are illegal */ legalFormat = GL_FALSE; break; default: legalFormat = _mesa_base_tex_format(ctx, internalformat) > 0; } if (!legalFormat) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, _mesa_lookup_enum_by_nr(internalformat)); return GL_TRUE; } /* size check */ if (width < 1 || height < 1 || depth < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* levels check */ if (levels < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); return GL_TRUE; } /* check levels against maximum (note different error than above) */ if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); return GL_TRUE; } /* check levels against width/height/depth */ if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || (texObj->Name == 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); return GL_TRUE; } /* Check if texObj->Immutable is set */ if (texObj->Immutable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); return GL_TRUE; } return GL_FALSE; }
/** * Common code called by glFramebufferTexture1D/2D/3DEXT(). */ static void framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { struct gl_renderbuffer_attachment *att; struct gl_texture_object *texObj = NULL; struct gl_framebuffer *fb; ASSERT_OUTSIDE_BEGIN_END(ctx); if (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture%sEXT(target)", caller); return; } fb = ctx->DrawBuffer; ASSERT(fb); /* check framebuffer binding */ if (fb->Name == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%sEXT", caller); return; } /* The textarget, level, and zoffset parameters are only validated if * texture is non-zero. */ if (texture) { GLboolean err = GL_TRUE; texObj = _mesa_lookup_texture(ctx, texture); if (texObj != NULL) { if (textarget == 0) { err = (texObj->Target != GL_TEXTURE_3D) && (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); } else { err = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? !IS_CUBE_FACE(textarget) : (texObj->Target != textarget); } } if (err) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%sEXT(texture target mismatch)", caller); return; } if (texObj->Target == GL_TEXTURE_3D) { const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); if (zoffset < 0 || zoffset >= maxSize) { _mesa_error(ctx, GL_INVALID_VALUE, "glFramebufferTexture%sEXT(zoffset)", caller); return; } } else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) { if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) { _mesa_error(ctx, GL_INVALID_VALUE, "glFramebufferTexture%sEXT(layer)", caller); return; } } if ((level < 0) || (level >= _mesa_max_texture_levels(ctx, texObj->Target))) { _mesa_error(ctx, GL_INVALID_VALUE, "glFramebufferTexture%sEXT(level)", caller); return; } } att = _mesa_get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture%sEXT(attachment)", caller); return; } FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* The above doesn't fully flush the drivers in the way that a * glFlush does, but that is required here: */ if (ctx->Driver.Flush) ctx->Driver.Flush(ctx); _glthread_LOCK_MUTEX(fb->Mutex); if (texObj) { _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, level, zoffset); } else { _mesa_remove_attachment(ctx, att); } _glthread_UNLOCK_MUTEX(fb->Mutex); }
/** * Do error checking for a glGetTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean 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 GLint maxLevels = _mesa_max_texture_levels(ctx, target); const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; GLenum baseFormat, err; if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); return GL_TRUE; } err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glGetTexImage(format/type)"); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* non-existant texture image */ return GL_TRUE; } 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, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depthstencil_format(format) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_dudv_format(format) && !_mesa_is_dudv_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } 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 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, "glGetTexImage(PBO is mapped)"); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for a glGetCompressedTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean 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 GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLuint compressedSize; if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", target); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(bad level = %d)", level); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* probably invalid mipmap level */ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB(texture is not compressed)"); return GL_TRUE; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ if (clientMemSize < compressedSize) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetnCompressedTexImageARB(out of bounds access:" " bufSize (%d) is too small)", clientMemSize); return GL_TRUE; } } 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 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; } } return GL_FALSE; }
/** * Do error checking for a glGetTexImage() call. * \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 ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); GLenum baseFormat; if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); return GL_TRUE; } if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); return GL_TRUE; } if (_mesa_sizeof_packed_type(type) <= 0) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); return GL_TRUE; } if (_mesa_components_in_format(format) <= 0 || format == GL_STENCIL_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; } if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.EXT_packed_depth_stencil && _mesa_is_depthstencil_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.ATI_envmap_bumpmap && _mesa_is_dudv_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || _mesa_is_proxy_texture(target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* out of memory */ 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. */ 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_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depthstencil_format(format) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_dudv_format(format) && !_mesa_is_dudv_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 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)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(out of bounds PBO write)"); return GL_TRUE; } /* PBO should not be mapped */ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(PBO is mapped)"); return GL_TRUE; } } return GL_FALSE; }
/** * 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) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", target); return GL_TRUE; } if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(bad level = %d)", level); return GL_TRUE; } if (_mesa_is_proxy_texture(target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(bad target = %s)", _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* probably invalid mipmap level */ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB(texture is not compressed)"); return GL_TRUE; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { GLuint compressedSize; /* 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; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); /* 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)"); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { const GLboolean isProxy = _mesa_is_proxy_texture(target); struct gl_texture_object *texObj; GLuint maxDim; /* size check */ if (width < 1 || height < 1 || depth < 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); } return GL_TRUE; } /* levels check */ if (levels < 1 || height < 1 || depth < 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); } return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* check levels against maximum */ if (levels > _mesa_max_texture_levels(ctx, target)) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); } return GL_TRUE; } /* check levels against width/height/depth */ maxDim = MAX3(width, height, depth); if (levels > _mesa_logbase2(maxDim) + 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); } return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || (texObj->Name == 0 && !isProxy)) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); } return GL_TRUE; } /* Check if texObj->Immutable is set */ if (texObj->Immutable) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); } return GL_TRUE; } return GL_FALSE; }
/** * Do error checking for a glGetTex(ture)Image() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getteximage_error_check(struct gl_context *ctx, struct gl_texture_image *texImage, GLenum target, GLint level, GLenum format, GLenum type, GLsizei clientMemSize, GLvoid *pixels, bool dsa) { const GLint maxLevels = _mesa_max_texture_levels(ctx, target); const GLuint dimensions = 2; // const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; GLenum baseFormat; const char *suffix = dsa ? "ture" : ""; assert(texImage); assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetTex%sImage(level out of range)", suffix); return GL_TRUE; } /* * 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, "glGetTex%sImage(format mismatch)", suffix); return GL_TRUE; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTex%sImage(format mismatch)", suffix); return GL_TRUE; } else if (_mesa_is_stencil_format(format) && !ctx->Extensions.ARB_texture_stencil8) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sImage(format=GL_STENCIL_INDEX)", suffix); return GL_TRUE; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTex%sImage(format mismatch)", suffix); return GL_TRUE; } else if (_mesa_is_depthstencil_format(format) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTex%sImage(format mismatch)", suffix); return GL_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, "glGetTex%sImage(format mismatch)", suffix); return GL_TRUE; } 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, "glGetTex%sImage(out of bounds PBO access)", suffix); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(out of bounds access:" " bufSize (%d) is too small)", dsa ? "glGetTextureImage" : "glGetnTexImageARB", clientMemSize); } return GL_TRUE; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* PBO should not be mapped */ if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTex%sImage(PBO is mapped)", suffix); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for a glGetCompressedTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getcompressedteximage_error_check(struct gl_context *ctx, struct gl_texture_image *texImage, GLenum target, GLint level, GLsizei clientMemSize, GLvoid *img, bool dsa) { const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLuint compressedSize, dimensions; const char *suffix = dsa ? "ture" : ""; assert(texImage); if (!legal_getteximage_target(ctx, target, dsa)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTex%sImage(target=%s)", suffix, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTex%sImage(bad level = %d)", suffix, level); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTex%sImage(texture is not compressed)", suffix); return GL_TRUE; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); /* Check for invalid pixel storage modes */ dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, &ctx->Pack, dsa ? "glGetCompressedTextureImage": "glGetCompressedTexImage")) { return GL_TRUE; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ if (clientMemSize < (GLsizei) compressedSize) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(out of bounds access: bufSize (%d) is too small)", dsa ? "glGetCompressedTextureImage" : "glGetnCompressedTexImageARB", clientMemSize); return GL_TRUE; } } else { /* do bounds checking on PBO write */ if ((const GLubyte *) img + compressedSize > (const GLubyte *) ctx->Pack.BufferObj->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTex%sImage(out of bounds PBO access)", suffix); return GL_TRUE; } /* make sure PBO is not mapped */ if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTex%sImage(PBO is mapped)", suffix); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, _mesa_lookup_enum_by_nr(internalformat)); return GL_TRUE; } /* size check */ if (width < 1 || height < 1 || depth < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: * * "The ETC2/EAC texture compression algorithm supports only * two-dimensional images. If internalformat is an ETC2/EAC format, * CompressedTexImage3D will generate an INVALID_OPERATION error if * target is not TEXTURE_2D_ARRAY." * * This should also be applicable for glTexStorage3D(). */ if (_mesa_is_compressed_format(ctx, internalformat) && !_mesa_target_can_be_compressed(ctx, target, internalformat)) { _mesa_error(ctx, _mesa_is_desktop_gl(ctx)? GL_INVALID_ENUM : GL_INVALID_OPERATION, "glTexStorage3D(internalformat = %s)", _mesa_lookup_enum_by_nr(internalformat)); } /* levels check */ if (levels < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); return GL_TRUE; } /* check levels against maximum (note different error than above) */ if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); return GL_TRUE; } /* check levels against width/height/depth */ if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); return GL_TRUE; } /* Check if texObj->Immutable is set */ if (!_mesa_is_proxy_texture(target) && texObj->Immutable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); return GL_TRUE; } /* additional checks for depth textures */ if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat, dims, "glTexStorage")) return GL_TRUE; return GL_FALSE; }
/** * Do error checking for a glGetTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLenum baseFormat, err; if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); return GL_TRUE; } if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); return GL_TRUE; } if (_mesa_sizeof_packed_type(type) <= 0) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); return GL_TRUE; } if (_mesa_components_in_format(format) <= 0 || format == GL_STENCIL_INDEX || format == GL_COLOR_INDEX) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); return GL_TRUE; } if (_mesa_is_depth_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glGetTexImage(format/type)"); return GL_TRUE; } texObj = _mesa_select_tex_object(ctx, target); if (!texObj || _mesa_is_proxy_texture(target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* non-existant texture image */ return GL_TRUE; } 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, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } return GL_FALSE; }