/** * Helper used by _mesa_TexStorage1/2/3D(). */ static void texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; GLboolean error; GET_CURRENT_CONTEXT(ctx); texObj = _mesa_get_current_tex_object(ctx, target); error = tex_storage_error_check(ctx, dims, target, levels, internalformat, width, height, depth); if (!error) { setup_texstorage(ctx, texObj, dims, levels, internalformat, width, height, depth); } else if (_mesa_is_proxy_texture(target)) { /* clear all image fields for [levels] */ clear_image_fields(ctx, dims, texObj); } }
static void GLAPIENTRY _mesa_GetColorTable( GLenum target, GLenum format, GLenum type, GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_color_table *table = NULL; GLfloat rgba[MAX_COLOR_TABLE_SIZE][4]; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->NewState) { _mesa_update_state(ctx); } switch (target) { case GL_SHARED_TEXTURE_PALETTE_EXT: table = &ctx->Texture.Palette; break; case GL_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION]; break; case GL_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); return; } table = &(texUnit->ColorTable); break; case GL_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION]; break; case GL_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX]; break; default: /* try texture targets */ { struct gl_texture_object *texobj = _mesa_select_tex_object(ctx, texUnit, target); if (texobj && !_mesa_is_proxy_texture(target)) { table = &texobj->Palette; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); return; } } } ASSERT(table); if (table->Size <= 0) { return; } switch (table->_BaseFormat) { case GL_ALPHA: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = 0; rgba[i][GCOMP] = 0; rgba[i][BCOMP] = 0; rgba[i][ACOMP] = table->TableF[i]; } } break; case GL_LUMINANCE: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = table->TableF[i]; rgba[i][ACOMP] = 1.0F; } } break; case GL_LUMINANCE_ALPHA: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = table->TableF[i*2+0]; rgba[i][ACOMP] = table->TableF[i*2+1]; } } break; case GL_INTENSITY: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = rgba[i][ACOMP] = table->TableF[i]; } } break; case GL_RGB: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = table->TableF[i*3+0]; rgba[i][GCOMP] = table->TableF[i*3+1]; rgba[i][BCOMP] = table->TableF[i*3+2]; rgba[i][ACOMP] = 1.0F; } } break; case GL_RGBA: _mesa_memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat)); break; default: _mesa_problem(ctx, "bad table format in glGetColorTable"); return; } data = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack, table->Size, 1, 1, format, type, data, "glGetColorTable"); if (!data) return; _mesa_pack_rgba_span_float(ctx, table->Size, rgba, format, type, data, &ctx->Pack, 0x0); _mesa_unmap_pbo_dest(ctx, &ctx->Pack); }
void GLAPIENTRY _mesa_ColorSubTable( GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data ) { static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 }; static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 }; GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_texture_object *texObj = NULL; struct gl_color_table *table = NULL; const GLfloat *scale = one, *bias = zero; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); switch (target) { case GL_SHARED_TEXTURE_PALETTE_EXT: table = &ctx->Texture.Palette; break; case GL_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION]; break; case GL_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); return; } table = &(texUnit->ColorTable); scale = ctx->Pixel.TextureColorTableScale; bias = ctx->Pixel.TextureColorTableBias; break; case GL_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION]; break; case GL_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX]; break; default: /* try texture targets */ texObj = _mesa_select_tex_object(ctx, texUnit, target); if (texObj && !_mesa_is_proxy_texture(target)) { table = &texObj->Palette; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); return; } } assert(table); if (!_mesa_is_legal_format_and_type(ctx, format, type) || format == GL_INTENSITY) { _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)"); return; } if (count < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)"); return; } /* error should have been caught sooner */ assert(_mesa_components_in_format(table->_BaseFormat) > 0); if (start + count > (GLint) table->Size) { _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)"); return; } if (!table->TableF || !table->TableUB) { /* a GL_OUT_OF_MEMORY error would have been recorded previously */ return; } store_colortable_entries(ctx, table, start, count, format, type, data, scale[0], bias[0], scale[1], bias[1], scale[2], bias[2], scale[3], bias[3]); if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { /* per-texture object palette */ if (ctx->Driver.UpdateTexturePalette) { (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); } } ctx->NewState |= _NEW_PIXEL; }
void GLAPIENTRY _mesa_ColorTable( GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data ) { static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 }; static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 }; GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_texture_object *texObj = NULL; struct gl_color_table *table = NULL; GLboolean proxy = GL_FALSE; GLint baseFormat; const GLfloat *scale = one, *bias = zero; GLint comps; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ switch (target) { case GL_SHARED_TEXTURE_PALETTE_EXT: table = &ctx->Texture.Palette; break; case GL_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION]; break; case GL_PROXY_COLOR_TABLE: table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION]; proxy = GL_TRUE; break; case GL_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } table = &(texUnit->ColorTable); scale = ctx->Pixel.TextureColorTableScale; bias = ctx->Pixel.TextureColorTableBias; break; case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } table = &(texUnit->ProxyColorTable); proxy = GL_TRUE; break; case GL_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION]; break; case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION]; proxy = GL_TRUE; break; case GL_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX]; break; case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX]; proxy = GL_TRUE; break; default: /* try texture targets */ { struct gl_texture_object *texobj = _mesa_select_tex_object(ctx, texUnit, target); if (texobj) { table = &texobj->Palette; proxy = _mesa_is_proxy_texture(target); } else { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } } } assert(table); if (!_mesa_is_legal_format_and_type(ctx, format, type) || format == GL_INTENSITY) { _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)"); return; } baseFormat = base_colortab_format(internalFormat); if (baseFormat < 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)"); return; } if (width < 0 || (width != 0 && !_mesa_is_pow_two(width))) { /* error */ if (proxy) { table->Size = 0; table->InternalFormat = (GLenum) 0; table->_BaseFormat = (GLenum) 0; } else { _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width); } return; } if (width > (GLsizei) ctx->Const.MaxColorTableSize) { if (proxy) { table->Size = 0; table->InternalFormat = (GLenum) 0; table->_BaseFormat = (GLenum) 0; } else { _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)"); } return; } table->Size = width; table->InternalFormat = internalFormat; table->_BaseFormat = (GLenum) baseFormat; comps = _mesa_components_in_format(table->_BaseFormat); assert(comps > 0); /* error should have been caught sooner */ if (!proxy) { _mesa_free_colortable_data(table); if (width > 0) { table->TableF = (GLfloat *) _mesa_malloc(comps * width * sizeof(GLfloat)); table->TableUB = (GLubyte *) _mesa_malloc(comps * width * sizeof(GLubyte)); if (!table->TableF || !table->TableUB) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable"); return; } store_colortable_entries(ctx, table, 0, width, /* start, count */ format, type, data, scale[0], bias[0], scale[1], bias[1], scale[2], bias[2], scale[3], bias[3]); } } /* proxy */ /* do this after the table's Type and Format are set */ set_component_sizes(table); if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { /* texture object palette, texObj==NULL means the shared palette */ if (ctx->Driver.UpdateTexturePalette) { (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); } } ctx->NewState |= _NEW_PIXEL; }
static void GLAPIENTRY _mesa_GetnColorTableARB( GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_color_table *table = NULL; GLfloat rgba[MAX_COLOR_TABLE_SIZE][4]; GLbitfield transferOps = 0; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->NewState) { _mesa_update_state(ctx); } switch (target) { case GL_SHARED_TEXTURE_PALETTE_EXT: table = &ctx->Texture.Palette; break; default: /* try texture targets */ { struct gl_texture_object *texobj = _mesa_select_tex_object(ctx, texUnit, target); if (texobj && !_mesa_is_proxy_texture(target)) { table = &texobj->Palette; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); return; } } } ASSERT(table); if (table->Size <= 0) { return; } switch (table->_BaseFormat) { case GL_ALPHA: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = 0; rgba[i][GCOMP] = 0; rgba[i][BCOMP] = 0; rgba[i][ACOMP] = table->TableF[i]; } } break; case GL_LUMINANCE: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = table->TableF[i]; rgba[i][ACOMP] = 1.0F; } } break; case GL_LUMINANCE_ALPHA: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = table->TableF[i*2+0]; rgba[i][ACOMP] = table->TableF[i*2+1]; } } break; case GL_INTENSITY: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = rgba[i][ACOMP] = table->TableF[i]; } } break; case GL_RGB: { GLuint i; for (i = 0; i < table->Size; i++) { rgba[i][RCOMP] = table->TableF[i*3+0]; rgba[i][GCOMP] = table->TableF[i*3+1]; rgba[i][BCOMP] = table->TableF[i*3+2]; rgba[i][ACOMP] = 1.0F; } } break; case GL_RGBA: memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat)); break; default: _mesa_problem(ctx, "bad table format in glGetColorTable"); return; } data = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack, table->Size, 1, 1, format, type, bufSize, data, "glGetColorTable"); if (!data) return; /* TODO: is this correct? */ if(ctx->Color._ClampReadColor) transferOps |= IMAGE_CLAMP_BIT; _mesa_pack_rgba_span_float(ctx, table->Size, rgba, format, type, data, &ctx->Pack, transferOps); _mesa_unmap_pbo_dest(ctx, &ctx->Pack); }
/** * Helper that does the storage allocation for _mesa_TexStorage1/2/3D() * and _mesa_TextureStorage1/2/3D(). */ static void texture_storage(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texObj, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool dsa) { GLboolean sizeOK, dimensionsOK; mesa_format texFormat; const char* suffix = dsa ? "ture" : ""; assert(texObj); if (tex_storage_error_check(ctx, texObj, dims, target, levels, internalformat, width, height, depth, dsa)) { return; /* error was recorded */ } texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, internalformat, GL_NONE, GL_NONE); /* check that width, height, depth are legal for the mipmap level */ dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, width, height, depth, 0); sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, levels, 0, texFormat, 1, width, height, depth); if (_mesa_is_proxy_texture(target)) { if (dimensionsOK && sizeOK) { initialize_texture_fields(ctx, texObj, levels, width, height, depth, internalformat, texFormat); } else { /* clear all image fields for [levels] */ clear_texture_fields(ctx, texObj); } } else { if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(invalid width, height or depth)", suffix, dims); return; } if (!sizeOK) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD(texture too large)", suffix, dims); } assert(levels > 0); assert(width > 0); assert(height > 0); assert(depth > 0); if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth, internalformat, texFormat)) { return; } /* Do actual texture memory allocation */ if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels, width, height, depth)) { /* Reset the texture images' info to zeros. * Strictly speaking, we probably don't have to do this since * generating GL_OUT_OF_MEMORY can leave things in an undefined * state but this puts things in a consistent state. */ clear_texture_fields(ctx, texObj); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD", suffix, dims); return; } _mesa_set_texture_view_state(ctx, texObj, target, levels); update_fbo_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; 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); }
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)); }
/** * Helper used by _mesa_TexStorage1/2/3D(). */ static void texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; GLboolean sizeOK, dimensionsOK; gl_format texFormat; GET_CURRENT_CONTEXT(ctx); if (tex_storage_error_check(ctx, dims, target, levels, internalformat, width, height, depth)) { return; /* error was recorded */ } texObj = _mesa_get_current_tex_object(ctx, target); assert(texObj); texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, internalformat, GL_NONE, GL_NONE); assert(texFormat != MESA_FORMAT_NONE); /* check that width, height, depth are legal for the mipmap level */ dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, width, height, depth, 0); sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat, width, height, depth, 0); if (_mesa_is_proxy_texture(texObj->Target)) { if (dimensionsOK && sizeOK) { initialize_texture_fields(ctx, texObj, levels, width, height, depth, internalformat, texFormat); } else { /* clear all image fields for [levels] */ clear_texture_fields(ctx, texObj); } } else { if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(invalid width, height or depth)", dims); return; } if (!sizeOK) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD(texture too large)", dims); } assert(levels > 0); assert(width > 0); assert(height > 0); assert(depth > 0); if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth, internalformat, texFormat)) { return; } /* Do actual texture memory allocation */ if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels, width, height, depth)) { /* Reset the texture images' info to zeros. * Strictly speaking, we probably don't have to do this since * generating GL_OUT_OF_MEMORY can leave things in an undefined * state but this puts things in a consistent state. */ clear_texture_fields(ctx, texObj); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims); return; } texObj->Immutable = GL_TRUE; texObj->ImmutableLevels = levels; } }
/** * 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 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 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 actual memory allocation for glTexStorage1/2/3D(). */ static void setup_texstorage(struct gl_context *ctx, struct gl_texture_object *texObj, GLuint dims, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth) { const GLenum target = texObj->Target; const GLuint numFaces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; gl_format texFormat; GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; GLuint face; assert(levels > 0); assert(width > 0); assert(height > 0); assert(depth > 0); texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, internalFormat, GL_NONE, GL_NONE); /* Set up all the texture object's gl_texture_images */ for (level = 0; level < levels; level++) { for (face = 0; face < numFaces; face++) { const GLenum faceTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : target; struct gl_texture_image *texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); return; } _mesa_init_teximage_fields(ctx, target, texImage, levelWidth, levelHeight, levelDepth, 0, internalFormat, texFormat); } next_mipmap_level_size(target, &levelWidth, &levelHeight, &levelDepth); } assert(levelWidth > 0); assert(levelHeight > 0); assert(levelDepth > 0); if (!_mesa_is_proxy_texture(texObj->Target)) { /* Do actual texture memory allocation */ if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels, width, height, depth)) { /* Reset the texture images' info to zeros. * Strictly speaking, we probably don't have to do this since * generating GL_OUT_OF_MEMORY can leave things in an undefined * state but this puts things in a consistent state. */ for (level = 0; level < levels; level++) { for (face = 0; face < numFaces; face++) { struct gl_texture_image *texImage = texObj->Image[face][level]; if (texImage) { _mesa_init_teximage_fields(ctx, target, texImage, 0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE); } } } _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims); return; } } texObj->Immutable = GL_TRUE; }
/** * 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; }