📄 s_atifragshader.c
字号:
/*
*
* Copyright (C) 2004 David Airlie 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
* DAVID AIRLIE 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.
*/
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "atifragshader.h"
#include "macros.h"
#include "program.h"
#include "s_atifragshader.h"
#include "s_nvfragprog.h"
#include "s_span.h"
#include "s_texture.h"
/**
* 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]);
}
static void
apply_swizzle(struct atifs_machine *machine, GLuint reg, GLuint swizzle)
{
GLfloat s, t, r, q;
s = machine->Registers[reg][0];
t = machine->Registers[reg][1];
r = machine->Registers[reg][2];
q = machine->Registers[reg][3];
switch (swizzle) {
case GL_SWIZZLE_STR_ATI:
machine->Registers[reg][0] = s;
machine->Registers[reg][1] = t;
machine->Registers[reg][2] = r;
break;
case GL_SWIZZLE_STQ_ATI:
machine->Registers[reg][0] = s;
machine->Registers[reg][1] = t;
machine->Registers[reg][2] = q;
break;
case GL_SWIZZLE_STR_DR_ATI:
machine->Registers[reg][0] = s / r;
machine->Registers[reg][1] = t / r;
machine->Registers[reg][2] = 1 / r;
break;
case GL_SWIZZLE_STQ_DQ_ATI:
machine->Registers[reg][0] = s / q;
machine->Registers[reg][1] = t / q;
machine->Registers[reg][2] = 1 / q;
break;
}
machine->Registers[reg][3] = 0.0;
}
static void
apply_src_rep(GLint optype, GLuint rep, GLfloat * val)
{
GLint i;
GLint start, end;
if (!rep)
return;
start = optype ? 3 : 0;
end = optype ? 4 : 3;
for (i = start; i < end; i++) {
switch (rep) {
case GL_RED:
val[i] = val[0];
break;
case GL_GREEN:
val[i] = val[1];
break;
case GL_BLUE:
val[i] = val[2];
break;
case GL_ALPHA:
val[i] = val[3];
break;
}
}
}
static void
apply_src_mod(GLint optype, GLuint mod, GLfloat * val)
{
GLint i;
GLint start, end;
if (!mod)
return;
start = optype ? 3 : 0;
end = optype ? 4 : 3;
for (i = start; i < end; i++) {
if (mod & GL_COMP_BIT_ATI)
val[i] = 1 - val[i];
if (mod & GL_BIAS_BIT_ATI)
val[i] = val[i] - 0.5;
if (mod & GL_2X_BIT_ATI)
val[i] = 2 * val[i];
if (mod & GL_NEGATE_BIT_ATI)
val[i] = -val[i];
}
}
static void
apply_dst_mod(GLuint optype, GLuint mod, GLfloat * val)
{
GLint i;
GLint has_sat = mod & GL_SATURATE_BIT_ATI;
GLint start, end;
mod &= ~GL_SATURATE_BIT_ATI;
start = optype ? 3 : 0;
end = optype ? 4 : 3;
for (i = start; i < end; i++) {
switch (mod) {
case GL_2X_BIT_ATI:
val[i] = 2 * val[i];
break;
case GL_4X_BIT_ATI:
val[i] = 4 * val[i];
break;
case GL_8X_BIT_ATI:
val[i] = 8 * val[i];
break;
case GL_HALF_BIT_ATI:
val[i] = val[i] * 0.5;
break;
case GL_QUARTER_BIT_ATI:
val[i] = val[i] * 0.25;
break;
case GL_EIGHTH_BIT_ATI:
val[i] = val[i] * 0.125;
break;
}
if (has_sat) {
if (val[i] < 0.0)
val[i] = 0;
else if (val[i] > 1.0)
val[i] = 1.0;
}
else {
if (val[i] < -8.0)
val[i] = -8.0;
else if (val[i] > 8.0)
val[i] = 8.0;
}
}
}
static void
write_dst_addr(GLuint optype, GLuint mod, GLuint mask, GLfloat * src,
GLfloat * dst)
{
GLint i;
apply_dst_mod(optype, mod, src);
if (optype == ATI_FRAGMENT_SHADER_COLOR_OP) {
if (mask) {
if (mask & GL_RED_BIT_ATI)
dst[0] = src[0];
if (mask & GL_GREEN_BIT_ATI)
dst[1] = src[1];
if (mask & GL_BLUE_BIT_ATI)
dst[2] = src[2];
}
else {
for (i = 0; i < 3; i++)
dst[i] = src[i];
}
}
else
dst[3] = src[3];
}
static void
finish_pass(struct atifs_machine *machine)
{
GLint i;
for (i = 0; i < 6; i++) {
COPY_4V(machine->PrevPassRegisters[i], machine->Registers[i]);
}
}
/**
* Execute the given fragment shader
* NOTE: we do everything in single-precision floating point; we don't
* currently observe the single/half/fixed-precision qualifiers.
* \param ctx - rendering context
* \param program - the fragment program to execute
* \param machine - machine state (register file)
* \param maxInst - max number of instructions to execute
* \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
*/
struct ati_fs_opcode_st ati_fs_opcodes[] = {
{GL_ADD_ATI, 2},
{GL_SUB_ATI, 2},
{GL_MUL_ATI, 2},
{GL_MAD_ATI, 3},
{GL_LERP_ATI, 3},
{GL_MOV_ATI, 1},
{GL_CND_ATI, 3},
{GL_CND0_ATI, 3},
{GL_DOT2_ADD_ATI, 3},
{GL_DOT3_ATI, 2},
{GL_DOT4_ATI, 2}
};
static void
handle_pass_op(struct atifs_machine *machine, struct atifs_instruction *inst,
const struct sw_span *span, GLuint column)
{
GLuint idx = inst->DstReg[0].Index - GL_REG_0_ATI;
GLuint swizzle = inst->DstReg[0].Swizzle;
GLuint pass_tex = inst->SrcReg[0][0].Index;
/* if we get here after passing pass one then we are starting pass two - backup the registers */
if (machine->pass == 1) {
finish_pass(machine);
machine->pass = 2;
}
if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) {
pass_tex -= GL_TEXTURE0_ARB;
COPY_4V(machine->Registers[idx],
span->array->texcoords[pass_tex][column]);
}
else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI
&& machine->pass == 2) {
pass_tex -= GL_REG_0_ATI;
COPY_4V(machine->Registers[idx], machine->PrevPassRegisters[pass_tex]);
}
apply_swizzle(machine, idx, swizzle);
}
static void
handle_sample_op(GLcontext * ctx, struct atifs_machine *machine,
struct atifs_instruction *inst, const struct sw_span *span,
GLuint column)
{
GLuint idx = inst->DstReg[0].Index - GL_REG_0_ATI;
GLuint swizzle = inst->DstReg[0].Swizzle;
GLuint sample_tex = inst->SrcReg[0][0].Index;
/* if we get here after passing pass one then we are starting pass two - backup the registers */
if (machine->pass == 1) {
finish_pass(machine);
machine->pass = 2;
}
if (sample_tex >= GL_TEXTURE0_ARB && sample_tex <= GL_TEXTURE7_ARB) {
sample_tex -= GL_TEXTURE0_ARB;
fetch_texel(ctx, span->array->texcoords[sample_tex][column], 0.0F,
sample_tex, machine->Registers[idx]);
}
else if (sample_tex >= GL_REG_0_ATI && sample_tex <= GL_REG_5_ATI) {
/* this is wrong... */
sample_tex -= GL_REG_0_ATI;
fetch_texel(ctx, machine->Registers[sample_tex], 0, sample_tex,
machine->Registers[idx]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -