summaryrefslogtreecommitdiffstats
path: root/src/mesa/main
diff options
context:
space:
mode:
authorLaura Ekstrand <[email protected]>2014-10-30 17:19:24 -0700
committerLaura Ekstrand <[email protected]>2015-01-08 11:37:28 -0800
commit77aabd8be237b68921d2e7c69fd1a0be3d36de01 (patch)
tree818af9caa403960275a6ba1e63e8c06ef9054a97 /src/mesa/main
parent4b381e84db5ee1a03c9b9afca2817d8bd374c0b0 (diff)
main: Added entry point for BindTextureUnit.
The following preparations were made in texstate.c and texstate.h to better facilitate the BindTextureUnit function: Dylan Noblesmith: mesa: add _mesa_get_tex_unit() mesa: factor out _mesa_max_tex_unit() This is about to appear in a lot more places, so reduce boilerplate copy paste. add _mesa_get_tex_unit_err() checking getter function Reduce boilerplate across files. Laura Ekstrand: Made note of why BindTextureUnit should throw GL_INVALID_OPERATION if the unit is out of range. Added assert(unit > 0) to _mesa_get_tex_unit. Reviewed-by: Anuj Phogat <[email protected]>
Diffstat (limited to 'src/mesa/main')
-rw-r--r--src/mesa/main/tests/dispatch_sanity.cpp1
-rw-r--r--src/mesa/main/texobj.c104
-rw-r--r--src/mesa/main/texobj.h7
-rw-r--r--src/mesa/main/texstate.c4
-rw-r--r--src/mesa/main/texstate.h39
5 files changed, 150 insertions, 5 deletions
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index c9decb7af8b..0ef48c9b299 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -962,6 +962,7 @@ const struct function gl_core_functions_possible[] = {
{ "glTextureSubImage1D", 45, -1 },
{ "glTextureSubImage2D", 45, -1 },
{ "glTextureSubImage3D", 45, -1 },
+ { "glBindTextureUnit", 45, -1 },
{ NULL, 0, -1 }
};
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 416b7df20c9..e9f5fbfbf45 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -502,6 +502,9 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr,
mtx_unlock(&oldTex->Mutex);
if (deleteFlag) {
+ /* Passing in the context drastically changes the driver code for
+ * framebuffer deletion.
+ */
GET_CURRENT_CONTEXT(ctx);
if (ctx)
ctx->Driver.DeleteTexture(ctx, oldTex);
@@ -1598,6 +1601,107 @@ _mesa_BindTexture( GLenum target, GLuint texName )
ctx->Driver.BindTexture(ctx, ctx->Texture.CurrentUnit, target, newTexObj);
}
+/**
+ * Do the actual binding to a numbered texture unit.
+ * The refcount on the previously bound
+ * texture object will be decremented. It'll be deleted if the
+ * count hits zero.
+ */
+void
+_mesa_bind_texture_unit(struct gl_context *ctx,
+ GLuint unit,
+ struct gl_texture_object *texObj)
+{
+ struct gl_texture_unit *texUnit;
+
+ /* Get the texture unit (this is an array look-up) */
+ texUnit = _mesa_get_tex_unit_err(ctx, unit, "glBindTextureUnit");
+ if (!texUnit)
+ return;
+
+ /* Check if this texture is only used by this context and is already bound.
+ * If so, just return.
+ */
+ {
+ bool early_out;
+ mtx_lock(&ctx->Shared->Mutex);
+ early_out = ((ctx->Shared->RefCount == 1)
+ && (texObj == texUnit->CurrentTex[texObj->TargetIndex]));
+ mtx_unlock(&ctx->Shared->Mutex);
+ if (early_out) {
+ return;
+ }
+ }
+
+ /* flush before changing binding */
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ _mesa_reference_texobj(&texUnit->CurrentTex[texObj->TargetIndex],
+ texObj);
+ ASSERT(texUnit->CurrentTex[texObj->TargetIndex]);
+ ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
+ unit + 1);
+ texUnit->_BoundTextures |= (1 << texObj->TargetIndex);
+
+
+ /* Pass BindTexture call to device driver */
+ if (ctx->Driver.BindTexture) {
+ ctx->Driver.BindTexture(ctx, unit, texObj->Target, texObj);
+ }
+}
+
+/**
+ * Bind a named texture to the specified texture unit.
+ *
+ * \param unit texture unit.
+ * \param texture texture name.
+ *
+ * \sa glBindTexture().
+ *
+ * If the named texture is 0, this will reset each target for the specified
+ * texture unit to its default texture.
+ * If the named texture is not 0 or a recognized texture name, this throws
+ * GL_INVALID_OPERATION.
+ */
+void GLAPIENTRY
+_mesa_BindTextureUnit(GLuint unit, GLuint texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_object *texObj;
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
+ _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture);
+
+ /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
+ * (20141030) says:
+ * "When texture is zero, each of the targets enumerated at the
+ * beginning of this section is reset to its default texture for the
+ * corresponding texture image unit."
+ */
+ if (texture == 0) {
+ unbind_textures_from_unit(ctx, unit);
+ return;
+ }
+
+ /* Get the non-default texture object */
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ /* Error checking */
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindTextureUnit(non-gen name)");
+ return;
+ }
+ if (texObj->Target == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindTextureUnit(target)");
+ return;
+ }
+ assert(valid_texture_object(texObj));
+
+ _mesa_bind_texture_unit(ctx, unit, texObj);
+}
+
void GLAPIENTRY
_mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index e7aabbe8912..723b2773b62 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -198,6 +198,11 @@ _mesa_unlock_context_textures( struct gl_context *ctx );
extern void
_mesa_lock_context_textures( struct gl_context *ctx );
+extern void
+_mesa_bind_texture_unit(struct gl_context *ctx,
+ GLuint unit,
+ struct gl_texture_object *texObj);
+
/*@}*/
/**
@@ -218,6 +223,8 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures );
extern void GLAPIENTRY
_mesa_BindTexture( GLenum target, GLuint texture );
+extern void GLAPIENTRY
+_mesa_BindTextureUnit(GLuint unit, GLuint texture);
extern void GLAPIENTRY
_mesa_BindTextures( GLuint first, GLsizei count, const GLuint *textures );
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 36eefa6e654..66fd7183e3b 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -290,9 +290,7 @@ _mesa_ActiveTexture(GLenum texture)
GLuint k;
GET_CURRENT_CONTEXT(ctx);
- /* See OpenGL spec for glActiveTexture: */
- k = MAX2(ctx->Const.MaxCombinedTextureImageUnits,
- ctx->Const.MaxTextureCoordUnits);
+ k = _mesa_max_tex_unit(ctx);
ASSERT(k <= Elements(ctx->Texture.Unit));
diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h
index 5cd1684f225..2514d104b62 100644
--- a/src/mesa/main/texstate.h
+++ b/src/mesa/main/texstate.h
@@ -33,9 +33,19 @@
#include "compiler.h"
+#include "enums.h"
+#include "macros.h"
#include "mtypes.h"
+static inline struct gl_texture_unit *
+_mesa_get_tex_unit(struct gl_context *ctx, GLuint unit)
+{
+ ASSERT(unit >= 0);
+ ASSERT(unit < Elements(ctx->Texture.Unit));
+ return &(ctx->Texture.Unit[unit]);
+}
+
/**
* Return pointer to current texture unit.
* This the texture unit set by glActiveTexture(), not glClientActiveTexture().
@@ -43,8 +53,33 @@
static inline struct gl_texture_unit *
_mesa_get_current_tex_unit(struct gl_context *ctx)
{
- ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit));
- return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
+ return _mesa_get_tex_unit(ctx, ctx->Texture.CurrentUnit);
+}
+
+static inline GLuint
+_mesa_max_tex_unit(struct gl_context *ctx)
+{
+ /* See OpenGL spec for glActiveTexture: */
+ return MAX2(ctx->Const.MaxCombinedTextureImageUnits,
+ ctx->Const.MaxTextureCoordUnits);
+}
+
+static inline struct gl_texture_unit *
+_mesa_get_tex_unit_err(struct gl_context *ctx, GLuint unit, const char *func)
+{
+ if (unit < _mesa_max_tex_unit(ctx))
+ return _mesa_get_tex_unit(ctx, unit);
+
+ /* Note: This error is a precedent set by glBindTextures. From the GL 4.5
+ * specification (30.10.2014) Section 8.1 ("Texture Objects"):
+ *
+ * "An INVALID_OPERATION error is generated if first + count is greater
+ * than the number of texture image units supported by the
+ * implementation."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unit=%s)", func,
+ _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit));
+ return NULL;
}