Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * 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
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "main/glheader.h"
  29. #include "main/macros.h"
  30. #include "main/mtypes.h"
  31. #include "main/simple_list.h"
  32. #include "main/enums.h"
  33. #include "main/mm.h"
  34.  
  35. #include "intel_screen.h"
  36. #include "intel_tex.h"
  37.  
  38. #include "i830_context.h"
  39. #include "i830_reg.h"
  40.  
  41.  
  42. /* ================================================================
  43.  * Texture combine functions
  44.  */
  45. static GLuint
  46. pass_through(GLuint * state, GLuint blendUnit)
  47. {
  48.    state[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
  49.                TEXPIPE_COLOR |
  50.                ENABLE_TEXOUTPUT_WRT_SEL |
  51.                TEXOP_OUTPUT_CURRENT |
  52.                DISABLE_TEX_CNTRL_STAGE |
  53.                TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
  54.    state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
  55.                TEXPIPE_ALPHA |
  56.                ENABLE_TEXOUTPUT_WRT_SEL |
  57.                TEXOP_OUTPUT_CURRENT |
  58.                TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
  59.    state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
  60.                TEXPIPE_COLOR |
  61.                TEXBLEND_ARG1 |
  62.                TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT);
  63.    state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
  64.                TEXPIPE_ALPHA |
  65.                TEXBLEND_ARG1 |
  66.                TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT);
  67.  
  68.    return 4;
  69. }
  70.  
  71. static GLuint
  72. emit_factor(GLuint blendUnit, GLuint * state, GLuint count,
  73.             const GLfloat * factor)
  74. {
  75.    GLubyte r, g, b, a;
  76.    GLuint col;
  77.  
  78.    if (0)
  79.       fprintf(stderr, "emit constant %d: %.2f %.2f %.2f %.2f\n",
  80.               blendUnit, factor[0], factor[1], factor[2], factor[3]);
  81.  
  82.    UNCLAMPED_FLOAT_TO_UBYTE(r, factor[0]);
  83.    UNCLAMPED_FLOAT_TO_UBYTE(g, factor[1]);
  84.    UNCLAMPED_FLOAT_TO_UBYTE(b, factor[2]);
  85.    UNCLAMPED_FLOAT_TO_UBYTE(a, factor[3]);
  86.  
  87.    col = ((a << 24) | (r << 16) | (g << 8) | b);
  88.  
  89.    state[count++] = _3DSTATE_COLOR_FACTOR_N_CMD(blendUnit);
  90.    state[count++] = col;
  91.  
  92.    return count;
  93. }
  94.  
  95.  
  96. static INLINE GLuint
  97. GetTexelOp(GLint unit)
  98. {
  99.    switch (unit) {
  100.    case 0:
  101.       return TEXBLENDARG_TEXEL0;
  102.    case 1:
  103.       return TEXBLENDARG_TEXEL1;
  104.    case 2:
  105.       return TEXBLENDARG_TEXEL2;
  106.    case 3:
  107.       return TEXBLENDARG_TEXEL3;
  108.    default:
  109.       return TEXBLENDARG_TEXEL0;
  110.    }
  111. }
  112.  
  113.  
  114. /**
  115.  * Calculate the hardware instuctions to setup the current texture enviromnemt
  116.  * settings.  Since \c gl_texture_unit::_CurrentCombine is used, both
  117.  * "classic" texture enviroments and GL_ARB_texture_env_combine type texture
  118.  * environments are treated identically.
  119.  *
  120.  * \todo
  121.  * This function should return \c bool.  When \c false is returned,
  122.  * it means that an environment is selected that the hardware cannot do.  This
  123.  * is the way the Radeon and R200 drivers work.
  124.  *
  125.  * \todo
  126.  * Looking at i830_3d_regs.h, it seems the i830 can do part of
  127.  * GL_ATI_texture_env_combine3.  It can handle using \c GL_ONE and
  128.  * \c GL_ZERO as combine inputs (which the code already supports).  It can
  129.  * also handle the \c GL_MODULATE_ADD_ATI mode.  Is it worth investigating
  130.  * partial support for the extension?
  131.  */
  132. GLuint
  133. i830SetTexEnvCombine(struct i830_context * i830,
  134.                      const struct gl_tex_env_combine_state * combine,
  135.                      GLint blendUnit,
  136.                      GLuint texel_op, GLuint * state, const GLfloat * factor)
  137. {
  138.    const GLuint numColorArgs = combine->_NumArgsRGB;
  139.    const GLuint numAlphaArgs = combine->_NumArgsA;
  140.  
  141.    GLuint blendop;
  142.    GLuint ablendop;
  143.    GLuint args_RGB[3];
  144.    GLuint args_A[3];
  145.    GLuint rgb_shift;
  146.    GLuint alpha_shift;
  147.    bool need_factor = 0;
  148.    int i;
  149.    unsigned used;
  150.    static const GLuint tex_blend_rgb[3] = {
  151.       TEXPIPE_COLOR | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS,
  152.       TEXPIPE_COLOR | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS,
  153.       TEXPIPE_COLOR | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
  154.    };
  155.    static const GLuint tex_blend_a[3] = {
  156.       TEXPIPE_ALPHA | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS,
  157.       TEXPIPE_ALPHA | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS,
  158.       TEXPIPE_ALPHA | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
  159.    };
  160.  
  161.    if (INTEL_DEBUG & DEBUG_TEXTURE)
  162.       fprintf(stderr, "%s\n", __FUNCTION__);
  163.  
  164.  
  165.    /* The EXT version of the DOT3 extension does not support the
  166.     * scale factor, but the ARB version (and the version in OpenGL
  167.     * 1.3) does.
  168.     */
  169.    switch (combine->ModeRGB) {
  170.    case GL_DOT3_RGB_EXT:
  171.       alpha_shift = combine->ScaleShiftA;
  172.       rgb_shift = 0;
  173.       break;
  174.  
  175.    case GL_DOT3_RGBA_EXT:
  176.       alpha_shift = 0;
  177.       rgb_shift = 0;
  178.       break;
  179.  
  180.    default:
  181.       rgb_shift = combine->ScaleShiftRGB;
  182.       alpha_shift = combine->ScaleShiftA;
  183.       break;
  184.    }
  185.  
  186.  
  187.    switch (combine->ModeRGB) {
  188.    case GL_REPLACE:
  189.       blendop = TEXBLENDOP_ARG1;
  190.       break;
  191.    case GL_MODULATE:
  192.       blendop = TEXBLENDOP_MODULATE;
  193.       break;
  194.    case GL_ADD:
  195.       blendop = TEXBLENDOP_ADD;
  196.       break;
  197.    case GL_ADD_SIGNED:
  198.       blendop = TEXBLENDOP_ADDSIGNED;
  199.       break;
  200.    case GL_INTERPOLATE:
  201.       blendop = TEXBLENDOP_BLEND;
  202.       break;
  203.    case GL_SUBTRACT:
  204.       blendop = TEXBLENDOP_SUBTRACT;
  205.       break;
  206.    case GL_DOT3_RGB_EXT:
  207.    case GL_DOT3_RGB:
  208.       blendop = TEXBLENDOP_DOT3;
  209.       break;
  210.    case GL_DOT3_RGBA_EXT:
  211.    case GL_DOT3_RGBA:
  212.       blendop = TEXBLENDOP_DOT3;
  213.       break;
  214.    default:
  215.       return pass_through(state, blendUnit);
  216.    }
  217.  
  218.    blendop |= (rgb_shift << TEXOP_SCALE_SHIFT);
  219.  
  220.  
  221.    /* Handle RGB args */
  222.    for (i = 0; i < 3; i++) {
  223.       switch (combine->SourceRGB[i]) {
  224.       case GL_TEXTURE:
  225.          args_RGB[i] = texel_op;
  226.          break;
  227.       case GL_TEXTURE0:
  228.       case GL_TEXTURE1:
  229.       case GL_TEXTURE2:
  230.       case GL_TEXTURE3:
  231.          args_RGB[i] = GetTexelOp(combine->SourceRGB[i] - GL_TEXTURE0);
  232.          break;
  233.       case GL_CONSTANT:
  234.          args_RGB[i] = TEXBLENDARG_FACTOR_N;
  235.          need_factor = 1;
  236.          break;
  237.       case GL_PRIMARY_COLOR:
  238.          args_RGB[i] = TEXBLENDARG_DIFFUSE;
  239.          break;
  240.       case GL_PREVIOUS:
  241.          args_RGB[i] = TEXBLENDARG_CURRENT;
  242.          break;
  243.       default:
  244.          return pass_through(state, blendUnit);
  245.       }
  246.  
  247.       switch (combine->OperandRGB[i]) {
  248.       case GL_SRC_COLOR:
  249.          args_RGB[i] |= 0;
  250.          break;
  251.       case GL_ONE_MINUS_SRC_COLOR:
  252.          args_RGB[i] |= TEXBLENDARG_INV_ARG;
  253.          break;
  254.       case GL_SRC_ALPHA:
  255.          args_RGB[i] |= TEXBLENDARG_REPLICATE_ALPHA;
  256.          break;
  257.       case GL_ONE_MINUS_SRC_ALPHA:
  258.          args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA | TEXBLENDARG_INV_ARG);
  259.          break;
  260.       default:
  261.          return pass_through(state, blendUnit);
  262.       }
  263.    }
  264.  
  265.  
  266.    /* Need to knobble the alpha calculations of TEXBLENDOP_DOT4 to
  267.     * match the spec.  Can't use DOT3 as it won't propogate values
  268.     * into alpha as required:
  269.     *
  270.     * Note - the global factor is set up with alpha == .5, so
  271.     * the alpha part of the DOT4 calculation should be zero.
  272.     */
  273.    if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
  274.        combine->ModeRGB == GL_DOT3_RGBA) {
  275.       ablendop = TEXBLENDOP_DOT4;
  276.       args_A[0] = TEXBLENDARG_FACTOR;   /* the global factor */
  277.       args_A[1] = TEXBLENDARG_FACTOR;
  278.       args_A[2] = TEXBLENDARG_FACTOR;
  279.    }
  280.    else {
  281.       switch (combine->ModeA) {
  282.       case GL_REPLACE:
  283.          ablendop = TEXBLENDOP_ARG1;
  284.          break;
  285.       case GL_MODULATE:
  286.          ablendop = TEXBLENDOP_MODULATE;
  287.          break;
  288.       case GL_ADD:
  289.          ablendop = TEXBLENDOP_ADD;
  290.          break;
  291.       case GL_ADD_SIGNED:
  292.          ablendop = TEXBLENDOP_ADDSIGNED;
  293.          break;
  294.       case GL_INTERPOLATE:
  295.          ablendop = TEXBLENDOP_BLEND;
  296.          break;
  297.       case GL_SUBTRACT:
  298.          ablendop = TEXBLENDOP_SUBTRACT;
  299.          break;
  300.       default:
  301.          return pass_through(state, blendUnit);
  302.       }
  303.  
  304.  
  305.       ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
  306.  
  307.       /* Handle A args */
  308.       for (i = 0; i < 3; i++) {
  309.          switch (combine->SourceA[i]) {
  310.          case GL_TEXTURE:
  311.             args_A[i] = texel_op;
  312.             break;
  313.          case GL_TEXTURE0:
  314.          case GL_TEXTURE1:
  315.          case GL_TEXTURE2:
  316.          case GL_TEXTURE3:
  317.             args_A[i] = GetTexelOp(combine->SourceA[i] - GL_TEXTURE0);
  318.             break;
  319.          case GL_CONSTANT:
  320.             args_A[i] = TEXBLENDARG_FACTOR_N;
  321.             need_factor = 1;
  322.             break;
  323.          case GL_PRIMARY_COLOR:
  324.             args_A[i] = TEXBLENDARG_DIFFUSE;
  325.             break;
  326.          case GL_PREVIOUS:
  327.             args_A[i] = TEXBLENDARG_CURRENT;
  328.             break;
  329.          default:
  330.             return pass_through(state, blendUnit);
  331.          }
  332.  
  333.          switch (combine->OperandA[i]) {
  334.          case GL_SRC_ALPHA:
  335.             args_A[i] |= 0;
  336.             break;
  337.          case GL_ONE_MINUS_SRC_ALPHA:
  338.             args_A[i] |= TEXBLENDARG_INV_ARG;
  339.             break;
  340.          default:
  341.             return pass_through(state, blendUnit);
  342.          }
  343.       }
  344.    }
  345.  
  346.  
  347.  
  348.    /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
  349.    /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
  350.    /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
  351.  
  352.    /* When we render we need to figure out which is the last really enabled
  353.     * tex unit, and put last stage on it
  354.     */
  355.  
  356.  
  357.    /* Build color & alpha pipelines */
  358.  
  359.    used = 0;
  360.    state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
  361.                     TEXPIPE_COLOR |
  362.                     ENABLE_TEXOUTPUT_WRT_SEL |
  363.                     TEXOP_OUTPUT_CURRENT |
  364.                     DISABLE_TEX_CNTRL_STAGE | TEXOP_MODIFY_PARMS | blendop);
  365.    state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
  366.                     TEXPIPE_ALPHA |
  367.                     ENABLE_TEXOUTPUT_WRT_SEL |
  368.                     TEXOP_OUTPUT_CURRENT | TEXOP_MODIFY_PARMS | ablendop);
  369.  
  370.    for (i = 0; i < numColorArgs; i++) {
  371.       state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
  372.                        tex_blend_rgb[i] | args_RGB[i]);
  373.    }
  374.  
  375.    for (i = 0; i < numAlphaArgs; i++) {
  376.       state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
  377.                        tex_blend_a[i] | args_A[i]);
  378.    }
  379.  
  380.  
  381.    if (need_factor)
  382.       return emit_factor(blendUnit, state, used, factor);
  383.    else
  384.       return used;
  385. }
  386.  
  387.  
  388. static void
  389. emit_texblend(struct i830_context *i830, GLuint unit, GLuint blendUnit,
  390.               bool last_stage)
  391. {
  392.    struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
  393.    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
  394.  
  395.  
  396.    if (0)
  397.       fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
  398.  
  399.    /* Update i830->state.TexBlend
  400.     */
  401.    tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit,
  402.                                  GetTexelOp(unit), tmp, texUnit->EnvColor);
  403.  
  404.    if (last_stage)
  405.       tmp[0] |= TEXOP_LAST_STAGE;
  406.  
  407.    if (tmp_sz != i830->state.TexBlendWordsUsed[blendUnit] ||
  408.        memcmp(tmp, i830->state.TexBlend[blendUnit],
  409.               tmp_sz * sizeof(GLuint))) {
  410.  
  411.       I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(blendUnit));
  412.       memcpy(i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint));
  413.       i830->state.TexBlendWordsUsed[blendUnit] = tmp_sz;
  414.    }
  415.  
  416.    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), true);
  417. }
  418.  
  419. static void
  420. emit_passthrough(struct i830_context *i830)
  421. {
  422.    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
  423.    GLuint unit = 0;
  424.  
  425.    tmp_sz = pass_through(tmp, unit);
  426.    tmp[0] |= TEXOP_LAST_STAGE;
  427.  
  428.    if (tmp_sz != i830->state.TexBlendWordsUsed[unit] ||
  429.        memcmp(tmp, i830->state.TexBlend[unit], tmp_sz * sizeof(GLuint))) {
  430.  
  431.       I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(unit));
  432.       memcpy(i830->state.TexBlend[unit], tmp, tmp_sz * sizeof(GLuint));
  433.       i830->state.TexBlendWordsUsed[unit] = tmp_sz;
  434.    }
  435.  
  436.    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), true);
  437. }
  438.  
  439. void
  440. i830EmitTextureBlend(struct i830_context *i830)
  441. {
  442.    struct gl_context *ctx = &i830->intel.ctx;
  443.    GLuint unit, last_stage = 0, blendunit = 0;
  444.  
  445.    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND_ALL, false);
  446.  
  447.    if (ctx->Texture._EnabledUnits) {
  448.       for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
  449.          if (ctx->Texture.Unit[unit]._ReallyEnabled)
  450.             last_stage = unit;
  451.  
  452.       for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
  453.          if (ctx->Texture.Unit[unit]._ReallyEnabled)
  454.             emit_texblend(i830, unit, blendunit++, last_stage == unit);
  455.    }
  456.    else {
  457.       emit_passthrough(i830);
  458.    }
  459. }
  460.