diff options
Diffstat (limited to 'src/mesa/main/texobj.c')
-rw-r--r-- | src/mesa/main/texobj.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 7c8b789ca39..2a82c2d4ee3 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -1151,6 +1151,28 @@ unbind_texobj_from_image_units(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, unit, 0, texObj); + + texUnit->_BoundTextures &= ~(1 << index); + ctx->NewState |= _NEW_TEXTURE; + } +} /** * Delete named textures. @@ -1397,6 +1419,104 @@ _mesa_BindTexture( GLenum target, GLuint texName ) void GLAPIENTRY _mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures) { + GET_CURRENT_CONTEXT(ctx); + GLint 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=%d > the value of " + "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)", + first, count, ctx->Const.MaxCombinedTextureImageUnits); + return; + } + + /* Flush before changing bindings */ + FLUSH_VERTICES(ctx, 0); + + ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed, + first + count); + + 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; + + if (current && current->Name == textures[i]) + texObj = current; + else + texObj = _mesa_lookup_texture_locked(ctx, textures[i]); + + if (texObj && texObj->Target != 0) { + const gl_texture_index targetIndex = texObj->TargetIndex; + + if (texUnit->CurrentTex[targetIndex] != texObj) { + /* 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); + + texUnit->_BoundTextures |= (1 << targetIndex); + ctx->NewState |= _NEW_TEXTURE; + + /* Pass the BindTexture call to the device driver */ + if (ctx->Driver.BindTexture) + ctx->Driver.BindTexture(ctx, first + i, + texObj->Target, texObj); + } + } else { + /* 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)." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindTextures(textures[%d]=%u is not zero " + "or the name of an existing texture object)", + i, textures[i]); + } + } 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); + } } |