[Mesa-dev] [PATCH 08/18] mesa: Implement glBindTextures()

Brian Paul brianp at vmware.com
Wed Jan 22 09:01:08 PST 2014


On 01/21/2014 03:35 PM, Fredrik Höglund wrote:
> ---
>   src/mesa/main/texobj.c |  121 ++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 121 insertions(+)
>
> diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
> index c9fe11d..2ff3f9d 100644
> --- a/src/mesa/main/texobj.c
> +++ b/src/mesa/main/texobj.c
> @@ -1140,6 +1140,28 @@ unbind_texobj_from_imgunits(struct gl_context *ctx,
>      }
>   }
>
> +/**
> + * Unbinds all textures bound to the given texture image unit.
> + */
> +static void
> +unbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
> +{
> +   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
> +
> +   while (texUnit->_BoundTextures) {
> +      const GLuint index = ffs(texUnit->_BoundTextures) - 1;
> +      struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
> +
> +      _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
> +
> +      /* Pass BindTexture call to device driver */
> +      if (ctx->Driver.BindTexture)
> +         ctx->Driver.BindTexture(ctx, 0, texObj);
> +
> +      texUnit->_BoundTextures ^= (1 << index);

       texUnit->_BoundTextures &= ~(1 << index);


> +      ctx->NewState |= _NEW_TEXTURE;
> +   }
> +}
>
>   /**
>    * Delete named textures.
> @@ -1384,6 +1406,105 @@ _mesa_BindTexture( GLenum target, GLuint texName )
>   void GLAPIENTRY
>   _mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
>   {
> +   GET_CURRENT_CONTEXT(ctx);
> +   GLuint i;

GLint/GLsizei i;


> +
> +   /* The ARB_multi_bind spec says:
> +    *
> +    *     "An INVALID_OPERATION error is generated if <first> + <count>
> +    *      is greater than the number of texture image units supported
> +    *      by the implementation."
> +    */
> +   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glBindTextures(first=%u + count=%u > the value of "
> +                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
> +                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
> +      return;
> +   }
> +
> +   /* Flush before changing bindings */
> +   FLUSH_VERTICES(ctx, 0);
> +
> +   if (textures) {
> +      /* Note that the error semantics for multi-bind commands differ from
> +       * those of other GL commands.
> +       *
> +       * The issues section in the ARB_multi_bind spec says:
> +       *
> +       *    "(11) Typically, OpenGL specifies that if an error is generated by
> +       *          a command, that command has no effect.  This is somewhat
> +       *          unfortunate for multi-bind commands, because it would require
> +       *          a first pass to scan the entire list of bound objects for
> +       *          errors and then a second pass to actually perform the
> +       *          bindings.  Should we have different error semantics?
> +       *
> +       *       RESOLVED:  Yes.  In this specification, when the parameters for
> +       *       one of the <count> binding points are invalid, that binding
> +       *       point is not updated and an error will be generated.  However,
> +       *       other binding points in the same command will be updated if
> +       *       their parameters are valid and no other error occurs."
> +       */
> +
> +      _mesa_begin_texture_lookups(ctx);
> +
> +      for (i = 0; i < count; i++) {
> +         if (textures[i] != 0) {
> +            struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
> +            struct gl_texture_object *current = texUnit->_Current;
> +            struct gl_texture_object *texObj;
> +            GLenum target;
> +            GLuint targetIndex;

gl_texture_index targetIndex;


> +
> +            if (current && current->Name == textures[i])
> +               texObj = current;
> +            else
> +               texObj = _mesa_lookup_texture_without_locking(ctx, textures[i]);
> +
> +            /* The ARB_multi_bind spec says:
> +             *
> +             *     "An INVALID_OPERATION error is generated if any value
> +             *      in <textures> is not zero or the name of an existing
> +             *      texture object (per binding)."
> +             */
> +            if (!texObj || texObj->Target == 0) {
> +               _mesa_error(ctx, GL_INVALID_OPERATION,
> +                           "glBindTextures(textures[%u]=%u is not zero "
> +                           "or the name of an existing texture object)",
> +                           i, textures[i]);
> +               continue;
> +            }
> +
> +            target = texObj->Target;
> +            targetIndex = texObj->TargetIndex;
> +
> +            if (texUnit->CurrentTex[targetIndex] == texObj)
> +               continue;
> +
> +            /* Do the actual binding.  The refcount on the previously bound
> +             * texture object will be decremented.  It will be deleted if the
> +             * count hits zero.
> +             */
> +            _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], texObj);
> +            ASSERT(texUnit->CurrentTex[targetIndex]);
> +
> +            texUnit->_BoundTextures |= (1 << targetIndex);
> +            ctx->NewState |= _NEW_TEXTURE;
> +
> +            /* Pass BindTexture call to device driver */
> +            if (ctx->Driver.BindTexture)
> +               ctx->Driver.BindTexture(ctx, target, texObj);

Again, I'd probably restructure the chunk above to avoid using continue 
(but not a big deal).  I don't think the assertion is needed either 
since texObj will be non-null.



> +         } else {
> +            unbind_textures_from_unit(ctx, first + i);
> +         }
> +      }
> +
> +      _mesa_end_texture_lookups(ctx);
> +   } else {
> +      /* Unbind all textures in the range <first> through <first>+<count>-1 */
> +      for (i = 0; i < count; i++)
> +         unbind_textures_from_unit(ctx, first + i);
> +   }
>   }
>
>
>



More information about the mesa-dev mailing list