Ejemplo n.º 1
0
static void
create_new_program( const struct state_key *key,
                    struct gl_vertex_program *program,
                    GLboolean mvp_with_dp4,
                    GLuint max_temps)
{
   struct tnl_program p;

   memset(&p, 0, sizeof(p));
   p.state = key;
   p.program = program;
   p.eye_position = undef;
   p.eye_position_z = undef;
   p.eye_position_normalized = undef;
   p.transformed_normal = undef;
   p.identity = undef;
   p.temp_in_use = 0;
   p.mvp_with_dp4 = mvp_with_dp4;

   if (max_temps >= sizeof(int) * 8)
      p.temp_reserved = 0;
   else
      p.temp_reserved = ~((1<<max_temps)-1);

   /* Start by allocating 32 instructions.
    * If we need more, we'll grow the instruction array as needed.
    */
   p.max_inst = 32;
   p.program->Base.Instructions = _mesa_alloc_instructions(p.max_inst);
   p.program->Base.String = NULL;
   p.program->Base.NumInstructions =
   p.program->Base.NumTemporaries =
   p.program->Base.NumParameters =
   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
   p.program->Base.Parameters = _mesa_new_parameter_list();
   p.program->Base.InputsRead = 0;
   p.program->Base.OutputsWritten = 0;

   build_tnl_program( &p );
}
Ejemplo n.º 2
0
/**
 * Combine two programs into one.  Fix instructions so the outputs of
 * the first program go to the inputs of the second program.
 */
struct gl_program *
_mesa_combine_programs(GLcontext *ctx,
                       const struct gl_program *progA,
                       const struct gl_program *progB)
{
   struct prog_instruction *newInst;
   struct gl_program *newProg;
   const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
   const GLuint lenB = progB->NumInstructions;
   const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
   const GLuint newLength = lenA + lenB;
   GLbitfield inputsB;
   GLuint i;

   ASSERT(progA->Target == progB->Target);

   newInst = _mesa_alloc_instructions(newLength);
   if (!newInst)
      return GL_FALSE;

   _mesa_copy_instructions(newInst, progA->Instructions, lenA);
   _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);

   /* adjust branch / instruction addresses for B's instructions */
   for (i = 0; i < lenB; i++) {
      newInst[lenA + i].BranchTarget += lenA;
   }

   newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
   newProg->Instructions = newInst;
   newProg->NumInstructions = newLength;

   if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
      struct gl_fragment_program *fprogA, *fprogB, *newFprog;
      fprogA = (struct gl_fragment_program *) progA;
      fprogB = (struct gl_fragment_program *) progB;
      newFprog = (struct gl_fragment_program *) newProg;

      newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;

      /* Connect color outputs of fprogA to color inputs of fprogB, via a
       * new temporary register.
       */
      if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) &&
          (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) {
         GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY);
         if (tempReg < 0) {
            _mesa_problem(ctx, "No free temp regs found in "
                          "_mesa_combine_programs(), using 31");
            tempReg = 31;
         }
         /* replace writes to result.color[0] with tempReg */
         replace_registers(newInst, lenA,
                           PROGRAM_OUTPUT, FRAG_RESULT_COLR,
                           PROGRAM_TEMPORARY, tempReg);
         /* replace reads from input.color[0] with tempReg */
         replace_registers(newInst + lenA, lenB,
                           PROGRAM_INPUT, FRAG_ATTRIB_COL0,
                           PROGRAM_TEMPORARY, tempReg);
      }

      inputsB = progB->InputsRead;
      if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) {
         inputsB &= ~(1 << FRAG_ATTRIB_COL0);
      }
      newProg->InputsRead = progA->InputsRead | inputsB;
      newProg->OutputsWritten = progB->OutputsWritten;
      newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
   }
   else {
      /* vertex program */
      assert(0);      /* XXX todo */
   }

   /*
    * Merge parameters (uniforms, constants, etc)
    */
   newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
                                                       progB->Parameters);

   adjust_param_indexes(newInst + lenA, lenB, numParamsA);


   return newProg;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
/**
 * This function inserts instructions for coordinate modelview * projection
 * into a vertex program.
 * May be used to implement the position_invariant option.
 */
static void
_mesa_insert_mvp_dp4_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
{
    struct prog_instruction *newInst;
    const GLuint origLen = vprog->Base.NumInstructions;
    const GLuint newLen = origLen + 4;
    GLuint i;

    /*
     * Setup state references for the modelview/projection matrix.
     * XXX we should check if these state vars are already declared.
     */
    static const gl_state_index mvpState[4][STATE_LENGTH] = {
        { STATE_MVP_MATRIX, 0, 0, 0, 0 },  /* state.matrix.mvp.row[0] */
        { STATE_MVP_MATRIX, 0, 1, 1, 0 },  /* state.matrix.mvp.row[1] */
        { STATE_MVP_MATRIX, 0, 2, 2, 0 },  /* state.matrix.mvp.row[2] */
        { STATE_MVP_MATRIX, 0, 3, 3, 0 },  /* state.matrix.mvp.row[3] */
    };
    GLint mvpRef[4];

    for (i = 0; i < 4; i++) {
        mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters,
                                              mvpState[i]);
    }

    /* Alloc storage for new instructions */
    newInst = _mesa_alloc_instructions(newLen);
    if (!newInst) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY,
                    "glProgramString(inserting position_invariant code)");
        return;
    }

    /*
     * Generated instructions:
     * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position;
     * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position;
     * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position;
     * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position;
     */
    _mesa_init_instructions(newInst, 4);
    for (i = 0; i < 4; i++) {
        newInst[i].Opcode = OPCODE_DP4;
        newInst[i].DstReg.File = PROGRAM_OUTPUT;
        newInst[i].DstReg.Index = VARYING_SLOT_POS;
        newInst[i].DstReg.WriteMask = (WRITEMASK_X << i);
        newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR;
        newInst[i].SrcReg[0].Index = mvpRef[i];
        newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
        newInst[i].SrcReg[1].File = PROGRAM_INPUT;
        newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS;
        newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
    }

    /* Append original instructions after new instructions */
    _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen);

    /* free old instructions */
    _mesa_free_instructions(vprog->Base.Instructions, origLen);

    /* install new instructions */
    vprog->Base.Instructions = newInst;
    vprog->Base.NumInstructions = newLen;
    vprog->Base.InputsRead |= VERT_BIT_POS;
    vprog->Base.OutputsWritten |= BITFIELD64_BIT(VARYING_SLOT_POS);
}
Ejemplo n.º 5
0
/**
 * Append instructions to implement fog
 *
 * The \c fragment.fogcoord input is used to compute the fog blend factor.
 *
 * \param ctx      The GL context
 * \param fprog    Fragment program that fog instructions will be appended to.
 * \param fog_mode Fog mode.  One of \c GL_EXP, \c GL_EXP2, or \c GL_LINEAR.
 * \param saturate True if writes to color outputs should be clamped to [0, 1]
 *
 * \note
 * This function sets \c VARYING_BIT_FOGC in \c fprog->Base.InputsRead.
 *
 * \todo With a little work, this function could be adapted to add fog code
 * to vertex programs too.
 */
