mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-03 12:08:06 +02:00
At keithw's request, remove all traces of the "fragment program to C" and
TCC experiment.
This commit is contained in:
parent
4884db6eb2
commit
5374e4ba7e
6 changed files with 0 additions and 992 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
@ -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 */
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Reference in a new issue