s_fragprog.c revision c1f859d4
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.0.3 4 * 5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#include "main/glheader.h" 26#include "main/colormac.h" 27#include "main/context.h" 28#include "main/texstate.h" 29#include "shader/prog_instruction.h" 30 31#include "s_fragprog.h" 32#include "s_span.h" 33 34 35/** 36 * Fetch a texel with given lod. 37 * Called via machine->FetchTexelLod() 38 */ 39static void 40fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda, 41 GLuint unit, GLfloat color[4] ) 42{ 43 const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; 44 45 if (texObj) { 46 SWcontext *swrast = SWRAST_CONTEXT(ctx); 47 GLchan rgba[4]; 48 49 lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod); 50 51 /* XXX use a float-valued TextureSample routine here!!! */ 52 swrast->TextureSample[unit](ctx, texObj, 1, 53 (const GLfloat (*)[4]) texcoord, 54 &lambda, &rgba); 55 color[0] = CHAN_TO_FLOAT(rgba[0]); 56 color[1] = CHAN_TO_FLOAT(rgba[1]); 57 color[2] = CHAN_TO_FLOAT(rgba[2]); 58 color[3] = CHAN_TO_FLOAT(rgba[3]); 59 } 60 else { 61 color[0] = color[1] = color[2] = 0.0F; 62 color[3] = 1.0F; 63 } 64} 65 66 67/** 68 * Fetch a texel with the given partial derivatives to compute a level 69 * of detail in the mipmap. 70 * Called via machine->FetchTexelDeriv() 71 */ 72static void 73fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4], 74 const GLfloat texdx[4], const GLfloat texdy[4], 75 GLfloat lodBias, GLuint unit, GLfloat color[4] ) 76{ 77 SWcontext *swrast = SWRAST_CONTEXT(ctx); 78 const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; 79 80 if (texObj) { 81 const struct gl_texture_image *texImg = 82 texObj->Image[0][texObj->BaseLevel]; 83 const GLfloat texW = (GLfloat) texImg->WidthScale; 84 const GLfloat texH = (GLfloat) texImg->HeightScale; 85 GLfloat lambda; 86 GLchan rgba[4]; 87 88 lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */ 89 texdx[1], texdy[1], /* dt/dx, dt/dy */ 90 texdx[3], texdy[2], /* dq/dx, dq/dy */ 91 texW, texH, 92 texcoord[0], texcoord[1], texcoord[3], 93 1.0F / texcoord[3]) + lodBias; 94 95 lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod); 96 97 /* XXX use a float-valued TextureSample routine here!!! */ 98 swrast->TextureSample[unit](ctx, texObj, 1, 99 (const GLfloat (*)[4]) texcoord, 100 &lambda, &rgba); 101 color[0] = CHAN_TO_FLOAT(rgba[0]); 102 color[1] = CHAN_TO_FLOAT(rgba[1]); 103 color[2] = CHAN_TO_FLOAT(rgba[2]); 104 color[3] = CHAN_TO_FLOAT(rgba[3]); 105 } 106 else { 107 color[0] = color[1] = color[2] = 0.0F; 108 color[3] = 1.0F; 109 } 110} 111 112 113/** 114 * Initialize the virtual fragment program machine state prior to running 115 * fragment program on a fragment. This involves initializing the input 116 * registers, condition codes, etc. 117 * \param machine the virtual machine state to init 118 * \param program the fragment program we're about to run 119 * \param span the span of pixels we'll operate on 120 * \param col which element (column) of the span we'll operate on 121 */ 122static void 123init_machine(GLcontext *ctx, struct gl_program_machine *machine, 124 const struct gl_fragment_program *program, 125 const SWspan *span, GLuint col) 126{ 127 if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) { 128 /* Clear temporary registers (undefined for ARB_f_p) */ 129 _mesa_bzero(machine->Temporaries, 130 MAX_PROGRAM_TEMPS * 4 * sizeof(GLfloat)); 131 } 132 133 /* Setup pointer to input attributes */ 134 machine->Attribs = span->array->attribs; 135 136 machine->DerivX = (GLfloat (*)[4]) span->attrStepX; 137 machine->DerivY = (GLfloat (*)[4]) span->attrStepY; 138 machine->NumDeriv = FRAG_ATTRIB_MAX; 139 140 machine->Samplers = program->Base.SamplerUnits; 141 142 /* if running a GLSL program (not ARB_fragment_program) */ 143 if (ctx->Shader.CurrentProgram) { 144 /* Store front/back facing value in register FOGC.Y */ 145 machine->Attribs[FRAG_ATTRIB_FOGC][col][1] = 1.0 - span->facing; 146 /* Note FOGC.ZW is gl_PointCoord if drawing a sprite */ 147 } 148 149 machine->CurElement = col; 150 151 /* init condition codes */ 152 machine->CondCodes[0] = COND_EQ; 153 machine->CondCodes[1] = COND_EQ; 154 machine->CondCodes[2] = COND_EQ; 155 machine->CondCodes[3] = COND_EQ; 156 157 /* init call stack */ 158 machine->StackDepth = 0; 159 160 machine->FetchTexelLod = fetch_texel_lod; 161 machine->FetchTexelDeriv = fetch_texel_deriv; 162} 163 164 165/** 166 * Run fragment program on the pixels in span from 'start' to 'end' - 1. 167 */ 168static void 169run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end) 170{ 171 SWcontext *swrast = SWRAST_CONTEXT(ctx); 172 const struct gl_fragment_program *program = ctx->FragmentProgram._Current; 173 const GLbitfield outputsWritten = program->Base.OutputsWritten; 174 struct gl_program_machine *machine = &swrast->FragProgMachine; 175 GLuint i; 176 177 for (i = start; i < end; i++) { 178 if (span->array->mask[i]) { 179 init_machine(ctx, machine, program, span, i); 180 181 if (_mesa_execute_program(ctx, &program->Base, machine)) { 182 183 /* Store result color */ 184 if (outputsWritten & (1 << FRAG_RESULT_COLR)) { 185 COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i], 186 machine->Outputs[FRAG_RESULT_COLR]); 187 } 188 else { 189 /* Multiple drawbuffers / render targets 190 * Note that colors beyond 0 and 1 will overwrite other 191 * attributes, such as FOGC, TEX0, TEX1, etc. That's OK. 192 */ 193 GLuint buf; 194 for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { 195 if (outputsWritten & (1 << (FRAG_RESULT_DATA0 + buf))) { 196 COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0 + buf][i], 197 machine->Outputs[FRAG_RESULT_DATA0 + buf]); 198 } 199 } 200 } 201 202 /* Store result depth/z */ 203 if (outputsWritten & (1 << FRAG_RESULT_DEPR)) { 204 const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPR][2]; 205 if (depth <= 0.0) 206 span->array->z[i] = 0; 207 else if (depth >= 1.0) 208 span->array->z[i] = ctx->DrawBuffer->_DepthMax; 209 else 210 span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF); 211 } 212 } 213 else { 214 /* killed fragment */ 215 span->array->mask[i] = GL_FALSE; 216 span->writeAll = GL_FALSE; 217 } 218 } 219 } 220} 221 222 223/** 224 * Execute the current fragment program for all the fragments 225 * in the given span. 226 */ 227void 228_swrast_exec_fragment_program( GLcontext *ctx, SWspan *span ) 229{ 230 const struct gl_fragment_program *program = ctx->FragmentProgram._Current; 231 232 /* incoming colors should be floats */ 233 if (program->Base.InputsRead & FRAG_BIT_COL0) { 234 ASSERT(span->array->ChanType == GL_FLOAT); 235 } 236 237 ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */ 238 239 run_program(ctx, span, 0, span->end); 240 241 if (program->Base.OutputsWritten & (1 << FRAG_RESULT_COLR)) { 242 span->interpMask &= ~SPAN_RGBA; 243 span->arrayMask |= SPAN_RGBA; 244 } 245 246 if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) { 247 span->interpMask &= ~SPAN_Z; 248 span->arrayMask |= SPAN_Z; 249 } 250 251 ctx->_CurrentProgram = 0; 252} 253 254