Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. #include "main/glheader.h"
  26. #include "main/macros.h"
  27. #include "main/samplerobj.h"
  28. #include "main/teximage.h"
  29. #include "program/prog_instruction.h"
  30.  
  31. #include "s_context.h"
  32. #include "s_fragprog.h"
  33. #include "s_span.h"
  34.  
  35. /**
  36.  * \brief Should swrast use a fragment program?
  37.  *
  38.  * \return true if the current fragment program exists and is not the fixed
  39.  *         function fragment program
  40.  */
  41. GLboolean
  42. _swrast_use_fragment_program(struct gl_context *ctx)
  43. {
  44.    struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
  45.    return fp && !(fp == ctx->FragmentProgram._TexEnvProgram
  46.                   && fp->Base.NumInstructions == 0);
  47. }
  48.  
  49. /**
  50.  * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
  51.  * and return results in 'colorOut'.
  52.  */
  53. static inline void
  54. swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
  55. {
  56.    if (swizzle == SWIZZLE_NOOP) {
  57.       COPY_4V(colorOut, texel);
  58.    }
  59.    else {
  60.       GLfloat vector[6];
  61.       vector[SWIZZLE_X] = texel[0];
  62.       vector[SWIZZLE_Y] = texel[1];
  63.       vector[SWIZZLE_Z] = texel[2];
  64.       vector[SWIZZLE_W] = texel[3];
  65.       vector[SWIZZLE_ZERO] = 0.0F;
  66.       vector[SWIZZLE_ONE] = 1.0F;
  67.       colorOut[0] = vector[GET_SWZ(swizzle, 0)];
  68.       colorOut[1] = vector[GET_SWZ(swizzle, 1)];
  69.       colorOut[2] = vector[GET_SWZ(swizzle, 2)];
  70.       colorOut[3] = vector[GET_SWZ(swizzle, 3)];
  71.    }
  72. }
  73.  
  74.  
  75. /**
  76.  * Fetch a texel with given lod.
  77.  * Called via machine->FetchTexelLod()
  78.  */
  79. static void
  80. fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
  81.                  GLuint unit, GLfloat color[4] )
  82. {
  83.    const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
  84.  
  85.    if (texObj) {
  86.       SWcontext *swrast = SWRAST_CONTEXT(ctx);
  87.       GLfloat rgba[4];
  88.       const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
  89.  
  90.       lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);
  91.  
  92.       swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
  93.                                   1, (const GLfloat (*)[4]) texcoord,
  94.                                   &lambda, &rgba);
  95.       swizzle_texel(rgba, color, texObj->_Swizzle);
  96.    }
  97.    else {
  98.       ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  99.    }
  100. }
  101.  
  102.  
  103. /**
  104.  * Fetch a texel with the given partial derivatives to compute a level
  105.  * of detail in the mipmap.
  106.  * Called via machine->FetchTexelDeriv()
  107.  * \param lodBias  the lod bias which may be specified by a TXB instruction,
  108.  *                 otherwise zero.
  109.  */
  110. static void
  111. fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
  112.                    const GLfloat texdx[4], const GLfloat texdy[4],
  113.                    GLfloat lodBias, GLuint unit, GLfloat color[4] )
  114. {
  115.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  116.    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  117.    const struct gl_texture_object *texObj = texUnit->_Current;
  118.  
  119.    if (texObj) {
  120.       const struct gl_texture_image *texImg = _mesa_base_tex_image(texObj);
  121.       const struct swrast_texture_image *swImg =
  122.          swrast_texture_image_const(texImg);
  123.       const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
  124.       const GLfloat texW = (GLfloat) swImg->WidthScale;
  125.       const GLfloat texH = (GLfloat) swImg->HeightScale;
  126.       GLfloat lambda;
  127.       GLfloat rgba[4];
  128.  
  129.       lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
  130.                                       texdx[1], texdy[1], /* dt/dx, dt/dy */
  131.                                       texdx[3], texdy[3], /* dq/dx, dq/dy */
  132.                                       texW, texH,
  133.                                       texcoord[0], texcoord[1], texcoord[3],
  134.                                       1.0F / texcoord[3]);
  135.  
  136.       lambda += lodBias + texUnit->LodBias + samp->LodBias;
  137.  
  138.       lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);
  139.  
  140.       swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
  141.                                   1, (const GLfloat (*)[4]) texcoord,
  142.                                   &lambda, &rgba);
  143.       swizzle_texel(rgba, color, texObj->_Swizzle);
  144.    }
  145.    else {
  146.       ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  147.    }
  148. }
  149.  
  150.  
  151. /**
  152.  * Initialize the virtual fragment program machine state prior to running
  153.  * fragment program on a fragment.  This involves initializing the input
  154.  * registers, condition codes, etc.
  155.  * \param machine  the virtual machine state to init
  156.  * \param program  the fragment program we're about to run
  157.  * \param span  the span of pixels we'll operate on
  158.  * \param col  which element (column) of the span we'll operate on
  159.  */
  160. static void
  161. init_machine(struct gl_context *ctx, struct gl_program_machine *machine,
  162.              const struct gl_fragment_program *program,
  163.              const SWspan *span, GLuint col)
  164. {
  165.    GLfloat *wpos = span->array->attribs[VARYING_SLOT_POS][col];
  166.  
  167.    /* ARB_fragment_coord_conventions */
  168.    if (program->OriginUpperLeft)
  169.       wpos[1] = ctx->DrawBuffer->Height - 1 - wpos[1];
  170.    if (!program->PixelCenterInteger) {
  171.       wpos[0] += 0.5F;
  172.       wpos[1] += 0.5F;
  173.    }
  174.  
  175.    /* Setup pointer to input attributes */
  176.    machine->Attribs = span->array->attribs;
  177.  
  178.    machine->DerivX = (GLfloat (*)[4]) span->attrStepX;
  179.    machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
  180.    machine->NumDeriv = VARYING_SLOT_MAX;
  181.  
  182.    machine->Samplers = program->Base.SamplerUnits;
  183.  
  184.    /* if running a GLSL program (not ARB_fragment_program) */
  185.    if (ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
  186.       /* Store front/back facing value */
  187.       machine->Attribs[VARYING_SLOT_FACE][col][0] = 1.0F - span->facing;
  188.    }
  189.  
  190.    machine->CurElement = col;
  191.  
  192.    /* init condition codes */
  193.    machine->CondCodes[0] = COND_EQ;
  194.    machine->CondCodes[1] = COND_EQ;
  195.    machine->CondCodes[2] = COND_EQ;
  196.    machine->CondCodes[3] = COND_EQ;
  197.  
  198.    /* init call stack */
  199.    machine->StackDepth = 0;
  200.  
  201.    machine->FetchTexelLod = fetch_texel_lod;
  202.    machine->FetchTexelDeriv = fetch_texel_deriv;
  203. }
  204.  
  205.  
  206. /**
  207.  * Run fragment program on the pixels in span from 'start' to 'end' - 1.
  208.  */
  209. static void
  210. run_program(struct gl_context *ctx, SWspan *span, GLuint start, GLuint end)
  211. {
  212.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  213.    const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
  214.    const GLbitfield64 outputsWritten = program->Base.OutputsWritten;
  215.    struct gl_program_machine *machine = &swrast->FragProgMachine;
  216.    GLuint i;
  217.  
  218.    for (i = start; i < end; i++) {
  219.       if (span->array->mask[i]) {
  220.          init_machine(ctx, machine, program, span, i);
  221.  
  222.          if (_mesa_execute_program(ctx, &program->Base, machine)) {
  223.  
  224.             /* Store result color */
  225.             if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
  226.                COPY_4V(span->array->attribs[VARYING_SLOT_COL0][i],
  227.                        machine->Outputs[FRAG_RESULT_COLOR]);
  228.             }
  229.             else {
  230.                /* Multiple drawbuffers / render targets
  231.                 * Note that colors beyond 0 and 1 will overwrite other
  232.                 * attributes, such as FOGC, TEX0, TEX1, etc.  That's OK.
  233.                 */
  234.                GLuint buf;
  235.                for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
  236.                   if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + buf)) {
  237.                      COPY_4V(span->array->attribs[VARYING_SLOT_COL0 + buf][i],
  238.                              machine->Outputs[FRAG_RESULT_DATA0 + buf]);
  239.                   }
  240.                }
  241.             }
  242.  
  243.             /* Store result depth/z */
  244.             if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
  245.                const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
  246.                if (depth <= 0.0)
  247.                   span->array->z[i] = 0;
  248.                else if (depth >= 1.0)
  249.                   span->array->z[i] = ctx->DrawBuffer->_DepthMax;
  250.                else
  251.                   span->array->z[i] =
  252.                      (GLuint) (depth * ctx->DrawBuffer->_DepthMaxF + 0.5F);
  253.             }
  254.          }
  255.          else {
  256.             /* killed fragment */
  257.             span->array->mask[i] = GL_FALSE;
  258.             span->writeAll = GL_FALSE;
  259.          }
  260.       }
  261.    }
  262. }
  263.  
  264.  
  265. /**
  266.  * Execute the current fragment program for all the fragments
  267.  * in the given span.
  268.  */
  269. void
  270. _swrast_exec_fragment_program( struct gl_context *ctx, SWspan *span )
  271. {
  272.    const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
  273.  
  274.    /* incoming colors should be floats */
  275.    if (program->Base.InputsRead & VARYING_BIT_COL0) {
  276.       assert(span->array->ChanType == GL_FLOAT);
  277.    }
  278.  
  279.    run_program(ctx, span, 0, span->end);
  280.  
  281.    if (program->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
  282.       span->interpMask &= ~SPAN_RGBA;
  283.       span->arrayMask |= SPAN_RGBA;
  284.    }
  285.  
  286.    if (program->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
  287.       span->interpMask &= ~SPAN_Z;
  288.       span->arrayMask |= SPAN_Z;
  289.    }
  290. }
  291.  
  292.