Esempio n. 1
0
/**
 * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
 * program object.
 */
void
meta_set_fragment_program(struct dri_metaops *meta,
			  struct gl_fragment_program **prog,
			  const char *prog_string)
{
   GLcontext *ctx = meta->ctx;
   assert(meta->saved_fp == NULL);

   _mesa_reference_fragprog(ctx, &meta->saved_fp,
			    ctx->FragmentProgram.Current);
   if (*prog == NULL) {
      GLuint prog_name;
      _mesa_GenPrograms(1, &prog_name);
      _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
      _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
			     GL_PROGRAM_FORMAT_ASCII_ARB,
			     strlen(prog_string), (const GLubyte *)prog_string);
      _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
      /* Note that DeletePrograms unbinds the program on us */
      _mesa_DeletePrograms(1, &prog_name);
   }

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
   ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));

   meta->saved_fp_enable = ctx->FragmentProgram.Enabled;
   _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
}
Esempio n. 2
0
/**
 * Restores the previous fragment program after
 * meta_set_fragment_program()
 */
void
meta_restore_fragment_program(struct dri_metaops *meta)
{
   GLcontext *ctx = meta->ctx;

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
			    meta->saved_fp);
   _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL);
   ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
			   &ctx->FragmentProgram.Current->Base);

   if (!meta->saved_fp_enable)
      _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
}
Esempio n. 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
}
Esempio n. 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);
}
Esempio n. 5
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
}
Esempio n. 6
0
void
st_destroy_drawpix(struct st_context *st)
{
   GLuint i;

   for (i = 0; i < Elements(st->drawpix.shaders); i++) {
      if (st->drawpix.shaders[i])
         _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL);
   }

   st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
   if (st->drawpix.vert_shaders[0])
      ureg_free_tokens(st->drawpix.vert_shaders[0]);
   if (st->drawpix.vert_shaders[1])
      ureg_free_tokens(st->drawpix.vert_shaders[1]);
}
Esempio n. 7
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;
}
Esempio n. 8
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);
   }
}
Esempio n. 9
0
/**
 * Translate a Mesa fragment shader into a TGSI shader using extra info in
 * the key.
 * \return  new fragment program variant
 */
