X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Ftexobj.c;h=f0ff605fc506a89cef6f10a362c4114d902b8378;hb=de42431a9d761305c9911f30b5880a9a049a2d60;hp=221746ffd0ed86575023447fc0724cdc15cca03e;hpb=b8ee235e721ffd2503f4e8114d38685d58a0ceae;p=mesa.git diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 221746ffd0e..f0ff605fc50 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -89,7 +89,7 @@ _mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id) * * Called via ctx->Driver.NewTextureObject, unless overridden by a device * driver. - * + * * \param shared the shared GL state structure to contain the texture object * \param name integer name for the texture object * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, @@ -268,7 +268,6 @@ _mesa_delete_texture_object(struct gl_context *ctx, } - /** * Copy texture object state from one texture object to another. * Use for glPush/PopAttrib. @@ -653,7 +652,8 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) { height /= 2; } - if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) { + if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY + && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) { depth /= 2; } @@ -675,22 +675,25 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, return; } if (img->Width2 != width) { - incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i, img->Width2); + incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i, + img->Width2); return; } if (img->Height2 != height) { - incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i, img->Height2); + incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i, + img->Height2); return; } if (img->Depth2 != depth) { - incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i, img->Depth2); + incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i, + img->Depth2); return; } /* Extra checks for cube textures */ if (face > 0) { /* check that cube faces are the same size */ - if (img->Width2 != t->Image[0][i]->Width2 || + if (img->Width2 != t->Image[0][i]->Width2 || img->Height2 != t->Image[0][i]->Height2) { incomplete(t, MIPMAP, "CubeMap Image[n][i] bad size"); return; @@ -698,7 +701,7 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, } } } - + if (width == 1 && height == 1 && depth == 1) { return; /* found smallest needed mipmap, all done! */ } @@ -772,18 +775,21 @@ _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) { if (!ctx->Shared->FallbackTex[tex]) { /* create fallback texture now */ - const GLsizei width = 1, height = 1, depth = 1; - GLubyte texel[4]; + const GLsizei width = 1, height = 1; + GLsizei depth = 1; + GLubyte texel[24]; struct gl_texture_object *texObj; struct gl_texture_image *texImage; mesa_format texFormat; GLuint dims, face, numFaces = 1; GLenum target; - texel[0] = - texel[1] = - texel[2] = 0x0; - texel[3] = 0xff; + for (face = 0; face < 6; face++) { + texel[4*face + 0] = + texel[4*face + 1] = + texel[4*face + 2] = 0x0; + texel[4*face + 3] = 0xff; + } switch (tex) { case TEXTURE_2D_ARRAY_INDEX: @@ -822,6 +828,7 @@ _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) case TEXTURE_CUBE_ARRAY_INDEX: dims = 3; target = GL_TEXTURE_CUBE_MAP_ARRAY; + depth = 6; break; case TEXTURE_EXTERNAL_INDEX: dims = 2; @@ -946,6 +953,7 @@ _mesa_total_texture_memory(struct gl_context *ctx) return total; } + static struct gl_texture_object * invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture, GLint level, const char *name) @@ -1018,7 +1026,7 @@ invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture, * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture * IDs which are stored in \p textures. Corresponding empty texture * objects are also generated. - */ + */ void GLAPIENTRY _mesa_GenTextures( GLsizei n, GLuint *textures ) { @@ -1152,6 +1160,30 @@ 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. * @@ -1279,10 +1311,10 @@ _mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target) /** * Bind a named texture to a texturing target. - * + * * \param target texture target. * \param texName texture name. - * + * * \sa glBindTexture(). * * Determines the old texture object bound and returns immediately if rebinding @@ -1324,7 +1356,9 @@ _mesa_BindTexture( GLenum target, GLuint texName ) if (newTexObj) { /* error checking */ if (newTexObj->Target != 0 && newTexObj->Target != target) { - /* the named texture object's target doesn't match the given target */ + /* The named texture object's target doesn't match the + * given target + */ _mesa_error( ctx, GL_INVALID_OPERATION, "glBindTexture(target mismatch)" ); return; @@ -1335,7 +1369,8 @@ _mesa_BindTexture( GLenum target, GLuint texName ) } else { if (ctx->API == API_OPENGL_CORE) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTexture(non-gen name)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindTexture(non-gen name)"); return; } @@ -1390,25 +1425,123 @@ _mesa_BindTexture( GLenum target, GLuint texName ) /* Pass BindTexture call to device driver */ if (ctx->Driver.BindTexture) - ctx->Driver.BindTexture(ctx, target, newTexObj); + ctx->Driver.BindTexture(ctx, ctx->Texture.CurrentUnit, target, newTexObj); } 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 + + * 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 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 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 through +-1 */ + for (i = 0; i < count; i++) + unbind_textures_from_unit(ctx, first + i); + } } /** * Set texture priorities. - * + * * \param n number of textures. * \param texName texture names. * \param priorities corresponding texture priorities. - * + * * \sa glPrioritizeTextures(). - * + * * Looks up each texture in the hash, clamps the corresponding priority between * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture. */ @@ -1448,13 +1581,14 @@ _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName, /** * See if textures are loaded in texture memory. - * + * * \param n number of textures to query. * \param texName array with the texture names. * \param residences array which will hold the residence status. * - * \return GL_TRUE if all textures are resident and \p residences is left unchanged, - * + * \return GL_TRUE if all textures are resident and + * residences is left unchanged, + * * Note: we assume all textures are always resident */ GLboolean GLAPIENTRY @@ -1490,7 +1624,7 @@ _mesa_AreTexturesResident(GLsizei n, const GLuint *texName, return GL_FALSE; } } - + return allResident; } @@ -1502,7 +1636,7 @@ _mesa_AreTexturesResident(GLsizei n, const GLuint *texName, * * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE * otherwise. - * + * * \sa glIsTexture(). * * Calls _mesa_HashLookup(). @@ -1557,6 +1691,7 @@ _mesa_unlock_context_textures( struct gl_context *ctx ) mtx_unlock(&ctx->Shared->TexMutex); } + void GLAPIENTRY _mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, @@ -1703,6 +1838,7 @@ _mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, return; } + void GLAPIENTRY _mesa_InvalidateTexImage(GLuint texture, GLint level) {