void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct state_key *key;
   GLuint hash;
   const struct gl_vertex_program *prev = ctx->VertexProgram._Current;

   if (!ctx->VertexProgram._Current ||
       ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
      struct gl_vertex_program *newProg;

      /* Grab all the relevent state and put it in a single structure:
       */
      key = make_state_key(ctx);
      hash = hash_key(key);

      /* Look for an already-prepared program for this state:
       */
      newProg = search_cache( tnl->vp_cache, hash, key, sizeof(*key));
   
      /* OK, we'll have to build a new one:
       */
      if (!newProg) {

	 if (0)
	    _mesa_printf("Build new TNL program\n");
	 
	 newProg = (struct gl_vertex_program *)
	    ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 

	 create_new_program( key, newProg, ctx->Const.VertexProgram.MaxTemps );

	 if (ctx->Driver.ProgramStringNotify)
	    ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB, 
                                             &newProg->Base );

         /* Our ownership of newProg is transferred to the cache */
	 cache_item(ctx, tnl->vp_cache, hash, key, newProg);
      }
      else {
	 FREE(key);
      }

      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, newProg);
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, newProg);
   }

   /* Tell the driver about the change.  Could define a new target for
    * this?
    */
   if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
      ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
                            (struct gl_program *) ctx->VertexProgram._Current);
   }
}
/**
 * Restores the previous vertex program after
 * meta_set_passthrough_vertex_program()
 */
void
meta_restore_vertex_program(struct dri_metaops *meta)
{
   GLcontext *ctx = meta->ctx;

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
			    meta->saved_vp);
   _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL);
   ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
			   &ctx->VertexProgram.Current->Base);

   if (!meta->saved_vp_enable)
      _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
}
Example #3
0
/**
 * Update the default program objects in the given context to reference those
 * specified in the shared state and release those referencing the old
 * shared state.
 */
void
_mesa_update_default_objects_program(GLcontext *ctx)
{
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
                            (struct gl_vertex_program *)
                            ctx->Shared->DefaultVertexProgram);
   assert(ctx->VertexProgram.Current);
#endif

#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
                            (struct gl_fragment_program *)
                            ctx->Shared->DefaultFragmentProgram);
   assert(ctx->FragmentProgram.Current);
#endif

   /* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader
   if (ctx->ATIFragmentShader.Current) {
      ctx->ATIFragmentShader.Current->RefCount--;
      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
         _mesa_free(ctx->ATIFragmentShader.Current);
      }
   }
   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
   assert(ctx->ATIFragmentShader.Current);
   ctx->ATIFragmentShader.Current->RefCount++;
#endif
}
Example #4
0
/**
 * Free a context's vertex/fragment program state
 */
void
_mesa_free_program_data(struct gl_context *ctx)
{
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
   _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
#endif
#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
   _mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache);
#endif
#if FEATURE_ARB_geometry_shader4
   _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL);
   _mesa_delete_program_cache(ctx, ctx->GeometryProgram.Cache);
#endif
   /* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader
   if (ctx->ATIFragmentShader.Current) {
      ctx->ATIFragmentShader.Current->RefCount--;
      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
         free(ctx->ATIFragmentShader.Current);
      }
   }
#endif
   free((void *) ctx->Program.ErrorString);
}
/**
 * Set up a vertex program to pass through the position and first texcoord
 * for pixel path.
 */
void
meta_set_passthrough_vertex_program(struct dri_metaops *meta)
{
   GLcontext *ctx = meta->ctx;
   static const char *vp =
      "!!ARBvp1.0\n"
      "TEMP vertexClip;\n"
      "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
      "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
      "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
      "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
      "MOV result.position, vertexClip;\n"
      "MOV result.texcoord[0], vertex.texcoord[0];\n"
      "MOV result.color, vertex.color;\n"
      "END\n";

   assert(meta->saved_vp == NULL);

   _mesa_reference_vertprog(ctx, &meta->saved_vp,
			    ctx->VertexProgram.Current);
   if (meta->passthrough_vp == NULL) {
      GLuint prog_name;
      _mesa_GenPrograms(1, &prog_name);
      _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
      _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
			     GL_PROGRAM_FORMAT_ASCII_ARB,
			     strlen(vp), (const GLubyte *)vp);
      _mesa_reference_vertprog(ctx, &meta->passthrough_vp,
			       ctx->VertexProgram.Current);
      _mesa_DeletePrograms(1, &prog_name);
   }

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
			    meta->passthrough_vp);
   ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
			   &meta->passthrough_vp->Base);

   meta->saved_vp_enable = ctx->VertexProgram.Enabled;
   _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
}
Example #6
0
static void freeVertProgCache(GLcontext *ctx, struct r300_vertex_program_cont *cache)
{
    struct r300_vertex_program *tmp, *vp = cache->progs;

    while (vp) {
        tmp = vp->next;
        rc_constants_destroy(&vp->code.constants);
        _mesa_reference_vertprog(ctx, &vp->Base, NULL);
        _mesa_free(vp);
        vp = tmp;
    }
}
Example #7
0
/**
 * Init context's vertex/fragment program state
 */
