⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s_fragprog_to_c.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Mesa 3-D graphics library
 * Version:  6.1
 *
 * Copyright (C) 1999-2004  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 "nvfragprog.h"
#include "macros.h"
#include "program.h"

#include "s_nvfragprog.h"
#include "s_span.h"
#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
 * 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 fp_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 fp_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 fp_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 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( struct fragment_program *p,
			   const struct fp_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 fp_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]) 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -