mesa: remove unneeded semicolons
[mesa.git] / src / mesa / main / texstate.c
index 9b5928c4306d95035eb8c7cac55adf7d8ab9b3bc..8f87cac0ce446a08d54ea05911286e48bfb4803e 100644 (file)
 #include "context.h"
 #include "enums.h"
 #include "macros.h"
-#include "shaderimage.h"
 #include "texobj.h"
 #include "teximage.h"
 #include "texstate.h"
 #include "mtypes.h"
+#include "state.h"
+#include "util/bitscan.h"
 #include "util/bitset.h"
 
 
@@ -279,14 +280,12 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
 }
 
 
-
-
 /* GL_ARB_multitexture */
-void GLAPIENTRY
-_mesa_ActiveTexture(GLenum texture)
+static ALWAYS_INLINE void
+active_texture(GLenum texture, bool no_error)
 {
    const GLuint texUnit = texture - GL_TEXTURE0;
-   GLuint k;
+
    GET_CURRENT_CONTEXT(ctx);
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
@@ -296,18 +295,18 @@ _mesa_ActiveTexture(GLenum texture)
    if (ctx->Texture.CurrentUnit == texUnit)
       return;
 
-   k = _mesa_max_tex_unit(ctx);
+   if (!no_error) {
+      GLuint k = _mesa_max_tex_unit(ctx);
 
-   assert(k <= ARRAY_SIZE(ctx->Texture.Unit));
+      assert(k <= ARRAY_SIZE(ctx->Texture.Unit));
 
-   if (texUnit >= k) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture=%s)",
-                  _mesa_enum_to_string(texture));
-      return;
+      if (texUnit >= k) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture=%s)",
+                     _mesa_enum_to_string(texture));
+         return;
+      }
    }
 
-   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-
    ctx->Texture.CurrentUnit = texUnit;
    if (ctx->Transform.MatrixMode == GL_TEXTURE) {
       /* update current stack pointer */
@@ -316,6 +315,20 @@ _mesa_ActiveTexture(GLenum texture)
 }
 
 
+void GLAPIENTRY
+_mesa_ActiveTexture_no_error(GLenum texture)
+{
+   active_texture(texture, true);
+}
+
+
+void GLAPIENTRY
+_mesa_ActiveTexture(GLenum texture)
+{
+   active_texture(texture, false);
+}
+
+
 /* GL_ARB_multitexture */
 void GLAPIENTRY
 _mesa_ClientActiveTexture(GLenum texture)
@@ -331,11 +344,12 @@ _mesa_ClientActiveTexture(GLenum texture)
       return;
 
    if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
+      _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture=%s)",
+                  _mesa_enum_to_string(texture));
       return;
    }
 
-   FLUSH_VERTICES(ctx, _NEW_ARRAY);
+   /* Don't flush vertices. This is a "latched" state. */
    ctx->Array.ActiveTexture = texUnit;
 }
 
@@ -349,13 +363,13 @@ _mesa_ClientActiveTexture(GLenum texture)
 /**
  * \note This routine refers to derived texture attribute values to
  * compute the ENABLE_TEXMAT flags, but is only called on
- * _NEW_TEXTURE_MATRIX.  On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
- * flags are updated by _mesa_update_textures(), below.
+ * _NEW_TEXTURE_MATRIX.  On changes to _NEW_TEXTURE_OBJECT/STATE,
+ * the ENABLE_TEXMAT flags are updated by _mesa_update_textures(), below.
  *
  * \param ctx GL context.
  */
-static void
-update_texture_matrices( struct gl_context *ctx )
+void
+_mesa_update_texture_matrices(struct gl_context *ctx)
 {
    GLuint u;
 
@@ -374,6 +388,107 @@ update_texture_matrices( struct gl_context *ctx )
 }
 
 