void
_mesa_append_fog_code(struct gl_context *ctx,
                      struct gl_fragment_program *fprog, GLenum fog_mode,
                      GLboolean saturate)
{
    static const gl_state_index fogPStateOpt[STATE_LENGTH]
        = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
    static const gl_state_index fogColorState[STATE_LENGTH]
        = { STATE_FOG_COLOR, 0, 0, 0, 0};
    struct prog_instruction *newInst, *inst;
    const GLuint origLen = fprog->Base.NumInstructions;
    const GLuint newLen = origLen + 5;
    GLuint i;
    GLint fogPRefOpt, fogColorRef; /* state references */
    GLuint colorTemp, fogFactorTemp; /* temporary registerss */

    if (fog_mode == GL_NONE) {
        _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program"
                      " with fog_mode == GL_NONE");
        return;
    }

    if (!(fprog->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR))) {
        /* program doesn't output color, so nothing to do */
        return;
    }

    /* Alloc storage for new instructions */
    newInst = _mesa_alloc_instructions(newLen);
    if (!newInst) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY,
                    "glProgramString(inserting fog_option code)");
        return;
    }

    /* Copy orig instructions into new instruction buffer */
    _mesa_copy_instructions(newInst, fprog->Base.Instructions, origLen);

    /* PARAM fogParamsRefOpt = internal optimized fog params; */
    fogPRefOpt
        = _mesa_add_state_reference(fprog->Base.Parameters, fogPStateOpt);
    /* PARAM fogColorRef = state.fog.color; */
    fogColorRef
        = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState);

    /* TEMP colorTemp; */
    colorTemp = fprog->Base.NumTemporaries++;
    /* TEMP fogFactorTemp; */
    fogFactorTemp = fprog->Base.NumTemporaries++;

    /* Scan program to find where result.color is written */
    inst = newInst;
    for (i = 0; i < fprog->Base.NumInstructions; i++) {
        if (inst->Opcode == OPCODE_END)
            break;
        if (inst->DstReg.File == PROGRAM_OUTPUT &&
                inst->DstReg.Index == FRAG_RESULT_COLOR) {
            /* change the instruction to write to colorTemp w/ clamping */
            inst->DstReg.File = PROGRAM_TEMPORARY;
            inst->DstReg.Index = colorTemp;
            inst->SaturateMode = saturate;
            /* don't break (may be several writes to result.color) */
        }
        inst++;
    }
    assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */

    _mesa_init_instructions(inst, 5);

    /* emit instructions to compute fog blending factor */
    /* this is always clamped to [0, 1] regardless of fragment clamping */
    if (fog_mode == GL_LINEAR) {
        /* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */
        inst->Opcode = OPCODE_MAD;
        inst->DstReg.File = PROGRAM_TEMPORARY;
        inst->DstReg.Index = fogFactorTemp;
        inst->DstReg.WriteMask = WRITEMASK_X;
        inst->SrcReg[0].File = PROGRAM_INPUT;
        inst->SrcReg[0].Index = VARYING_SLOT_FOGC;
        inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
        inst->SrcReg[1].File = PROGRAM_STATE_VAR;
        inst->SrcReg[1].Index = fogPRefOpt;
        inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
        inst->SrcReg[2].File = PROGRAM_STATE_VAR;
        inst->SrcReg[2].Index = fogPRefOpt;
        inst->SrcReg[2].Swizzle = SWIZZLE_YYYY;
        inst->SaturateMode = SATURATE_ZERO_ONE;
        inst++;
    }
    else {
        ASSERT(fog_mode == GL_EXP || fog_mode == GL_EXP2);
        /* fogPRefOpt.z = d/ln(2), fogPRefOpt.w = d/sqrt(ln(2) */
        /* EXP: MUL fogFactorTemp.x, fogPRefOpt.z, fragment.fogcoord.x; */
        /* EXP2: MUL fogFactorTemp.x, fogPRefOpt.w, fragment.fogcoord.x; */
        inst->Opcode = OPCODE_MUL;
        inst->DstReg.File = PROGRAM_TEMPORARY;
        inst->DstReg.Index = fogFactorTemp;
        inst->DstReg.WriteMask = WRITEMASK_X;
        inst->SrcReg[0].File = PROGRAM_STATE_VAR;
        inst->SrcReg[0].Index = fogPRefOpt;
        inst->SrcReg[0].Swizzle
            = (fog_mode == GL_EXP) ? SWIZZLE_ZZZZ : SWIZZLE_WWWW;
        inst->SrcReg[1].File = PROGRAM_INPUT;
        inst->SrcReg[1].Index = VARYING_SLOT_FOGC;
        inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
        inst++;
        if (fog_mode == GL_EXP2) {
            /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */
            inst->Opcode = OPCODE_MUL;
            inst->DstReg.File = PROGRAM_TEMPORARY;
            inst->DstReg.Index = fogFactorTemp;
            inst->DstReg.WriteMask = WRITEMASK_X;
            inst->SrcReg[0].File = PROGRAM_TEMPORARY;
            inst->SrcReg[0].Index = fogFactorTemp;
            inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
            inst->SrcReg[1].File = PROGRAM_TEMPORARY;
            inst->SrcReg[1].Index = fogFactorTemp;
            inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
            inst++;
        }
        /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */
        inst->Opcode = OPCODE_EX2;
        inst->DstReg.File = PROGRAM_TEMPORARY;
        inst->DstReg.Index = fogFactorTemp;
        inst->DstReg.WriteMask = WRITEMASK_X;
        inst->SrcReg[0].File = PROGRAM_TEMPORARY;
        inst->SrcReg[0].Index = fogFactorTemp;
        inst->SrcReg[0].Negate = NEGATE_XYZW;
        inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
        inst->SaturateMode = SATURATE_ZERO_ONE;
        inst++;
    }
    /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */
    inst->Opcode = OPCODE_LRP;
    inst->DstReg.File = PROGRAM_OUTPUT;
    inst->DstReg.Index = FRAG_RESULT_COLOR;
    inst->DstReg.WriteMask = WRITEMASK_XYZ;
    inst->SrcReg[0].File = PROGRAM_TEMPORARY;
    inst->SrcReg[0].Index = fogFactorTemp;
    inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
    inst->SrcReg[1].File = PROGRAM_TEMPORARY;
    inst->SrcReg[1].Index = colorTemp;
    inst->SrcReg[1].Swizzle = SWIZZLE_NOOP;
    inst->SrcReg[2].File = PROGRAM_STATE_VAR;
    inst->SrcReg[2].Index = fogColorRef;
    inst->SrcReg[2].Swizzle = SWIZZLE_NOOP;
    inst++;
    /* MOV result.color.w, colorTemp.x;  # copy alpha */
    inst->Opcode = OPCODE_MOV;
    inst->DstReg.File = PROGRAM_OUTPUT;
    inst->DstReg.Index = FRAG_RESULT_COLOR;
    inst->DstReg.WriteMask = WRITEMASK_W;
    inst->SrcReg[0].File = PROGRAM_TEMPORARY;
    inst->SrcReg[0].Index = colorTemp;
    inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
    inst++;
    /* END; */
    inst->Opcode = OPCODE_END;
    inst++;

    /* free old instructions */
    _mesa_free_instructions(fprog->Base.Instructions, origLen);

    /* install new instructions */
    fprog->Base.Instructions = newInst;
    fprog->Base.NumInstructions = inst - newInst;
    fprog->Base.InputsRead |= VARYING_BIT_FOGC;
    assert(fprog->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR));
}
Ejemplo n.º 6
0
static void
_mesa_insert_mvp_mad_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
{
    struct prog_instruction *newInst;
    const GLuint origLen = vprog->Base.NumInstructions;
    const GLuint newLen = origLen + 4;
    GLuint hposTemp;
    GLuint i;

    /*
     * Setup state references for the modelview/projection matrix.
     * XXX we should check if these state vars are already declared.
     */
    static const gl_state_index mvpState[4][STATE_LENGTH] = {
        { STATE_MVP_MATRIX, 0, 0, 0, STATE_MATRIX_TRANSPOSE },
        { STATE_MVP_MATRIX, 0, 1, 1, STATE_MATRIX_TRANSPOSE },
        { STATE_MVP_MATRIX, 0, 2, 2, STATE_MATRIX_TRANSPOSE },
        { STATE_MVP_MATRIX, 0, 3, 3, STATE_MATRIX_TRANSPOSE },
    };
    GLint mvpRef[4];

    for (i = 0; i < 4; i++) {
        mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters,
                                              mvpState[i]);
    }

    /* Alloc storage for new instructions */
    newInst = _mesa_alloc_instructions(newLen);
    if (!newInst) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY,
                    "glProgramString(inserting position_invariant code)");
        return;
    }

    /* TEMP hposTemp; */
    hposTemp = vprog->Base.NumTemporaries++;

    /*
     * Generated instructions:
     *    emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
     *    emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
     *    emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
     *    emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
     */
    _mesa_init_instructions(newInst, 4);

    newInst[0].Opcode = OPCODE_MUL;
    newInst[0].DstReg.File = PROGRAM_TEMPORARY;
    newInst[0].DstReg.Index = hposTemp;
    newInst[0].DstReg.WriteMask = WRITEMASK_XYZW;
    newInst[0].SrcReg[0].File = PROGRAM_INPUT;
    newInst[0].SrcReg[0].Index = VERT_ATTRIB_POS;
    newInst[0].SrcReg[0].Swizzle = SWIZZLE_XXXX;
    newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR;
    newInst[0].SrcReg[1].Index = mvpRef[0];
    newInst[0].SrcReg[1].Swizzle = SWIZZLE_NOOP;

    for (i = 1; i <= 2; i++) {
        newInst[i].Opcode = OPCODE_MAD;
        newInst[i].DstReg.File = PROGRAM_TEMPORARY;
        newInst[i].DstReg.Index = hposTemp;
        newInst[i].DstReg.WriteMask = WRITEMASK_XYZW;
        newInst[i].SrcReg[0].File = PROGRAM_INPUT;
        newInst[i].SrcReg[0].Index = VERT_ATTRIB_POS;
        newInst[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(i,i,i,i);
        newInst[i].SrcReg[1].File = PROGRAM_STATE_VAR;
        newInst[i].SrcReg[1].Index = mvpRef[i];
        newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
        newInst[i].SrcReg[2].File = PROGRAM_TEMPORARY;
        newInst[i].SrcReg[2].Index = hposTemp;
        newInst[1].SrcReg[2].Swizzle = SWIZZLE_NOOP;
    }

    newInst[3].Opcode = OPCODE_MAD;
    newInst[3].DstReg.File = PROGRAM_OUTPUT;
    newInst[3].DstReg.Index = VARYING_SLOT_POS;
    newInst[3].DstReg.WriteMask = WRITEMASK_XYZW;
    newInst[3].SrcReg[0].File = PROGRAM_INPUT;
    newInst[3].SrcReg[0].Index = VERT_ATTRIB_POS;
    newInst[3].SrcReg[0].Swizzle = SWIZZLE_WWWW;
    newInst[3].SrcReg[1].File = PROGRAM_STATE_VAR;
    newInst[3].SrcReg[1].Index = mvpRef[3];
    newInst[3].SrcReg[1].Swizzle = SWIZZLE_NOOP;
    newInst[3].SrcReg[2].File = PROGRAM_TEMPORARY;
    newInst[3].SrcReg[2].Index = hposTemp;
    newInst[3].SrcReg[2].Swizzle = SWIZZLE_NOOP;


    /* Append original instructions after new instructions */
    _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen);

    /* free old instructions */
    _mesa_free_instructions(vprog->Base.Instructions, origLen);

    /* install new instructions */
    vprog->Base.Instructions = newInst;
    vprog->Base.NumInstructions = newLen;
    vprog->Base.InputsRead |= VERT_BIT_POS;
    vprog->Base.OutputsWritten |= BITFIELD64_BIT(VARYING_SLOT_POS);
}
Ejemplo n.º 7
0
/**
 * Combine two programs into one.  Fix instructions so the outputs of
 * the first program go to the inputs of the second program.
 */
