📄 s_nvfragprog.c
字号:
/*
* 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 + -