Browse Source

At keithw's request, remove all traces of the "fragment program to C" and

TCC experiment.
tags/mesa_20060201
Ian Romanick 20 years ago
parent
commit
5374e4ba7e

+ 0
- 5
src/mesa/main/mtypes.h View File

@@ -1807,11 +1807,6 @@ struct fragment_program
GLenum FogOption;
struct program_parameter_list *Parameters; /**< array [NumParameters] */
GLboolean UsesKill;

#ifdef USE_TCC
char c_str[4096]; /* experimental... */
int c_strlen;
#endif
};

struct ati_fragment_shader

+ 0
- 2
src/mesa/sources View File

@@ -93,7 +93,6 @@ SWRAST_SOURCES = \
swrast/s_drawpix.c \
swrast/s_feedback.c \
swrast/s_fog.c \
swrast/s_fragprog_to_c.c \
swrast/s_imaging.c \
swrast/s_lines.c \
swrast/s_logic.c \
@@ -104,7 +103,6 @@ SWRAST_SOURCES = \
swrast/s_readpix.c \
swrast/s_span.c \
swrast/s_stencil.c \
swrast/s_tcc.c \
swrast/s_texcombine.c \
swrast/s_texfilter.c \
swrast/s_texstore.c \

+ 0
- 14
src/mesa/swrast/s_context.h View File

@@ -391,18 +391,4 @@ _swrast_validate_derived( GLcontext *ctx );
#define FixedToChan(X) FixedToInt(X)
#endif



extern void
_swrast_translate_program( GLcontext *ctx );

extern GLboolean
_swrast_execute_codegen_program(GLcontext *ctx,
const struct fragment_program *program,
GLuint maxInst,
struct fp_machine *machine,
const struct sw_span *span,
GLuint column );


#endif

+ 0
- 777
src/mesa/swrast/s_fragprog_to_c.c View File

@@ -1,777 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* An amusing little utility to print ARB fragment programs out as a C
* function. Resulting code not tested except visually.
*/


#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "program_instruction.h"
#include "macros.h"
#include "program.h"

#include "s_nvfragprog.h"
#include "s_span.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
* it's overkill & we could probably just pass around the original
* datatypes instead.
*/

#define UREG_TYPE_TEMP 0
#define UREG_TYPE_INTERP 1
#define UREG_TYPE_LOCAL_CONST 2
#define UREG_TYPE_ENV_CONST 3
#define UREG_TYPE_STATE_CONST 4
#define UREG_TYPE_PARAM 5
#define UREG_TYPE_OUTPUT 6
#define UREG_TYPE_MASK 0x7

#define UREG_TYPE_SHIFT 29
#define UREG_NR_SHIFT 24
#define UREG_NR_MASK 0x1f /* 31 */
#define UREG_CHANNEL_X_NEGATE_SHIFT 23
#define UREG_CHANNEL_X_SHIFT 20
#define UREG_CHANNEL_Y_NEGATE_SHIFT 19
#define UREG_CHANNEL_Y_SHIFT 16
#define UREG_CHANNEL_Z_NEGATE_SHIFT 15
#define UREG_CHANNEL_Z_SHIFT 12
#define UREG_CHANNEL_W_NEGATE_SHIFT 11
#define UREG_CHANNEL_W_SHIFT 8
#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5
#define UREG_CHANNEL_ZERO_SHIFT 4
#define UREG_CHANNEL_ONE_NEGATE_MBZ 1
#define UREG_CHANNEL_ONE_SHIFT 0

#define UREG_BAD 0xffffffff /* not a valid ureg */

#define _X 0
#define _Y 1
#define _Z 2
#define _W 3
#define _ZERO 4 /* NOTE! */
#define _ONE 5 /* NOTE! */


/* Construct a ureg:
*/
#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \
((nr) << UREG_NR_SHIFT) | \
(_X << UREG_CHANNEL_X_SHIFT) | \
(_Y << UREG_CHANNEL_Y_SHIFT) | \
(_Z << UREG_CHANNEL_Z_SHIFT) | \
(_W << UREG_CHANNEL_W_SHIFT) | \
(_ZERO << UREG_CHANNEL_ZERO_SHIFT) | \
(_ONE << UREG_CHANNEL_ONE_SHIFT))

#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & \
(0xf<<UREG_CHANNEL_X_SHIFT))
#define CHANNEL_SRC( src, channel ) (src>>(channel*4))

#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)&UREG_TYPE_MASK)
#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)&UREG_NR_MASK)



#define UREG_XYZW_CHANNEL_MASK 0x00ffff00

#define deref(reg,pos) swizzle(reg, pos, pos, pos, pos)


static INLINE int is_swizzled( int reg )
{
return ((reg & UREG_XYZW_CHANNEL_MASK) !=
(UREG(0,0) & UREG_XYZW_CHANNEL_MASK));
}


/* One neat thing about the UREG representation:
*/
static INLINE int swizzle( int reg, int x, int y, int z, int w )
{
return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, y ), 1 ) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, z ), 2 ) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, w ), 3 ));
}

/* Another neat thing about the UREG representation:
*/
static INLINE int negate( int reg, int x, int y, int z, int w )
{
return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)|
((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)|
((z&1)<<UREG_CHANNEL_Z_NEGATE_SHIFT)|
((w&1)<<UREG_CHANNEL_W_NEGATE_SHIFT));
}



static GLuint src_reg_file( GLuint file )
{
switch (file) {
case PROGRAM_TEMPORARY: return UREG_TYPE_TEMP;
case PROGRAM_INPUT: return UREG_TYPE_INTERP;
case PROGRAM_LOCAL_PARAM: return UREG_TYPE_LOCAL_CONST;
case PROGRAM_ENV_PARAM: return UREG_TYPE_ENV_CONST;

case PROGRAM_STATE_VAR: return UREG_TYPE_STATE_CONST;
case PROGRAM_NAMED_PARAM: return UREG_TYPE_PARAM;
default: return UREG_BAD;
}
}

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
* constants, apply swizzling and negation as needed.
*/
static GLuint src_vector( const struct prog_src_register *source )
{
GLuint src;

assert(source->Index < 32); /* limitiation of UREG representation */

src = UREG( src_reg_file( source->File ), source->Index );

src = swizzle(src,
_X + source->Swizzle[0],
_X + source->Swizzle[1],
_X + source->Swizzle[2],
_X + source->Swizzle[3]);

if (source->NegateBase)
src = negate( src, 1,1,1,1 );

return src;
}


static void print_header( struct fragment_program *p )
{
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"
" float temp[32][4];\n"
);
}

static void print_footer( struct fragment_program *p )
{
emit(p, " return 1;");
emit(p, "}\n");
}

static void print_dest_reg( struct fragment_program *p,
const struct prog_instruction *inst )
{
switch (inst->DstReg.File) {
case PROGRAM_OUTPUT:
emit(p, "outputs[%d]", inst->DstReg.Index);
break;
case PROGRAM_TEMPORARY:
emit(p, "temp[%d]", inst->DstReg.Index);
break;
default:
break;
}
}

static void print_dest( struct fragment_program *p,
const struct prog_instruction *inst,
GLuint idx )
{
print_dest_reg(p, inst);
emit(p, "[%d]", idx);
}


#define UREG_SRC0(reg) (((reg)>>UREG_CHANNEL_X_SHIFT) & 0x7)

static void print_reg( struct fragment_program *p,
GLuint arg )
{
switch (GET_UREG_TYPE(arg)) {
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, "local_param"); break;
};
emit(p, "[%d]", GET_UREG_NR(arg));

if (GET_UREG_TYPE(arg) == UREG_TYPE_STATE_CONST) {
emit(p, ".Values");
}
}


static void print_arg( struct fragment_program *p,
GLuint arg )
{
GLuint src = UREG_SRC0(arg);

if (src == _ZERO) {
emit(p, "0");
return;
}

if (arg & (1<<UREG_CHANNEL_X_NEGATE_SHIFT))
emit(p, "-");

if (src == _ONE) {
emit(p, "1");
return;
}

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( p, arg );

switch (src){
case _X: emit(p, "[0]"); break;
case _Y: emit(p, "[1]"); break;
case _Z: emit(p, "[2]"); break;
case _W: emit(p, "[3]"); break;
}
}


/* This is where the handling of expressions breaks down into string
* processing:
*/
static void print_expression( struct fragment_program *p,
GLuint i,
const char *fmt,
va_list ap )
{
while (*fmt) {
if (*fmt == '%' && *(fmt+1) == 's') {
int reg = va_arg(ap, int);

/* Use of deref() is a bit of a hack:
*/
print_arg( p, deref(reg, i) );
fmt += 2;
}
else {
emit_char(p, *fmt);
fmt++;
}
}

emit(p, ";\n");
}

static void do_tex_kill( struct fragment_program *p,
const struct prog_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( struct fragment_program *p,
const struct prog_instruction *inst,
const char *fn, GLuint texunit, GLuint arg )
{
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( struct fragment_program *p,
const struct prog_instruction *inst,
const char *fn, GLuint texunit, GLuint arg )
{
GLuint i;
GLboolean need_tex = GL_FALSE, need_result = GL_FALSE;

for (i = 0; i < 4; i++)
if (!inst->DstReg.WriteMask[i])
need_result = GL_TRUE;

if (is_swizzled(arg))
need_tex = GL_TRUE;

if (!need_tex && !need_result) {
do_tex_simple( p, inst, fn, texunit, arg );
return;
}

emit(p, " {\n");
emit(p, " float texcoord[4];\n");
emit(p, " float result[4];\n");

for (i = 0; i < 4; i++) {
emit(p, " texcoord[%d] = ", i);
print_arg( p, deref(arg, i) );
emit(p, ";\n");
}

emit(p, " %s( ctx, texcoord, %d, result);\n", fn, texunit );

for (i = 0; i < 4; i++) {
if (inst->DstReg.WriteMask[i]) {
emit(p, " ");
print_dest(p, inst, i);
emit(p, " = result[%d];\n", i);
}
}

emit(p, " }\n");
}


static void saturate( struct fragment_program *p,
const struct prog_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,
struct fragment_program *p,
const struct prog_instruction *inst,
const char *fmt,
... )
{
va_list ap;
va_start( ap, fmt );

if (inst->DstReg.WriteMask[i]) {
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( struct fragment_program *p,
const struct prog_instruction *inst,
const char *fmt,
... )
{
GLuint i;
va_list ap;
va_start( ap, fmt );

for (i = 0; i < 4; i++)
if (inst->DstReg.WriteMask[i]) {
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( struct fragment_program *p,
const struct prog_instruction *inst,
const char *fmt,
... )
{
GLuint i, first = 0;
GLboolean ok = 0;
va_list ap;

for (i = 0; i < 4; i++)
if (inst->DstReg.WriteMask[i]) {
ok = 1;
first = i;
break;
}

if (!ok) return;

va_start( ap, fmt );

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");
}
}

static void translate_program( struct fragment_program *p )
{
const struct prog_instruction *inst = p->Instructions;

for (; inst->Opcode != OPCODE_END; inst++) {

GLuint src[3], i;
GLuint nr = _mesa_num_inst_src_regs( inst->Opcode );
for (i = 0; i < nr; i++)
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;
emit(p, " /* ");
while (*s != ';') {
emit_char(p, *s);
s++;
}
emit(p, "; */\n");
}

switch (inst->Opcode) {
case OPCODE_ABS:
assign4(p, inst, "fabsf(%s)", src[0]);
break;

case OPCODE_ADD:
assign4(p, inst, "%s + %s", src[0], src[1]);
break;

case OPCODE_CMP:
assign4(p, inst, "%s < 0.0F ? %s : %s", src[0], src[1], src[2]);
break;

case OPCODE_COS:
assign4_replicate(p, inst, "COS(%s)", src[0]);
break;

case OPCODE_DP3:
assign4_replicate(p, inst,
"%s*%s + %s*%s + %s*%s",
deref(src[0],_X),
deref(src[1],_X),
deref(src[0],_Y),
deref(src[1],_Y),
deref(src[0],_Z),
deref(src[1],_Z));
break;

case OPCODE_DP4:
assign4_replicate(p, inst,
"%s*%s + %s*%s + %s*%s + %s*%s",
deref(src[0],_X),
deref(src[1],_X),
deref(src[0],_Y),
deref(src[1],_Y),
deref(src[0],_Z),
deref(src[1],_Z));
break;

case OPCODE_DPH:
assign4_replicate(p, inst,
"%s*%s + %s*%s + %s*%s + %s",
deref(src[0],_X),
deref(src[1],_X),
deref(src[0],_Y),
deref(src[1],_Y),
deref(src[1],_Z));
break;

case OPCODE_DST:
/* result[0] = 1 * 1;
* result[1] = a[1] * b[1];
* result[2] = a[2] * 1;
* result[3] = 1 * b[3];
*/
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 OPCODE_EX2:
assign4_replicate(p, inst, "powf(2.0, %s)", src[0]);
break;

case OPCODE_FLR:
assign4_replicate(p, inst, "floorf(%s)", src[0]);
break;

case OPCODE_FRC:
assign4_replicate(p, inst, "%s - floorf(%s)", src[0], src[0]);
break;

case OPCODE_KIL:
do_tex_kill(p, inst, src[0]);
break;

case OPCODE_LG2:
assign4_replicate(p, inst, "LOG2(%s)", src[0]);
break;

case 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) ? expf(%s * MIN2(%s, 0)) : 0.0",
deref(src[0], _X),
deref(src[0], _Z),
deref(src[0], _Y));
assign_single(3, p, inst, "1.0");
break;

case OPCODE_LRP:
assign4(p, inst,
"%s * %s + (1.0 - %s) * %s",
src[0], src[1], src[0], src[2]);
break;

case OPCODE_MAD:
assign4(p, inst, "%s * %s + %s", src[0], src[1], src[2]);
break;

case OPCODE_MAX:
assign4(p, inst, "MAX2(%s, %s)", src[0], src[1]);
break;

case OPCODE_MIN:
assign4(p, inst, "MIN2(%s, %s)", src[0], src[1]);
break;

case OPCODE_MOV:
assign4(p, inst, "%s", src[0]);
break;

case OPCODE_MUL:
assign4(p, inst, "%s * %s", src[0], src[1]);
break;

case OPCODE_POW:
assign4_replicate(p, inst, "powf(%s, %s)", src[0], src[1]);
break;

case OPCODE_RCP:
assign4_replicate(p, inst, "1.0/%s", src[0]);
break;

case OPCODE_RSQ:
assign4_replicate(p, inst, "_mesa_inv_sqrtf(%s)", src[0]);
break;
case OPCODE_SCS:
if (inst->DstReg.WriteMask[0]) {
assign_single(0, p, inst, "cosf(%s)", deref(src[0], _X));
}

if (inst->DstReg.WriteMask[1]) {
assign_single(1, p, inst, "sinf(%s)", deref(src[0], _X));
}
break;

case OPCODE_SGE:
assign4(p, inst, "%s >= %s ? 1.0 : 0.0", src[0], src[1]);
break;

case OPCODE_SIN:
assign4_replicate(p, inst, "sinf(%s)", src[0]);
break;

case OPCODE_SLT:
assign4(p, inst, "%s < %s ? 1.0 : 0.0", src[0], src[1]);
break;

case OPCODE_SUB:
assign4(p, inst, "%s - %s", src[0], src[1]);
break;

case OPCODE_SWZ: /* same implementation as MOV: */
assign4(p, inst, "%s", src[0]);
break;

case OPCODE_TEX:
do_tex(p, inst, "TEX", inst->TexSrcUnit, src[0]);
break;

case OPCODE_TXB:
do_tex(p, inst, "TXB", inst->TexSrcUnit, src[0]);
break;

case OPCODE_TXP:
do_tex(p, inst, "TXP", inst->TexSrcUnit, src[0]);
break;

case 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;
* result.z = src[0].x * src[1].y - src[0].y * src[1].x;
* result.w = undef;
*/
assign4(p, inst,
"%s * %s - %s * %s",
swizzle(src[0], _Y, _Z, _X, _ONE),
swizzle(src[1], _Z, _X, _Y, _ONE),
swizzle(src[0], _Z, _X, _Y, _ONE),
swizzle(src[1], _Y, _Z, _X, _ONE));
break;

default:
emit(p, "BOGUS OPCODE\n");
return;
}
}
}





void _swrast_translate_program( GLcontext *ctx )
{
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*/

+ 0
- 9
src/mesa/swrast/s_nvfragprog.c View File

@@ -1466,20 +1466,11 @@ _swrast_exec_fragment_program( GLcontext *ctx, struct sw_span *span )
init_machine(ctx, &ctx->FragmentProgram.Machine,
ctx->FragmentProgram._Current, span, i);

#ifdef USE_TCC
if (!_swrast_execute_codegen_program(ctx, program, ~0,
&ctx->FragmentProgram.Machine,
span, i)) {
span->array->mask[i] = GL_FALSE; /* killed fragment */
span->writeAll = GL_FALSE;
}
#else
if (!execute_program(ctx, program, ~0,
&ctx->FragmentProgram.Machine, span, i)) {
span->array->mask[i] = GL_FALSE; /* killed fragment */
span->writeAll = GL_FALSE;
}
#endif

/* Store output registers */
{

+ 0
- 185
src/mesa/swrast/s_tcc.c View File

@@ -1,185 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* An attempt to hook s_fragprog_to_c.c up to libtcc.a to try &
* generate some real code.
*
* TCC isn't threadsafe, so it will need additional locking help if we
* end up using it as a backend in mesa.
*/

#include "glheader.h"
#include "imports.h"
#include "colormac.h"
#include "context.h"
#include "program_instruction.h"
#include "macros.h"
#include "program.h"

#include "s_nvfragprog.h"

#ifdef USE_TCC

#include <libtcc.h>

typedef int (*cfunc)( void *ctx,
const GLfloat (*local_param)[4],
const GLfloat (*env_param)[4],
const struct program_parameter *state_param,
const GLfloat (*interp)[4],
GLfloat (*outputs)[4]);


static cfunc current_func;
static struct fragment_program *current_program;
static TCCState *current_tcc_state;


static void TEX( void *cc, const float *texcoord, int unit, float *result )
{
GLcontext *ctx = (GLcontext *)cc;
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat lambda = 1.0; /* hack */
GLchan rgba[4];

swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
1, (const GLfloat (*)[4]) texcoord,
&lambda, &rgba);

result[0] = CHAN_TO_FLOAT(rgba[0]);
result[1] = CHAN_TO_FLOAT(rgba[1]);
result[2] = CHAN_TO_FLOAT(rgba[2]);
result[3] = CHAN_TO_FLOAT(rgba[3]);
}


static void TXB( void *cc, const float *texcoord, int unit, float *result )
{
GLcontext *ctx = (GLcontext *)cc;
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat lambda = 1.0; /* hack */
GLchan rgba[4];

/* texcoord[3] is the bias to add to lambda */
lambda += texcoord[3];


/* Is it necessary to reset texcoord[3] to 1 at this point?
*/
swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
1, (const GLfloat (*)[4]) texcoord,
&lambda, &rgba);

result[0] = CHAN_TO_FLOAT(rgba[0]);
result[1] = CHAN_TO_FLOAT(rgba[1]);
result[2] = CHAN_TO_FLOAT(rgba[2]);
result[3] = CHAN_TO_FLOAT(rgba[3]);
}


static void TXP( void *cc, const float *texcoord, int unit, float *result )
{
/* I think that TEX needs to undo the perspective divide which has
* already occurred. In the meantime, TXP is correct to do this:
*/
TEX( cc, texcoord, unit, result );
}


static cfunc codegen( TCCState *s, const char *prog, const char *fname )
{
unsigned long val;

if (s)
tcc_delete(s);
s = tcc_new();
if (!s)
return 0;

tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
tcc_compile_string(s, prog);

/* tcc_add_dll("/usr/lib/libm.so"); */

tcc_add_symbol(s, "TEX", (unsigned long)&TEX);
tcc_add_symbol(s, "TXB", (unsigned long)&TXB);
tcc_add_symbol(s, "TXP", (unsigned long)&TXP);


tcc_relocate(s);
tcc_get_symbol(s, &val, fname);
return (cfunc) val;
}

/* TCC isn't threadsafe and even seems not to like having more than
* one TCCState created or used at any one time in a single threaded
* environment. So, this code is all for investigation only and can't
* currently be used in Mesa proper.
*
* I've taken some liberties with globals myself, now.
*/
GLboolean
_swrast_execute_codegen_program( GLcontext *ctx,
const struct fragment_program *program, GLuint maxInst,
struct fp_machine *machine, const struct sw_span *span,
GLuint column )
{
if (program != current_program) {
_swrast_translate_program( ctx );

fprintf(stderr, "%s: compiling:\n%s\n", __FUNCTION__, program->c_str);

current_program = program;
current_func = codegen( current_tcc_state, program->c_str,
"run_program" );
}

assert(current_func);

return current_func( ctx,
program->Base.LocalParams,
(const GLfloat (*)[4])ctx->FragmentProgram.Parameters,
program->Parameters->Parameters,
(const GLfloat (*)[4])machine->Inputs,
machine->Outputs );
}

#else /* USE_TCC */

GLboolean
_swrast_execute_codegen_program( GLcontext *ctx,
const struct fragment_program *program, GLuint maxInst,
struct fp_machine *machine, const struct sw_span *span,
GLuint column )
{
(void) ctx;
(void) program; (void) maxInst;
(void) machine; (void) span;
(void) column;
return 0;
}

#endif

Loading…
Cancel
Save