+/**
+ * Translate GL combiner state into a MODE_x value
+ */
+static uint32_t
+tex_combine_translate_mode(GLenum envMode, GLenum mode)
+{
+   switch (mode) {
+   case GL_REPLACE: return TEXENV_MODE_REPLACE;
+   case GL_MODULATE: return TEXENV_MODE_MODULATE;
+   case GL_ADD:
+      if (envMode == GL_COMBINE4_NV)
+        return TEXENV_MODE_ADD_PRODUCTS_NV;
+      else
+        return TEXENV_MODE_ADD;
+   case GL_ADD_SIGNED:
+      if (envMode == GL_COMBINE4_NV)
+        return TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV;
+      else
+        return TEXENV_MODE_ADD_SIGNED;
+   case GL_INTERPOLATE: return TEXENV_MODE_INTERPOLATE;
+   case GL_SUBTRACT: return TEXENV_MODE_SUBTRACT;
+   case GL_DOT3_RGB: return TEXENV_MODE_DOT3_RGB;
+   case GL_DOT3_RGB_EXT: return TEXENV_MODE_DOT3_RGB_EXT;
+   case GL_DOT3_RGBA: return TEXENV_MODE_DOT3_RGBA;
+   case GL_DOT3_RGBA_EXT: return TEXENV_MODE_DOT3_RGBA_EXT;
+   case GL_MODULATE_ADD_ATI: return TEXENV_MODE_MODULATE_ADD_ATI;
+   case GL_MODULATE_SIGNED_ADD_ATI: return TEXENV_MODE_MODULATE_SIGNED_ADD_ATI;
+   case GL_MODULATE_SUBTRACT_ATI: return TEXENV_MODE_MODULATE_SUBTRACT_ATI;
+   default:
+      unreachable("Invalid TexEnv Combine mode");
+   }
+}
+
+
+static uint8_t
+tex_combine_translate_source(GLenum src)
+{
+   switch (src) {
+   case GL_TEXTURE0:
+   case GL_TEXTURE1:
+   case GL_TEXTURE2:
+   case GL_TEXTURE3:
+   case GL_TEXTURE4:
+   case GL_TEXTURE5:
+   case GL_TEXTURE6:
+   case GL_TEXTURE7: return TEXENV_SRC_TEXTURE0 + (src - GL_TEXTURE0);
+   case GL_TEXTURE: return TEXENV_SRC_TEXTURE;
+   case GL_PREVIOUS: return TEXENV_SRC_PREVIOUS;
+   case GL_PRIMARY_COLOR: return TEXENV_SRC_PRIMARY_COLOR;
+   case GL_CONSTANT: return TEXENV_SRC_CONSTANT;
+   case GL_ZERO: return TEXENV_SRC_ZERO;
+   case GL_ONE: return TEXENV_SRC_ONE;
+   default:
+      unreachable("Invalid TexEnv Combine argument source");
+   }
+}
+
+
+static uint8_t
+tex_combine_translate_operand(GLenum operand)
+{
+   switch (operand) {
+   case GL_SRC_COLOR: return TEXENV_OPR_COLOR;
+   case GL_ONE_MINUS_SRC_COLOR: return TEXENV_OPR_ONE_MINUS_COLOR;
+   case GL_SRC_ALPHA: return TEXENV_OPR_ALPHA;
+   case GL_ONE_MINUS_SRC_ALPHA: return TEXENV_OPR_ONE_MINUS_ALPHA;
+   default:
+      unreachable("Invalid TexEnv Combine argument source");
+   }
+}
+
+
+static void
+pack_tex_combine(struct gl_texture_unit *texUnit)
+{
+   struct gl_tex_env_combine_state *state = texUnit->_CurrentCombine;
+   struct gl_tex_env_combine_packed *packed = &texUnit->_CurrentCombinePacked;
+
+   memset(packed, 0, sizeof *packed);
+
+   packed->ModeRGB = tex_combine_translate_mode(texUnit->EnvMode, state->ModeRGB);
+   packed->ModeA = tex_combine_translate_mode(texUnit->EnvMode, state->ModeA);
+   packed->ScaleShiftRGB = state->ScaleShiftRGB;
+   packed->ScaleShiftA = state->ScaleShiftA;
+   packed->NumArgsRGB = state->_NumArgsRGB;
+   packed->NumArgsA = state->_NumArgsA;
+
+   for (int i = 0; i < state->_NumArgsRGB; ++i)
+   {
+      packed->ArgsRGB[i].Source = tex_combine_translate_source(state->SourceRGB[i]);
+      packed->ArgsRGB[i].Operand = tex_combine_translate_operand(state->OperandRGB[i]);
+   }
+
+   for (int i = 0; i < state->_NumArgsA; ++i)
+   {
+      packed->ArgsA[i].Source = tex_combine_translate_source(state->SourceA[i]);
+      packed->ArgsA[i].Operand = tex_combine_translate_operand(state->OperandA[i]);
+   }
+}
+
+
 /**
  * Examine texture unit's combine/env state to update derived state.
  */
@@ -466,6 +581,8 @@ update_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit)
       _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
       break;
    }
+
+   pack_tex_combine(texUnit);
 }
 
 static void
