V2: - fix formatting issues - generate GL_OUT_OF_MEMORY if teximage cannot be allocated - fix for state moving from texobj to image
Signed-off-by: Chris Forbes <chr...@ijw.co.nz> --- src/mesa/main/teximage.c | 153 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 4 deletions(-) diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index dbeaa93..39e6364 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -4163,13 +4163,158 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, /** GL_ARB_texture_multisample */ +static void +teximagemultisample(GLuint dims, GLenum target, GLsizei samples, + GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations) +{ + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLboolean sizeOK, dimensionsOK; + gl_format texFormat; + + GET_CURRENT_CONTEXT(ctx); + + if (!(ctx->Extensions.ARB_texture_multisample + && _mesa_is_desktop_gl(ctx))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%uDMultisample", dims); + return; + } + + if ((dims == 2 && target != GL_TEXTURE_2D_MULTISAMPLE) || + (dims == 3 && target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uDMultisample(target)", dims); + return; + } + + /* check that the specified internalformat is color/depth/stencil-renderable; + * refer GL3.1 spec 4.4.4 + */ + + if (!_mesa_base_fbo_format(ctx, internalformat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%uDMultisample(internalformat=%s)", + dims, + _mesa_lookup_enum_by_nr(internalformat)); + return; + } + + if (_mesa_is_enum_format_integer(internalformat)) { + if (samples > ctx->Const.MaxIntegerSamples) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%uDMultisample(samples>GL_MAX_INTEGER_SAMPLES)", + dims); + return; + } + } + else if (_mesa_is_depth_or_stencil_format(internalformat)) { + if (samples > ctx->Const.MaxDepthTextureSamples) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%uDMultisample(samples>GL_MAX_DEPTH_TEXTURE_SAMPLES)", + dims); + return; + } + } + else { + if (samples > ctx->Const.MaxColorTextureSamples) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%uDMultisample(samples>GL_MAX_COLOR_TEXTURE_SAMPLES)", + dims); + return; + } + } + + /* TODO: should ask the driver for the exact limit for this internalformat + * once IDR's internalformat_query bits land + */ + + texObj = _mesa_get_current_tex_object(ctx, target); + texImage = _mesa_get_tex_image(ctx, texObj, 0, 0); + + if (texImage == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uDMultisample()", dims); + return; + } + + switch(internalformat) { + /* XXX horrid hack: _mesa_choose_texture_format will be + * very upset by these. a similar hack exists in the i965 + * renderbufferstorage path. + */ + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1: + case GL_STENCIL_INDEX4: + case GL_STENCIL_INDEX8: + case GL_STENCIL_INDEX16: + texFormat = MESA_FORMAT_S8; + break; + default: + texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, + internalformat, GL_NONE, GL_NONE); + } + assert(texFormat != MESA_FORMAT_NONE); + + 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(target)) { + if (dimensionsOK && sizeOK) { + _mesa_init_teximage_fields(ctx, texImage, + width, height, depth, 0, internalformat, texFormat); + texImage->NumSamples = samples; + texImage->FixedSampleLocations = fixedsamplelocations; + } + else { + /* clear all image fields */ + _mesa_init_teximage_fields(ctx, texImage, + 0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE); + } + } + else { + if (!dimensionsOK) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%uDMultisample(invalid width or height)", dims); + return; + } + + if (!sizeOK) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glTexImage%uDMultisample(texture too large)", dims); + return; + } + + assert(width > 0); + assert(height > 0); + assert(depth > 0); + + _mesa_init_teximage_fields(ctx, texImage, + width, height, depth, 0, internalformat, texFormat); + + texImage->NumSamples = samples; + texImage->FixedSampleLocations = fixedsamplelocations; + + if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1, + width, height, depth)) { + /* tidy up the texture image state. strictly speaking, + * we're allowed to just leave this in whatever state we + * like, but being tidy is good. + */ + _mesa_init_teximage_fields(ctx, texImage, + 0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE); + } + } +} + void GLAPIENTRY _mesa_TexImage2DMultisample(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) { - assert(!"Not implemented"); - /* allocate a single 2d multisample texture */ + teximagemultisample(2, target, samples, internalformat, + width, height, 1, fixedsamplelocations); } void GLAPIENTRY @@ -4177,6 +4322,6 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) { - assert(!"Not implemented"); - /* allocate an array of 2d multisample textures */ + teximagemultisample(3, target, samples, internalformat, + width, height, depth, fixedsamplelocations); } -- 1.8.1.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev