#include "main/imports.h"
#include "main/mtypes.h"
+#include "main/macros.h"
+#include "shader/program.h"
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
-#include "cso_cache/cso_cache.h"
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
#include "st_context.h"
-#include "st_cache.h"
#include "st_atom.h"
#include "st_program.h"
#include "st_atom_shader.h"
/** Maps VERT_RESULT_x to slot */
GLuint output_to_slot[VERT_RESULT_MAX];
-
- /** The program in TGSI format */
- struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
+ ubyte output_to_semantic_name[VERT_RESULT_MAX];
+ ubyte output_to_semantic_index[VERT_RESULT_MAX];
/** Pointer to the translated vertex program */
struct st_vertex_program *vp;
-/**
- * Free data hanging off the st vert prog.
- */
-void
-st_remove_vertex_program(struct st_context *st, struct st_vertex_program *stvp)
-{
- /* no-op, for now? */
-}
-
-
-/**
- * Free data hanging off the st frag prog.
- */
-void
-st_remove_fragment_program(struct st_context *st,
- struct st_fragment_program *stfp)
-{
- struct translated_vertex_program *xvp, *next;
-
- for (xvp = stfp->vertex_programs; xvp; xvp = next) {
- next = xvp->next;
- /* XXX free xvp->vs */
- free(xvp);
- }
-}
-
-
-
/**
* Given a vertex program output attribute, return the corresponding
* fragment program input attribute.
/*
* Translate fragment program if needed.
*/
- if (!stfp->cso) {
+ if (!stfp->state.tokens) {
GLuint inAttr, numIn = 0;
for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
assert(stfp->Base.Base.NumInstructions > 1);
- (void) st_translate_fragment_program(st, stfp,
- stfp->input_to_slot,
- stfp->tokens,
- ST_MAX_SHADER_TOKENS);
- assert(stfp->cso);
+ st_translate_fragment_program(st, stfp, stfp->input_to_slot);
}
/* No? Allocate translated vp object now */
if (!xvp) {
- xvp = CALLOC_STRUCT(translated_vertex_program);
+ xvp = ST_CALLOC_STRUCT(translated_vertex_program);
xvp->frag_inputs = fragInputsRead;
xvp->master = stvp;
GLuint outAttr, dummySlot;
const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
GLuint numVpOuts = 0;
+ GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
+ GLint maxGeneric;
/* Compute mapping of vertex program outputs to slots, which depends
* on the fragment program's input->slot mapping.
*/
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
- /* set default: */
+ /* set defaults: */
xvp->output_to_slot[outAttr] = UNUSED;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
+ xvp->output_to_semantic_index[outAttr] = 99;
if (outAttr == VERT_RESULT_HPOS) {
/* always put xformed position into slot zero */
xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
+ xvp->output_to_semantic_index[outAttr] = 0;
numVpOuts++;
}
else if (outputsWritten & (1 << outAttr)) {
if (fpInAttrib >= 0) {
GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
if (fpInSlot != ~0) {
+ /* match this vp output to the fp input */
GLuint vpOutSlot = stfp->input_map[fpInSlot];
xvp->output_to_slot[outAttr] = vpOutSlot;
+ xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
+ xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
numVpOuts++;
}
}
- else if (outAttr == VERT_RESULT_PSIZ ||
- outAttr == VERT_RESULT_BFC0 ||
- outAttr == VERT_RESULT_BFC1) {
- /* backface colors go into last slots */
- xvp->output_to_slot[outAttr] = numVpOuts++;
- }
+ else if (outAttr == VERT_RESULT_PSIZ)
+ emitPntSize = GL_TRUE;
+ else if (outAttr == VERT_RESULT_BFC0)
+ emitBFC0 = GL_TRUE;
+ else if (outAttr == VERT_RESULT_BFC1)
+ emitBFC1 = GL_TRUE;
}
- /*
- printf("output_to_slot[%d] = %d\n", outAttr,
+#if 0 /*debug*/
+ printf("assign vp output_to_slot[%d] = %d\n", outAttr,
xvp->output_to_slot[outAttr]);
- */
+#endif
+ }
+
+ /* must do these last */
+ if (emitPntSize) {
+ xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
+ xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
+ xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
+ }
+ if (emitBFC0) {
+ xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
+ }
+ if (emitBFC1) {
+ xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
}
/* Unneeded vertex program outputs will go to this slot.
*/
dummySlot = numVpOuts;
- /* Map vert program outputs that aren't used to the dummy slot */
+ /* find max GENERIC slot index */
+ maxGeneric = -1;
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
+ maxGeneric = MAX2(maxGeneric,
+ xvp->output_to_semantic_index[outAttr]);
+ }
+ }
+
+ /* Map vert program outputs that aren't used to the dummy slot
+ * (and an unused generic attribute slot).
+ */
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (outputsWritten & (1 << outAttr)) {
- if (xvp->output_to_slot[outAttr] == UNUSED)
+ if (xvp->output_to_slot[outAttr] == UNUSED) {
xvp->output_to_slot[outAttr] = dummySlot;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
+ xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
+ }
}
+
+#if 0 /*debug*/
+ printf("vp output_to_slot[%d] = %d\n", outAttr,
+ xvp->output_to_slot[outAttr]);
+#endif
}
assert(stvp->Base.Base.NumInstructions > 1);
- st_translate_vertex_program(st, stvp,
- xvp->output_to_slot,
- xvp->tokens,
- ST_MAX_SHADER_TOKENS);
+ st_translate_vertex_program(st, stvp, xvp->output_to_slot,
+ xvp->output_to_semantic_name,
+ xvp->output_to_semantic_index);
- assert(stvp->cso);
xvp->vp = stvp;
/* translated VP is up to date now */
}
+void
+st_free_translated_vertex_programs(struct st_context *st,
+ struct translated_vertex_program *xvp)
+{
+ struct translated_vertex_program *next;
+
+ while (xvp) {
+ next = xvp->next;
+ _mesa_free(xvp);
+ xvp = next;
+ }
+}
+
+
+static void *
+get_passthrough_fs(struct st_context *st)
+{
+ if (!st->passthrough_fs) {
+ st->passthrough_fs =
+ util_make_fragment_passthrough_shader(st->pipe);
+ }
+
+ return st->passthrough_fs;
+}
+
+
static void
update_linkage( struct st_context *st )
{
*/
assert(st->ctx->VertexProgram._Current);
stvp = st_vertex_program(st->ctx->VertexProgram._Current);
+ assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
assert(st->ctx->FragmentProgram._Current);
stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
+ assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
xvp = find_translated_vp(st, stvp, stfp);
- st->vp = stvp;
- st->state.vs = xvp->vp;
- st->pipe->bind_vs_state(st->pipe, st->state.vs->cso->data);
+ st_reference_vertprog(st, &st->vp, stvp);
+ st_reference_fragprog(st, &st->fp, stfp);
- st->fp = stfp;
- st->state.fs = stfp->cso;
- st->pipe->bind_fs_state(st->pipe, st->state.fs->data);
+ cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
+
+ if (st->missing_textures) {
+ /* use a pass-through frag shader that uses no textures */
+ void *fs = get_passthrough_fs(st);
+ cso_set_fragment_shader_handle(st->cso_context, fs);
+ }
+ else {
+ cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
+ }
st->vertex_result_to_slot = xvp->output_to_slot;
}
const struct st_tracked_state st_update_shader = {
- .name = "st_update_shader",
- .dirty = {
- .mesa = 0,
- .st = ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM
+ "st_update_shader", /* name */
+ { /* dirty */
+ 0, /* mesa */
+ ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */
},
- .update = update_linkage
+ update_linkage /* update */
};