void
_mesa_init_program(GLcontext *ctx)
{
   GLuint i;

   /*
    * If this assertion fails, we need to increase the field
    * size for register indexes.
    */
   ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
          <= (1 << INST_INDEX_BITS));
   ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
          <= (1 << INST_INDEX_BITS));

   ctx->Program.ErrorPos = -1;
   ctx->Program.ErrorString = _mesa_strdup("");

#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
   ctx->VertexProgram.Enabled = GL_FALSE;
#if FEATURE_es2_glsl
   ctx->VertexProgram.PointSizeEnabled = GL_TRUE;
#else
   ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
#endif
   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
                            ctx->Shared->DefaultVertexProgram);
   assert(ctx->VertexProgram.Current);
   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
      ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
      ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
   }
   ctx->VertexProgram.Cache = _mesa_new_program_cache();
#endif

#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
   ctx->FragmentProgram.Enabled = GL_FALSE;
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
                            ctx->Shared->DefaultFragmentProgram);
   assert(ctx->FragmentProgram.Current);
   ctx->FragmentProgram.Cache = _mesa_new_program_cache();
#endif


   /* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader
   ctx->ATIFragmentShader.Enabled = GL_FALSE;
   ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
   assert(ctx->ATIFragmentShader.Current);
   ctx->ATIFragmentShader.Current->RefCount++;
#endif
}
void _tnl_ProgramCacheDestroy( GLcontext *ctx )
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct tnl_cache_item *c, *next;
   GLuint i;

   for (i = 0; i < tnl->vp_cache->size; i++)
      for (c = tnl->vp_cache->items[i]; c; c = next) {
	 next = c->next;
	 FREE(c->key);
	 _mesa_reference_vertprog(ctx, &c->prog, NULL);
	 FREE(c);
      }

   FREE(tnl->vp_cache->items);
   FREE(tnl->vp_cache);
}
Example #9
0
static void freeVertProgCache(GLcontext *ctx, struct r700_vertex_program_cont *cache)
{
	struct r700_vertex_program *tmp, *vp = cache->progs;

	while (vp) {
		tmp = vp->next;
		/* Release DMA region */
		r600DeleteShader(ctx, vp->shaderbo);
		/* Clean up */
		Clean_Up_Assembler(&(vp->r700AsmCode));
		Clean_Up_Shader(&(vp->r700Shader));
		
		_mesa_reference_vertprog(ctx, &vp->mesa_program, NULL);
		_mesa_free(vp);
		vp = tmp;
	}
}
Example #10
0
/**
 * Update vertex/fragment program state.  In particular, update these fields:
 *   ctx->VertexProgram._Current
 *   ctx->VertexProgram._TnlProgram,
 * These point to the highest priority enabled vertex/fragment program or are
 * NULL if fixed-function processing is to be done.
 *
 * 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(GLcontext *ctx)
{
   const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
   const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
   const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
   GLbitfield new_state = 0x0;

   /*
    * 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. 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 (shProg && shProg->LinkStatus && shProg->FragmentProgram) {
      /* Use shader programs */
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               shProg->FragmentProgram);
   }
   else if (ctx->FragmentProgram._Enabled) {
      /* use user-defined vertex program */
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               ctx->FragmentProgram.Current);
   }
   else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
      /* Use fragment program generated from fixed-function state.
       */
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               _mesa_get_fixed_func_fragment_program(ctx));
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
                               ctx->FragmentProgram._Current);
   }
   else {
      /* no fragment program */
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
   }

   /* Examine vertex program after fragment program as
    * _mesa_get_fixed_func_vertex_program() needs to know active
    * fragprog inputs.
    */
   if (shProg && shProg->LinkStatus && shProg->VertexProgram) {
      /* Use shader programs */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
                            shProg->VertexProgram);
   }
   else if (ctx->VertexProgram._Enabled) {
      /* use user-defined vertex program */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
                               ctx->VertexProgram.Current);
   }
   else if (ctx->VertexProgram._MaintainTnlProgram) {
      /* Use vertex program generated from fixed-function state.
       */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
                               _mesa_get_fixed_func_vertex_program(ctx));
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram,
                               ctx->VertexProgram._Current);
   }
   else {
      /* no vertex program */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
   }

   /* Let the driver know what's happening:
    */
   if (ctx->FragmentProgram._Current != prevFP) {
      new_state |= _NEW_PROGRAM;
      if (ctx->Driver.BindProgram) {
         ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
                          (struct gl_program *) ctx->FragmentProgram._Current);
      }
   }
   
   if (ctx->VertexProgram._Current != prevVP) {
      new_state |= _NEW_PROGRAM;
      if (ctx->Driver.BindProgram) {
         ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
                            (struct gl_program *) ctx->VertexProgram._Current);
      }
   }

   return new_state;
}
Example #11
0
/**
 * Free the data associated with the given context.
 * 
 * But doesn't free the GLcontext struct itself.
 *
 * \sa _mesa_initialize_context() and init_attrib_groups().
 */
