mesa: consolidate glTexImage1/2/3D() code

Something similar could be done for glCopyTex[Sub]Image() and the
compressed texture image functions as well.
This commit is contained in:
Brian Paul
2010-12-06 17:08:16 -07:00
parent 6dca66b620
commit d0b2b8da7d

View File

@@ -1318,6 +1318,62 @@ target_can_be_compressed(struct gl_context *ctx, GLenum target)
} }
/**
* Check if the given texture target value is legal for a
* glTexImage1/2/3D call.
*/
static GLboolean
legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
{
switch (dims) {
case 1:
switch (target) {
case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_1D:
return GL_TRUE;
default:
return GL_FALSE;
}
case 2:
switch (target) {
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
return GL_TRUE;
case GL_PROXY_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return ctx->Extensions.ARB_texture_cube_map;
case GL_TEXTURE_RECTANGLE_NV:
case GL_PROXY_TEXTURE_RECTANGLE_NV:
return ctx->Extensions.NV_texture_rectangle;
case GL_TEXTURE_1D_ARRAY_EXT:
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
return ctx->Extensions.MESA_texture_array;
default:
return GL_FALSE;
}
case 3:
switch (target) {
case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
return GL_TRUE;
case GL_TEXTURE_2D_ARRAY_EXT:
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
return ctx->Extensions.MESA_texture_array;
default:
return GL_FALSE;
}
default:
_mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims);
return GL_FALSE;
}
}
/** /**
* Test the glTexImage[123]D() parameters for errors. * Test the glTexImage[123]D() parameters for errors.
* *
@@ -1384,16 +1440,10 @@ texture_error_check( struct gl_context *ctx,
* level, width, height and depth. * level, width, height and depth.
*/ */
if (dimensions == 1) { if (dimensions == 1) {
if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
proxy_target = GL_PROXY_TEXTURE_1D; proxy_target = GL_PROXY_TEXTURE_1D;
height = 1; height = 1;
depth = 1; depth = 1;
} }
else {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
return GL_TRUE;
}
}
else if (dimensions == 2) { else if (dimensions == 2) {
depth = 1; depth = 1;
if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
@@ -1402,19 +1452,11 @@ texture_error_check( struct gl_context *ctx,
else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
(target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
if (!ctx->Extensions.ARB_texture_cube_map) {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
return GL_TRUE;
}
proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
sizeOK = (width == height); sizeOK = (width == height);
} }
else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
target == GL_TEXTURE_RECTANGLE_NV) { target == GL_TEXTURE_RECTANGLE_NV) {
if (!ctx->Extensions.NV_texture_rectangle) {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
return GL_TRUE;
}
proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
} }
else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
@@ -1422,11 +1464,13 @@ texture_error_check( struct gl_context *ctx,
proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
} }
else { else {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); _mesa_problem(ctx, "unexpected target in texture_error_check()");
return GL_TRUE; return GL_TRUE;
} }
} }
else if (dimensions == 3) { else {
assert(dimensions == 3);
if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
proxy_target = GL_PROXY_TEXTURE_3D; proxy_target = GL_PROXY_TEXTURE_3D;
} }
@@ -1435,14 +1479,10 @@ texture_error_check( struct gl_context *ctx,
proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
} }
else { else {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); _mesa_problem(ctx, "unexpected target in texture_error_check()");
return GL_TRUE; return GL_TRUE;
} }
} }
else {
_mesa_problem( ctx, "bad dims in texture_error_check" );
return GL_TRUE;
}
sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
internalFormat, format, internalFormat, format,
@@ -2355,219 +2395,48 @@ _mesa_choose_texture_format(struct gl_context *ctx,
} }
/**
/* * Common code to implement all the glTexImage1D/2D/3D functions.
* Called from the API. Note that width includes the border.
*/ */
void GLAPIENTRY static void
_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, teximage(struct gl_context *ctx, GLuint dims,
GLsizei width, GLint border, GLenum format, GLenum target, GLint level, GLint internalFormat,
GLenum type, const GLvoid *pixels ) GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const GLvoid *pixels)
{ {
GET_CURRENT_CONTEXT(ctx); GLboolean error;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
_mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n", _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n",
dims,
_mesa_lookup_enum_by_nr(target), level, _mesa_lookup_enum_by_nr(target), level,
_mesa_lookup_enum_by_nr(internalFormat), width, border, _mesa_lookup_enum_by_nr(internalFormat),
width, height, depth, border,
_mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels); _mesa_lookup_enum_by_nr(type), pixels);
internalFormat = override_internal_format(internalFormat, width, 1);
if (target == GL_TEXTURE_1D) {
/* non-proxy target */
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
const GLuint face = _mesa_tex_target_to_face(target);
if (texture_error_check(ctx, 1, target, level, internalFormat,
format, type, width, 1, 1, border)) {
return; /* error was recorded */
}
if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target);
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
}
else {
gl_format texFormat;
if (texImage->Data) {
ctx->Driver.FreeTexImageData( ctx, texImage );
}
ASSERT(texImage->Data == NULL);
texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
internalFormat, format,
type);
if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
_mesa_init_teximage_fields(ctx, target, texImage,
width, 1, 1,
border, internalFormat,
texFormat);
/* Give the texture to the driver. <pixels> may be null. */
ASSERT(ctx->Driver.TexImage1D);
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
check_gen_mipmap(ctx, target, texObj, level);
update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->_Complete = GL_FALSE;
ctx->NewState |= _NEW_TEXTURE;
}
else {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
}
}
}
_mesa_unlock_texture(ctx, texObj);
}
else if (target == GL_PROXY_TEXTURE_1D) {
/* Proxy texture: check for errors and update proxy state */
struct gl_texture_image *texImage;
texImage = _mesa_get_proxy_tex_image(ctx, target, level);
if (texture_error_check(ctx, 1, target, level, internalFormat,
format, type, width, 1, 1, border)) {
/* when error, clear all proxy texture image parameters */
if (texImage)
clear_teximage_fields(texImage);
}
else {
/* no error, set the tex image parameters */
struct gl_texture_object *texObj =
_mesa_get_current_tex_object(ctx, target);
gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, target,
level,
internalFormat,
format, type);
if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
_mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
border, internalFormat, texFormat);
}
else if (texImage) {
clear_teximage_fields(texImage);
}
}
}
else {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
return;
}
}
void GLAPIENTRY
_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type,
const GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
_mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n",
_mesa_lookup_enum_by_nr(target), level,
_mesa_lookup_enum_by_nr(internalFormat), width, height,
border, _mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels);
internalFormat = override_internal_format(internalFormat, width, height); internalFormat = override_internal_format(internalFormat, width, height);
if (target == GL_TEXTURE_2D || /* target error checking */
(ctx->Extensions.ARB_texture_cube_map && if (!legal_teximage_target(ctx, dims, target)) {
target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)",
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || dims, _mesa_lookup_enum_by_nr(target));
(ctx->Extensions.NV_texture_rectangle && return;
target == GL_TEXTURE_RECTANGLE_NV) ||
(ctx->Extensions.MESA_texture_array &&
target == GL_TEXTURE_1D_ARRAY_EXT)) {
/* non-proxy target */
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
const GLuint face = _mesa_tex_target_to_face(target);
if (texture_error_check(ctx, 2, target, level, internalFormat,
format, type, width, height, 1, border)) {
return; /* error was recorded */
} }
if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) /* general error checking */
_mesa_update_state(ctx); error = texture_error_check(ctx, dims, target, level, internalFormat,
format, type, width, height, depth, border);
texObj = _mesa_get_current_tex_object(ctx, target); if (_mesa_is_proxy_texture(target)) {
_mesa_lock_texture(ctx, texObj); /* Proxy texture: just clear or set state depending on error checking */
{ struct gl_texture_image *texImage =
texImage = _mesa_get_tex_image(ctx, texObj, target, level); _mesa_get_proxy_tex_image(ctx, target, level);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
}
else {
gl_format texFormat;
if (texImage->Data) { if (error) {
ctx->Driver.FreeTexImageData( ctx, texImage );
}
ASSERT(texImage->Data == NULL);
texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
internalFormat, format,
type);
if (legal_texture_size(ctx, texFormat, width, height, 1)) {
_mesa_init_teximage_fields(ctx, target, texImage, width,
height, 1, border, internalFormat,
texFormat);
/* Give the texture to the driver. <pixels> may be null. */
ASSERT(ctx->Driver.TexImage2D);
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, &ctx->Unpack, texObj, texImage);
check_gen_mipmap(ctx, target, texObj, level);
update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->_Complete = GL_FALSE;
ctx->NewState |= _NEW_TEXTURE;
}
else {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
}
}
}
_mesa_unlock_texture(ctx, texObj);
}
else if (target == GL_PROXY_TEXTURE_2D ||
(target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
ctx->Extensions.ARB_texture_cube_map) ||
(target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
ctx->Extensions.NV_texture_rectangle) ||
(ctx->Extensions.MESA_texture_array &&
target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
/* Proxy texture: check for errors and update proxy state */
struct gl_texture_image *texImage;
texImage = _mesa_get_proxy_tex_image(ctx, target, level);
if (texture_error_check(ctx, 2, target, level, internalFormat,
format, type, width, height, 1, border)) {
/* when error, clear all proxy texture image parameters */ /* when error, clear all proxy texture image parameters */
if (texImage) if (texImage)
clear_teximage_fields(texImage); clear_teximage_fields(texImage);
@@ -2580,9 +2449,11 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
target, level, target, level,
internalFormat, internalFormat,
format, type); format, type);
if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
_mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, if (legal_texture_size(ctx, texFormat, width, height, depth)) {
border, internalFormat, texFormat); _mesa_init_teximage_fields(ctx, target, texImage, width, height,
depth, border, internalFormat,
texFormat);
} }
else if (texImage) { else if (texImage) {
clear_teximage_fields(texImage); clear_teximage_fields(texImage);
@@ -2590,44 +2461,12 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
} }
} }
else { else {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
return;
}
}
/*
* Called by the API or display list executor.
* Note that width and height include the border.
*/
void GLAPIENTRY
_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
_mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n",
_mesa_lookup_enum_by_nr(target), level,
_mesa_lookup_enum_by_nr(internalFormat), width, height,
depth, border, _mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels);
internalFormat = override_internal_format(internalFormat, width, height);
if (target == GL_TEXTURE_3D ||
(ctx->Extensions.MESA_texture_array &&
target == GL_TEXTURE_2D_ARRAY_EXT)) {
/* non-proxy target */ /* non-proxy target */
const GLuint face = _mesa_tex_target_to_face(target);
struct gl_texture_object *texObj; struct gl_texture_object *texObj;
struct gl_texture_image *texImage; struct gl_texture_image *texImage;
const GLuint face = _mesa_tex_target_to_face(target);
if (texture_error_check(ctx, 3, target, level, (GLint) internalFormat, if (error) {
format, type, width, height, depth, border)) {
return; /* error was recorded */ return; /* error was recorded */
} }
@@ -2635,11 +2474,13 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
_mesa_update_state(ctx); _mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target); texObj = _mesa_get_current_tex_object(ctx, target);
_mesa_lock_texture(ctx, texObj); _mesa_lock_texture(ctx, texObj);
{ {
texImage = _mesa_get_tex_image(ctx, texObj, target, level); texImage = _mesa_get_tex_image(ctx, texObj, target, level);
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
} }
else { else {
gl_format texFormat; gl_format texFormat;
@@ -2660,10 +2501,28 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
/* Give the texture to the driver. <pixels> may be null. */ /* Give the texture to the driver. <pixels> may be null. */
ASSERT(ctx->Driver.TexImage3D); ASSERT(ctx->Driver.TexImage3D);
switch (dims) {
case 1:
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border, format,
type, pixels, &ctx->Unpack, texObj,
texImage);
break;
case 2:
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border, format,
type, pixels, &ctx->Unpack, texObj,
texImage);
break;
case 3:
ctx->Driver.TexImage3D(ctx, target, level, internalFormat, ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
width, height, depth, border, format, width, height, depth, border, format,
type, pixels, &ctx->Unpack, texObj, type, pixels, &ctx->Unpack, texObj,
texImage); texImage);
break;
default:
_mesa_problem(ctx, "invalid dims=%u in teximage()", dims);
}
check_gen_mipmap(ctx, target, texObj, level); check_gen_mipmap(ctx, target, texObj, level);
@@ -2674,46 +2533,54 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
ctx->NewState |= _NEW_TEXTURE; ctx->NewState |= _NEW_TEXTURE;
} }
else { else {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
} }
} }
} }
_mesa_unlock_texture(ctx, texObj); _mesa_unlock_texture(ctx, texObj);
} }
else if (target == GL_PROXY_TEXTURE_3D || }
(ctx->Extensions.MESA_texture_array &&
target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
/* Proxy texture: check for errors and update proxy state */ /*
struct gl_texture_image *texImage; * Called from the API. Note that width includes the border.
texImage = _mesa_get_proxy_tex_image(ctx, target, level); */
if (texture_error_check(ctx, 3, target, level, internalFormat, void GLAPIENTRY
format, type, width, height, depth, border)) { _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
/* when error, clear all proxy texture image parameters */ GLsizei width, GLint border, GLenum format,
if (texImage) GLenum type, const GLvoid *pixels )
clear_teximage_fields(texImage); {
} GET_CURRENT_CONTEXT(ctx);
else { teximage(ctx, 1, target, level, internalFormat, width, 1, 1,
/* no error, set the tex image parameters */ border, format, type, pixels);
struct gl_texture_object *texObj = }
_mesa_get_current_tex_object(ctx, target);
gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
target, level, void GLAPIENTRY
internalFormat, _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
format, type); GLsizei width, GLsizei height, GLint border,
if (legal_texture_size(ctx, texFormat, width, height, depth)) { GLenum format, GLenum type,
_mesa_init_teximage_fields(ctx, target, texImage, width, height, const GLvoid *pixels )
depth, border, internalFormat, {
texFormat); GET_CURRENT_CONTEXT(ctx);
} teximage(ctx, 2, target, level, internalFormat, width, height, 1,
else if (texImage) { border, format, type, pixels);
clear_teximage_fields(texImage); }
}
}
} /*
else { * Called by the API or display list executor.
_mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); * Note that width and height include the border.
return; */
} void GLAPIENTRY
_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
teximage(ctx, 3, target, level, internalFormat, width, height, depth,
border, format, type, pixels);
} }