struct gl_program *
_mesa_combine_programs(struct gl_context *ctx,
                       const struct gl_program *progA,
                       const struct gl_program *progB)
{
   struct prog_instruction *newInst;
   struct gl_program *newProg;
   const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
   const GLuint lenB = progB->NumInstructions;
   const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
   const GLuint newLength = lenA + lenB;
   GLboolean usedTemps[MAX_PROGRAM_TEMPS];
   GLuint firstTemp = 0;
   GLbitfield inputsB;
   GLuint i;

   ASSERT(progA->Target == progB->Target);

   newInst = _mesa_alloc_instructions(newLength);
   if (!newInst)
      return GL_FALSE;

   _mesa_copy_instructions(newInst, progA->Instructions, lenA);
   _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);

   /* adjust branch / instruction addresses for B's instructions */
   for (i = 0; i < lenB; i++) {
      newInst[lenA + i].BranchTarget += lenA;
   }

   newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
   newProg->Instructions = newInst;
   newProg->NumInstructions = newLength;

   /* find used temp regs (we may need new temps below) */
   _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY,
                             usedTemps, MAX_PROGRAM_TEMPS);

   if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
      struct gl_fragment_program *fprogA, *fprogB, *newFprog;
      GLbitfield progB_inputsRead = progB->InputsRead;
      GLint progB_colorFile, progB_colorIndex;

      fprogA = (struct gl_fragment_program *) progA;
      fprogB = (struct gl_fragment_program *) progB;
      newFprog = (struct gl_fragment_program *) newProg;

      newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;

      /* We'll do a search and replace for instances
       * of progB_colorFile/progB_colorIndex below...
       */
      progB_colorFile = PROGRAM_INPUT;
      progB_colorIndex = FRAG_ATTRIB_COL0;

      /*
       * The fragment program may get color from a state var rather than
       * a fragment input (vertex output) if it's constant.
       * See the texenvprogram.c code.
       * So, search the program's parameter list now to see if the program
       * gets color from a state var instead of a conventional fragment
       * input register.
       */
      for (i = 0; i < progB->Parameters->NumParameters; i++) {
         struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
         if (p->Type == PROGRAM_STATE_VAR &&
             p->StateIndexes[0] == STATE_INTERNAL &&
             p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
             (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) {
            progB_inputsRead |= FRAG_BIT_COL0;
            progB_colorFile = PROGRAM_STATE_VAR;
            progB_colorIndex = i;
            break;
         }
      }

      /* Connect color outputs of fprogA to color inputs of fprogB, via a
       * new temporary register.
       */
      if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) &&
          (progB_inputsRead & FRAG_BIT_COL0)) {
         GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS,
                                                  firstTemp);
         if (tempReg < 0) {
            _mesa_problem(ctx, "No free temp regs found in "
                          "_mesa_combine_programs(), using 31");
            tempReg = 31;
         }
         firstTemp = tempReg + 1;

         /* replace writes to result.color[0] with tempReg */
         replace_registers(newInst, lenA,
                           PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
                           PROGRAM_TEMPORARY, tempReg);
         /* replace reads from the input color with tempReg */
         replace_registers(newInst + lenA, lenB,
                           progB_colorFile, progB_colorIndex, /* search for */
                           PROGRAM_TEMPORARY, tempReg  /* replace with */ );
      }

      /* compute combined program's InputsRead */
      inputsB = progB_inputsRead;
      if (progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
         inputsB &= ~(1 << FRAG_ATTRIB_COL0);
      }
      newProg->InputsRead = progA->InputsRead | inputsB;
      newProg->OutputsWritten = progB->OutputsWritten;
      newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
   }
   else {
      /* vertex program */
      assert(0);      /* XXX todo */
   }

   /*
    * Merge parameters (uniforms, constants, etc)
    */
   newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
                                                       progB->Parameters);

   adjust_param_indexes(newInst + lenA, lenB, numParamsA);


   return newProg;
}
/**
 * Parse/compile the 'str' returning the compiled 'program'.
 * ctx->Program.ErrorPos will be -1 if successful.  Otherwise, ErrorPos
 * indicates the position of the error in 'str'.
 */
