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/colormac.h"
  27. #include "main/samplerobj.h"
  28. #include "program/prog_instruction.h"
  29.  
  30. #include "s_context.h"
  31. #include "s_fragprog.h"
  32. #include "s_span.h"
  33.  
  34. /**
  35.  * \brief Should swrast use a fragment program?
  36.  *
  37.  * \return true if the current fragment program exists and is not the fixed
  38.  *         function fragment program
  39.  */
  40. GLboolean
  41. _swrast_use_fragment_program(struct gl_context *ctx)
  42. {
  43.    struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
  44.    return fp && !(fp == ctx->FragmentProgram._TexEnvProgram
  45.                   && fp->Base.NumInstructions == 0);
  46. }
  47.  
  48. /**
  49.  * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
  50.  * and return results in 'colorOut'.
  51.  */
  52. static inline void
  53. swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
  54. {
  55.    if (swizzle == SWIZZLE_NOOP) {
  56.       COPY_4V(colorOut, texel);
  57.    }
  58.    else {
  59.       GLfloat vector[6];
  60.       vector[SWIZZLE_X] = texel[0];
  61.       vector[SWIZZLE_Y] = texel[1];
  62.       vector[SWIZZLE_Z] = texel[2];
  63.       vector[SWIZZLE_W] = texel[3];
  64.       vector[SWIZZLE_ZERO] = 0.0F;
  65.       vector[SWIZZLE_ONE] = 1.0F;
  66.       colorOut[0] = vector[GET_SWZ(swizzle, 0)];
  67.       colorOut[1] = vector[GET_SWZ(swizzle, 1)];
  68.       colorOut[2] = vector[GET_SWZ(swizzle, 2)];
  69.       colorOut[3] = vector[GET_SWZ(swizzle, 3)];
  70.    }
  71. }
  72.  
  73.  
  74. /**
  75.  * Fetch a texel with given lod.
  76.  * Called via machine->FetchTexelLod()
  77.  */
  78. static void
  79. fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
  80.                  GLuint unit, GLfloat color[4] )
  81. {
  82.    const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
  83.  
  84.    if (texObj) {
  85.       SWcontext *swrast = SWRAST_CONTEXT(ctx);
  86.       GLfloat rgba[4];
  87.       const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
  88.  
  89.       lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);
  90.  
  91.       swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
  92.                                   1, (const GLfloat (*)[4]) texcoord,
  93.                                   &lambda, &rgba);
  94.       swizzle_texel(rgba, color, texObj->_Swizzle);
  95.    }
  96.    else {
  97.       ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  98.    }
  99. }
  100.  
  101.  
  102. /**
  103.  * Fetch a texel with the given partial derivatives to compute a level
  104.  * of detail in the mipmap.
  105.  * Called via machine->FetchTexelDeriv()
  106.  * \param lodBias  the lod bias which may be specified by a TXB instruction,
  107.  *                 otherwise zero.
  108.  */
  109. static void
  110. fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
  111.                    const GLfloat texdx[4], const GLfloat texdy[4],
  112.                    GLfloat lodBias, GLuint unit, GLfloat color[4] )
  113. {
  114.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  115.    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  116.    const struct gl_texture_object *texObj = texUnit->_Current;
  117.  
  118.    if (texObj) {
  119.       const struct gl_texture_image *texImg =
  120.          texObj->Image[0][texObj->BaseLevel];
  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.CurrentFragmentProgram) {
  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.