Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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 "program/prog_instruction.h"
  28.  
  29. #include "s_context.h"
  30. #include "s_fragprog.h"
  31. #include "s_span.h"
  32.  
  33.  
  34. /**
  35.  * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
  36.  * and return results in 'colorOut'.
  37.  */
  38. static INLINE void
  39. swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
  40. {
  41.    if (swizzle == SWIZZLE_NOOP) {
  42.       COPY_4V(colorOut, texel);
  43.    }
  44.    else {
  45.       GLfloat vector[6];
  46.       vector[SWIZZLE_X] = texel[0];
  47.       vector[SWIZZLE_Y] = texel[1];
  48.       vector[SWIZZLE_Z] = texel[2];
  49.       vector[SWIZZLE_W] = texel[3];
  50.       vector[SWIZZLE_ZERO] = 0.0F;
  51.       vector[SWIZZLE_ONE] = 1.0F;
  52.       colorOut[0] = vector[GET_SWZ(swizzle, 0)];
  53.       colorOut[1] = vector[GET_SWZ(swizzle, 1)];
  54.       colorOut[2] = vector[GET_SWZ(swizzle, 2)];
  55.       colorOut[3] = vector[GET_SWZ(swizzle, 3)];
  56.    }
  57. }
  58.  
  59.  
  60. /**
  61.  * Fetch a texel with given lod.
  62.  * Called via machine->FetchTexelLod()
  63.  */
  64. static void
  65. fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
  66.                  GLuint unit, GLfloat color[4] )
  67. {
  68.    const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
  69.  
  70.    if (texObj) {
  71.       SWcontext *swrast = SWRAST_CONTEXT(ctx);
  72.       GLfloat rgba[4];
  73.  
  74.       lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
  75.  
  76.       swrast->TextureSample[unit](ctx, texObj, 1,
  77.                                   (const GLfloat (*)[4]) texcoord,
  78.                                   &lambda, &rgba);
  79.       swizzle_texel(rgba, color, texObj->_Swizzle);
  80.    }
  81.    else {
  82.       ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  83.    }
  84. }
  85.  
  86.  
  87. /**
  88.  * Fetch a texel with the given partial derivatives to compute a level
  89.  * of detail in the mipmap.
  90.  * Called via machine->FetchTexelDeriv()
  91.  * \param lodBias  the lod bias which may be specified by a TXB instruction,
  92.  *                 otherwise zero.
  93.  */
  94. static void
  95. fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
  96.                    const GLfloat texdx[4], const GLfloat texdy[4],
  97.                    GLfloat lodBias, GLuint unit, GLfloat color[4] )
  98. {
  99.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  100.    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  101.    const struct gl_texture_object *texObj = texUnit->_Current;
  102.  
  103.    if (texObj) {
  104.       const struct gl_texture_image *texImg =
  105.          texObj->Image[0][texObj->BaseLevel];
  106.       const GLfloat texW = (GLfloat) texImg->WidthScale;
  107.       const GLfloat texH = (GLfloat) texImg->HeightScale;
  108.       GLfloat lambda;
  109.       GLfloat rgba[4];
  110.  
  111.       lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
  112.                                       texdx[1], texdy[1], /* dt/dx, dt/dy */
  113.                                       texdx[3], texdy[3], /* dq/dx, dq/dy */
  114.                                       texW, texH,
  115.                                       texcoord[0], texcoord[1], texcoord[3],
  116.                                       1.0F / texcoord[3]);
  117.  
  118.       lambda += lodBias + texUnit->LodBias + texObj->LodBias;
  119.  
  120.       lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
  121.  
  122.       swrast->TextureSample[unit](ctx, texObj, 1,
  123.                                   (const GLfloat (*)[4]) texcoord,
  124.                                   &lambda, &rgba);
  125.       swizzle_texel(rgba, color, texObj->_Swizzle);
  126.    }
  127.    else {
  128.       ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  129.    }
  130. }
  131.  
  132.  
  133. /**
  134.  * Initialize the virtual fragment program machine state prior to running
  135.  * fragment program on a fragment.  This involves initializing the input
  136.  * registers, condition codes, etc.
  137.  * \param machine  the virtual machine state to init
  138.  * \param program  the fragment program we're about to run
  139.  * \param span  the span of pixels we'll operate on
  140.  * \param col  which element (column) of the span we'll operate on
  141.  */
  142. static void
  143. init_machine(struct gl_context *ctx, struct gl_program_machine *machine,
  144.              const struct gl_fragment_program *program,
  145.              const SWspan *span, GLuint col)
  146. {
  147.    GLfloat *wpos = span->array->attribs[FRAG_ATTRIB_WPOS][col];
  148.  
  149.    if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
  150.       /* Clear temporary registers (undefined for ARB_f_p) */
  151.       memset(machine->Temporaries, 0, MAX_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
  152.    }
  153.  
  154.    /* ARB_fragment_coord_conventions */
  155.    if (program->OriginUpperLeft)
  156.       wpos[1] = ctx->DrawBuffer->Height - 1 - wpos[1];
  157.    if (!program->PixelCenterInteger) {
  158.       wpos[0] += 0.5F;
  159.       wpos[1] += 0.5F;
  160.    }
  161.  
  162.    /* Setup pointer to input attributes */
  163.    machine->Attribs = span->array->attribs;
  164.  
  165.    machine->DerivX = (GLfloat (*)[4]) span->attrStepX;
  166.    machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
  167.    machine->NumDeriv = FRAG_ATTRIB_MAX;
  168.  
  169.    machine->Samplers = program->Base.SamplerUnits;
  170.  
  171.    /* if running a GLSL program (not ARB_fragment_program) */
  172.    if (ctx->Shader.CurrentFragmentProgram) {
  173.       /* Store front/back facing value */
  174.       machine->Attribs[FRAG_ATTRIB_FACE][col][0] = 1.0F - span->facing;
  175.    }
  176.  
  177.    machine->CurElement = col;
  178.  
  179.    /* init condition codes */
  180.    machine->CondCodes[0] = COND_EQ;
  181.    machine->CondCodes[1] = COND_EQ;
  182.    machine->CondCodes[2] = COND_EQ;
  183.    machine->CondCodes[3] = COND_EQ;
  184.  
  185.    /* init call stack */
  186.    machine->StackDepth = 0;
  187.  
  188.    machine->FetchTexelLod = fetch_texel_lod;
  189.    machine->FetchTexelDeriv = fetch_texel_deriv;
  190. }
  191.  
  192.  
  193. /**
  194.  * Run fragment program on the pixels in span from 'start' to 'end' - 1.
  195.  */
  196. static void
  197. run_program(struct gl_context *ctx, SWspan *span, GLuint start, GLuint end)
  198. {
  199.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  200.    const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
  201.    const GLbitfield64 outputsWritten = program->Base.OutputsWritten;
  202.    struct gl_program_machine *machine = &swrast->FragProgMachine;
  203.    GLuint i;
  204.  
  205.    for (i = start; i < end; i++) {
  206.       if (span->array->mask[i]) {
  207.          init_machine(ctx, machine, program, span, i);
  208.  
  209.          if (_mesa_execute_program(ctx, &program->Base, machine)) {
  210.  
  211.             /* Store result color */
  212.             if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
  213.                COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i],
  214.                        machine->Outputs[FRAG_RESULT_COLOR]);
  215.             }
  216.             else {
  217.                /* Multiple drawbuffers / render targets
  218.                 * Note that colors beyond 0 and 1 will overwrite other
  219.                 * attributes, such as FOGC, TEX0, TEX1, etc.  That's OK.
  220.                 */
  221.                GLuint buf;
  222.                for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
  223.                   if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + buf)) {
  224.                      COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0 + buf][i],
  225.                              machine->Outputs[FRAG_RESULT_DATA0 + buf]);
  226.                   }
  227.                }
  228.             }
  229.  
  230.             /* Store result depth/z */
  231.             if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
  232.                const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
  233.                if (depth <= 0.0)
  234.                   span->array->z[i] = 0;
  235.                else if (depth >= 1.0)
  236.                   span->array->z[i] = ctx->DrawBuffer->_DepthMax;
  237.                else
  238.                   span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF);
  239.             }
  240.          }
  241.          else {
  242.             /* killed fragment */
  243.             span->array->mask[i] = GL_FALSE;
  244.             span->writeAll = GL_FALSE;
  245.          }
  246.       }
  247.    }
  248. }
  249.  
  250.  
  251. /**
  252.  * Execute the current fragment program for all the fragments
  253.  * in the given span.
  254.  */
  255. void
  256. _swrast_exec_fragment_program( struct gl_context *ctx, SWspan *span )
  257. {
  258.    const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
  259.  
  260.    /* incoming colors should be floats */
  261.    if (program->Base.InputsRead & FRAG_BIT_COL0) {
  262.       ASSERT(span->array->ChanType == GL_FLOAT);
  263.    }
  264.  
  265.    run_program(ctx, span, 0, span->end);
  266.  
  267.    if (program->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
  268.       span->interpMask &= ~SPAN_RGBA;
  269.       span->arrayMask |= SPAN_RGBA;
  270.    }
  271.  
  272.    if (program->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
  273.       span->interpMask &= ~SPAN_Z;
  274.       span->arrayMask |= SPAN_Z;
  275.    }
  276. }
  277.  
  278.