Esempio n. 1
0
/**
 * Update ctx->VertexProgram._VPMode.
 * This is to distinguish whether we're running
 *   a vertex program/shader,
 *   a fixed-function TNL program or
 *   a fixed function vertex transformation without any program.
 */
void
_mesa_update_vertex_processing_mode(struct gl_context *ctx)
{
   if (ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX])
      set_vertex_processing_mode(ctx, VP_MODE_SHADER);
   else if (_mesa_arb_vertex_program_enabled(ctx))
      set_vertex_processing_mode(ctx, VP_MODE_SHADER);
   else
      set_vertex_processing_mode(ctx, VP_MODE_FF);
}
Esempio n. 2
0
static void transition_to_hwtnl( struct gl_context *ctx )
{
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);

   _tnl_need_projected_coords( ctx, GL_FALSE );

   r200UpdateMaterial( ctx );

   tnl->Driver.NotifyMaterialChange = r200UpdateMaterial;

   if ( rmesa->radeon.dma.flush )			
      rmesa->radeon.dma.flush( &rmesa->radeon.glCtx );	

   rmesa->radeon.dma.flush = NULL;
   
   R200_STATECHANGE( rmesa, vap );
   rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE;
   rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE;

   if (_mesa_arb_vertex_program_enabled(ctx)) {
      rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE;
   }

   if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
      == R200_FOG_USE_SPEC_ALPHA) &&
      (ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) {
      R200_STATECHANGE( rmesa, ctx );
      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG;
   }

   R200_STATECHANGE( rmesa, vte );
   rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT);
   rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT;

   if (R200_DEBUG & RADEON_FALLBACKS)
      fprintf(stderr, "R200 end tcl fallback\n");
}
Esempio n. 3
0
/* TCL render.
 */
static GLboolean r200_run_tcl_render( struct gl_context *ctx,
				      struct tnl_pipeline_stage *stage )
{
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   GLuint i;
   GLubyte *vimap_rev;
/* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, 
   color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use
   more than 12 of those at the same time. */
   GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255,
			    255, 255, 255, 255, 255, 255, 255};


   /* TODO: separate this from the swtnl pipeline 
    */
   if (rmesa->radeon.TclFallback)
      return GL_TRUE;	/* fallback to software t&l */

   radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __func__);

   if (VB->Count == 0)
      return GL_FALSE;

   /* Validate state:
    */
   if (rmesa->radeon.NewGLState)
      if (!r200ValidateState( ctx ))
         return GL_TRUE; /* fallback to sw t&l */

   if (!_mesa_arb_vertex_program_enabled(ctx)) {
   /* NOTE: inputs != tnl->render_inputs - these are the untransformed
    * inputs.
    */
      map_rev_fixed[0] = VERT_ATTRIB_POS;
      /* technically there is no reason we always need VA_COLOR0. In theory
         could disable it depending on lighting, color materials, texturing... */
      map_rev_fixed[4] = VERT_ATTRIB_COLOR0;

      if (ctx->Light.Enabled) {
	 map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
      }

      /* this also enables VA_COLOR1 when using separate specular
         lighting model, which is unnecessary.
         FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses
         the secondary color (if lighting is disabled). The chip seems
         misconfigured for that though elsewhere (tcl output, might lock up) */
      if (_mesa_need_secondary_color(ctx)) {
	 map_rev_fixed[5] = VERT_ATTRIB_COLOR1;
      }

      if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
	 map_rev_fixed[3] = VERT_ATTRIB_FOG;
      }

      for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
	 if (ctx->Texture.Unit[i]._Current) {
	    if (rmesa->TexGenNeedNormals[i]) {
	       map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
	    }
	    map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i;
	 }
      }
      vimap_rev = &map_rev_fixed[0];
   }
   else {
      /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment
	 part", since using some vertex interpolator later which is not in
	 out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex
	 prog to a not enabled output however, so just don't mess with it.
	 We only need to change compsel. */
      GLuint out_compsel = 0;
      const GLbitfield64 vp_out =
	 rmesa->curr_vp_hw->mesa_program.info.outputs_written;

      vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0];
      assert(vp_out & BITFIELD64_BIT(VARYING_SLOT_POS));
      out_compsel = R200_OUTPUT_XYZW;
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL0)) {
	 out_compsel |= R200_OUTPUT_COLOR_0;
      }
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL1)) {
	 out_compsel |= R200_OUTPUT_COLOR_1;
      }
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_FOGC)) {
         out_compsel |= R200_OUTPUT_DISCRETE_FOG;
      }
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_PSIZ)) {
	 out_compsel |= R200_OUTPUT_PT_SIZE;
      }
      for (i = VARYING_SLOT_TEX0; i < VARYING_SLOT_TEX6; i++) {
	 if (vp_out & BITFIELD64_BIT(i)) {
	    out_compsel |= R200_OUTPUT_TEX_0 << (i - VARYING_SLOT_TEX0);
	 }
      }
      if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) {
	 R200_STATECHANGE( rmesa, vtx );
	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel;
      }
   }

   /* Do the actual work:
    */
   radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
   GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev )
     + rmesa->radeon.cmdbuf.cs->cdw;
   r200EmitArrays( ctx, vimap_rev );

   for (i = 0 ; i < VB->PrimitiveCount ; i++)
   {
      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
      GLuint start = VB->Primitive[i].start;
      GLuint length = VB->Primitive[i].count;

      if (!length)
	 continue;

      if (VB->Elts)
	 r200EmitEltPrimitive( ctx, start, start+length, prim );
      else
	 r200EmitPrimitive( ctx, start, start+length, prim );
   }
   if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw )
     WARN_ONCE("Rendering was %d commands larger than predicted size."
	 " We might overflow  command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);

   return GL_FALSE;		/* finished the pipe */
}
/**
 * glRasterPos transformation.  Typically called via ctx->Driver.RasterPos().
 *
 * \param vObj  vertex position in object space
 */