void
_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
                              const GLubyte *str, GLsizei len,
                              struct gl_vertex_program *program)
{
   struct parse_state parseState;
   struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
   struct prog_instruction *newInst;
   GLenum target;
   GLubyte *programString;

   /* Make a null-terminated copy of the program string */
   programString = (GLubyte *) MALLOC(len + 1);
   if (!programString) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
      return;
   }
   MEMCPY(programString, str, len);
   programString[len] = 0;

   /* Get ready to parse */
   parseState.ctx = ctx;
   parseState.start = programString;
   parseState.isPositionInvariant = GL_FALSE;
   parseState.isVersion1_1 = GL_FALSE;
   parseState.numInst = 0;
   parseState.inputsRead = 0;
   parseState.outputsWritten = 0;
   parseState.anyProgRegsWritten = GL_FALSE;

   /* Reset error state */
   _mesa_set_program_error(ctx, -1, NULL);

   /* check the program header */
   if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
      target = GL_VERTEX_PROGRAM_NV;
      parseState.pos = programString + 7;
      parseState.isStateProgram = GL_FALSE;
   }
   else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
      target = GL_VERTEX_PROGRAM_NV;
      parseState.pos = programString + 7;
      parseState.isStateProgram = GL_FALSE;
      parseState.isVersion1_1 = GL_TRUE;
   }
   else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
      target = GL_VERTEX_STATE_PROGRAM_NV;
      parseState.pos = programString + 8;
      parseState.isStateProgram = GL_TRUE;
   }
   else {
      /* invalid header */
      ctx->Program.ErrorPos = 0;
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
      return;
   }

   /* make sure target and header match */
   if (target != dstTarget) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glLoadProgramNV(target mismatch)");
      return;
   }


   if (Parse_Program(&parseState, instBuffer)) {
      /* successful parse! */

      if (parseState.isStateProgram) {
         if (!parseState.anyProgRegsWritten) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glLoadProgramNV(c[#] not written)");
            return;
         }
      }
      else {
         if (!parseState.isPositionInvariant &&
             !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) {
            /* bit 1 = HPOS register */
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glLoadProgramNV(HPOS not written)");
            return;
         }
      }

      /* copy the compiled instructions */
      assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS);
      newInst = _mesa_alloc_instructions(parseState.numInst);
      if (!newInst) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
         _mesa_free(programString);
         return;  /* out of memory */
      }
      _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);

      /* install the program */
      program->Base.Target = target;
      if (program->Base.String) {
         _mesa_free(program->Base.String);
      }
      program->Base.String = programString;
      program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
      if (program->Base.Instructions) {
         _mesa_free(program->Base.Instructions);
      }
      program->Base.Instructions = newInst;
      program->Base.InputsRead = parseState.inputsRead;
      if (parseState.isPositionInvariant)
         program->Base.InputsRead |= VERT_BIT_POS;
      program->Base.NumInstructions = parseState.numInst;
      program->Base.OutputsWritten = parseState.outputsWritten;
      program->IsPositionInvariant = parseState.isPositionInvariant;
      program->IsNVProgram = GL_TRUE;

