else
insert_mvp_mad_code( ctx, vprog );
}
-
-
-
-
-
-
-/**
- * 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 FOG_EXP, \c FOG_EXP2, or \c FOG_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->info.inputs_read.
- *
- * \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_program *fprog,
- enum gl_fog_mode fog_mode, GLboolean saturate)
-{
- static const gl_state_index16 fogPStateOpt[STATE_LENGTH]
- = { STATE_FOG_PARAMS_OPTIMIZED, 0, 0 };
- static const gl_state_index16 fogColorState[STATE_LENGTH]
- = { STATE_FOG_COLOR, 0, 0, 0 };
- struct prog_instruction *newInst, *inst;
- const GLuint origLen = fprog->arb.NumInstructions;
- const GLuint newLen = origLen + 5;
- GLuint i;
- GLint fogPRefOpt, fogColorRef; /* state references */
- GLuint colorTemp, fogFactorTemp; /* temporary registerss */
-
- if (fog_mode == FOG_NONE) {
- _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program"
- " with fog_mode == GL_NONE");
- return;
- }
-
- if (!(fprog->info.outputs_written & (1 << FRAG_RESULT_COLOR))) {
- /* program doesn't output color, so nothing to do */
- return;
- }
-
- /* Alloc storage for new instructions */
- newInst = rzalloc_array(fprog, struct prog_instruction, 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->arb.Instructions, origLen);
-
- /* PARAM fogParamsRefOpt = internal optimized fog params; */
- fogPRefOpt
- = _mesa_add_state_reference(fprog->Parameters, fogPStateOpt);
- /* PARAM fogColorRef = state.fog.color; */
- fogColorRef
- = _mesa_add_state_reference(fprog->Parameters, fogColorState);
-
- /* TEMP colorTemp; */
- colorTemp = fprog->arb.NumTemporaries++;
- /* TEMP fogFactorTemp; */
- fogFactorTemp = fprog->arb.NumTemporaries++;
-
- /* Scan program to find where result.color is written */
- inst = newInst;
- for (i = 0; i < fprog->arb.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->Saturate = 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 == FOG_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->Saturate = GL_TRUE;
- inst++;
- }
- else {
- assert(fog_mode == FOG_EXP || fog_mode == FOG_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 == FOG_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 == FOG_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->Saturate = GL_TRUE;
- 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 */
- ralloc_free(fprog->arb.Instructions);
-
- /* install new instructions */
- fprog->arb.Instructions = newInst;
- fprog->arb.NumInstructions = inst - newInst;
- fprog->info.inputs_read |= VARYING_BIT_FOGC;
- assert(fprog->info.outputs_written & (1 << FRAG_RESULT_COLOR));
-}