void
_mesa_free_context_data( GLcontext *ctx )
{
   GLint RefCount;

   if (!_mesa_get_current_context()){
      /* No current context, but we may need one in order to delete
       * texture objs, etc.  So temporarily bind the context now.
       */
      _mesa_make_current(ctx, NULL, NULL);
   }

   /* unreference WinSysDraw/Read buffers */
   _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL);

   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);

   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);

   _mesa_free_attrib_data(ctx);
   _mesa_free_lighting_data( ctx );
   _mesa_free_eval_data( ctx );
   _mesa_free_texture_data( ctx );
   _mesa_free_matrix_data( ctx );
   _mesa_free_viewport_data( ctx );
   _mesa_free_colortables_data( ctx );
   _mesa_free_program_data(ctx);
   _mesa_free_shader_state(ctx);
   _mesa_free_queryobj_data(ctx);
#if FEATURE_ARB_sync
   _mesa_free_sync_data(ctx);
#endif
   _mesa_free_varray_data(ctx);

   _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);

#if FEATURE_ARB_pixel_buffer_object
   _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
   _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
#endif

#if FEATURE_ARB_vertex_buffer_object
   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
#endif

   /* free dispatch tables */
   _mesa_free(ctx->Exec);
   _mesa_free(ctx->Save);

   /* Shared context state (display lists, textures, etc) */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   RefCount = --ctx->Shared->RefCount;
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   assert(RefCount >= 0);
   if (RefCount == 0) {
      /* free shared state */
      _mesa_free_shared_state( ctx, ctx->Shared );
   }

   /* needs to be after freeing shared state */
   _mesa_free_display_list_data(ctx);

   if (ctx->Extensions.String)
      _mesa_free((void *) ctx->Extensions.String);

   /* unbind the context if it's currently bound */
   if (ctx == _mesa_get_current_context()) {
      _mesa_make_current(NULL, NULL, NULL);
   }
}
Example #12
0
/**
 * Bind a program (make it current)
 * \note Called from the GL API dispatcher by both glBindProgramNV
 * and glBindProgramARB.
 */
