X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_fragprog_to_c.c;h=d5d27d0bcf713cddb35a3ea8f69983b8a8cf035d;hb=4102a3045cb64a7875c524a58f13766a48bbe164;hp=b649da2a3ed57e4349bdf5f1d7336d54108f4b15;hpb=41d389909bc87d21cf7ef8639bead1b4494e3b0e;p=mesa.git diff --git a/src/mesa/swrast/s_fragprog_to_c.c b/src/mesa/swrast/s_fragprog_to_c.c index b649da2a3ed..d5d27d0bcf7 100644 --- a/src/mesa/swrast/s_fragprog_to_c.c +++ b/src/mesa/swrast/s_fragprog_to_c.c @@ -39,6 +39,8 @@ #include "s_texture.h" +#ifdef USE_TCC + /* UREG - a way of representing an FP source register including * swizzling and negation in a single GLuint. Major flaw is the * limitiation to source->Index < 32. Secondary flaw is the fact that @@ -150,6 +152,29 @@ static GLuint src_reg_file( GLuint file ) } } +static void emit( struct fragment_program *p, + const char *fmt, + ... ) +{ + va_list ap; + va_start( ap, fmt ); + + if (p->c_strlen < sizeof(p->c_str)) + p->c_strlen += vsnprintf( p->c_str + p->c_strlen, + sizeof(p->c_str) - p->c_strlen, + fmt, ap ); + + va_end( ap ); +} + +static INLINE void emit_char( struct fragment_program *p, char c ) +{ + if (p->c_strlen < sizeof(p->c_str)) { + p->c_str[p->c_strlen] = c; + p->c_strlen++; + } +} + /** * Retrieve a ureg for the given source register. Will emit @@ -159,9 +184,6 @@ static GLuint src_vector( const struct fp_src_register *source ) { GLuint src; -/* fprintf(stderr, "%s File %d, Index %d\n", */ -/* __FUNCTION__, source->File, source->Index); */ - assert(source->Index < 32); /* limitiation of UREG representation */ src = UREG( src_reg_file( source->File ), source->Index ); @@ -178,92 +200,145 @@ static GLuint src_vector( const struct fp_src_register *source ) return src; } -static void print_header( void ) + +static void print_header( struct fragment_program *p ) { - printf("static void run_program( const GLfloat (*local_param)[4], \n" - " const GLfloat (*env_param)[4], \n" - " const GLfloat (*state_param)[4], \n" - " const GLfloat (*interp)[4], \n" - " GLfloat *outputs)\n" + emit(p, "\n\n\n"); + + /* Mesa's program_parameter struct: + */ + emit(p, + "struct program_parameter\n" + "{\n" + " const char *Name;\n" + " int Type;\n" + " int StateIndexes[6];\n" + " float Values[4];\n" + "};\n"); + + + /* Texture samplers, not written yet: + */ + emit(p, "extern void TEX( void *ctx, const float *txc, int unit, float *rslt );\n" + "extern void TXB( void *ctx, const float *txc, int unit, float *rslt );\n" + "extern void TXP( void *ctx, const float *txc, int unit, float *rslt );\n"); + + /* Resort to the standard math library (float versions): + */ + emit(p, "extern float fabsf( float );\n" + "extern float cosf( float );\n" + "extern float sinf( float );\n" + "extern float expf( float );\n" + "extern float powf( float, float );\n" + "extern float floorf( float );\n"); + + /* These ones we have fast code in Mesa for: + */ + emit(p, "extern float LOG2( float );\n" + "extern float _mesa_inv_sqrtf( float );\n"); + + /* The usual macros, not really needed, but handy: + */ + emit(p, "#define MIN2(x,y) ((x)<(y)?(x):(y))\n" + "#define MAX2(x,y) ((x)<(y)?(x):(y))\n" + "#define SATURATE(x) ((x)>1.0?1.0:((x)<0.0?0.0:(x)))\n"); + + /* Our function! + */ + emit(p, "int run_program( void *ctx, \n" + " const float (*local_param)[4], \n" + " const float (*env_param)[4], \n" + " const struct program_parameter *state_param, \n" + " const float (*interp)[4], \n" + " float (*outputs)[4])\n" "{\n" - " GLfloat temp[32][4];\n" + " float temp[32][4];\n" ); } -static void print_footer( void ) +static void print_footer( struct fragment_program *p ) { - printf("}\n"); + emit(p, " return 1;"); + emit(p, "}\n"); } -static void print_dest_reg( const struct fp_instruction *inst ) +static void print_dest_reg( struct fragment_program *p, + const struct fp_instruction *inst ) { switch (inst->DstReg.File) { case PROGRAM_OUTPUT: - printf("outputs[%d]", inst->DstReg.Index); + emit(p, "outputs[%d]", inst->DstReg.Index); break; case PROGRAM_TEMPORARY: - printf("temp[%d]", inst->DstReg.Index); + emit(p, "temp[%d]", inst->DstReg.Index); break; default: break; } } -static void print_dest( const struct fp_instruction *inst, +static void print_dest( struct fragment_program *p, + const struct fp_instruction *inst, GLuint idx ) { - print_dest_reg(inst); - printf("[%d]", idx); + print_dest_reg(p, inst); + emit(p, "[%d]", idx); } #define UREG_SRC0(reg) (((reg)>>UREG_CHANNEL_X_SHIFT) & 0x7) -static void print_reg( GLuint arg ) +static void print_reg( struct fragment_program *p, + GLuint arg ) { switch (GET_UREG_TYPE(arg)) { - case UREG_TYPE_TEMP: printf("temp"); break; - case UREG_TYPE_INTERP: printf("interp"); break; - case UREG_TYPE_LOCAL_CONST: printf("local_const"); break; - case UREG_TYPE_ENV_CONST: printf("env_const"); break; - case UREG_TYPE_STATE_CONST: printf("state_const"); break; - case UREG_TYPE_PARAM: printf("param"); break; + case UREG_TYPE_TEMP: emit(p, "temp"); break; + case UREG_TYPE_INTERP: emit(p, "interp"); break; + case UREG_TYPE_LOCAL_CONST: emit(p, "local_const"); break; + case UREG_TYPE_ENV_CONST: emit(p, "env_const"); break; + case UREG_TYPE_STATE_CONST: emit(p, "state_param"); break; + case UREG_TYPE_PARAM: emit(p, "param"); break; }; - printf("[%d]", GET_UREG_NR(arg)); + emit(p, "[%d]", GET_UREG_NR(arg)); + + if (GET_UREG_TYPE(arg) == UREG_TYPE_STATE_CONST) { + emit(p, ".Values"); + } } -static void print_arg( const struct fragment_program *p, +static void print_arg( struct fragment_program *p, GLuint arg ) { GLuint src = UREG_SRC0(arg); if (src == _ZERO) { - printf("0"); + emit(p, "0"); return; } if (arg & (1<Parameters->Parameters[GET_UREG_NR(arg)].Values[src]); + if (GET_UREG_TYPE(arg) == UREG_TYPE_STATE_CONST && + p->Parameters->Parameters[GET_UREG_NR(arg)].Type == CONSTANT) { + emit(p, "%g", p->Parameters->Parameters[GET_UREG_NR(arg)].Values[src]); return; } - print_reg( arg ); + print_reg( p, arg ); switch (src){ - case _X: printf("[0]"); break; - case _Y: printf("[1]"); break; - case _Z: printf("[2]"); break; - case _W: printf("[3]"); break; + case _X: emit(p, "[0]"); break; + case _Y: emit(p, "[1]"); break; + case _Z: emit(p, "[2]"); break; + case _W: emit(p, "[3]"); break; } } @@ -271,7 +346,7 @@ static void print_arg( const struct fragment_program *p, /* This is where the handling of expressions breaks down into string * processing: */ -static void print_expression( const struct fragment_program *p, +static void print_expression( struct fragment_program *p, GLuint i, const char *fmt, va_list ap ) @@ -286,27 +361,47 @@ static void print_expression( const struct fragment_program *p, fmt += 2; } else { - putchar(*fmt); + emit_char(p, *fmt); fmt++; } } - printf(";\n"); + emit(p, ";\n"); +} + +static void do_tex_kill( struct fragment_program *p, + const struct fp_instruction *inst, + GLuint arg ) +{ + GLuint i; + + emit(p, "if ("); + + for (i = 0; i < 4; i++) { + print_arg( p, deref(arg, i) ); + emit(p, " < 0 "); + if (i + 1 < 4) + emit(p, "|| "); + } + + emit(p, ")\n"); + emit(p, " return 0;\n"); + } -static void do_tex_simple( const struct fragment_program *p, +static void do_tex_simple( struct fragment_program *p, const struct fp_instruction *inst, const char *fn, GLuint texunit, GLuint arg ) { - printf(" %s( ctx, ", fn); - print_reg(arg); - printf(", %d, ", texunit ); - print_dest_reg(inst); - printf(");\n"); + emit(p, " %s( ctx, ", fn); + print_reg( p, arg ); + emit(p, ", %d, ", texunit ); + print_dest_reg(p, inst); + emit(p, ");\n"); } -static void do_tex( const struct fragment_program *p, +static void do_tex( struct fragment_program *p, const struct fp_instruction *inst, const char *fn, GLuint texunit, GLuint arg ) { @@ -325,31 +420,43 @@ static void do_tex( const struct fragment_program *p, return; } - printf(" {\n"); - printf(" GLfloat texcoord[4];\n"); - printf(" GLfloat result[4];\n"); + emit(p, " {\n"); + emit(p, " float texcoord[4];\n"); + emit(p, " float result[4];\n"); for (i = 0; i < 4; i++) { - printf(" texcoord[%d] = ", i); + emit(p, " texcoord[%d] = ", i); print_arg( p, deref(arg, i) ); - printf(";\n"); + emit(p, ";\n"); } - printf(" %s( ctx, texcoord, %d, result);\n", fn, texunit ); + emit(p, " %s( ctx, texcoord, %d, result);\n", fn, texunit ); for (i = 0; i < 4; i++) { if (inst->DstReg.WriteMask[i]) { - printf(" "); - print_dest(inst, i); - printf(" = result[%d];\n", i); + emit(p, " "); + print_dest(p, inst, i); + emit(p, " = result[%d];\n", i); } } - printf(" }\n"); + emit(p, " }\n"); +} + + +static void saturate( struct fragment_program *p, + const struct fp_instruction *inst, + GLuint i ) +{ + emit(p, " "); + print_dest(p, inst, i); + emit(p, " = SATURATE( "); + print_dest(p, inst, i); + emit(p, ");\n"); } static void assign_single( GLuint i, - const struct fragment_program *p, + struct fragment_program *p, const struct fp_instruction *inst, const char *fmt, ... ) @@ -358,16 +465,18 @@ static void assign_single( GLuint i, va_start( ap, fmt ); if (inst->DstReg.WriteMask[i]) { - printf(" "); - print_dest(inst, i); - printf(" = "); + emit(p, " "); + print_dest(p, inst, i); + emit(p, " = "); print_expression( p, i, fmt, ap); + if (inst->Saturate) + saturate(p, inst, i); } va_end( ap ); } -static void assign4( const struct fragment_program *p, +static void assign4( struct fragment_program *p, const struct fp_instruction *inst, const char *fmt, ... ) @@ -378,47 +487,56 @@ static void assign4( const struct fragment_program *p, for (i = 0; i < 4; i++) if (inst->DstReg.WriteMask[i]) { - printf(" "); - print_dest(inst, i); - printf(" = "); + emit(p, " "); + print_dest(p, inst, i); + emit(p, " = "); print_expression( p, i, fmt, ap); + if (inst->Saturate) + saturate(p, inst, i); } va_end( ap ); } -static void assign4_replicate( const struct fragment_program *p, +static void assign4_replicate( struct fragment_program *p, const struct fp_instruction *inst, const char *fmt, ... ) { - GLuint i; + GLuint i, first = 0; GLboolean ok = 0; va_list ap; for (i = 0; i < 4; i++) - if (inst->DstReg.WriteMask[i]) + if (inst->DstReg.WriteMask[i]) { ok = 1; + first = i; + break; + } if (!ok) return; va_start( ap, fmt ); - printf(" "); - - for (i = 0; i < 4; i++) - if (inst->DstReg.WriteMask[i]) { - print_dest(inst, i); - printf(" = "); - } + emit(p, " "); + print_dest(p, inst, first); + emit(p, " = "); print_expression( p, 0, fmt, ap); - + if (inst->Saturate) + saturate(p, inst, first); va_end( ap ); -} - - + for (i = first+1; i < 4; i++) + if (inst->DstReg.WriteMask[i]) { + emit(p, " "); + print_dest(p, inst, i); + emit(p, " = "); + print_dest(p, inst, first); + emit(p, ";\n"); + } +} + @@ -464,7 +582,7 @@ static GLuint nr_args( GLuint opcode ) -static void upload_program( const struct fragment_program *p ) +static void translate_program( struct fragment_program *p ) { const struct fp_instruction *inst = p->Instructions; @@ -477,19 +595,20 @@ static void upload_program( const struct fragment_program *p ) src[i] = src_vector( &inst->SrcReg[i] ); /* Print the original program instruction string */ + if (p->Base.String) { const char *s = (const char *) p->Base.String + inst->StringPos; - printf(" /* "); + emit(p, " /* "); while (*s != ';') { - putchar(*s); + emit_char(p, *s); s++; } - printf("; */\n"); + emit(p, "; */\n"); } switch (inst->Opcode) { case FP_OPCODE_ABS: - assign4(p, inst, "FABSF(%s)", src[0]); + assign4(p, inst, "fabsf(%s)", src[0]); break; case FP_OPCODE_ADD: @@ -541,39 +660,40 @@ static void upload_program( const struct fragment_program *p ) * result[1] = a[1] * b[1]; * result[2] = a[2] * 1; * result[3] = 1 * b[3]; - * - * Here we hope that the compiler can optimize away "x*1" to "x". */ - assign4(p, inst, - "%s*%s", - swizzle(src[0], _ONE, _Y, _Z, _ONE), - swizzle(src[1], _ONE, _Y, _ONE, _W )); + assign_single(0, p, inst, "1.0"); + + assign_single(1, p, inst, "%s * %s", + deref(src[0], _Y), deref(src[1], _Y)); + + assign_single(2, p, inst, "%s", deref(src[0], _Z)); + assign_single(3, p, inst, "%s", deref(src[1], _W)); break; case FP_OPCODE_EX2: - assign4_replicate(p, inst, "EX2(%s)", src[0]); + assign4_replicate(p, inst, "powf(2.0, %s)", src[0]); break; case FP_OPCODE_FLR: - assign4_replicate(p, inst, "FLR(%s)", src[0]); + assign4_replicate(p, inst, "floorf(%s)", src[0]); break; case FP_OPCODE_FRC: - assign4_replicate(p, inst, "FRC(%s)", src[0]); + assign4_replicate(p, inst, "%s - floorf(%s)", src[0], src[0]); break; case FP_OPCODE_KIL: - /* TODO */ + do_tex_kill(p, inst, src[0]); break; case FP_OPCODE_LG2: - assign4_replicate(p, inst, "LOG(%s)", deref(src[0], _X)); + assign4_replicate(p, inst, "LOG2(%s)", src[0]); break; case FP_OPCODE_LIT: assign_single(0, p, inst, "1.0"); assign_single(1, p, inst, "MIN2(%s, 0)", deref(src[0], _X)); - assign_single(2, p, inst, "(%s > 0.0) ? EXP(%s * MIN2(%s, 0)) : 0.0", + assign_single(2, p, inst, "(%s > 0.0) ? expf(%s * MIN2(%s, 0)) : 0.0", deref(src[0], _X), deref(src[0], _Z), deref(src[0], _Y)); @@ -607,26 +727,24 @@ static void upload_program( const struct fragment_program *p ) break; case FP_OPCODE_POW: - assign4_replicate(p, inst, "POW(%s, %s)", - deref(src[0], _X), - deref(src[1], _X)); + assign4_replicate(p, inst, "powf(%s, %s)", src[0], src[1]); break; case FP_OPCODE_RCP: - assign4_replicate(p, inst, "1.0/%s", deref(src[0], _X)); + assign4_replicate(p, inst, "1.0/%s", src[0]); break; case FP_OPCODE_RSQ: - assign4_replicate(p, inst, "INV_SQRTF(%s)", deref(src[0], _X)); + assign4_replicate(p, inst, "_mesa_inv_sqrtf(%s)", src[0]); break; case FP_OPCODE_SCS: if (inst->DstReg.WriteMask[0]) { - assign_single(0, p, inst, "COS(%s)", deref(src[0], _X)); + assign_single(0, p, inst, "cosf(%s)", deref(src[0], _X)); } if (inst->DstReg.WriteMask[1]) { - assign_single(1, p, inst, "SIN(%s)", deref(src[0], _X)); + assign_single(1, p, inst, "sinf(%s)", deref(src[0], _X)); } break; @@ -635,7 +753,7 @@ static void upload_program( const struct fragment_program *p ) break; case FP_OPCODE_SIN: - assign4_replicate(p, inst, "SIN(%s)", deref(src[0], _X)); + assign4_replicate(p, inst, "sinf(%s)", src[0]); break; case FP_OPCODE_SLT: @@ -662,7 +780,7 @@ static void upload_program( const struct fragment_program *p ) do_tex(p, inst, "TXP", inst->TexSrcUnit, src[0]); break; - case FP_OPCODE_X2D: + case FP_OPCODE_XPD: /* Cross product: * result.x = src[0].y * src[1].z - src[0].z * src[1].y; * result.y = src[0].z * src[1].x - src[0].x * src[1].z; @@ -678,6 +796,7 @@ static void upload_program( const struct fragment_program *p ) break; default: + emit(p, "BOGUS OPCODE\n"); return; } } @@ -689,10 +808,15 @@ static void upload_program( const struct fragment_program *p ) void _swrast_translate_program( GLcontext *ctx ) { - if (ctx->FragmentProgram.Current) { - print_header(); - upload_program( ctx->FragmentProgram.Current ); - print_footer(); + struct fragment_program *p = ctx->FragmentProgram.Current; + + if (p) { + p->c_strlen = 0; + + print_header( p ); + translate_program( p ); + print_footer( p ); } } +#endif /*USE_TCC*/