示例#1
0
/**
 * \note This routine refers to derived texture matrix values to
 * compute the ENABLE_TEXMAT flags, but is only called on
 * _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.
 */
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);

   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_OBJECT | _NEW_TEXTURE_STATE;

   ctx->Texture._GenFlags = 0x0;
   ctx->Texture._TexMatEnabled = 0x0;
   ctx->Texture._TexGenEnabled = 0x0;
   ctx->Texture._MaxEnabledTexImageUnit = -1;
   ctx->Texture._EnabledCoordUnits = 0x0;

   memset(&enabled_texture_units, 0, sizeof(enabled_texture_units));

   /* First, walk over our programs pulling in all the textures for them.
    * Programs dictate specific texture targets to be enabled, and for a draw
    * call to be valid they can't conflict about which texture targets are
    * used.
    */
   update_program_texture_state(ctx, prog, enabled_texture_units);

   /* Also pull in any textures necessary for fixed function fragment shading.
    */
   if (!prog[MESA_SHADER_FRAGMENT])
      update_ff_texture_state(ctx, enabled_texture_units);

   /* Now, clear out the _Current of any disabled texture units. */
   for (i = 0; i <= ctx->Texture._MaxEnabledTexImageUnit; i++) {
      if (!BITSET_TEST(enabled_texture_units, i))
         _mesa_reference_texobj(&ctx->Texture.Unit[i]._Current, NULL);
   }
   for (i = ctx->Texture._MaxEnabledTexImageUnit + 1; i <= old_max_unit; i++) {
      _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);
}
示例#2
0
/**
 * Update the ctx->*Program._Current pointers to point to the
 * current/active programs.
 *
 * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment
 * programs or programs derived from fixed-function state.
 *
 * This function needs to be called after texture state validation in case
 * we're generating a fragment program from fixed-function texture state.
 *
 * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex
 * or fragment program is being used.
 */
static GLbitfield
update_program(struct gl_context *ctx)
{
   struct gl_program *vsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
   struct gl_program *tcsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
   struct gl_program *tesProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
   struct gl_program *gsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
   struct gl_program *fsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
   struct gl_program *csProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
   const struct gl_program *prevVP = ctx->VertexProgram._Current;
   const struct gl_program *prevFP = ctx->FragmentProgram._Current;
   const struct gl_program *prevGP = ctx->GeometryProgram._Current;
   const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current;
   const struct gl_program *prevTEP = ctx->TessEvalProgram._Current;
   const struct gl_program *prevCP = ctx->ComputeProgram._Current;

   /*
    * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
    * pointers to the programs that should be used for rendering.  If either
    * is NULL, use fixed-function code paths.
    *
    * These programs may come from several sources.  The priority is as
    * follows:
    *   1. OpenGL 2.0/ARB vertex/fragment shaders
    *   2. ARB/NV vertex/fragment programs
    *   3. ATI fragment shader
    *   4. Programs derived from fixed-function state.
    *
    * Note: it's possible for a vertex shader to get used with a fragment
    * program (and vice versa) here, but in practice that shouldn't ever
    * come up, or matter.
    */

   if (fsProg) {
      /* Use GLSL fragment shader */
      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, fsProg);
      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
                              NULL);
   }
   else if (_mesa_arb_fragment_program_enabled(ctx)) {
      /* Use user-defined fragment program */
      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
                              ctx->FragmentProgram.Current);
      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
			      NULL);
   }
   else if (_mesa_ati_fragment_shader_enabled(ctx) &&
            ctx->ATIFragmentShader.Current->Program) {
       /* Use the enabled ATI fragment shader's associated program */
      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
                              ctx->ATIFragmentShader.Current->Program);
      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
                              NULL);
   }
   else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
      /* Use fragment program generated from fixed-function state */
      struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx);

      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
			      f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);
      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
			      f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);
   }
   else {
      /* No fragment program */
      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, NULL);
      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
			      NULL);
   }

   if (gsProg) {
      /* Use GLSL geometry shader */
      _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, gsProg);
   } else {
      /* No geometry program */
      _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, NULL);
   }

   if (tesProg) {
      /* Use GLSL tessellation evaluation shader */
      _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, tesProg);
   }
   else {
      /* No tessellation evaluation program */
      _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, NULL);
   }

   if (tcsProg) {
      /* Use GLSL tessellation control shader */
      _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, tcsProg);
   }
   else {
      /* No tessellation control program */
      _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, NULL);
   }

   /* Examine vertex program after fragment program as
    * _mesa_get_fixed_func_vertex_program() needs to know active
    * fragprog inputs.
    */
   if (vsProg) {
      /* Use GLSL vertex shader */
      assert(VP_MODE_SHADER == ctx->VertexProgram._VPMode);
      _mesa_reference_program(ctx, &ctx->VertexProgram._Current, vsProg);
   }
   else if (_mesa_arb_vertex_program_enabled(ctx)) {
      /* Use user-defined vertex program */
      assert(VP_MODE_SHADER == ctx->VertexProgram._VPMode);
      _mesa_reference_program(ctx, &ctx->VertexProgram._Current,
                              ctx->VertexProgram.Current);
   }
   else if (ctx->VertexProgram._MaintainTnlProgram) {
      /* Use vertex program generated from fixed-function state */
      assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
      _mesa_reference_program(ctx, &ctx->VertexProgram._Current,
                              _mesa_get_fixed_func_vertex_program(ctx));
      _mesa_reference_program(ctx, &ctx->VertexProgram._TnlProgram,
                              ctx->VertexProgram._Current);
   }
   else {
      /* no vertex program */
      assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
      _mesa_reference_program(ctx, &ctx->VertexProgram._Current, NULL);
   }

   if (csProg) {
      /* Use GLSL compute shader */
      _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, csProg);
   } else {
      /* no compute program */
      _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, NULL);
   }

   /* Let the driver know what's happening:
    */
   if (ctx->FragmentProgram._Current != prevFP ||
       ctx->VertexProgram._Current != prevVP ||
       ctx->GeometryProgram._Current != prevGP ||
       ctx->TessEvalProgram._Current != prevTEP ||
       ctx->TessCtrlProgram._Current != prevTCP ||
       ctx->ComputeProgram._Current != prevCP)
      return _NEW_PROGRAM;

   return 0;
}
/**
 * Check if any fragment operations are in effect which might effect
 * glDraw/CopyPixels.
 */