void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id)
{
   struct gl_program *curProg, *newProg;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   /* Error-check target and get curProg */
   if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
        (ctx->Extensions.NV_vertex_program ||
         ctx->Extensions.ARB_vertex_program)) {
      curProg = &ctx->VertexProgram.Current->Base;
   }
   else if ((target == GL_FRAGMENT_PROGRAM_NV
             && ctx->Extensions.NV_fragment_program) ||
            (target == GL_FRAGMENT_PROGRAM_ARB
             && ctx->Extensions.ARB_fragment_program)) {
      curProg = &ctx->FragmentProgram.Current->Base;
   }
   else {
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
      return;
   }

   /*
    * Get pointer to new program to bind.
    * NOTE: binding to a non-existant program is not an error.
    * That's supposed to be caught in glBegin.
    */
   if (id == 0) {
      /* Bind a default program */
      newProg = NULL;
      if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */
         newProg = &ctx->Shared->DefaultVertexProgram->Base;
      else
         newProg = &ctx->Shared->DefaultFragmentProgram->Base;
   }
   else {
      /* Bind a user program */
      newProg = _mesa_lookup_program(ctx, id);
      if (!newProg || newProg == &_mesa_DummyProgram) {
         /* allocate a new program now */
         newProg = ctx->Driver.NewProgram(ctx, target, id);
         if (!newProg) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
            return;
         }
         _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
      }
      else if (!compatible_program_targets(newProg->Target, target)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glBindProgramNV/ARB(target mismatch)");
         return;
      }
   }

   /** All error checking is complete now **/

   if (curProg->Id == id) {
      /* binding same program - no change */
      return;
   }

   /* signal new program (and its new constants) */
   FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);

   /* bind newProg */
   if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
                               (struct gl_vertex_program *) newProg);
   }
   else if (target == GL_FRAGMENT_PROGRAM_NV ||
            target == GL_FRAGMENT_PROGRAM_ARB) {
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
                               (struct gl_fragment_program *) newProg);
   }

   /* Never null pointers */
   ASSERT(ctx->VertexProgram.Current);
   ASSERT(ctx->FragmentProgram.Current);

   if (ctx->Driver.BindProgram)
      ctx->Driver.BindProgram(ctx, target, newProg);
}
Example #13
0
/**
 * Shader linker.  Currently:
 *
 * 1. The last attached vertex shader and fragment shader are linked.
 * 2. Varying vars in the two shaders are combined so their locations
 *    agree between the vertex and fragment stages.  They're treated as
 *    vertex program output attribs and as fragment program input attribs.
 * 3. The vertex and fragment programs are cloned and modified to update
 *    src/dst register references so they use the new, linked varying
 *    storage locations.
 */
void
_slang_link(GLcontext *ctx,
            GLhandleARB programObj,
            struct gl_shader_program *shProg)
{
   const struct gl_vertex_program *vertProg = NULL;
   const struct gl_fragment_program *fragProg = NULL;
   GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE;
   GLuint numSamplers = 0;
   GLuint i;

   _mesa_clear_shader_program_data(ctx, shProg);

   /* Initialize LinkStatus to "success".  Will be cleared if error. */
   shProg->LinkStatus = GL_TRUE;

   /* check that all programs compiled successfully */
   for (i = 0; i < shProg->NumShaders; i++) {
      if (!shProg->Shaders[i]->CompileStatus) {
         link_error(shProg, "linking with uncompiled shader\n");
         return;
      }
   }

   shProg->Uniforms = _mesa_new_uniform_list();
   shProg->Varying = _mesa_new_parameter_list();

   /*
    * Find the vertex and fragment shaders which define main()
    */
   {
      struct gl_shader *vertShader, *fragShader;
      vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
      fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
      if (vertShader)
         vertProg = vertex_program(vertShader->Program);
      if (fragShader)
         fragProg = fragment_program(fragShader->Program);
      if (!shProg->LinkStatus)
         return;
   }

#if FEATURE_es2_glsl
   /* must have both a vertex and fragment program for ES2 */
   if (!vertProg) {
      link_error(shProg, "missing vertex shader\n");
      return;
   }
   if (!fragProg) {
      link_error(shProg, "missing fragment shader\n");
      return;
   }
#endif

   /*
    * Make copies of the vertex/fragment programs now since we'll be
    * changing src/dst registers after merging the uniforms and varying vars.
    */
   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
   if (vertProg) {
      struct gl_vertex_program *linked_vprog =
         _mesa_clone_vertex_program(ctx, vertProg);
      shProg->VertexProgram = linked_vprog; /* refcount OK */
      /* vertex program ID not significant; just set Id for debugging purposes */
      shProg->VertexProgram->Base.Id = shProg->Name;
      ASSERT(shProg->VertexProgram->Base.RefCount == 1);
   }

   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
   if (fragProg) {
      struct gl_fragment_program *linked_fprog = 
         _mesa_clone_fragment_program(ctx, fragProg);
      shProg->FragmentProgram = linked_fprog; /* refcount OK */
      /* vertex program ID not significant; just set Id for debugging purposes */
      shProg->FragmentProgram->Base.Id = shProg->Name;
      ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
   }

