static void emit_expr(Node *node) { SAVE; switch (node->type) { case AST_LITERAL: emit_literal(node); return; case AST_STRING: emit_literal_string(node); return; case AST_LVAR: emit_lvar(node); return; case AST_GVAR: emit_gvar(node); return; case AST_FUNCALL: case AST_FUNCPTR_CALL: emit_func_call(node); return; case AST_DECL: emit_decl(node); return; case AST_CONV: emit_conv(node); return; case AST_ADDR: emit_addr(node->operand); return; case AST_DEREF: emit_deref(node); return; case AST_IF: case AST_TERNARY: emit_ternary(node); return; case AST_FOR: emit_for(node); return; case AST_WHILE: emit_while(node); return; case AST_DO: emit_do(node); return; case AST_SWITCH: emit_switch(node); return; case AST_CASE: emit_case(node); return; case AST_DEFAULT: emit_default(node); return; case AST_GOTO: emit_goto(node); return; case AST_LABEL: if (node->newlabel) emit_label(node->newlabel); return; case AST_RETURN: emit_return(node); return; case AST_BREAK: emit_break(node); return; case AST_CONTINUE: emit_continue(node); return; case AST_COMPOUND_STMT: emit_compound_stmt(node); return; case AST_STRUCT_REF: emit_load_struct_ref(node->struc, node->ctype, 0); return; case AST_VA_START: emit_va_start(node); return; case AST_VA_ARG: emit_va_arg(node); return; case OP_UMINUS: emit_uminus(node); return; case OP_PRE_INC: emit_pre_inc_dec(node, "add"); return; case OP_PRE_DEC: emit_pre_inc_dec(node, "sub"); return; case OP_POST_INC: emit_post_inc_dec(node, "add"); return; case OP_POST_DEC: emit_post_inc_dec(node, "sub"); return; case '!': emit_lognot(node); return; case '&': emit_bitand(node); return; case '|': emit_bitor(node); return; case '~': emit_bitnot(node); return; case OP_LOGAND: emit_logand(node); return; case OP_LOGOR: emit_logor(node); return; case OP_CAST: emit_cast(node); return; case ',': emit_comma(node); return; case '=': emit_assign(node); return; case OP_LABEL_ADDR: emit_label_addr(node); return; case AST_COMPUTED_GOTO: emit_computed_goto(node); return; default: emit_binop(node); } }
static void emit_expr(Node *node) { SAVE; maybe_print_source_loc(node); switch (node->kind) { case AST_LITERAL: emit_literal(node); return; case AST_LVAR: emit_lvar(node); return; case AST_GVAR: emit_gvar(node); return; case AST_FUNCDESG: return; case AST_FUNCALL: if (maybe_emit_builtin(node)) return; // fall through case AST_FUNCPTR_CALL: emit_func_call(node); return; case AST_DECL: emit_decl(node); return; case AST_CONV: emit_conv(node); return; case AST_ADDR: emit_addr(node->operand); return; case AST_DEREF: emit_deref(node); return; case AST_IF: case AST_TERNARY: emit_ternary(node); return; case AST_GOTO: emit_goto(node); return; case AST_LABEL: if (node->newlabel) emit_label(node->newlabel); return; case AST_RETURN: emit_return(node); return; case AST_COMPOUND_STMT: emit_compound_stmt(node); return; case AST_STRUCT_REF: emit_load_struct_ref(node->struc, node->ty, 0); return; case OP_PRE_INC: emit_pre_inc_dec(node, "add"); return; case OP_PRE_DEC: emit_pre_inc_dec(node, "sub"); return; case OP_POST_INC: emit_post_inc_dec(node, "add"); return; case OP_POST_DEC: emit_post_inc_dec(node, "sub"); return; case '!': emit_lognot(node); return; case '&': emit_bitand(node); return; case '|': emit_bitor(node); return; case '~': emit_bitnot(node); return; case OP_LOGAND: emit_logand(node); return; case OP_LOGOR: emit_logor(node); return; case OP_CAST: emit_cast(node); return; case ',': emit_comma(node); return; case '=': emit_assign(node); return; case OP_LABEL_ADDR: emit_label_addr(node); return; case AST_COMPUTED_GOTO: emit_computed_goto(node); return; default: emit_binop(node); } }
/** * Emit declaration for PS front/back-face input register. */ static boolean emit_vface_decl(struct svga_shader_emitter *emit) { if (!emit->emitted_vface) { SVGA3dShaderDestToken reg = dst_register(SVGA3DREG_MISCTYPE, SVGA3DMISCREG_FACE); if (!emit_decl( emit, reg, 0, 0 )) return FALSE; emit->emitted_vface = TRUE; } return TRUE; }
/** * Declare VS output for holding depth/fog. */ static boolean vs30_output_emit_depth_fog(struct svga_shader_emitter *emit, SVGA3dShaderDestToken *out) { SVGA3dShaderDestToken reg; if (emit->emitted_depth_fog) { *out = emit->vs_depth_fog; return TRUE; } reg = dst_register( SVGA3DREG_OUTPUT, emit->vs30_output_count++ ); *out = emit->vs_depth_fog = reg; emit->emitted_depth_fog = TRUE; return emit_decl( emit, reg, SVGA3D_DECLUSAGE_TEXCOORD, 0 ); }
/** * Emit PS input register to pass depth/fog coordinates. * Note that this always goes into texcoord[0]. */ static boolean ps30_input_emit_depth_fog( struct svga_shader_emitter *emit, struct src_register *out ) { struct src_register reg; if (emit->emitted_depth_fog) { *out = emit->ps_depth_fog; return TRUE; } if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) return FALSE; reg = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ ); *out = emit->ps_depth_fog = reg; emit->emitted_depth_fog = TRUE; return emit_decl( emit, dst( reg ), SVGA3D_DECLUSAGE_TEXCOORD, 0 ); }
/** * Process a PS input declaration. * We'll emit a declaration like "dcl_texcoord1 v2" */ static boolean ps30_input(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { unsigned usage, index; SVGA3dShaderDestToken reg; if (semantic.Name == TGSI_SEMANTIC_POSITION) { emit->ps_true_pos = src_register( SVGA3DREG_MISCTYPE, SVGA3DMISCREG_POSITION ); emit->ps_true_pos.base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y ); reg = writemask( dst(emit->ps_true_pos), TGSI_WRITEMASK_XY ); emit->ps_reads_pos = TRUE; if (emit->info.reads_z) { emit->ps_temp_pos = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp ); emit->input_map[idx] = src_register( SVGA3DREG_TEMP, emit->nr_hw_temp ); emit->nr_hw_temp++; if (!ps30_input_emit_depth_fog( emit, &emit->ps_depth_pos )) return FALSE; emit->ps_depth_pos.base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W ); } else { emit->input_map[idx] = emit->ps_true_pos; } return emit_decl( emit, reg, 0, 0 ); } else if (emit->key.fs.light_twoside && (semantic.Name == TGSI_SEMANTIC_COLOR)) { if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; emit->internal_color_idx[emit->internal_color_count] = idx; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count ); emit->ps30_input_count++; emit->internal_color_count++; reg = dst( emit->input_map[idx] ); if (!emit_decl( emit, reg, usage, index )) return FALSE; semantic.Name = TGSI_SEMANTIC_BCOLOR; if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) return FALSE; reg = dst_register( SVGA3DREG_INPUT, emit->ps30_input_count++ ); if (!emit_decl( emit, reg, usage, index )) return FALSE; if (!emit_vface_decl( emit )) return FALSE; return TRUE; } else if (semantic.Name == TGSI_SEMANTIC_FACE) { if (!emit_vface_decl( emit )) return FALSE; emit->emit_frontface = TRUE; emit->internal_frontface_idx = idx; return TRUE; } else if (semantic.Name == TGSI_SEMANTIC_FOG) { assert(semantic.Index == 0); if (!ps30_input_emit_depth_fog( emit, &emit->input_map[idx] )) return FALSE; emit->input_map[idx].base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X ); return TRUE; } else { if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) return FALSE; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ ); reg = dst( emit->input_map[idx] ); if (!emit_decl( emit, reg, usage, index )) return FALSE; if (semantic.Name == TGSI_SEMANTIC_GENERIC && emit->key.sprite_origin_lower_left && index >= 1 && emit->key.tex[index - 1].sprite_texgen) { /* This is a sprite texture coord with lower-left origin. * We need to invert the texture T coordinate since the SVGA3D * device only supports an upper-left origin. */ unsigned unit = index - 1; emit->inverted_texcoords |= (1 << unit); /* save original texcoord reg */ emit->ps_true_texcoord[unit] = emit->input_map[idx]; /* this temp register will be the results of the MAD instruction */ emit->ps_inverted_texcoord[unit] = src_register(SVGA3DREG_TEMP, emit->nr_hw_temp); emit->nr_hw_temp++; emit->ps_inverted_texcoord_input[unit] = idx; /* replace input_map entry with the temp register */ emit->input_map[idx] = emit->ps_inverted_texcoord[unit]; } return TRUE; } }