Beispiel #1
0
/**
 * Init context's vertex/fragment program state
 */
void
_mesa_init_program(struct gl_context *ctx)
{
   /*
    * If this assertion fails, we need to increase the field
    * size for register indexes (see INST_INDEX_BITS).
    */
   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents / 4
          <= (1 << INST_INDEX_BITS));
   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents / 4
          <= (1 << INST_INDEX_BITS));

   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps <= (1 << INST_INDEX_BITS));
   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= (1 << INST_INDEX_BITS));
   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTemps <= (1 << INST_INDEX_BITS));
   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= (1 << INST_INDEX_BITS));

   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents <= 4 * MAX_UNIFORMS);
   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents <= 4 * MAX_UNIFORMS);

   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxAddressOffset <= (1 << INST_INDEX_BITS));
   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAddressOffset <= (1 << INST_INDEX_BITS));

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

   /* If this fails, increase prog_instruction::TexSrcTarget size */
   STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4));

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

   ctx->VertexProgram.Enabled = GL_FALSE;
   ctx->VertexProgram.PointSizeEnabled =
      (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
   _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
                           ctx->Shared->DefaultVertexProgram);
   assert(ctx->VertexProgram.Current);
   ctx->VertexProgram.Cache = _mesa_new_program_cache();

   ctx->FragmentProgram.Enabled = GL_FALSE;
   _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
                           ctx->Shared->DefaultFragmentProgram);
   assert(ctx->FragmentProgram.Current);
   ctx->FragmentProgram.Cache = _mesa_new_program_cache();

   /* XXX probably move this stuff */
   ctx->ATIFragmentShader.Enabled = GL_FALSE;
   ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
   assert(ctx->ATIFragmentShader.Current);
   ctx->ATIFragmentShader.Current->RefCount++;
}
Beispiel #2
0
/**
 * Delete a shader object.
 */
void
_mesa_delete_linked_shader(struct gl_context *ctx,
                           struct gl_linked_shader *sh)
{
   _mesa_reference_program(ctx, &sh->Program, NULL);
   ralloc_free(sh);
}
Beispiel #3
0
/**
 * Delete a shader object.
 * Called via ctx->Driver.DeleteShader().
 */
static void
_mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh)
{
   free((void *)sh->Source);
   _mesa_reference_program(ctx, &sh->Program, NULL);
   ralloc_free(sh);
}
Beispiel #4
0
void
st_delete_program(GLcontext *ctx, struct gl_program *prog)
{
   struct st_context *st = st_context(ctx);

   switch( prog->Target ) {
   case GL_VERTEX_PROGRAM_ARB:
      {
         struct st_vertex_program *stvp = (struct st_vertex_program *) prog;

         if (stvp->driver_shader) {
            cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
            stvp->driver_shader = NULL;
         }

         if (stvp->draw_shader) {
#if FEATURE_feedback || FEATURE_drawpix
            /* this would only have been allocated for the RasterPos path */
            draw_delete_vertex_shader(st->draw, stvp->draw_shader);
            stvp->draw_shader = NULL;
#endif
         }

         if (stvp->state.tokens) {
            st_free_tokens(stvp->state.tokens);
            stvp->state.tokens = NULL;
         }
      }
      break;
   case GL_FRAGMENT_PROGRAM_ARB:
      {
         struct st_fragment_program *stfp = (struct st_fragment_program *) prog;

         if (stfp->driver_shader) {
            cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
            stfp->driver_shader = NULL;
         }
         
         if (stfp->state.tokens) {
            st_free_tokens(stfp->state.tokens);
            stfp->state.tokens = NULL;
         }

         if (stfp->bitmap_program) {
            struct gl_program *prg = &stfp->bitmap_program->Base.Base;
            _mesa_reference_program(ctx, &prg, NULL);
            stfp->bitmap_program = NULL;
         }

         st_free_translated_vertex_programs(st, stfp->vertex_programs);
      }
      break;
   default:
      assert(0); /* problem */
   }

   /* delete base class */
   _mesa_delete_program( ctx, prog );
}
Beispiel #5
0
/**
 * Free a context's vertex/fragment program state
 */