bool
intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one)
{
   if (ctx->NewState)
      _mesa_update_state(ctx);

   if (_mesa_arb_fragment_program_enabled(ctx)) {
      DBG("fallback due to fragment program\n");
      return false;
   }

   if (ctx->Color.BlendEnabled &&
       (effective_func(ctx->Color.Blend[0].SrcRGB, src_alpha_is_one) != GL_ONE ||
	effective_func(ctx->Color.Blend[0].DstRGB, src_alpha_is_one) != GL_ZERO ||
	ctx->Color.Blend[0].EquationRGB != GL_FUNC_ADD ||
	effective_func(ctx->Color.Blend[0].SrcA, src_alpha_is_one) != GL_ONE ||
	effective_func(ctx->Color.Blend[0].DstA, src_alpha_is_one) != GL_ZERO ||
	ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) {
      DBG("fallback due to blend\n");
      return false;
   }

   if (ctx->Texture._MaxEnabledTexImageUnit != -1) {
      DBG("fallback due to texturing\n");
      return false;
   }

   if (!(ctx->Color.ColorMask[0][0] &&
	 ctx->Color.ColorMask[0][1] &&
	 ctx->Color.ColorMask[0][2] &&
	 ctx->Color.ColorMask[0][3])) {
      DBG("fallback due to color masking\n");
      return false;
   }

   if (ctx->Color.AlphaEnabled) {
      DBG("fallback due to alpha\n");
      return false;
   }

   if (ctx->Depth.Test) {
      DBG("fallback due to depth test\n");
      return false;
   }

   if (ctx->Fog.Enabled) {
      DBG("fallback due to fog\n");
      return false;
   }

   if (ctx->_ImageTransferState) {
      DBG("fallback due to image transfer\n");
      return false;
   }

   if (_mesa_stencil_is_enabled(ctx)) {
      DBG("fallback due to image stencil\n");
      return false;
   }

   if (ctx->RenderMode != GL_RENDER) {
      DBG("fallback due to render mode\n");
      return false;
   }

   return true;
}