static struct st_fp_variant *
st_translate_fragment_program(struct st_context *st,
                              struct st_fragment_program *stfp,
                              const struct st_fp_variant_key *key)
{
   struct pipe_context *pipe = st->pipe;
   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
   GLboolean deleteFP = GL_FALSE;

   GLuint outputMapping[FRAG_RESULT_MAX];
   GLuint inputMapping[VARYING_SLOT_MAX];
   GLuint interpMode[PIPE_MAX_SHADER_INPUTS];  /* XXX size? */
   GLuint interpLocation[PIPE_MAX_SHADER_INPUTS];
   GLuint attr;
   GLbitfield64 inputsRead;
   struct ureg_program *ureg;

   GLboolean write_all = GL_FALSE;

   ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
   ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
   uint fs_num_inputs = 0;

   ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
   ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
   uint fs_num_outputs = 0;

   if (!variant)
      return NULL;

   assert(!(key->bitmap && key->drawpixels));

   if (key->bitmap) {
      /* glBitmap drawing */
      struct gl_fragment_program *fp; /* we free this temp program below */

      st_make_bitmap_fragment_program(st, &stfp->Base,
                                      &fp, &variant->bitmap_sampler);

      variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
      stfp = st_fragment_program(fp);
      deleteFP = GL_TRUE;
   }
   else if (key->drawpixels) {
      /* glDrawPixels drawing */
      struct gl_fragment_program *fp; /* we free this temp program below */

      if (key->drawpixels_z || key->drawpixels_stencil) {
         fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
                                                key->drawpixels_stencil);
      }
      else {
         /* RGBA */
         st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
         variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
         deleteFP = GL_TRUE;
      }
      stfp = st_fragment_program(fp);
   }

   if (!stfp->glsl_to_tgsi)
      _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);

   /*
    * Convert Mesa program inputs to TGSI input register semantics.
    */
   inputsRead = stfp->Base.Base.InputsRead;
   for (attr = 0; attr < VARYING_SLOT_MAX; attr++) {
      if ((inputsRead & BITFIELD64_BIT(attr)) != 0) {
         const GLuint slot = fs_num_inputs++;

         inputMapping[attr] = slot;
         if (stfp->Base.IsCentroid & BITFIELD64_BIT(attr))
            interpLocation[slot] = TGSI_INTERPOLATE_LOC_CENTROID;
         else if (stfp->Base.IsSample & BITFIELD64_BIT(attr))
            interpLocation[slot] = TGSI_INTERPOLATE_LOC_SAMPLE;
         else
            interpLocation[slot] = TGSI_INTERPOLATE_LOC_CENTER;

         if (key->persample_shading)
            interpLocation[slot] = TGSI_INTERPOLATE_LOC_SAMPLE;

         switch (attr) {
         case VARYING_SLOT_POS:
            input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
            break;
         case VARYING_SLOT_COL0:
            input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            input_semantic_index[slot] = 0;
            interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
                                                   TRUE);
            break;
         case VARYING_SLOT_COL1:
            input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            input_semantic_index[slot] = 1;
            interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
                                                   TRUE);
            break;
         case VARYING_SLOT_FOGC:
            input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
            break;
         case VARYING_SLOT_FACE:
            input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
            break;
         case VARYING_SLOT_PRIMITIVE_ID:
            input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
            break;
         case VARYING_SLOT_LAYER:
            input_semantic_name[slot] = TGSI_SEMANTIC_LAYER;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
            break;
         case VARYING_SLOT_VIEWPORT:
            input_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
            break;
         case VARYING_SLOT_CLIP_DIST0:
            input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
            break;
         case VARYING_SLOT_CLIP_DIST1:
            input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
            input_semantic_index[slot] = 1;
            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
            break;
            /* In most cases, there is nothing special about these
             * inputs, so adopt a convention to use the generic
             * semantic name and the mesa VARYING_SLOT_ number as the
             * index.
             *
             * All that is required is that the vertex shader labels
             * its own outputs similarly, and that the vertex shader
             * generates at least every output required by the
             * fragment shader plus fixed-function hardware (such as
             * BFC).
             *
             * However, some drivers may need us to identify the PNTC and TEXi
             * varyings if, for example, their capability to replace them with
             * sprite coordinates is limited.
             */
         case VARYING_SLOT_PNTC:
            if (st->needs_texcoord_semantic) {
               input_semantic_name[slot] = TGSI_SEMANTIC_PCOORD;
               input_semantic_index[slot] = 0;
               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
               break;
            }
            /* fall through */
         case VARYING_SLOT_TEX0:
         case VARYING_SLOT_TEX1:
         case VARYING_SLOT_TEX2:
         case VARYING_SLOT_TEX3:
         case VARYING_SLOT_TEX4:
         case VARYING_SLOT_TEX5:
         case VARYING_SLOT_TEX6:
         case VARYING_SLOT_TEX7:
            if (st->needs_texcoord_semantic) {
               input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD;
               input_semantic_index[slot] = attr - VARYING_SLOT_TEX0;
               interpMode[slot] =
                  st_translate_interp(stfp->Base.InterpQualifier[attr], FALSE);
               break;
            }
            /* fall through */
         case VARYING_SLOT_VAR0:
         default:
            /* Semantic indices should be zero-based because drivers may choose
             * to assign a fixed slot determined by that index.
             * This is useful because ARB_separate_shader_objects uses location
             * qualifiers for linkage, and if the semantic index corresponds to
             * these locations, linkage passes in the driver become unecessary.
             *
             * If needs_texcoord_semantic is true, no semantic indices will be
             * consumed for the TEXi varyings, and we can base the locations of
             * the user varyings on VAR0.  Otherwise, we use TEX0 as base index.
             */
            assert(attr >= VARYING_SLOT_TEX0);
            input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
            input_semantic_index[slot] = st_get_generic_varying_index(st, attr);
            if (attr == VARYING_SLOT_PNTC)
               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
            else
               interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
                                                      FALSE);
            break;
         }
      }
      else {
         inputMapping[attr] = -1;
      }
   }

   /*
    * Semantics and mapping for outputs
    */
   {
      uint numColors = 0;
      GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;

      /* if z is written, emit that first */
      if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
         fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
         fs_output_semantic_index[fs_num_outputs] = 0;
         outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
         fs_num_outputs++;
         outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
      }

      if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
         fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
         fs_output_semantic_index[fs_num_outputs] = 0;
         outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
         fs_num_outputs++;
         outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
      }

      if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) {
         fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_SAMPLEMASK;
         fs_output_semantic_index[fs_num_outputs] = 0;
         outputMapping[FRAG_RESULT_SAMPLE_MASK] = fs_num_outputs;
         fs_num_outputs++;
         outputsWritten &= ~(1 << FRAG_RESULT_SAMPLE_MASK);
      }

      /* handle remaining outputs (color) */
      for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
         if (outputsWritten & BITFIELD64_BIT(attr)) {
            switch (attr) {
            case FRAG_RESULT_DEPTH:
            case FRAG_RESULT_STENCIL:
            case FRAG_RESULT_SAMPLE_MASK:
               /* handled above */
               assert(0);
               break;
            case FRAG_RESULT_COLOR:
               write_all = GL_TRUE; /* fallthrough */
            default:
               assert(attr == FRAG_RESULT_COLOR ||
                      (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
               fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
               fs_output_semantic_index[fs_num_outputs] = numColors;
               outputMapping[attr] = fs_num_outputs;
               numColors++;
               break;
            }

            fs_num_outputs++;
         }
      }
   }

   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
   if (ureg == NULL) {
      free(variant);
      return NULL;
   }

   if (ST_DEBUG & DEBUG_MESA) {
      _mesa_print_program(&stfp->Base.Base);
      _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
      debug_printf("\n");
   }
   if (write_all == GL_TRUE)
      ureg_property(ureg, TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS, 1);

   if (stfp->Base.FragDepthLayout != FRAG_DEPTH_LAYOUT_NONE) {
      switch (stfp->Base.FragDepthLayout) {
      case FRAG_DEPTH_LAYOUT_ANY:
         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
                       TGSI_FS_DEPTH_LAYOUT_ANY);
         break;
      case FRAG_DEPTH_LAYOUT_GREATER:
         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
                       TGSI_FS_DEPTH_LAYOUT_GREATER);
         break;
      case FRAG_DEPTH_LAYOUT_LESS:
         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
                       TGSI_FS_DEPTH_LAYOUT_LESS);
         break;
      case FRAG_DEPTH_LAYOUT_UNCHANGED:
         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
                       TGSI_FS_DEPTH_LAYOUT_UNCHANGED);
         break;
      default:
         assert(0);
      }
   }

   if (stfp->glsl_to_tgsi)
      st_translate_program(st->ctx,
                           TGSI_PROCESSOR_FRAGMENT,
                           ureg,
                           stfp->glsl_to_tgsi,
                           &stfp->Base.Base,
                           /* inputs */
                           fs_num_inputs,
                           inputMapping,
                           input_semantic_name,
                           input_semantic_index,
                           interpMode,
                           interpLocation,
                           /* outputs */
                           fs_num_outputs,
                           outputMapping,
                           fs_output_semantic_name,
                           fs_output_semantic_index, FALSE,
                           key->clamp_color );
   else
      st_translate_mesa_program(st->ctx,
                                TGSI_PROCESSOR_FRAGMENT,
                                ureg,
                                &stfp->Base.Base,
                                /* inputs */
                                fs_num_inputs,
                                inputMapping,
                                input_semantic_name,
                                input_semantic_index,
                                interpMode,
                                /* outputs */
                                fs_num_outputs,
                                outputMapping,
                                fs_output_semantic_name,
                                fs_output_semantic_index, FALSE,
                                key->clamp_color);

   variant->tgsi.tokens = ureg_get_tokens( ureg, NULL );
   ureg_destroy( ureg );

   if (ST_DEBUG & DEBUG_TGSI) {
      tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/);
      debug_printf("\n");
   }

   /* fill in variant */
   variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi);
   variant->key = *key;

   if (deleteFP) {
      /* Free the temporary program made above */
      struct gl_fragment_program *fp = &stfp->Base;
      _mesa_reference_fragprog(st->ctx, &fp, NULL);
   }

   return variant;
}
Esempio n. 10
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);
}
Esempio n. 11
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);
   }
}
Esempio n. 12
0
/**
 * Translate a Mesa fragment shader into a TGSI shader using extra info in
 * the key.
 * \return  new fragment program variant
 */
