[Mesa-dev] [PATCH V4 12/19] mesa: implement TexImage*Multisample

Ian Romanick idr at freedesktop.org
Tue Feb 26 08:08:40 PST 2013


On 02/26/2013 02:10 AM, Chris Forbes wrote:
> V2: - fix formatting issues
>      - generate GL_OUT_OF_MEMORY if teximage cannot be allocated
>      - fix for state moving from texobj to image
>
> V3: - remove ridiculous stencil hack
>      - alter format check to not allow a base format of STENCIL_INDEX
>      - allow width/height/depth to be zero, to deallocate the texture
>      - dont forget to call _mesa_update_fbo_texture
>
> V4: - fix indentation
>      - don't throw errors on proxy texture targets
>
> Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
> ---
>   src/mesa/main/teximage.c | 167 +++++++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 163 insertions(+), 4 deletions(-)
>
> diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
> index 9209d86..0dcf88a 100644
> --- a/src/mesa/main/teximage.c
> +++ b/src/mesa/main/teximage.c
> @@ -4159,15 +4159,174 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
>      texbufferrange(ctx, target, internalFormat, bufObj, offset, size);
>   }
>
> +static GLboolean
> +is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
> +{
> +   /* Everything that is allowed for renderbuffers,
> +    * except for a base format of GL_STENCIL_INDEX.
> +    */
> +   GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat);
> +   return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
> +}
>
>   /** GL_ARB_texture_multisample */
> +static GLboolean
> +check_multisample_target(GLuint dims, GLenum target)
> +{
> +   switch(target) {
> +   case GL_TEXTURE_2D_MULTISAMPLE:
> +   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
> +      return dims == 2;
> +
> +   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
> +   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
> +      return dims == 3;
> +
> +   default:
> +      return GL_FALSE;
> +   }
> +}
> +
> +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 (!check_multisample_target(dims, target)) {
> +      _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 (!is_renderable_texture_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
> +    */

That all landed.  I thought you had another patch that took care of this 
interaction.  Is that queued for after this series?

> +
> +   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;
> +   }
> +
> +   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;
> +      }
> +
> +      ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
> +
> +      _mesa_init_teximage_fields(ctx, texImage,
> +            width, height, depth, 0, internalformat, texFormat);
> +
> +      texImage->NumSamples = samples;
> +      texImage->FixedSampleLocations = fixedsamplelocations;
> +
> +      if (width > 0 && height > 0 && depth > 0) {
> +
> +         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);
> +         }
> +      }
> +
> +      _mesa_update_fbo_texture(ctx, texObj, 0, 0);
> +   }
> +}
> +
>   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
> @@ -4176,6 +4335,6 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
>                               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);
>   }
>



More information about the mesa-dev mailing list