void
_mesa_free_program_data(struct gl_context *ctx)
{
   _mesa_reference_program(ctx, &ctx->VertexProgram.Current, NULL);
   _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
   _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, NULL);
   _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);

   /* XXX probably move this stuff */
   if (ctx->ATIFragmentShader.Current) {
      ctx->ATIFragmentShader.Current->RefCount--;
      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
         free(ctx->ATIFragmentShader.Current);
      }
   }

   free((void *) ctx->Program.ErrorString);
}
Beispiel #6
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(struct gl_context *ctx)
{
   _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
                           ctx->Shared->DefaultVertexProgram);
   assert(ctx->VertexProgram.Current);

   _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
                            ctx->Shared->DefaultFragmentProgram);
   assert(ctx->FragmentProgram.Current);

   /* XXX probably move this stuff */
   if (ctx->ATIFragmentShader.Current) {
      ctx->ATIFragmentShader.Current->RefCount--;
      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
         free(ctx->ATIFragmentShader.Current);
      }
   }
   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
   assert(ctx->ATIFragmentShader.Current);
   ctx->ATIFragmentShader.Current->RefCount++;
}
Beispiel #7
0
/**
 * Delete a list of programs.
 * \note Not compiled into display lists.
 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
 */
void GLAPIENTRY 
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (n < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
      return;
   }

   for (i = 0; i < n; i++) {
      if (ids[i] != 0) {
         struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
         if (prog == &_mesa_DummyProgram) {
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
         }
         else if (prog) {
            /* Unbind program if necessary */
            if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */
                prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
               if (ctx->VertexProgram.Current &&
                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgram(prog->Target, 0);
               }
            }
            else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
                     prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
               if (ctx->FragmentProgram.Current &&
                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgram(prog->Target, 0);
               }
            }
            else {
               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
               return;
            }
            /* The ID is immediately available for re-use now */
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
            _mesa_reference_program(ctx, &prog, NULL);
         }
      }
   }
}
Beispiel #8
0
/**
 * Delete a list of programs.
 * \note Not compiled into display lists.
 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
 */
void GLAPIENTRY 
_mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

   FLUSH_VERTICES(ctx, 0);

   if (n < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
      return;
   }

   for (i = 0; i < n; i++) {
      if (ids[i] != 0) {
         struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
         if (prog == &_mesa_DummyProgram) {
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
         }
         else if (prog) {
            /* Unbind program if necessary */
            switch (prog->Target) {
            case GL_VERTEX_PROGRAM_ARB:
               if (ctx->VertexProgram.Current &&
                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgramARB(prog->Target, 0);
               }
               break;
            case GL_FRAGMENT_PROGRAM_ARB:
               if (ctx->FragmentProgram.Current &&
                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgramARB(prog->Target, 0);
               }
               break;
            default:
               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
               return;
            }
            /* The ID is immediately available for re-use now */
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
            _mesa_reference_program(ctx, &prog, NULL);
         }
      }
   }
}
void r300TranslateFragmentShader(r300ContextPtr r300,
				 struct r300_fragment_program *fp)
{
	struct r300_fragment_program_external_state state;

	build_state(r300, fp, &state);
	if (_mesa_memcmp(&fp->state, &state, sizeof(state))) {
		/* TODO: cache compiled programs */
		fp->translated = GL_FALSE;
		_mesa_memcpy(&fp->state, &state, sizeof(state));
	}

