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

📄 s_nvfragprog.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Mesa 3-D graphics library
 * Version:  6.4
 *
 * 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.
 */

/*
 * Regarding GL_NV_fragment_program:
 *
 * Portions of this software may use or implement intellectual
 * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
 * any and all warranties with respect to such intellectual property,
 * including any use thereof or modifications thereto.
 */

#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"


/* if 1, print some debugging info */
#define DEBUG_FRAG 0

/**
 * Fetch a texel.
 */
static void
fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
             GLuint unit, GLfloat color[4] )
{
   GLchan rgba[4];
   SWcontext *swrast = SWRAST_CONTEXT(ctx);

   /* XXX use a float-valued TextureSample routine here!!! */
   swrast->TextureSample[unit](ctx, unit, ctx->Texture.Unit[unit]._Current,
                               1, (const GLfloat (*)[4]) texcoord,
                               &lambda, &rgba);
   color[0] = CHAN_TO_FLOAT(rgba[0]);
   color[1] = CHAN_TO_FLOAT(rgba[1]);
   color[2] = CHAN_TO_FLOAT(rgba[2]);
   color[3] = CHAN_TO_FLOAT(rgba[3]);
}


/**
 * Fetch a texel with the given partial derivatives to compute a level
 * of detail in the mipmap.
 */
static void
fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
                   const GLfloat texdx[4], const GLfloat texdy[4],
                   GLuint unit, GLfloat color[4] )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
   const struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
   const GLfloat texW = (GLfloat) texImg->WidthScale;
   const GLfloat texH = (GLfloat) texImg->HeightScale;
   GLchan rgba[4];

   GLfloat lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
                                         texdx[1], texdy[1], /* dt/dx, dt/dy */
                                         texdx[3], texdy[2], /* dq/dx, dq/dy */
                                         texW, texH,
                                         texcoord[0], texcoord[1], texcoord[3],
                                         1.0F / texcoord[3]);

   swrast->TextureSample[unit](ctx, unit, ctx->Texture.Unit[unit]._Current,
                               1, (const GLfloat (*)[4]) texcoord,
                               &lambda, &rgba);
   color[0] = CHAN_TO_FLOAT(rgba[0]);
   color[1] = CHAN_TO_FLOAT(rgba[1]);
   color[2] = CHAN_TO_FLOAT(rgba[2]);
   color[3] = CHAN_TO_FLOAT(rgba[3]);
}


/**
 * Return a pointer to the 4-element float vector specified by the given
 * source register.
 */
static INLINE const GLfloat *
get_register_pointer( GLcontext *ctx,
                      const struct fp_src_register *source,
                      const struct fp_machine *machine,
                      const struct fragment_program *program )
{
   const GLfloat *src;
   switch (source->File) {
      case PROGRAM_TEMPORARY:
         ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_TEMPS);
         src = machine->Temporaries[source->Index];
         break;
      case PROGRAM_INPUT:
         ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
         src = machine->Inputs[source->Index];
         break;
      case PROGRAM_OUTPUT:
         /* This is only for PRINT */
         ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
         src = machine->Outputs[source->Index];
         break;
      case PROGRAM_LOCAL_PARAM:
         ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
         src = program->Base.LocalParams[source->Index];
         break;
      case PROGRAM_ENV_PARAM:
         ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_PARAMS);
         src = ctx->FragmentProgram.Parameters[source->Index];
         break;
      case PROGRAM_STATE_VAR:
         /* Fallthrough */
      case PROGRAM_NAMED_PARAM:
         ASSERT(source->Index < (GLint) program->Parameters->NumParameters);
         src = program->Parameters->ParameterValues[source->Index];
         break;
      default:
         _mesa_problem(ctx, "Invalid input register file %d in fetch_vector4", source->File);
         src = NULL;
   }
   return src;
}


/**
 * Fetch a 4-element float vector from the given source register.
 * Apply swizzling and negating as needed.
 */
static void
fetch_vector4( GLcontext *ctx,
               const struct fp_src_register *source,
               const struct fp_machine *machine,
               const struct fragment_program *program,
               GLfloat result[4] )
{
   const GLfloat *src = get_register_pointer(ctx, source, machine, program);
   ASSERT(src);

   result[0] = src[GET_SWZ(source->Swizzle, 0)];
   result[1] = src[GET_SWZ(source->Swizzle, 1)];
   result[2] = src[GET_SWZ(source->Swizzle, 2)];
   result[3] = src[GET_SWZ(source->Swizzle, 3)];

   if (source->NegateBase) {
      result[0] = -result[0];
      result[1] = -result[1];
      result[2] = -result[2];
      result[3] = -result[3];
   }
   if (source->Abs) {
      result[0] = FABSF(result[0]);
      result[1] = FABSF(result[1]);
      result[2] = FABSF(result[2]);
      result[3] = FABSF(result[3]);
   }
   if (source->NegateAbs) {
      result[0] = -result[0];
      result[1] = -result[1];
      result[2] = -result[2];
      result[3] = -result[3];
   }
}


/**
 * Fetch the derivative with respect to X for the given register.
 * \return GL_TRUE if it was easily computed or GL_FALSE if we
 * need to execute another instance of the program (ugh)!
 */
static GLboolean
fetch_vector4_deriv( GLcontext *ctx,
                     const struct fp_src_register *source,
                     const struct sw_span *span,
                     char xOrY, GLint column, GLfloat result[4] )
{
   GLfloat src[4];

   ASSERT(xOrY == 'X' || xOrY == 'Y');

   switch (source->Index) {
   case FRAG_ATTRIB_WPOS:
      if (xOrY == 'X') {
         src[0] = 1.0;
         src[1] = 0.0;
         src[2] = span->dzdx / ctx->DrawBuffer->_DepthMaxF;
         src[3] = span->dwdx;
      }
      else {
         src[0] = 0.0;
         src[1] = 1.0;
         src[2] = span->dzdy / ctx->DrawBuffer->_DepthMaxF;
         src[3] = span->dwdy;
      }
      break;
   case FRAG_ATTRIB_COL0:
      if (xOrY == 'X') {
         src[0] = span->drdx * (1.0F / CHAN_MAXF);
         src[1] = span->dgdx * (1.0F / CHAN_MAXF);
         src[2] = span->dbdx * (1.0F / CHAN_MAXF);
         src[3] = span->dadx * (1.0F / CHAN_MAXF);
      }
      else {
         src[0] = span->drdy * (1.0F / CHAN_MAXF);
         src[1] = span->dgdy * (1.0F / CHAN_MAXF);
         src[2] = span->dbdy * (1.0F / CHAN_MAXF);
         src[3] = span->dady * (1.0F / CHAN_MAXF);
      }
      break;
   case FRAG_ATTRIB_COL1:
      if (xOrY == 'X') {
         src[0] = span->dsrdx * (1.0F / CHAN_MAXF);
         src[1] = span->dsgdx * (1.0F / CHAN_MAXF);
         src[2] = span->dsbdx * (1.0F / CHAN_MAXF);
         src[3] = 0.0; /* XXX need this */
      }
      else {
         src[0] = span->dsrdy * (1.0F / CHAN_MAXF);
         src[1] = span->dsgdy * (1.0F / CHAN_MAXF);
         src[2] = span->dsbdy * (1.0F / CHAN_MAXF);
         src[3] = 0.0; /* XXX need this */
      }
      break;
   case FRAG_ATTRIB_FOGC:
      if (xOrY == 'X') {
         src[0] = span->dfogdx;
         src[1] = 0.0;
         src[2] = 0.0;
         src[3] = 0.0;
      }
      else {
         src[0] = span->dfogdy;
         src[1] = 0.0;
         src[2] = 0.0;
         src[3] = 0.0;
      }
      break;
   case FRAG_ATTRIB_TEX0:
   case FRAG_ATTRIB_TEX1:
   case FRAG_ATTRIB_TEX2:
   case FRAG_ATTRIB_TEX3:
   case FRAG_ATTRIB_TEX4:
   case FRAG_ATTRIB_TEX5:
   case FRAG_ATTRIB_TEX6:
   case FRAG_ATTRIB_TEX7:
      if (xOrY == 'X') {
         const GLuint u = source->Index - FRAG_ATTRIB_TEX0;
         /* this is a little tricky - I think I've got it right */
         const GLfloat invQ = 1.0f / (span->tex[u][3]
                                      + span->texStepX[u][3] * column);
         src[0] = span->texStepX[u][0] * invQ;
         src[1] = span->texStepX[u][1] * invQ;
         src[2] = span->texStepX[u][2] * invQ;
         src[3] = span->texStepX[u][3] * invQ;
      }
      else {
         const GLuint u = source->Index - FRAG_ATTRIB_TEX0;
         /* Tricky, as above, but in Y direction */
         const GLfloat invQ = 1.0f / (span->tex[u][3] + span->texStepY[u][3]);
         src[0] = span->texStepY[u][0] * invQ;
         src[1] = span->texStepY[u][1] * invQ;
         src[2] = span->texStepY[u][2] * invQ;
         src[3] = span->texStepY[u][3] * invQ;
      }
      break;
   default:
      return GL_FALSE;
   }

   result[0] = src[GET_SWZ(source->Swizzle, 0)];
   result[1] = src[GET_SWZ(source->Swizzle, 1)];
   result[2] = src[GET_SWZ(source->Swizzle, 2)];
   result[3] = src[GET_SWZ(source->Swizzle, 3)];

   if (source->NegateBase) {
      result[0] = -result[0];
      result[1] = -result[1];
      result[2] = -result[2];
      result[3] = -result[3];
   }
   if (source->Abs) {
      result[0] = FABSF(result[0]);
      result[1] = FABSF(result[1]);
      result[2] = FABSF(result[2]);
      result[3] = FABSF(result[3]);
   }
   if (source->NegateAbs) {
      result[0] = -result[0];
      result[1] = -result[1];
      result[2] = -result[2];
      result[3] = -result[3];
   }
   return GL_TRUE;
}