   /* link varying vars */
   if (shProg->VertexProgram) {
      if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
         return;
   }
   if (shProg->FragmentProgram) {
      if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
         return;
   }

   /* link uniform vars */
   if (shProg->VertexProgram) {
      if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
                             &numSamplers)) {
         return;
      }
   }
   if (shProg->FragmentProgram) {
      if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
                             &numSamplers)) {
         return;
      }
   }

   /*_mesa_print_uniforms(shProg->Uniforms);*/

   if (shProg->VertexProgram) {
      if (!_slang_resolve_attributes(shProg, &vertProg->Base,
                                     &shProg->VertexProgram->Base)) {
         return;
      }
   }

   if (shProg->VertexProgram) {
      _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
      _slang_count_temporaries(&shProg->VertexProgram->Base);
      if (!(shProg->VertexProgram->Base.OutputsWritten
	    & BITFIELD64_BIT(VERT_RESULT_HPOS))) {
         /* the vertex program did not compute a vertex position */
         link_error(shProg,
                    "gl_Position was not written by vertex shader\n");
         return;
      }
   }
   if (shProg->FragmentProgram) {
      _slang_count_temporaries(&shProg->FragmentProgram->Base);
      _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
   }

   /* Check that all the varying vars needed by the fragment shader are
    * actually produced by the vertex shader.
    */
   if (shProg->FragmentProgram) {
      const GLbitfield varyingRead
         = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
      const GLbitfield64 varyingWritten = shProg->VertexProgram ?
         shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
      if ((varyingRead & varyingWritten) != varyingRead) {
         link_error(shProg,
          "Fragment program using varying vars not written by vertex shader\n");
         return;
      }         
   }

   /* check that gl_FragColor and gl_FragData are not both written to */
   if (shProg->FragmentProgram) {
      const GLbitfield64 outputsWritten =
	 shProg->FragmentProgram->Base.OutputsWritten;
      if ((outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
          (outputsWritten >= BITFIELD64_BIT(FRAG_RESULT_DATA0))) {
         link_error(shProg, "Fragment program cannot write both gl_FragColor"
                    " and gl_FragData[].\n");
         return;
      }         
   }


   if (fragProg && shProg->FragmentProgram) {
      /* Compute initial program's TexturesUsed info */
      _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);

      /* notify driver that a new fragment program has been compiled/linked */
      vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
                                                 &shProg->FragmentProgram->Base);
      if (ctx->Shader.Flags & GLSL_DUMP) {
         printf("Mesa pre-link fragment program:\n");
         _mesa_print_program(&fragProg->Base);
         _mesa_print_program_parameters(ctx, &fragProg->Base);

         printf("Mesa post-link fragment program:\n");
         _mesa_print_program(&shProg->FragmentProgram->Base);
         _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
      }
   }

   if (vertProg && shProg->VertexProgram) {
      /* Compute initial program's TexturesUsed info */
      _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);

      /* notify driver that a new vertex program has been compiled/linked */
      fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
                                                   &shProg->VertexProgram->Base);
      if (ctx->Shader.Flags & GLSL_DUMP) {
         printf("Mesa pre-link vertex program:\n");
         _mesa_print_program(&vertProg->Base);
         _mesa_print_program_parameters(ctx, &vertProg->Base);

         printf("Mesa post-link vertex program:\n");
         _mesa_print_program(&shProg->VertexProgram->Base);
         _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
      }
   }

   /* Debug: */
   if (0) {
      if (shProg->VertexProgram)
         _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
      if (shProg->FragmentProgram)
         _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
   }

   if (ctx->Shader.Flags & GLSL_DUMP) {
      printf("Varying vars:\n");
      _mesa_print_parameter_list(shProg->Varying);
      if (shProg->InfoLog) {
         printf("Info Log: %s\n", shProg->InfoLog);
      }
   }

   if (!vertNotify || !fragNotify) {
      /* driver rejected one/both of the vertex/fragment programs */
      if (!shProg->InfoLog) {
	 link_error(shProg,
		    "Vertex and/or fragment program rejected by driver\n");
      }
   }
   else {
      shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
   }
}
Example #14
0
/**
 * Init context's vertex/fragment program state
 */
