📄 s_nvfragprog.c
字号:
/* * 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. *//* * 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 "program_instruction.h"#include "program.h"#include "s_nvfragprog.h"#include "s_span.h"/* if 1, print some debugging info */#define DEBUG_FRAG 0/** * Fetch a texel. */static voidfetch_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, 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 voidfetch_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, 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 prog_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->Base.Parameters->NumParameters); src = program->Base.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 voidfetch_vector4( GLcontext *ctx, const struct prog_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 GLbooleanfetch_vector4_deriv( GLcontext *ctx, const struct prog_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 voidfetch_vector1( GLcontext *ctx, const struct prog_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 GLuintgenerate_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 GLbooleantest_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); case COND_LE: return (condCode == COND_LT || condCode == COND_EQ); case COND_GT: return (condCode == COND_GT); case COND_TR: return GL_TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -