/** * Create fragment shader that does a TEX() instruction to get a Z * value, then writes to FRAG_RESULT_DEPTH. * Pass fragment color through as-is. */ static struct st_fragment_program * make_fragment_shader_z(struct st_context *st) { GLcontext *ctx = st->ctx; struct gl_program *p; GLuint ic = 0; if (st->drawpix.z_shader) { return st->drawpix.z_shader; } /* * Create shader now */ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); if (!p) return NULL; 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); /* 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++; /* MOV result.color, fragment.color */ p->Instructions[ic].Opcode = OPCODE_MOV; p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR; p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0; ic++; /* END; */ p->Instructions[ic++].Opcode = OPCODE_END; assert(ic == p->NumInstructions); p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; p->OutputsWritten = (1 << FRAG_RESULT_COLOR) | (1 << FRAG_RESULT_DEPTH); p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ st->drawpix.z_shader = (struct st_fragment_program *) p; st_translate_fragment_program(st, st->drawpix.z_shader, NULL); return st->drawpix.z_shader; }
/** * Make the given fragment program into a "no-op" shader. * Actually, just copy the incoming fragment color (or texcoord) * to the output color. * This is for debug/test purposes. */ void _mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog) { struct prog_instruction *inst; GLuint inputAttr; inst = _mesa_alloc_instructions(2); if (!inst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "_mesa_nop_fragment_program"); return; } _mesa_init_instructions(inst, 2); inst[0].Opcode = OPCODE_MOV; inst[0].DstReg.File = PROGRAM_OUTPUT; inst[0].DstReg.Index = FRAG_RESULT_COLOR; inst[0].SrcReg[0].File = PROGRAM_INPUT; if (prog->Base.InputsRead & VARYING_BIT_COL0) inputAttr = VARYING_SLOT_COL0; else inputAttr = VARYING_SLOT_TEX0; inst[0].SrcReg[0].Index = inputAttr; inst[1].Opcode = OPCODE_END; _mesa_free_instructions(prog->Base.Instructions, prog->Base.NumInstructions); prog->Base.Instructions = inst; prog->Base.NumInstructions = 2; prog->Base.InputsRead = BITFIELD64_BIT(inputAttr); prog->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); }
/** * Make fragment program for glBitmap: * Sample the texture and kill the fragment if the bit is 0. * This program will be combined with the user's fragment program. */ static struct st_fragment_program * make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex) { struct st_context *st = st_context(ctx); struct st_fragment_program *stfp; struct gl_program *p; GLuint ic = 0; p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); if (!p) return NULL; 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); /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */ p->Instructions[ic].Opcode = OPCODE_TEX; p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; p->Instructions[ic].DstReg.Index = 0; p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; p->Instructions[ic].SrcReg[0].Index = VARYING_SLOT_TEX0; p->Instructions[ic].TexSrcUnit = samplerIndex; p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; ic++; /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */ p->Instructions[ic].Opcode = OPCODE_KIL; p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM) p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX; p->Instructions[ic].SrcReg[0].Index = 0; p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW; ic++; /* END; */ p->Instructions[ic++].Opcode = OPCODE_END; assert(ic == p->NumInstructions); p->InputsRead = VARYING_BIT_TEX0; p->OutputsWritten = 0x0; p->SamplersUsed = (1 << samplerIndex); stfp = (struct st_fragment_program *) p; stfp->Base.UsesKill = GL_TRUE; return stfp; }
/** * Insert 'count' NOP instructions at 'start' in the given program. * Adjust branch targets accordingly. */ GLboolean _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) { const GLuint origLen = prog->NumInstructions; const GLuint newLen = origLen + count; struct prog_instruction *newInst; GLuint i; /* adjust branches */ for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (inst->BranchTarget > 0) { if ((GLuint)inst->BranchTarget >= start) { inst->BranchTarget += count; } } } /* Alloc storage for new instructions */ newInst = _mesa_alloc_instructions(newLen); if (!newInst) { return GL_FALSE; } /* Copy 'start' instructions into new instruction buffer */ _mesa_copy_instructions(newInst, prog->Instructions, start); /* init the new instructions */ _mesa_init_instructions(newInst + start, count); /* Copy the remaining/tail instructions to new inst buffer */ _mesa_copy_instructions(newInst + start + count, prog->Instructions + start, origLen - start); /* free old instructions */ _mesa_free_instructions(prog->Instructions, origLen); /* install new instructions */ prog->Instructions = newInst; prog->NumInstructions = newLen; return GL_TRUE; }
/** * \sa _mesa_nop_fragment_program * Replace the given vertex program with a "no-op" program that just * transforms vertex position and emits color. */ void _mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog) { struct prog_instruction *inst; GLuint inputAttr; /* * Start with a simple vertex program that emits color. */ inst = _mesa_alloc_instructions(2); if (!inst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "_mesa_nop_vertex_program"); return; } _mesa_init_instructions(inst, 2); inst[0].Opcode = OPCODE_MOV; inst[0].DstReg.File = PROGRAM_OUTPUT; inst[0].DstReg.Index = VARYING_SLOT_COL0; inst[0].SrcReg[0].File = PROGRAM_INPUT; if (prog->Base.InputsRead & VERT_BIT_COLOR0) inputAttr = VERT_ATTRIB_COLOR0; else inputAttr = VERT_ATTRIB_TEX0; inst[0].SrcReg[0].Index = inputAttr; inst[1].Opcode = OPCODE_END; _mesa_free_instructions(prog->Base.Instructions, prog->Base.NumInstructions); prog->Base.Instructions = inst; prog->Base.NumInstructions = 2; prog->Base.InputsRead = BITFIELD64_BIT(inputAttr); prog->Base.OutputsWritten = BITFIELD64_BIT(VARYING_SLOT_COL0); /* * Now insert code to do standard modelview/projection transformation. */ _mesa_insert_mvp_code(ctx, prog); }
/** * 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); }
/** * 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)); }
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); }
static GLboolean Parse_InstructionSequence(struct parse_state *parseState, struct prog_instruction program[]) { while (1) { struct prog_instruction *inst = program + parseState->numInst; /* Initialize the instruction */ _mesa_init_instructions(inst, 1); if (Parse_String(parseState, "MOV")) { if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV)) RETURN_ERROR; } else if (Parse_String(parseState, "LIT")) { if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT)) RETURN_ERROR; } else if (Parse_String(parseState, "ABS")) { if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS)) RETURN_ERROR; } else if (Parse_String(parseState, "MUL")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL)) RETURN_ERROR; } else if (Parse_String(parseState, "ADD")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD)) RETURN_ERROR; } else if (Parse_String(parseState, "DP3")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3)) RETURN_ERROR; } else if (Parse_String(parseState, "DP4")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4)) RETURN_ERROR; } else if (Parse_String(parseState, "DST")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST)) RETURN_ERROR; } else if (Parse_String(parseState, "MIN")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN)) RETURN_ERROR; } else if (Parse_String(parseState, "MAX")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX)) RETURN_ERROR; } else if (Parse_String(parseState, "SLT")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT)) RETURN_ERROR; } else if (Parse_String(parseState, "SGE")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE)) RETURN_ERROR; } else if (Parse_String(parseState, "DPH")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH)) RETURN_ERROR; } else if (Parse_String(parseState, "SUB")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB)) RETURN_ERROR; } else if (Parse_String(parseState, "MAD")) { if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD)) RETURN_ERROR; } else if (Parse_String(parseState, "RCP")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP)) RETURN_ERROR; } else if (Parse_String(parseState, "RSQ")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ)) RETURN_ERROR; } else if (Parse_String(parseState, "EXP")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP)) RETURN_ERROR; } else if (Parse_String(parseState, "LOG")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG)) RETURN_ERROR; } else if (Parse_String(parseState, "RCC")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC)) RETURN_ERROR; } else if (Parse_String(parseState, "ARL")) { if (!Parse_AddressInstruction(parseState, inst)) RETURN_ERROR; } else if (Parse_String(parseState, "PRINT")) { if (!Parse_PrintInstruction(parseState, inst)) RETURN_ERROR; } else if (Parse_String(parseState, "END")) { if (!Parse_EndInstruction(parseState, inst)) RETURN_ERROR; else { parseState->numInst++; return GL_TRUE; /* all done */ } } else { /* bad instruction name */ RETURN_ERROR1("Unexpected token"); } /* examine input/output registers */ if (inst->DstReg.File == PROGRAM_OUTPUT) parseState->outputsWritten |= (1 << inst->DstReg.Index); else if (inst->DstReg.File == PROGRAM_ENV_PARAM) parseState->anyProgRegsWritten = GL_TRUE; if (inst->SrcReg[0].File == PROGRAM_INPUT) parseState->inputsRead |= (1 << inst->SrcReg[0].Index); if (inst->SrcReg[1].File == PROGRAM_INPUT) parseState->inputsRead |= (1 << inst->SrcReg[1].Index); if (inst->SrcReg[2].File == PROGRAM_INPUT) parseState->inputsRead |= (1 << inst->SrcReg[2].Index); parseState->numInst++; if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) RETURN_ERROR1("Program too long"); } RETURN_ERROR; }
static GLboolean Parse_InstructionSequence(struct parse_state *parseState, struct prog_instruction program[]) { while (1) { struct prog_instruction *inst = program + parseState->numInst; struct instruction_pattern instMatch; GLubyte token[100]; /* Initialize the instruction */ _mesa_init_instructions(inst, 1); /* special instructions */ if (Parse_String(parseState, "DEFINE")) { GLubyte id[100]; GLfloat value[7]; /* yes, 7 to be safe */ if (!Parse_Identifier(parseState, id)) RETURN_ERROR; /* XXX make sure id is not a reserved identifer, like R9 */ if (!Parse_String(parseState, "=")) RETURN_ERROR1("Expected ="); if (!Parse_VectorOrScalarConstant(parseState, value)) RETURN_ERROR; if (!Parse_String(parseState, ";")) RETURN_ERROR1("Expected ;"); if (_mesa_lookup_parameter_index(parseState->parameters, -1, (const char *) id) >= 0) { RETURN_ERROR2(id, "already defined"); } _mesa_add_named_parameter(parseState->parameters, (const char *) id, value); } else if (Parse_String(parseState, "DECLARE")) { GLubyte id[100]; GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0}; /* yes, to be safe */ if (!Parse_Identifier(parseState, id)) RETURN_ERROR; /* XXX make sure id is not a reserved identifer, like R9 */ if (Parse_String(parseState, "=")) { if (!Parse_VectorOrScalarConstant(parseState, value)) RETURN_ERROR; } if (!Parse_String(parseState, ";")) RETURN_ERROR1("Expected ;"); if (_mesa_lookup_parameter_index(parseState->parameters, -1, (const char *) id) >= 0) { RETURN_ERROR2(id, "already declared"); } _mesa_add_named_parameter(parseState->parameters, (const char *) id, value); } else if (Parse_String(parseState, "END")) { inst->Opcode = OPCODE_END; parseState->numInst++; if (Parse_Token(parseState, token)) { RETURN_ERROR1("Code after END opcode."); } break; } else { /* general/arithmetic instruction */ /* get token */ if (!Parse_Token(parseState, token)) { RETURN_ERROR1("Missing END instruction."); } /* try to find matching instuction */ instMatch = MatchInstruction(token); if (instMatch.opcode >= MAX_OPCODE) { /* bad instruction name */ RETURN_ERROR2("Unexpected token: ", token); } inst->Opcode = instMatch.opcode; inst->Precision = instMatch.suffixes & (_R | _H | _X); inst->SaturateMode = (instMatch.suffixes & (_S)) ? SATURATE_ZERO_ONE : SATURATE_OFF; inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE; /* * parse the input and output operands */ if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) { if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); } else if (instMatch.outputs == OUTPUT_NONE) { if (instMatch.opcode == OPCODE_KIL_NV) { /* This is a little weird, the cond code info is in * the dest register. */ if (!Parse_CondCodeMask(parseState, &inst->DstReg)) RETURN_ERROR; } else { ASSERT(instMatch.opcode == OPCODE_PRINT); } } if (instMatch.inputs == INPUT_1V) { if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; } else if (instMatch.inputs == INPUT_2V) { if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_VectorSrc(parseState, &inst->SrcReg[1])) RETURN_ERROR; } else if (instMatch.inputs == INPUT_3V) { if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_VectorSrc(parseState, &inst->SrcReg[1])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_VectorSrc(parseState, &inst->SrcReg[2])) RETURN_ERROR; } else if (instMatch.inputs == INPUT_1S) { if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) RETURN_ERROR; } else if (instMatch.inputs == INPUT_2S) { if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1])) RETURN_ERROR; } else if (instMatch.inputs == INPUT_CC) { /* XXX to-do */ } else if (instMatch.inputs == INPUT_1V_T) { GLubyte unit, idx; if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_TextureImageId(parseState, &unit, &idx)) RETURN_ERROR; inst->TexSrcUnit = unit; inst->TexSrcTarget = idx; } else if (instMatch.inputs == INPUT_3V_T) { GLubyte unit, idx; if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_VectorSrc(parseState, &inst->SrcReg[1])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_VectorSrc(parseState, &inst->SrcReg[2])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_TextureImageId(parseState, &unit, &idx)) RETURN_ERROR; inst->TexSrcUnit = unit; inst->TexSrcTarget = idx; } else if (instMatch.inputs == INPUT_1V_S) { if (!Parse_PrintInstruction(parseState, inst)) RETURN_ERROR; } /* end of statement semicolon */ if (!Parse_String(parseState, ";")) RETURN_ERROR1("Expected ;"); parseState->numInst++; if (parseState->numInst >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) RETURN_ERROR1("Program too long"); } } return GL_TRUE; }
/** * 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; }
/** * 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; }
/** * 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; }