	if (!fp->translated) {
		struct r300_fragment_program_compiler compiler;

		compiler.r300 = r300;
		compiler.fp = fp;
		compiler.code = &fp->code;
		compiler.program = _mesa_clone_program(r300->radeon.glCtx, &fp->mesa_program.Base);

		if (RADEON_DEBUG & DEBUG_PIXEL) {
			_mesa_printf("Fragment Program: Initial program:\n");
			_mesa_print_program(compiler.program);
		}

		insert_WPOS_trailer(&compiler);

		struct radeon_program_transformation transformations[] = {
			{ &transform_TEX, &compiler },
			{ &radeonTransformALU, 0 },
			{ &radeonTransformTrigSimple, 0 }
		};
		radeonLocalTransform(
			r300->radeon.glCtx,
			compiler.program,
			3, transformations);

		if (RADEON_DEBUG & DEBUG_PIXEL) {
			_mesa_printf("Fragment Program: After native rewrite:\n");
			_mesa_print_program(compiler.program);
		}

		struct radeon_nqssadce_descr nqssadce = {
			.Init = &nqssadce_init,
			.IsNativeSwizzle = &r300FPIsNativeSwizzle,
			.BuildSwizzle = &r300FPBuildSwizzle,
			.RewriteDepthOut = GL_TRUE
		};
		radeonNqssaDce(r300->radeon.glCtx, compiler.program, &nqssadce);

		if (RADEON_DEBUG & DEBUG_PIXEL) {
			_mesa_printf("Compiler: after NqSSA-DCE:\n");
			_mesa_print_program(compiler.program);
		}

		if (!r300FragmentProgramEmit(&compiler))
			fp->error = GL_TRUE;

		/* Subtle: Rescue any parameters that have been added during transformations */
		_mesa_free_parameter_list(fp->mesa_program.Base.Parameters);
		fp->mesa_program.Base.Parameters = compiler.program->Parameters;
		compiler.program->Parameters = 0;

		_mesa_reference_program(r300->radeon.glCtx, &compiler.program, NULL);

		if (!fp->error)
			fp->translated = GL_TRUE;
		if (fp->error || (RADEON_DEBUG & DEBUG_PIXEL))
			r300FragmentProgramDump(fp, &fp->code);
		r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM);
	}

	update_params(r300, fp);
}
Beispiel #10
0
/**
 * Return a copy of a program.
 * XXX Problem here if the program object is actually OO-derivation
 * made by a device driver.
 */
struct gl_program *
_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog)
{
   struct gl_program *clone;

   clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
   if (!clone)
      return NULL;

   assert(clone->Target == prog->Target);
   assert(clone->RefCount == 1);

   clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
   clone->Format = prog->Format;
   clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
   if (!clone->Instructions) {
      _mesa_reference_program(ctx, &clone, NULL);
      return NULL;
   }
   _mesa_copy_instructions(clone->Instructions, prog->Instructions,
                           prog->NumInstructions);
   clone->InputsRead = prog->InputsRead;
   clone->OutputsWritten = prog->OutputsWritten;
   clone->SamplersUsed = prog->SamplersUsed;
   clone->ShadowSamplers = prog->ShadowSamplers;
   memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));

   if (prog->Parameters)
      clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
   memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
   if (prog->Varying)
      clone->Varying = _mesa_clone_parameter_list(prog->Varying);
   if (prog->Attributes)
      clone->Attributes = _mesa_clone_parameter_list(prog->Attributes);
   memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
   clone->NumInstructions = prog->NumInstructions;
   clone->NumTemporaries = prog->NumTemporaries;
   clone->NumParameters = prog->NumParameters;
   clone->NumAttributes = prog->NumAttributes;
   clone->NumAddressRegs = prog->NumAddressRegs;
   clone->NumNativeInstructions = prog->NumNativeInstructions;
   clone->NumNativeTemporaries = prog->NumNativeTemporaries;
   clone->NumNativeParameters = prog->NumNativeParameters;
   clone->NumNativeAttributes = prog->NumNativeAttributes;
   clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
   clone->NumAluInstructions = prog->NumAluInstructions;
   clone->NumTexInstructions = prog->NumTexInstructions;
   clone->NumTexIndirections = prog->NumTexIndirections;
   clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
   clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
   clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;

   switch (prog->Target) {
   case GL_VERTEX_PROGRAM_ARB:
      {
         const struct gl_vertex_program *vp
            = (const struct gl_vertex_program *) prog;
         struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone;
         vpc->IsPositionInvariant = vp->IsPositionInvariant;
      }
      break;
   case GL_FRAGMENT_PROGRAM_ARB:
      {
         const struct gl_fragment_program *fp
            = (const struct gl_fragment_program *) prog;
         struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
         fpc->FogOption = fp->FogOption;
         fpc->UsesKill = fp->UsesKill;
      }
      break;
   default:
      _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
   }

   return clone;
}
Beispiel #11
0
/**
 * Update the ctx->*Program._Current pointers to point to the
 * current/active programs.
 *
 * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment
 * programs or programs derived from fixed-function state.
 *
 * This function needs to be called after texture state validation in case
 * we're generating a fragment program from fixed-function texture state.
 *
 * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex
 * or fragment program is being used.
 */