/**
 * As above, but only return result[0] element.
 */
static void
fetch_vector1( GLcontext *ctx,
               const struct fp_src_register *source,
               const struct fp_machine *machine,
               const struct fragment_program *program,
               GLfloat result[4] )
{
   const GLfloat *src = get_register_pointer(ctx, source, machine, program);
   ASSERT(src);

   result[0] = src[GET_SWZ(source->Swizzle, 0)];

   if (source->NegateBase) {
      result[0] = -result[0];
   }
   if (source->Abs) {
      result[0] = FABSF(result[0]);
   }
   if (source->NegateAbs) {
      result[0] = -result[0];
   }
}


/**
 * Test value against zero and return GT, LT, EQ or UN if NaN.
 */
static INLINE GLuint
generate_cc( float value )
{
   if (value != value)
      return COND_UN;  /* NaN */
   if (value > 0.0F)
      return COND_GT;
   if (value < 0.0F)
      return COND_LT;
   return COND_EQ;
}


/**
 * Test if the ccMaskRule is satisfied by the given condition code.
 * Used to mask destination writes according to the current condition codee.
 */
static INLINE GLboolean
test_cc(GLuint condCode, GLuint ccMaskRule)
{
   switch (ccMaskRule) {
   case COND_EQ: return (condCode == COND_EQ);
   case COND_NE: return (condCode != COND_EQ);
   case COND_LT: return (condCode == COND_LT);
   case COND_GE: return (condCode == COND_GT || condCode == COND_EQ);

⌨️ 快捷键说明

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