void
_mesa_init_program(struct gl_context *ctx)
{
   GLuint i;

   /*
    * If this assertion fails, we need to increase the field
    * size for register indexes (see INST_INDEX_BITS).
    */
   ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
          <= (1 << INST_INDEX_BITS));
   ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
          <= (1 << INST_INDEX_BITS));

   ASSERT(ctx->Const.VertexProgram.MaxTemps <= (1 << INST_INDEX_BITS));
   ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
   ASSERT(ctx->Const.FragmentProgram.MaxTemps <= (1 << INST_INDEX_BITS));
   ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));

   ASSERT(ctx->Const.VertexProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
   ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);

   /* If this fails, increase prog_instruction::TexSrcUnit size */
   ASSERT(MAX_TEXTURE_UNITS < (1 << 5));

   /* If this fails, increase prog_instruction::TexSrcTarget size */
   ASSERT(NUM_TEXTURE_TARGETS < (1 << 3));

   ctx->Program.ErrorPos = -1;
   ctx->Program.ErrorString = _mesa_strdup("");

#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
   ctx->VertexProgram.Enabled = GL_FALSE;
#if FEATURE_es2_glsl
   ctx->VertexProgram.PointSizeEnabled =
      (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
#else
   ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
#endif
   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
                            ctx->Shared->DefaultVertexProgram);
   assert(ctx->VertexProgram.Current);
   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
      ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
      ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
   }
   ctx->VertexProgram.Cache = _mesa_new_program_cache();
#endif

#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
   ctx->FragmentProgram.Enabled = GL_FALSE;
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
                            ctx->Shared->DefaultFragmentProgram);
   assert(ctx->FragmentProgram.Current);
   ctx->FragmentProgram.Cache = _mesa_new_program_cache();
#endif

#if FEATURE_ARB_geometry_shader4
   ctx->GeometryProgram.Enabled = GL_FALSE;
   /* right now by default we don't have a geometry program */
   _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
                            NULL);
   ctx->GeometryProgram.Cache = _mesa_new_program_cache();
