Ejemplo n.º 1
0
/**
 * \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.
 *
 * \param ctx GL context.
 */
static void
update_texture_state( GLcontext *ctx )
{
   GLuint unit;
   struct gl_fragment_program *fprog = NULL;
   struct gl_vertex_program *vprog = NULL;
   GLbitfield enabledFragUnits = 0x0;

   if (ctx->Shader.CurrentProgram &&
       ctx->Shader.CurrentProgram->LinkStatus) {
      fprog = ctx->Shader.CurrentProgram->FragmentProgram;
      vprog = ctx->Shader.CurrentProgram->VertexProgram;
   }
   else {
      if (ctx->FragmentProgram._Enabled) {
         fprog = ctx->FragmentProgram.Current;
      }
      if (ctx->VertexProgram._Enabled) {
         /* XXX enable this if/when non-shader vertex programs get
          * texture fetches:
         vprog = ctx->VertexProgram.Current;
         */
      }
   }

   /* TODO: only set this if there are actual changes */
   ctx->NewState |= _NEW_TEXTURE;

   ctx->Texture._EnabledUnits = 0x0;
   ctx->Texture._GenFlags = 0x0;
   ctx->Texture._TexMatEnabled = 0x0;
   ctx->Texture._TexGenEnabled = 0x0;

   /*
    * Update texture unit state.
    */
   for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
      GLbitfield enabledVertTargets = 0x0;
      GLbitfield enabledFragTargets = 0x0;
      GLbitfield enabledTargets = 0x0;
      GLuint texIndex;

      /* Get the bitmask of texture target enables.
       * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
       * which texture targets are enabled (fixed function) or referenced
       * by a fragment shader/program.  When multiple flags are set, we'll
       * settle on the one with highest priority (see below).
       */
      if (vprog) {
         enabledVertTargets |= vprog->Base.TexturesUsed[unit];
      }

      if (fprog) {
         enabledFragTargets |= fprog->Base.TexturesUsed[unit];
      }
      else {
         /* fixed-function fragment program */
         enabledFragTargets |= texUnit->Enabled;
      }

      enabledTargets = enabledVertTargets | enabledFragTargets;

      texUnit->_ReallyEnabled = 0x0;

      if (enabledTargets == 0x0) {
         /* neither vertex nor fragment processing uses this unit */
         continue;
      }

      /* Look for the highest priority texture target that's enabled (or used
       * by the vert/frag shaders) and "complete".  That's the one we'll use
       * for texturing.  If we're using vert/frag program we're guaranteed
       * that bitcount(enabledBits) <= 1.
       * Note that the TEXTURE_x_INDEX values are in high to low priority.
       */
      for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
         if (enabledTargets & (1 << texIndex)) {
            struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
            if (!texObj->_Complete) {
               _mesa_test_texobj_completeness(ctx, texObj);
            }
            if (texObj->_Complete) {
               texUnit->_ReallyEnabled = 1 << texIndex;
               _mesa_reference_texobj(&texUnit->_Current, texObj);
               break;
            }
         }
      }

      if (!texUnit->_ReallyEnabled) {
         if (fprog) {
            /* If we get here it means the shader is expecting a texture
             * object, but there isn't one (or it's incomplete).  Use the
             * fallback texture.
             */
            struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
            texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
            _mesa_reference_texobj(&texUnit->_Current, texObj);
         }
         else {
            /* fixed-function: texture unit is really disabled */
            continue;
         }
      }

      /* if we get here, we know this texture unit is enabled */

      ctx->Texture._EnabledUnits |= (1 << unit);

      if (enabledFragTargets)
         enabledFragUnits |= (1 << unit);

      update_tex_combine(ctx, texUnit);
   }


   /* Determine which texture coordinate sets are actually needed */
   if (fprog) {
      const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
      ctx->Texture._EnabledCoordUnits
         = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
   }
   else {
Ejemplo n.º 2
0
static void
update_ff_texture_state(struct gl_context *ctx,
                        BITSET_WORD *enabled_texture_units)
{
    int unit;

    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
        GLbitfield mask;
        bool complete;

        if (texUnit->Enabled == 0x0)
            continue;

        /* If a shader already dictated what texture target was used for this
         * unit, just go along with it.
         */
        if (BITSET_TEST(enabled_texture_units, unit))
            continue;

        /* From the GL 4.4 compat specification, section 16.2 ("Texture Application"):
         *
         *     "Texturing is enabled or disabled using the generic Enable and
         *      Disable commands, respectively, with the symbolic constants
         *      TEXTURE_1D, TEXTURE_2D, TEXTURE_RECTANGLE, TEXTURE_3D, or
         *      TEXTURE_CUBE_MAP to enable the one-, two-, rectangular,
         *      three-dimensional, or cube map texture, respectively. If more
         *      than one of these textures is enabled, the first one enabled
         *      from the following list is used:
         *
         *      • cube map texture
         *      • three-dimensional texture
         *      • rectangular texture
         *      • two-dimensional texture
         *      • one-dimensional texture"
         *
         * Note that the TEXTURE_x_INDEX values are in high to low priority.
         * Also:
         *
         *     "If a texture unit is disabled or has an invalid or incomplete
         *      texture (as defined in section 8.17) bound to it, then blending
         *      is disabled for that texture unit. If the texture environment
         *      for a given enabled texture unit references a disabled texture
         *      unit, or an invalid or incomplete texture that is bound to
         *      another unit, then the results of texture blending are
         *      undefined."
         */
        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 (!complete)
            continue;

        /* if we get here, we know this texture unit is enabled */
        BITSET_SET(enabled_texture_units, unit);
        ctx->Texture._MaxEnabledTexImageUnit =
            MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);

        ctx->Texture._EnabledCoordUnits |= 1 << unit;

        update_tex_combine(ctx, texUnit);
    }
}
Ejemplo n.º 3
0
/**
 * \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.
 *
 * \param ctx GL context.
 */
