/* This one is simple - just take the interpolated fog coordinate and * use it as the fog blend factor. */ static void fog_interpolated( struct brw_wm_compile *c ) { struct prog_src_register fogc = src_reg(PROGRAM_INPUT, FRAG_ATTRIB_FOGC); if (!(c->fp_interp_emitted & (1<<FRAG_ATTRIB_FOGC))) emit_interp(c, FRAG_ATTRIB_FOGC); fog_blend( c, src_swizzle1(fogc, GET_SWZ(fogc.Swizzle,X))); }
static void validate_src_regs( struct brw_wm_compile *c, const struct prog_instruction *inst ) { GLuint nr_args = brw_wm_nr_args( inst->Opcode ); GLuint i; for (i = 0; i < nr_args; i++) { if (inst->SrcReg[i].File == PROGRAM_INPUT) { GLuint idx = inst->SrcReg[i].Index; if (!(c->fp_interp_emitted & (1<<idx))) { emit_interp(c, idx); } } } }
/** * Initial pass for fragment program code generation. * This function is used by both the GLSL and non-GLSL paths. */ int brw_wm_pass_fp( struct brw_wm_compile *c ) { struct brw_fragment_shader *fs = c->fp; struct tgsi_parse_context parse; struct tgsi_full_instruction *inst; struct tgsi_full_declaration *decl; const float *imm; GLuint size; GLuint i; if (BRW_DEBUG & DEBUG_WM) { debug_printf("pre-fp:\n"); tgsi_dump(fs->tokens, 0); } c->fp_pixel_xy = src_undef(); c->fp_delta_xy = src_undef(); c->fp_pixel_w = src_undef(); c->nr_fp_insns = 0; c->nr_immediates = 0; /* Loop over all instructions doing assorted simplifications and * transformations. */ tgsi_parse_init( &parse, fs->tokens ); while( !tgsi_parse_end_of_tokens( &parse ) ) { tgsi_parse_token( &parse ); switch( parse.FullToken.Token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: /* Turn intput declarations into special WM_* instructions. * * XXX: For non-branching shaders, consider deferring variable * initialization as late as possible to minimize register * usage. This is how the original BRW driver worked. * * In a branching shader, must preamble instructions at decl * time, as instruction order in the shader does not * correspond to the order instructions are executed in the * wild. * * This is where special instructions such as WM_CINTERP, * WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to * compute shader inputs from the payload registers and pixel * position. */ decl = &parse.FullToken.FullDeclaration; if( decl->Declaration.File == TGSI_FILE_INPUT ) { unsigned first, last, mask; unsigned attrib; first = decl->Range.First; last = decl->Range.Last; mask = decl->Declaration.UsageMask; for (attrib = first; attrib <= last; attrib++) { emit_interp(c, attrib, decl->Semantic.Name, decl->Declaration.Interpolate ); } } break; case TGSI_TOKEN_TYPE_IMMEDIATE: /* Unlike VS programs we can probably manage fine encoding * immediate values directly into the emitted EU * instructions, as we probably only need to reference one * float value per instruction. Just save the data for now * and use directly later. */ i = c->nr_immediates++; imm = &parse.FullToken.FullImmediate.u[i].Float; size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; if (c->nr_immediates >= BRW_WM_MAX_CONST) return PIPE_ERROR_OUT_OF_MEMORY; for (i = 0; i < size; i++) c->immediate[c->nr_immediates].v[i] = imm[i]; for (; i < 4; i++) c->immediate[c->nr_immediates].v[i] = 0.0; c->immediate[c->nr_immediates].nr = size; c->nr_immediates++; break; case TGSI_TOKEN_TYPE_INSTRUCTION: inst = &parse.FullToken.FullInstruction; emit_insn(c, inst); break; } } if (BRW_DEBUG & DEBUG_WM) { brw_wm_print_fp_program( c, "pass_fp" ); debug_printf("\n"); } return c->error; }