#ifdef DEBUG_foo
      _mesa_printf("--- glLoadProgramNV result ---\n");
      _mesa_print_nv_vertex_program(program);
      _mesa_printf("------------------------------\n");
#endif
   }
   else {
      /* Error! */
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
      /* NOTE: _mesa_set_program_error would have been called already */
      /* GL_NV_vertex_program isn't supposed to set the error string
       * so we reset it here.
       */
      _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
   }
}
Ejemplo n.º 9
0
/**
 * Parse/compile the 'str' returning the compiled 'program'.
 * ctx->Program.ErrorPos will be -1 if successful.  Otherwise, ErrorPos
 * indicates the position of the error in 'str'.
 */
void
_mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum dstTarget,
                                const GLubyte *str, GLsizei len,
                                struct gl_fragment_program *program)
{
   struct parse_state parseState;
   struct prog_instruction instBuffer[MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS];
   struct prog_instruction *newInst;
   GLenum target;
   GLubyte *programString;

   /* Make a null-terminated copy of the program string */
   programString = (GLubyte *) MALLOC(len + 1);
   if (!programString) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
      return;
   }
   memcpy(programString, str, len);
   programString[len] = 0;

   /* Get ready to parse */
   memset(&parseState, 0, sizeof(struct parse_state));
   parseState.ctx = ctx;
   parseState.start = programString;
   parseState.program = program;
   parseState.numInst = 0;
   parseState.curLine = programString;
   parseState.parameters = _mesa_new_parameter_list();

   /* Reset error state */
   _mesa_set_program_error(ctx, -1, NULL);

   /* check the program header */
   if (strncmp((const char *) programString, "!!FP1.0", 7) == 0) {
      target = GL_FRAGMENT_PROGRAM_NV;
      parseState.pos = programString + 7;
   }
   else if (strncmp((const char *) programString, "!!FCP1.0", 8) == 0) {
      /* fragment / register combiner program - not supported */
      _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
      return;
   }
   else {
      /* invalid header */
      _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
      return;
   }

   /* make sure target and header match */
   if (target != dstTarget) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glLoadProgramNV(target mismatch 0x%x != 0x%x)",
                  target, dstTarget);
      return;
   }

   if (Parse_InstructionSequence(&parseState, instBuffer)) {
      GLuint u;
      /* successful parse! */

      if (parseState.outputsWritten == 0) {
         /* must write at least one output! */
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "Invalid fragment program - no outputs written.");
         return;
      }

      /* copy the compiled instructions */
      assert(parseState.numInst <= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS);
      newInst = _mesa_alloc_instructions(parseState.numInst);
      if (!newInst) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
         return;  /* out of memory */
      }
      _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);

      /* install the program */
      program->Base.Target = target;
      if (program->Base.String) {
         FREE(program->Base.String);
      }
      program->Base.String = programString;
      program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
      if (program->Base.Instructions) {
         free(program->Base.Instructions);
      }
      program->Base.Instructions = newInst;
      program->Base.NumInstructions = parseState.numInst;
      program->Base.InputsRead = parseState.inputsRead;
      program->Base.OutputsWritten = parseState.outputsWritten;
      for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
         program->Base.TexturesUsed[u] = parseState.texturesUsed[u];

      /* save program parameters */
      program->Base.Parameters = parseState.parameters;

      /* allocate registers for declared program parameters */
#if 00
      _mesa_assign_program_registers(&(program->SymbolTable));
#endif

#ifdef DEBUG_foo
      printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id);
      _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
      printf("----------------------------------\n");
#endif
   }
   else {
      /* Error! */
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
      /* NOTE: _mesa_set_program_error would have been called already */
   }
}
Ejemplo n.º 10
0
/**
 * Create fragment program that does a TEX() instruction to get a Z and/or
 * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
 * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
 * Pass fragment color through as-is.
 * \return pointer to the gl_fragment program
 */
struct gl_fragment_program *
st_make_drawpix_z_stencil_program(struct st_context *st,
                                  GLboolean write_depth,
                                  GLboolean write_stencil)
{
   struct gl_context *ctx = st->ctx;
   struct gl_program *p;
   struct gl_fragment_program *fp;
   GLuint ic = 0;
   const GLuint shaderIndex = write_depth * 2 + write_stencil;

   assert(shaderIndex < Elements(st->drawpix.shaders));

   if (st->drawpix.shaders[shaderIndex]) {
      /* already have the proper shader */
      return st->drawpix.shaders[shaderIndex];
   }

   /*
    * Create shader now
    */
   p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
   if (!p)
      return NULL;

   p->NumInstructions = write_depth ? 2 : 1;
   p->NumInstructions += write_stencil ? 1 : 0;

   p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
   if (!p->Instructions) {
      ctx->Driver.DeleteProgram(ctx, p);
      return NULL;
   }
   _mesa_init_instructions(p->Instructions, p->NumInstructions);

   if (write_depth) {
      /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
      p->Instructions[ic].Opcode = OPCODE_TEX;
      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
      p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
      p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
      p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
      p->Instructions[ic].TexSrcUnit = 0;
      p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
      ic++;
   }

   if (write_stencil) {
      /* TEX result.stencil, fragment.texcoord[0], texture[0], 2D; */
      p->Instructions[ic].Opcode = OPCODE_TEX;
      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
      p->Instructions[ic].DstReg.Index = FRAG_RESULT_STENCIL;
      p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Y;
      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
      p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
      p->Instructions[ic].TexSrcUnit = 1;
      p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
      ic++;
   }

   /* END; */
   p->Instructions[ic++].Opcode = OPCODE_END;

   assert(ic == p->NumInstructions);

   p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
   p->OutputsWritten = 0;
   if (write_depth)
      p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH);
   if (write_stencil)
      p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL);

   p->SamplersUsed =  0x1;  /* sampler 0 (bit 0) is used */
   if (write_stencil)
      p->SamplersUsed |= 1 << 1;

   fp = (struct gl_fragment_program *) p;

   /* save the new shader */
   st->drawpix.shaders[shaderIndex] = fp;

   return fp;
}
Ejemplo n.º 11
0
/**
 * Returns a fragment program which implements the current pixel transfer ops.
 */
static struct gl_fragment_program *
get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
{
   struct st_context *st = ctx->st;
   struct prog_instruction inst[MAX_INST];
   struct gl_program_parameter_list *params;
   struct gl_fragment_program *fp;
   GLuint ic = 0;
   const GLuint colorTemp = 0;

   fp = (struct gl_fragment_program *)
      ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
   if (!fp)
      return NULL;

   params = _mesa_new_parameter_list();

   /*
    * Get initial pixel color from the texture.
    * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
    */
   _mesa_init_instructions(inst + ic, 1);
   inst[ic].Opcode = OPCODE_TEX;
   inst[ic].DstReg.File = PROGRAM_TEMPORARY;
   inst[ic].DstReg.Index = colorTemp;
   inst[ic].SrcReg[0].File = PROGRAM_INPUT;
   inst[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
   inst[ic].TexSrcUnit = 0;
   inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
   ic++;
   fp->Base.InputsRead = (1 << FRAG_ATTRIB_TEX0);
   fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLR);
   fp->Base.SamplersUsed = 0x1;  /* sampler 0 (bit 0) is used */

   if (key->scaleAndBias) {
      static const gl_state_index scale_state[STATE_LENGTH] =
         { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
      static const gl_state_index bias_state[STATE_LENGTH] =
         { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
      GLfloat scale[4], bias[4];
      GLint scale_p, bias_p;

      scale[0] = ctx->Pixel.RedScale;
      scale[1] = ctx->Pixel.GreenScale;
      scale[2] = ctx->Pixel.BlueScale;
      scale[3] = ctx->Pixel.AlphaScale;
      bias[0] = ctx->Pixel.RedBias;
      bias[1] = ctx->Pixel.GreenBias;
      bias[2] = ctx->Pixel.BlueBias;
      bias[3] = ctx->Pixel.AlphaBias;

      scale_p = _mesa_add_state_reference(params, scale_state);
      bias_p = _mesa_add_state_reference(params, bias_state);

      /* MAD colorTemp, colorTemp, scale, bias; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_MAD;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = colorTemp;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[1].Index = scale_p;
      inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[2].Index = bias_p;
      ic++;
   }

   if (key->pixelMaps) {
      const GLuint temp = 1;

      /* create the colormap/texture now if not already done */
      if (!st->pixel_xfer.pixelmap_texture) {
         st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
      }

      /* with a little effort, we can do four pixel map look-ups with
       * two TEX instructions:
       */

      /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_TEX;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = temp;
      inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].TexSrcUnit = 1;
      inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
      ic++;

      /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_TEX;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = temp;
      inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
                                                 SWIZZLE_Z, SWIZZLE_W);
      inst[ic].TexSrcUnit = 1;
      inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
      ic++;

      /* MOV colorTemp, temp; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_MOV;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = colorTemp;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = temp;
      ic++;

      fp->Base.SamplersUsed |= (1 << 1);  /* sampler 1 is used */
   }

   if (key->colorMatrix) {
      static const gl_state_index row0_state[STATE_LENGTH] =
         { STATE_COLOR_MATRIX, 0, 0, 0, 0 };
      static const gl_state_index row1_state[STATE_LENGTH] =
         { STATE_COLOR_MATRIX, 0, 1, 1, 0 };
      static const gl_state_index row2_state[STATE_LENGTH] =
         { STATE_COLOR_MATRIX, 0, 2, 2, 0 };
      static const gl_state_index row3_state[STATE_LENGTH] =
         { STATE_COLOR_MATRIX, 0, 3, 3, 0 };

      GLint row0_p = _mesa_add_state_reference(params, row0_state);
      GLint row1_p = _mesa_add_state_reference(params, row1_state);
      GLint row2_p = _mesa_add_state_reference(params, row2_state);
      GLint row3_p = _mesa_add_state_reference(params, row3_state);
      const GLuint temp = 1;

      /* DP4 temp.x, colorTemp, matrow0; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_DP4;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = temp;
      inst[ic].DstReg.WriteMask = WRITEMASK_X;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[1].Index = row0_p;
      ic++;

      /* DP4 temp.y, colorTemp, matrow1; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_DP4;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = temp;
      inst[ic].DstReg.WriteMask = WRITEMASK_Y;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[1].Index = row1_p;
      ic++;

      /* DP4 temp.z, colorTemp, matrow2; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_DP4;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = temp;
      inst[ic].DstReg.WriteMask = WRITEMASK_Z;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[1].Index = row2_p;
      ic++;

      /* DP4 temp.w, colorTemp, matrow3; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_DP4;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = temp;
      inst[ic].DstReg.WriteMask = WRITEMASK_W;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[1].Index = row3_p;
      ic++;

      /* MOV colorTemp, temp; */
      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_MOV;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = colorTemp;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = temp;
      ic++;
   }

   if (key->colorMatrixPostScaleBias) {
      static const gl_state_index scale_state[STATE_LENGTH] =
         { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
      static const gl_state_index bias_state[STATE_LENGTH] =
         { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
      GLint scale_param, bias_param;

      scale_param = _mesa_add_state_reference(params, scale_state);
      bias_param = _mesa_add_state_reference(params, bias_state);

      _mesa_init_instructions(inst + ic, 1);
      inst[ic].Opcode = OPCODE_MAD;
      inst[ic].DstReg.File = PROGRAM_TEMPORARY;
      inst[ic].DstReg.Index = colorTemp;
      inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
      inst[ic].SrcReg[0].Index = colorTemp;
      inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[1].Index = scale_param;
      inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
      inst[ic].SrcReg[2].Index = bias_param;
      ic++;
   }

   /* Modify last instruction's dst reg to write to result.color */
   {
      struct prog_instruction *last = &inst[ic - 1];
      last->DstReg.File = PROGRAM_OUTPUT;
      last->DstReg.Index = FRAG_RESULT_COLR;
   }

   /* END; */
   _mesa_init_instructions(inst + ic, 1);
   inst[ic].Opcode = OPCODE_END;
   ic++;

   assert(ic <= MAX_INST);


   fp->Base.Instructions = _mesa_alloc_instructions(ic);
   if (!fp->Base.Instructions) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY,
                  "generating pixel transfer program");
      return NULL;
   }

   _mesa_copy_instructions(fp->Base.Instructions, inst, ic);
   fp->Base.NumInstructions = ic;
   fp->Base.Parameters = params;

#if 0
   printf("========= pixel transfer prog\n");
   _mesa_print_program(&fp->Base);
   _mesa_print_parameter_list(fp->Base.Parameters);
#endif

   return fp;
}
Ejemplo n.º 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;
}
Ejemplo n.º 13
0
/**
 * Create a simple vertex shader that just passes through the
 * vertex position and texcoord (and optionally, color).
 */
static struct st_vertex_program *
st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
{
   GLcontext *ctx = st->ctx;
   struct st_vertex_program *stvp;
   struct gl_program *p;
   GLuint ic = 0;

   if (st->drawpix.vert_shaders[passColor])
      return st->drawpix.vert_shaders[passColor];

   /*
    * Create shader now
    */
   p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
   if (!p)
      return NULL;

   if (passColor)
      p->NumInstructions = 4;
   else
      p->NumInstructions = 3;

   p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
   if (!p->Instructions) {
      ctx->Driver.DeleteProgram(ctx, p);
      return NULL;
   }
   _mesa_init_instructions(p->Instructions, p->NumInstructions);
   /* MOV result.pos, vertex.pos; */
   p->Instructions[0].Opcode = OPCODE_MOV;
   p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
   p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
   p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
   p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
   /* MOV result.texcoord0, vertex.texcoord0; */
   p->Instructions[1].Opcode = OPCODE_MOV;
   p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
   p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
   p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
   p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
   ic = 2;
   if (passColor) {
      /* MOV result.color0, vertex.color0; */
      p->Instructions[ic].Opcode = OPCODE_MOV;
      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
      p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
      p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
      ic++;
   }

   /* END; */
   p->Instructions[ic].Opcode = OPCODE_END;
   ic++;

   assert(ic == p->NumInstructions);

   p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
   p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
                        (1 << VERT_RESULT_HPOS));
   if (passColor) {
      p->InputsRead |= VERT_BIT_COLOR0;
      p->OutputsWritten |= (1 << VERT_RESULT_COL0);
   }

   stvp = (struct st_vertex_program *) p;
   st_translate_vertex_program(st, stvp, NULL, NULL, NULL);

   st->drawpix.vert_shaders[passColor] = stvp;

   return stvp;
}