void
_mesa_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
{
   if (_mesa_arb_vertex_program_enabled(ctx)) {
      /* XXX implement this */
      _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos");
      return;
   }
   else {
      GLfloat eye[4], clip[4], ndc[3], d;
      GLfloat *norm, eyenorm[3];
      GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
      float scale[3], translate[3];

      /* apply modelview matrix:  eye = MV * obj */
      TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj );
      /* apply projection matrix:  clip = Proj * eye */
      TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye );

      /* clip to view volume. */
      if (!ctx->Transform.DepthClamp) {
         if (viewclip_point_z(clip) == 0) {
            ctx->Current.RasterPosValid = GL_FALSE;
            return;
         }
      }
      if (!ctx->Transform.RasterPositionUnclipped) {
         if (viewclip_point_xy(clip) == 0) {
            ctx->Current.RasterPosValid = GL_FALSE;
            return;
         }
      }

      /* clip to user clipping planes */
      if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) {
         ctx->Current.RasterPosValid = GL_FALSE;
         return;
      }

      /* ndc = clip / W */
      d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3];
      ndc[0] = clip[0] * d;
      ndc[1] = clip[1] * d;
      ndc[2] = clip[2] * d;
      /* wincoord = viewport_mapping(ndc) */
      _mesa_get_viewport_xform(ctx, 0, scale, translate);
      ctx->Current.RasterPos[0] = ndc[0] * scale[0] + translate[0];
      ctx->Current.RasterPos[1] = ndc[1] * scale[1] + translate[1];
      ctx->Current.RasterPos[2] = ndc[2] * scale[2] + translate[2];
      ctx->Current.RasterPos[3] = clip[3];

      if (ctx->Transform.DepthClamp) {
	 ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3],
					   ctx->ViewportArray[0].Near,
					   ctx->ViewportArray[0].Far);
      }

      /* compute raster distance */
      if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
         ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
      else
         ctx->Current.RasterDistance =
                        sqrtf( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );

      /* compute transformed normal vector (for lighting or texgen) */
      if (ctx->_NeedEyeCoords) {
         const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv;
         TRANSFORM_NORMAL( eyenorm, objnorm, inv );
         norm = eyenorm;
      }
      else {
         norm = objnorm;
      }

      /* update raster color */
      if (ctx->Light.Enabled) {
         /* lighting */
         shade_rastpos( ctx, vObj, norm,
                        ctx->Current.RasterColor,
                        ctx->Current.RasterSecondaryColor );
      }
      else {
         /* use current color */
	 COPY_4FV(ctx->Current.RasterColor,
		  ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
	 COPY_4FV(ctx->Current.RasterSecondaryColor,
		  ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
      }

      /* texture coords */
      {
         GLuint u;
         for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
            GLfloat tc[4];
            COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]);
            if (ctx->Texture.Unit[u].TexGenEnabled) {
               compute_texgen(ctx, vObj, eye, norm, u, tc);
            }
            TRANSFORM_POINT(ctx->Current.RasterTexCoords[u],
                            ctx->TextureMatrixStack[u].Top->m, tc);
         }
      }

      ctx->Current.RasterPosValid = GL_TRUE;
   }

   if (ctx->RenderMode == GL_SELECT) {
      _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
   }
}
Esempio n. 5
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;
}