static void
update_texture_state( struct gl_context *ctx )
{
   GLuint unit;
   struct gl_program *fprog = NULL;
   struct gl_program *vprog = NULL;
   struct gl_program *gprog = NULL;
   GLbitfield enabledFragUnits = 0x0;

   if (ctx->Shader.CurrentVertexProgram &&
       ctx->Shader.CurrentVertexProgram->LinkStatus) {
      vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
   }

   if (ctx->Shader.CurrentGeometryProgram &&
       ctx->Shader.CurrentGeometryProgram->LinkStatus) {
      gprog = ctx->Shader.CurrentGeometryProgram->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
   }

   if (ctx->Shader.CurrentFragmentProgram &&
       ctx->Shader.CurrentFragmentProgram->LinkStatus) {
      fprog = ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
   }
   else if (ctx->FragmentProgram._Enabled) {
      fprog = &ctx->FragmentProgram.Current->Base;
   }

   /* TODO: only set this if there are actual changes */
   ctx->NewState |= _NEW_TEXTURE;

   ctx->Texture._EnabledUnits = 0x0;
   ctx->Texture._GenFlags = 0x0;
   ctx->Texture._TexMatEnabled = 0x0;
   ctx->Texture._TexGenEnabled = 0x0;

   /*
    * Update texture unit state.
    */
   for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) {
      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
      GLbitfield enabledVertTargets = 0x0;
      GLbitfield enabledFragTargets = 0x0;
      GLbitfield enabledGeomTargets = 0x0;
      GLbitfield enabledTargets = 0x0;
      GLuint texIndex;

      /* Get the bitmask of texture target enables.
       * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
       * which texture targets are enabled (fixed function) or referenced
       * by a fragment program/program.  When multiple flags are set, we'll
       * settle on the one with highest priority (see below).
       */
      if (vprog) {
         enabledVertTargets |= vprog->TexturesUsed[unit];
      }

      if (gprog) {
         enabledGeomTargets |= gprog->TexturesUsed[unit];
      }

      if (fprog) {
         enabledFragTargets |= fprog->TexturesUsed[unit];
      }
      else {
         /* fixed-function fragment program */
         enabledFragTargets |= texUnit->Enabled;
      }

      enabledTargets = enabledVertTargets | enabledFragTargets |
                       enabledGeomTargets;

      texUnit->_ReallyEnabled = 0x0;

      if (enabledTargets == 0x0) {
         /* neither vertex nor fragment processing uses this unit */
         continue;
      }

      /* Look for the highest priority texture target that's enabled (or used
       * by the vert/frag shaders) and "complete".  That's the one we'll use
       * for texturing.
       *
       * Note that the TEXTURE_x_INDEX values are in high to low priority.
       */
      for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
         if (enabledTargets & (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)) {
               texUnit->_ReallyEnabled = 1 << texIndex;
               _mesa_reference_texobj(&texUnit->_Current, texObj);
               break;
            }
         }
      }

      if (!texUnit->_ReallyEnabled) {
         if (fprog) {
            /* If we get here it means the shader is expecting a texture
             * object, but there isn't one (or it's incomplete).  Use the
             * fallback texture.
             */
            struct gl_texture_object *texObj;
            gl_texture_index texTarget;

            texTarget = (gl_texture_index) (ffs(enabledTargets) - 1);
            texObj = _mesa_get_fallback_texture(ctx, texTarget);
            
            assert(texObj);
            if (!texObj) {
               /* invalid fallback texture: don't enable the texture unit */
               continue;
            }

            _mesa_reference_texobj(&texUnit->_Current, texObj);
            texUnit->_ReallyEnabled = 1 << texTarget;
         }
         else {
            /* fixed-function: texture unit is really disabled */
            continue;
         }
      }

      /* if we get here, we know this texture unit is enabled */

      ctx->Texture._EnabledUnits |= (1 << unit);

      if (enabledFragTargets)
         enabledFragUnits |= (1 << unit);

      if (!fprog)
         update_tex_combine(ctx, texUnit);
   }


   /* Determine which texture coordinate sets are actually needed */
   if (fprog) {
      const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
      ctx->Texture._EnabledCoordUnits
         = (fprog->InputsRead >> VARYING_SLOT_TEX0) & coordMask;
   }
   else {