@@ -508,18 +625,13 @@ update_texgen(struct gl_context *ctx)
 
 static struct gl_texture_object *
 update_single_program_texture(struct gl_context *ctx, struct gl_program *prog,
-                              int s)
+                              int unit)
 {
    gl_texture_index target_index;
    struct gl_texture_unit *texUnit;
    struct gl_texture_object *texObj;
    struct gl_sampler_object *sampler;
-   int unit;
-
-   if (!(prog->SamplersUsed & (1 << s)))
-      return NULL;
 
-   unit = prog->SamplerUnits[s];
    texUnit = &ctx->Texture.Unit[unit];
 
    /* Note: If more than one bit was set in TexturesUsed[unit], then we should
@@ -565,6 +677,22 @@ update_single_program_texture(struct gl_context *ctx, struct gl_program *prog,
    return texObj;
 }
 
+static inline void
+update_single_program_texture_state(struct gl_context *ctx,
+                                    struct gl_program *prog,
+                                    int unit,
+                                    BITSET_WORD *enabled_texture_units)
+{
+   struct gl_texture_object *texObj;
+
+   texObj = update_single_program_texture(ctx, prog, unit);
+
+   _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj);
+   BITSET_SET(enabled_texture_units, unit);
+   ctx->Texture._MaxEnabledTexImageUnit =
+      MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
+}
+
 static void
 update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
                              BITSET_WORD *enabled_texture_units)
@@ -572,25 +700,34 @@ update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
    int i;
 
    for (i = 0; i < MESA_SHADER_STAGES; i++) {
-      int s;
+      GLbitfield mask;
+      GLuint s;
 
       if (!prog[i])
          continue;
 
-      /* We can't only do the shifting trick as the loop condition because if
-       * sampler 31 is active, the next iteration tries to shift by 32, which is
-       * undefined.
-       */
-      for (s = 0; s < MAX_SAMPLERS && (1 << s) <= prog[i]->SamplersUsed; s++) {
-         struct gl_texture_object *texObj;
-
-         texObj = update_single_program_texture(ctx, prog[i], s);
-         if (texObj) {
-            int unit = prog[i]->SamplerUnits[s];
-            _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj);
-            BITSET_SET(enabled_texture_units, unit);
-            ctx->Texture._MaxEnabledTexImageUnit =
-               MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
+      mask = prog[i]->SamplersUsed;
+
+      while (mask) {
+         s = u_bit_scan(&mask);
+
+         update_single_program_texture_state(ctx, prog[i],
+                                             prog[i]->SamplerUnits[s],
+                                             enabled_texture_units);
+      }
+
+      if (unlikely(prog[i]->sh.HasBoundBindlessSampler)) {
+         /* Loop over bindless samplers bound to texture units.
+          */
+         for (s = 0; s < prog[i]->sh.NumBindlessSamplers; s++) {
+            struct gl_bindless_sampler *sampler =
+               &prog[i]->sh.BindlessSamplers[s];
+
+            if (!sampler->bound)
+               continue;
+
+            update_single_program_texture_state(ctx, prog[i], sampler->unit,
+                                                enabled_texture_units);
          }
       }
    }
@@ -598,7 +735,7 @@ update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
    if (prog[MESA_SHADER_FRAGMENT]) {
       const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
       ctx->Texture._EnabledCoordUnits |=
-         (prog[MESA_SHADER_FRAGMENT]->InputsRead >> VARYING_SLOT_TEX0) &
+         (prog[MESA_SHADER_FRAGMENT]->info.inputs_read >> VARYING_SLOT_TEX0) &
          coordMask;
    }
 }