#endif

   /* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader
   ctx->ATIFragmentShader.Enabled = GL_FALSE;
   ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
   assert(ctx->ATIFragmentShader.Current);
   ctx->ATIFragmentShader.Current->RefCount++;
#endif
}
Example #15
0
File: state.c Project: olvaffe/mesa
/**
 * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point
 * to the current/active programs.  Then call ctx->Driver.BindProgram() to
 * tell the driver which programs to use.
 *
 * 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)
{
   const struct gl_shader_program *vsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
   const struct gl_shader_program *gsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
   struct gl_shader_program *fsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
   const struct gl_shader_program *csProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
   const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
   const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
   const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current;
   const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current;
   GLbitfield new_state = 0x0;

   /*
    * 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. 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 && fsProg->LinkStatus
       && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
      /* Use GLSL fragment shader */
      _mesa_reference_shader_program(ctx,
                                     &ctx->_Shader->_CurrentFragmentProgram,
				     fsProg);
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               gl_fragment_program(fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program));
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
			       NULL);
   }
   else if (ctx->FragmentProgram._Enabled) {
      /* Use user-defined fragment program */
      _mesa_reference_shader_program(ctx,
                                     &ctx->_Shader->_CurrentFragmentProgram,
				     NULL);
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               ctx->FragmentProgram.Current);
      _mesa_reference_fragprog(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_shader_program(ctx,
                                     &ctx->_Shader->_CurrentFragmentProgram,
				     f);
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
			       gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program));
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
			       gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program));
   }
   else {
      /* No fragment program */
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
			       NULL);
   }

   if (gsProg && gsProg->LinkStatus
       && gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) {
      /* Use GLSL geometry shader */
      _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current,
			       gl_geometry_program(gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program));
   } else {
      /* No geometry program */
      _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL);
   }

   /* Examine vertex program after fragment program as
    * _mesa_get_fixed_func_vertex_program() needs to know active
    * fragprog inputs.
    */
   if (vsProg && vsProg->LinkStatus
       && vsProg->_LinkedShaders[MESA_SHADER_VERTEX]) {
      /* Use GLSL vertex shader */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
			       gl_vertex_program(vsProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program));
   }
   else if (ctx->VertexProgram._Enabled) {
      /* Use user-defined vertex program */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
                               ctx->VertexProgram.Current);
   }
   else if (ctx->VertexProgram._MaintainTnlProgram) {
      /* Use vertex program generated from fixed-function state */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
                               _mesa_get_fixed_func_vertex_program(ctx));
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram,
                               ctx->VertexProgram._Current);
   }
   else {
      /* no vertex program */
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
   }

   if (csProg && csProg->LinkStatus
       && csProg->_LinkedShaders[MESA_SHADER_COMPUTE]) {
      /* Use GLSL compute shader */
      _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current,
                               gl_compute_program(csProg->_LinkedShaders[MESA_SHADER_COMPUTE]->Program));
   } else {
      /* no compute program */
      _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, NULL);
   }

   /* Let the driver know what's happening:
    */
   if (ctx->FragmentProgram._Current != prevFP) {
      new_state |= _NEW_PROGRAM;
      if (ctx->Driver.BindProgram) {
         ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
                          (struct gl_program *) ctx->FragmentProgram._Current);
      }
   }

   if (ctx->GeometryProgram._Current != prevGP) {
      new_state |= _NEW_PROGRAM;
      if (ctx->Driver.BindProgram) {
         ctx->Driver.BindProgram(ctx, GL_GEOMETRY_PROGRAM_NV,
                            (struct gl_program *) ctx->GeometryProgram._Current);
      }
   }

   if (ctx->VertexProgram._Current != prevVP) {
      new_state |= _NEW_PROGRAM;
      if (ctx->Driver.BindProgram) {
         ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
                            (struct gl_program *) ctx->VertexProgram._Current);
      }
   }

   if (ctx->ComputeProgram._Current != prevCP) {
      new_state |= _NEW_PROGRAM;
      if (ctx->Driver.BindProgram) {
         ctx->Driver.BindProgram(ctx, GL_COMPUTE_PROGRAM_NV,
                                 (struct gl_program *) ctx->ComputeProgram._Current);
      }
   }

   return new_state;
}
Example #16
0
/**
 * Deallocate a shared state object and all children structures.
 *
 * \param ctx GL context.
 * \param shared shared state pointer.
 * 
 * Frees the display lists, the texture objects (calling the driver texture
 * deletion callback to free its private data) and the vertex programs, as well
 * as their hash tables.
 *
 * \sa alloc_shared_state().
 */
void
_mesa_free_shared_state(GLcontext *ctx, struct gl_shared_state *shared)
{
   GLuint i;

   /*
    * Free display lists
    */
   _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx);
   _mesa_DeleteHashTable(shared->DisplayList);

#if FEATURE_ARB_shader_objects
   _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx);
   _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx);
   _mesa_DeleteHashTable(shared->ShaderObjects);
#endif

   _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx);
   _mesa_DeleteHashTable(shared->Programs);

   _mesa_HashDeleteAll(shared->ArrayObjects, delete_arrayobj_cb, ctx);
   _mesa_DeleteHashTable(shared->ArrayObjects);

#if FEATURE_ARB_vertex_program
   _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL);
#endif

#if FEATURE_ARB_fragment_program
   _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL);
#endif

#if FEATURE_ATI_fragment_shader
   _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx);
   _mesa_DeleteHashTable(shared->ATIShaders);
   _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader);
#endif

#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
   _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx);
   _mesa_DeleteHashTable(shared->BufferObjects);
#endif

#if FEATURE_EXT_framebuffer_object
   _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx);
   _mesa_DeleteHashTable(shared->FrameBuffers);
   _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx);
   _mesa_DeleteHashTable(shared->RenderBuffers);
#endif

   /*
    * Free texture objects (after FBOs since some textures might have
    * been bound to FBOs).
    */
   ASSERT(ctx->Driver.DeleteTexture);
   /* the default textures */
   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
      ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]);
   }

   /* all other textures */
   _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
   _mesa_DeleteHashTable(shared->TexObjects);

   _glthread_DESTROY_MUTEX(shared->Mutex);
   _glthread_DESTROY_MUTEX(shared->TexMutex);

   _mesa_free(shared);
}