Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2003 VMware, Inc.
  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 VMWARE 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 "util/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.    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", __func__);
  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_DOT4;
  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.       numAlphaArgs = 2;
  277.       args_A[0] = TEXBLENDARG_FACTOR;   /* the global factor */
  278.       args_A[1] = TEXBLENDARG_FACTOR;
  279.       args_A[2] = TEXBLENDARG_FACTOR;
  280.    }
  281.    else {
  282.       switch (combine->ModeA) {
  283.       case GL_REPLACE:
  284.          ablendop = TEXBLENDOP_ARG1;
  285.          break;
  286.       case GL_MODULATE:
  287.          ablendop = TEXBLENDOP_MODULATE;
  288.          break;
  289.       case GL_ADD:
  290.          ablendop = TEXBLENDOP_ADD;
  291.          break;
  292.       case GL_ADD_SIGNED:
  293.          ablendop = TEXBLENDOP_ADDSIGNED;
  294.          break;
  295.       case GL_INTERPOLATE:
  296.          ablendop = TEXBLENDOP_BLEND;
  297.          break;
  298.       case GL_SUBTRACT:
  299.          ablendop = TEXBLENDOP_SUBTRACT;
  300.          break;
  301.       default:
  302.          return pass_through(state, blendUnit);
  303.       }
  304.  
  305.  
  306.       ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
  307.  
  308.       /* Handle A args */
  309.       for (i = 0; i < 3; i++) {
  310.          switch (combine->SourceA[i]) {
  311.          case GL_TEXTURE:
  312.             args_A[i] = texel_op;
  313.             break;
  314.          case GL_TEXTURE0:
  315.          case GL_TEXTURE1:
  316.          case GL_TEXTURE2:
  317.          case GL_TEXTURE3:
  318.             args_A[i] = GetTexelOp(combine->SourceA[i] - GL_TEXTURE0);
  319.             break;
  320.          case GL_CONSTANT:
  321.             args_A[i] = TEXBLENDARG_FACTOR_N;
  322.             need_factor = 1;
  323.             break;
  324.          case GL_PRIMARY_COLOR:
  325.             args_A[i] = TEXBLENDARG_DIFFUSE;
  326.             break;
  327.          case GL_PREVIOUS:
  328.             args_A[i] = TEXBLENDARG_CURRENT;
  329.             break;
  330.          default:
  331.             return pass_through(state, blendUnit);
  332.          }
  333.  
  334.          switch (combine->OperandA[i]) {
  335.          case GL_SRC_ALPHA:
  336.             args_A[i] |= 0;
  337.             break;
  338.          case GL_ONE_MINUS_SRC_ALPHA:
  339.             args_A[i] |= TEXBLENDARG_INV_ARG;
  340.             break;
  341.          default:
  342.             return pass_through(state, blendUnit);
  343.          }
  344.       }
  345.    }
  346.  
  347.  
  348.  
  349.    /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
  350.    /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
  351.    /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
  352.  
  353.    /* When we render we need to figure out which is the last really enabled
  354.     * tex unit, and put last stage on it
  355.     */
  356.  
  357.  
  358.    /* Build color & alpha pipelines */
  359.  
  360.    used = 0;
  361.    state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
  362.                     TEXPIPE_COLOR |
  363.                     ENABLE_TEXOUTPUT_WRT_SEL |
  364.                     TEXOP_OUTPUT_CURRENT |
  365.                     DISABLE_TEX_CNTRL_STAGE | TEXOP_MODIFY_PARMS | blendop);
  366.    state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
  367.                     TEXPIPE_ALPHA |
  368.                     ENABLE_TEXOUTPUT_WRT_SEL |
  369.                     TEXOP_OUTPUT_CURRENT | TEXOP_MODIFY_PARMS | ablendop);
  370.  
  371.    for (i = 0; i < numColorArgs; i++) {
  372.       state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
  373.                        tex_blend_rgb[i] | args_RGB[i]);
  374.    }
  375.  
  376.    for (i = 0; i < numAlphaArgs; i++) {
  377.       state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
  378.                        tex_blend_a[i] | args_A[i]);
  379.    }
  380.  
  381.  
  382.    if (need_factor)
  383.       return emit_factor(blendUnit, state, used, factor);
  384.    else
  385.       return used;
  386. }
  387.  
  388.  
  389. static void
  390. emit_texblend(struct i830_context *i830, GLuint unit, GLuint blendUnit,
  391.               bool last_stage)
  392. {
  393.    struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
  394.    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
  395.  
  396.  
  397.    if (0)
  398.       fprintf(stderr, "%s unit %d\n", __func__, unit);
  399.  
  400.    /* Update i830->state.TexBlend
  401.     */
  402.    tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit,
  403.                                  GetTexelOp(unit), tmp, texUnit->EnvColor);
  404.  
  405.    if (last_stage)
  406.       tmp[0] |= TEXOP_LAST_STAGE;
  407.  
  408.    if (tmp_sz != i830->state.TexBlendWordsUsed[blendUnit] ||
  409.        memcmp(tmp, i830->state.TexBlend[blendUnit],
  410.               tmp_sz * sizeof(GLuint))) {
  411.  
  412.       I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(blendUnit));
  413.       memcpy(i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint));
  414.       i830->state.TexBlendWordsUsed[blendUnit] = tmp_sz;
  415.    }
  416.  
  417.    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), true);
  418. }
  419.  
  420. static void
  421. emit_passthrough(struct i830_context *i830)
  422. {
  423.    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
  424.    GLuint unit = 0;
  425.  
  426.    tmp_sz = pass_through(tmp, unit);
  427.    tmp[0] |= TEXOP_LAST_STAGE;
  428.  
  429.    if (tmp_sz != i830->state.TexBlendWordsUsed[unit] ||
  430.        memcmp(tmp, i830->state.TexBlend[unit], tmp_sz * sizeof(GLuint))) {
  431.  
  432.       I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(unit));
  433.       memcpy(i830->state.TexBlend[unit], tmp, tmp_sz * sizeof(GLuint));
  434.       i830->state.TexBlendWordsUsed[unit] = tmp_sz;
  435.    }
  436.  
  437.    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), true);
  438. }
  439.  
  440. void
  441. i830EmitTextureBlend(struct i830_context *i830)
  442. {
  443.    struct gl_context *ctx = &i830->intel.ctx;
  444.    GLuint unit, blendunit = 0;
  445.  
  446.    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND_ALL, false);
  447.  
  448.    if (ctx->Texture._MaxEnabledTexImageUnit != -1) {
  449.       for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++)
  450.          if (ctx->Texture.Unit[unit]._Current)
  451.             emit_texblend(i830, unit, blendunit++,
  452.                           unit == ctx->Texture._MaxEnabledTexImageUnit);
  453.    } else {
  454.       emit_passthrough(i830);
  455.    }
  456. }
  457.