@@ -611,7 +748,8 @@ update_ff_texture_state(struct gl_context *ctx,
 
    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-      GLuint texIndex;
+      GLbitfield mask;
+      bool complete;
 
       if (texUnit->Enabled == 0x0)
          continue;
@@ -649,23 +787,25 @@ update_ff_texture_state(struct gl_context *ctx,
        *      another unit, then the results of texture blending are
        *      undefined."
        */
-      for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
-         if (texUnit->Enabled & (1 << texIndex)) {
-            struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
-            struct gl_sampler_object *sampler = texUnit->Sampler ?
-               texUnit->Sampler : &texObj->Sampler;
-
-            if (!_mesa_is_texture_complete(texObj, sampler)) {
-               _mesa_test_texobj_completeness(ctx, texObj);
-            }
-            if (_mesa_is_texture_complete(texObj, sampler)) {
-               _mesa_reference_texobj(&texUnit->_Current, texObj);
-               break;
-            }
+      complete = false;
+      mask = texUnit->Enabled;
+      while (mask) {
+         const int texIndex = u_bit_scan(&mask);
+         struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
+         struct gl_sampler_object *sampler = texUnit->Sampler ?
+            texUnit->Sampler : &texObj->Sampler;
+
+         if (!_mesa_is_texture_complete(texObj, sampler)) {
+            _mesa_test_texobj_completeness(ctx, texObj);
+         }
+         if (_mesa_is_texture_complete(texObj, sampler)) {
+            _mesa_reference_texobj(&texUnit->_Current, texObj);
+            complete = true;
+            break;
          }
       }
 
-      if (texIndex == NUM_TEXTURE_TARGETS)
+      if (!complete)
          continue;
 
       /* if we get here, we know this texture unit is enabled */
@@ -679,36 +819,55 @@ update_ff_texture_state(struct gl_context *ctx,
    }
 }
 
+static void
+fix_missing_textures_for_atifs(struct gl_context *ctx,
+                               struct gl_program *prog,
+                               BITSET_WORD *enabled_texture_units)
+{
+   GLbitfield mask = prog->SamplersUsed;
+
+   while (mask) {
+      const int s = u_bit_scan(&mask);
+      const int unit = prog->SamplerUnits[s];
+      const gl_texture_index target_index = ffs(prog->TexturesUsed[unit]) - 1;
+
+      if (!ctx->Texture.Unit[unit]._Current) {
+         struct gl_texture_object *texObj =
+            _mesa_get_fallback_texture(ctx, target_index);
+         _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj);
+         BITSET_SET(enabled_texture_units, unit);
+         ctx->Texture._MaxEnabledTexImageUnit =
+            MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
+      }
+   }
+}
+
 /**
  * \note This routine refers to derived texture matrix values to
  * compute the ENABLE_TEXMAT flags, but is only called on
- * _NEW_TEXTURE.  On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
- * flags are updated by _mesa_update_texture_matrices, above.
+ * _NEW_TEXTURE_OBJECT/STATE.  On changes to _NEW_TEXTURE_MATRIX,
+ * the ENABLE_TEXMAT flags are updated by _mesa_update_texture_matrices,
+ * above.
  *
  * \param ctx GL context.
  */
-static void
-update_texture_state( struct gl_context *ctx )
+void
+_mesa_update_texture_state(struct gl_context *ctx)
 {
    struct gl_program *prog[MESA_SHADER_STAGES];
    int i;
    int old_max_unit = ctx->Texture._MaxEnabledTexImageUnit;
    BITSET_DECLARE(enabled_texture_units, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
 
-   for (i = 0; i < MESA_SHADER_STAGES; i++) {
-      if (ctx->_Shader->CurrentProgram[i] &&
-          ctx->_Shader->CurrentProgram[i]->LinkStatus) {
-         prog[i] = ctx->_Shader->CurrentProgram[i]->_LinkedShaders[i]->Program;
-      } else {
-         if (i == MESA_SHADER_FRAGMENT && ctx->FragmentProgram._Enabled)
-            prog[i] = &ctx->FragmentProgram.Current->Base;
-         else
-            prog[i] = NULL;
-      }
+   memcpy(prog, ctx->_Shader->CurrentProgram, sizeof(prog));
+
+   if (prog[MESA_SHADER_FRAGMENT] == NULL &&
+       _mesa_arb_fragment_program_enabled(ctx)) {
+      prog[MESA_SHADER_FRAGMENT] = ctx->FragmentProgram.Current;
    }
 
    /* TODO: only set this if there are actual changes */
-   ctx->NewState |= _NEW_TEXTURE;
+   ctx->NewState |= _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE;
 
    ctx->Texture._GenFlags = 0x0;
    ctx->Texture._TexMatEnabled = 0x0;
@@ -739,24 +898,15 @@ update_texture_state( struct gl_context *ctx )
       _mesa_reference_texobj(&ctx->Texture.Unit[i]._Current, NULL);
    }
 
+   /* add fallback texture for SampleMapATI if there is nothing */
+   if (_mesa_ati_fragment_shader_enabled(ctx) &&
+       ctx->ATIFragmentShader.Current->Program)
+      fix_missing_textures_for_atifs(ctx,
+                                     ctx->ATIFragmentShader.Current->Program,
+                                     enabled_texture_units);
+
    if (!prog[MESA_SHADER_FRAGMENT] || !prog[MESA_SHADER_VERTEX])
       update_texgen(ctx);
-
-   _mesa_validate_image_units(ctx);
-}
-
-
-/**
- * Update texture-related derived state.
- */
-void
-_mesa_update_texture( struct gl_context *ctx, GLuint new_state )
-{
-   if (new_state & _NEW_TEXTURE_MATRIX)
-      update_texture_matrices( ctx );
-
-   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
-      update_texture_state( ctx );
 }
 
 
@@ -788,7 +938,7 @@ alloc_proxy_textures( struct gl_context *ctx )
       GL_TEXTURE_2D_ARRAY_EXT,
       GL_TEXTURE_1D_ARRAY_EXT,
       GL_TEXTURE_EXTERNAL_OES,
-      GL_TEXTURE_CUBE_MAP_ARB,
+      GL_TEXTURE_CUBE_MAP,
       GL_TEXTURE_3D,
       GL_TEXTURE_RECTANGLE_NV,
       GL_TEXTURE_2D,