static struct st_fp_variant *
st_translate_fragment_program(struct st_context *st,
                              struct st_fragment_program *stfp,
                              const struct st_fp_variant_key *key)
{
   struct pipe_context *pipe = st->pipe;
   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
   GLboolean deleteFP = GL_FALSE;

   if (!variant)
      return NULL;

   assert(!(key->bitmap && key->drawpixels));

#if FEATURE_drawpix
   if (key->bitmap) {
      /* glBitmap drawing */
      struct gl_fragment_program *fp; /* we free this temp program below */

      st_make_bitmap_fragment_program(st, &stfp->Base,
                                      &fp, &variant->bitmap_sampler);

      variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
      stfp = st_fragment_program(fp);
      deleteFP = GL_TRUE;
   }
   else if (key->drawpixels) {
      /* glDrawPixels drawing */
      struct gl_fragment_program *fp; /* we free this temp program below */

      if (key->drawpixels_z || key->drawpixels_stencil) {
         fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
                                                key->drawpixels_stencil);
      }
      else {
         /* RGBA */
         st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
         variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
         deleteFP = GL_TRUE;
      }
      stfp = st_fragment_program(fp);
   }
#endif

   if (!stfp->tgsi.tokens) {
      /* need to translate Mesa instructions to TGSI now */
      GLuint outputMapping[FRAG_RESULT_MAX];
      GLuint inputMapping[FRAG_ATTRIB_MAX];
      GLuint interpMode[PIPE_MAX_SHADER_INPUTS];  /* XXX size? */
      GLuint attr;
      enum pipe_error error;
      const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
      struct ureg_program *ureg;
      GLboolean write_all = GL_FALSE;

      ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
      ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
      uint fs_num_inputs = 0;

      ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
      ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
      uint fs_num_outputs = 0;


      _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);

      /*
       * Convert Mesa program inputs to TGSI input register semantics.
       */
      for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
         if (inputsRead & (1 << attr)) {
            const GLuint slot = fs_num_inputs++;

            inputMapping[attr] = slot;

            switch (attr) {
            case FRAG_ATTRIB_WPOS:
               input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
               input_semantic_index[slot] = 0;
               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
               break;
            case FRAG_ATTRIB_COL0:
               input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
               input_semantic_index[slot] = 0;
               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
               break;
            case FRAG_ATTRIB_COL1:
               input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
               input_semantic_index[slot] = 1;
               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
               break;
            case FRAG_ATTRIB_FOGC:
               input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
               input_semantic_index[slot] = 0;
               interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
               break;
            case FRAG_ATTRIB_FACE:
               input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
               input_semantic_index[slot] = 0;
               interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
               break;
               /* In most cases, there is nothing special about these
                * inputs, so adopt a convention to use the generic
                * semantic name and the mesa FRAG_ATTRIB_ number as the
                * index. 
                * 
                * All that is required is that the vertex shader labels
                * its own outputs similarly, and that the vertex shader
                * generates at least every output required by the
                * fragment shader plus fixed-function hardware (such as
                * BFC).
                * 
                * There is no requirement that semantic indexes start at
                * zero or be restricted to a particular range -- nobody
                * should be building tables based on semantic index.
                */
            case FRAG_ATTRIB_PNTC:
            case FRAG_ATTRIB_TEX0:
            case FRAG_ATTRIB_TEX1:
            case FRAG_ATTRIB_TEX2:
            case FRAG_ATTRIB_TEX3:
            case FRAG_ATTRIB_TEX4:
            case FRAG_ATTRIB_TEX5:
            case FRAG_ATTRIB_TEX6:
            case FRAG_ATTRIB_TEX7:
            case FRAG_ATTRIB_VAR0:
            default:
               /* Actually, let's try and zero-base this just for
                * readability of the generated TGSI.
                */
               assert(attr >= FRAG_ATTRIB_TEX0);
               input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
               input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
               if (attr == FRAG_ATTRIB_PNTC)
                  interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
               else
                  interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
               break;
            }
         }
         else {
            inputMapping[attr] = -1;
         }
      }

      /*
       * Semantics and mapping for outputs
       */
      {
         uint numColors = 0;
         GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;

         /* if z is written, emit that first */
         if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
            fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
            fs_output_semantic_index[fs_num_outputs] = 0;
            outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
            fs_num_outputs++;
            outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
         }

         if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
            fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
            fs_output_semantic_index[fs_num_outputs] = 0;
            outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
            fs_num_outputs++;
            outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
         }

         /* handle remaning outputs (color) */
         for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
            if (outputsWritten & BITFIELD64_BIT(attr)) {
               switch (attr) {
               case FRAG_RESULT_DEPTH:
               case FRAG_RESULT_STENCIL:
                  /* handled above */
                  assert(0);
                  break;
               case FRAG_RESULT_COLOR:
                  write_all = GL_TRUE; /* fallthrough */
               default:
                  assert(attr == FRAG_RESULT_COLOR ||
                         (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
                  fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
                  fs_output_semantic_index[fs_num_outputs] = numColors;
                  outputMapping[attr] = fs_num_outputs;
                  numColors++;
                  break;
               }

               fs_num_outputs++;
            }
         }
      }

      ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
      if (ureg == NULL)
         return NULL;

      if (ST_DEBUG & DEBUG_MESA) {
         _mesa_print_program(&stfp->Base.Base);
         _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
         debug_printf("\n");
      }
      if (write_all == GL_TRUE)
         ureg_property_fs_color0_writes_all_cbufs(ureg, 1);

      error = st_translate_mesa_program(st->ctx,
                                        TGSI_PROCESSOR_FRAGMENT,
                                        ureg,
                                        &stfp->Base.Base,
                                        /* inputs */
                                        fs_num_inputs,
                                        inputMapping,
                                        input_semantic_name,
                                        input_semantic_index,
                                        interpMode,
                                        /* outputs */
                                        fs_num_outputs,
                                        outputMapping,
                                        fs_output_semantic_name,
                                        fs_output_semantic_index, FALSE );

      stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
      ureg_destroy( ureg );
   }

   /* fill in variant */
   variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
   variant->key = *key;

   if (ST_DEBUG & DEBUG_TGSI) {
      tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
      debug_printf("\n");
   }

   if (deleteFP) {
      /* Free the temporary program made above */
      struct gl_fragment_program *fp = &stfp->Base;
      _mesa_reference_fragprog(st->ctx, &fp, NULL);
   }

   return variant;
}
Esempio n. 13
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
}
Esempio n. 14
0
File: state.c Progetto: 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;
}
Esempio n. 15
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);
}