static GLbitfield
update_program(struct gl_context *ctx)
{
   struct gl_program *vsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
   struct gl_program *tcsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
   struct gl_program *tesProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
   struct gl_program *gsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
   struct gl_program *fsProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
   struct gl_program *csProg =
      ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
   const struct gl_program *prevVP = ctx->VertexProgram._Current;
   const struct gl_program *prevFP = ctx->FragmentProgram._Current;
   const struct gl_program *prevGP = ctx->GeometryProgram._Current;
   const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current;
   const struct gl_program *prevTEP = ctx->TessEvalProgram._Current;
   const struct gl_program *prevCP = ctx->ComputeProgram._Current;

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

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

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

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

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

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

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

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

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

   return 0;
}
Beispiel #12
0
/**
 * Return a copy of a program.
 * XXX Problem here if the program object is actually OO-derivation
 * made by a device driver.
 */
struct gl_program *
_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
{
   struct gl_program *clone;

   clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
   if (!clone)
      return NULL;

   assert(clone->Target == prog->Target);
   assert(clone->RefCount == 1);

   clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
   clone->Format = prog->Format;
   clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
   if (!clone->Instructions) {
      _mesa_reference_program(ctx, &clone, NULL);
      return NULL;
   }
   _mesa_copy_instructions(clone->Instructions, prog->Instructions,
                           prog->NumInstructions);
   clone->InputsRead = prog->InputsRead;
   clone->OutputsWritten = prog->OutputsWritten;
   clone->SamplersUsed = prog->SamplersUsed;
   clone->ShadowSamplers = prog->ShadowSamplers;
   memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));

   if (prog->Parameters)
      clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
   memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
   memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
   clone->IndirectRegisterFiles = prog->IndirectRegisterFiles;
   clone->NumInstructions = prog->NumInstructions;
   clone->NumTemporaries = prog->NumTemporaries;
   clone->NumParameters = prog->NumParameters;
   clone->NumAttributes = prog->NumAttributes;
   clone->NumAddressRegs = prog->NumAddressRegs;
   clone->NumNativeInstructions = prog->NumNativeInstructions;
   clone->NumNativeTemporaries = prog->NumNativeTemporaries;
   clone->NumNativeParameters = prog->NumNativeParameters;
   clone->NumNativeAttributes = prog->NumNativeAttributes;
   clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
   clone->NumAluInstructions = prog->NumAluInstructions;
   clone->NumTexInstructions = prog->NumTexInstructions;
   clone->NumTexIndirections = prog->NumTexIndirections;
   clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
   clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
   clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;

   switch (prog->Target) {
   case GL_VERTEX_PROGRAM_ARB:
      {
         const struct gl_vertex_program *vp = gl_vertex_program_const(prog);
         struct gl_vertex_program *vpc = gl_vertex_program(clone);
         vpc->IsPositionInvariant = vp->IsPositionInvariant;
         vpc->IsNVProgram = vp->IsNVProgram;
      }
      break;
   case GL_FRAGMENT_PROGRAM_ARB:
      {
         const struct gl_fragment_program *fp = gl_fragment_program_const(prog);
         struct gl_fragment_program *fpc = gl_fragment_program(clone);
         fpc->UsesKill = fp->UsesKill;
         fpc->UsesDFdy = fp->UsesDFdy;
         fpc->OriginUpperLeft = fp->OriginUpperLeft;
         fpc->PixelCenterInteger = fp->PixelCenterInteger;
      }
      break;
   case MESA_GEOMETRY_PROGRAM:
      {
         const struct gl_geometry_program *gp = gl_geometry_program_const(prog);
         struct gl_geometry_program *gpc = gl_geometry_program(clone);
         gpc->VerticesOut = gp->VerticesOut;
         gpc->InputType = gp->InputType;
         gpc->OutputType = gp->OutputType;
      }
      break;
   default:
      _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
   }

   return clone;
}