Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  5.  * Copyright (C) 2009  VMware, Inc.  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.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. /**
  27.  * \file texenv.c
  28.  *
  29.  * glTexEnv-related functions
  30.  */
  31.  
  32.  
  33. #include "main/glheader.h"
  34. #include "main/context.h"
  35. #include "main/blend.h"
  36. #include "main/enums.h"
  37. #include "main/macros.h"
  38. #include "main/mtypes.h"
  39. #include "main/state.h"
  40. #include "main/texenv.h"
  41. #include "main/texstate.h"
  42.  
  43.  
  44. #define TE_ERROR(errCode, msg, value)                           \
  45.    _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
  46.  
  47.  
  48. /** Set texture env mode */
  49. static void
  50. set_env_mode(struct gl_context *ctx,
  51.              struct gl_texture_unit *texUnit,
  52.              GLenum mode)
  53. {
  54.    GLboolean legal;
  55.  
  56.    if (texUnit->EnvMode == mode)
  57.       return;
  58.  
  59.    switch (mode) {
  60.    case GL_MODULATE:
  61.    case GL_BLEND:
  62.    case GL_DECAL:
  63.    case GL_REPLACE:
  64.    case GL_ADD:
  65.    case GL_COMBINE:
  66.       legal = GL_TRUE;
  67.       break;
  68.    case GL_REPLACE_EXT:
  69.       mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */
  70.       legal = GL_TRUE;
  71.       break;
  72.    case GL_COMBINE4_NV:
  73.       legal = ctx->Extensions.NV_texture_env_combine4;
  74.       break;
  75.    default:
  76.       legal = GL_FALSE;
  77.    }
  78.  
  79.    if (legal) {
  80.       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  81.       texUnit->EnvMode = mode;
  82.    }
  83.    else {
  84.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
  85.    }
  86. }
  87.  
  88.  
  89. static void
  90. set_env_color(struct gl_context *ctx,
  91.               struct gl_texture_unit *texUnit,
  92.               const GLfloat *color)
  93. {
  94.    if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped))
  95.       return;
  96.    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  97.    COPY_4FV(texUnit->EnvColorUnclamped, color);
  98.    texUnit->EnvColor[0] = CLAMP(color[0], 0.0F, 1.0F);
  99.    texUnit->EnvColor[1] = CLAMP(color[1], 0.0F, 1.0F);
  100.    texUnit->EnvColor[2] = CLAMP(color[2], 0.0F, 1.0F);
  101.    texUnit->EnvColor[3] = CLAMP(color[3], 0.0F, 1.0F);
  102. }
  103.  
  104.  
  105. /** Set an RGB or A combiner mode/function */
  106. static void
  107. set_combiner_mode(struct gl_context *ctx,
  108.                   struct gl_texture_unit *texUnit,
  109.                   GLenum pname, GLenum mode)
  110. {
  111.    GLboolean legal;
  112.  
  113.    switch (mode) {
  114.    case GL_REPLACE:
  115.    case GL_MODULATE:
  116.    case GL_ADD:
  117.    case GL_ADD_SIGNED:
  118.    case GL_INTERPOLATE:
  119.       legal = GL_TRUE;
  120.       break;
  121.    case GL_SUBTRACT:
  122.       legal = ctx->Extensions.ARB_texture_env_combine;
  123.       break;
  124.    case GL_DOT3_RGB_EXT:
  125.    case GL_DOT3_RGBA_EXT:
  126.       legal = (ctx->API == API_OPENGL_COMPAT &&
  127.                ctx->Extensions.EXT_texture_env_dot3 &&
  128.                pname == GL_COMBINE_RGB);
  129.       break;
  130.    case GL_DOT3_RGB:
  131.    case GL_DOT3_RGBA:
  132.       legal = (ctx->Extensions.ARB_texture_env_dot3 &&
  133.                pname == GL_COMBINE_RGB);
  134.       break;
  135.    case GL_MODULATE_ADD_ATI:
  136.    case GL_MODULATE_SIGNED_ADD_ATI:
  137.    case GL_MODULATE_SUBTRACT_ATI:
  138.       legal = (ctx->API == API_OPENGL_COMPAT &&
  139.                ctx->Extensions.ATI_texture_env_combine3);
  140.       break;
  141.    default:
  142.       legal = GL_FALSE;
  143.    }
  144.  
  145.    if (!legal) {
  146.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
  147.       return;
  148.    }
  149.  
  150.    switch (pname) {
  151.    case GL_COMBINE_RGB:
  152.       if (texUnit->Combine.ModeRGB == mode)
  153.          return;
  154.       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  155.       texUnit->Combine.ModeRGB = mode;
  156.       break;
  157.  
  158.    case GL_COMBINE_ALPHA:
  159.       if (texUnit->Combine.ModeA == mode)
  160.          return;
  161.       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  162.       texUnit->Combine.ModeA = mode;
  163.       break;
  164.    default:
  165.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  166.    }
  167. }
  168.  
  169.  
  170.  
  171. /** Set an RGB or A combiner source term */
  172. static void
  173. set_combiner_source(struct gl_context *ctx,
  174.                     struct gl_texture_unit *texUnit,
  175.                     GLenum pname, GLenum param)
  176. {
  177.    GLuint term;
  178.    GLboolean alpha, legal;
  179.  
  180.    /*
  181.     * Translate pname to (term, alpha).
  182.     *
  183.     * The enums were given sequential values for a reason.
  184.     */
  185.    switch (pname) {
  186.    case GL_SOURCE0_RGB:
  187.    case GL_SOURCE1_RGB:
  188.    case GL_SOURCE2_RGB:
  189.    case GL_SOURCE3_RGB_NV:
  190.       term = pname - GL_SOURCE0_RGB;
  191.       alpha = GL_FALSE;
  192.       break;
  193.    case GL_SOURCE0_ALPHA:
  194.    case GL_SOURCE1_ALPHA:
  195.    case GL_SOURCE2_ALPHA:
  196.    case GL_SOURCE3_ALPHA_NV:
  197.       term = pname - GL_SOURCE0_ALPHA;
  198.       alpha = GL_TRUE;
  199.       break;
  200.    default:
  201.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  202.       return;
  203.    }
  204.  
  205.    if ((term == 3) && (ctx->API != API_OPENGL_COMPAT
  206.                        || !ctx->Extensions.NV_texture_env_combine4)) {
  207.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  208.       return;
  209.    }
  210.  
  211.    assert(term < MAX_COMBINER_TERMS);
  212.  
  213.    /*
  214.     * Error-check param (the source term)
  215.     */
  216.    switch (param) {
  217.    case GL_TEXTURE:
  218.    case GL_CONSTANT:
  219.    case GL_PRIMARY_COLOR:
  220.    case GL_PREVIOUS:
  221.       legal = GL_TRUE;
  222.       break;
  223.    case GL_TEXTURE0:
  224.    case GL_TEXTURE1:
  225.    case GL_TEXTURE2:
  226.    case GL_TEXTURE3:
  227.    case GL_TEXTURE4:
  228.    case GL_TEXTURE5:
  229.    case GL_TEXTURE6:
  230.    case GL_TEXTURE7:
  231.       legal = (ctx->Extensions.ARB_texture_env_crossbar &&
  232.                param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits);
  233.       break;
  234.    case GL_ZERO:
  235.       legal = (ctx->API == API_OPENGL_COMPAT &&
  236.                (ctx->Extensions.ATI_texture_env_combine3 ||
  237.                 ctx->Extensions.NV_texture_env_combine4));
  238.       break;
  239.    case GL_ONE:
  240.       legal = (ctx->API == API_OPENGL_COMPAT &&
  241.                ctx->Extensions.ATI_texture_env_combine3);
  242.       break;
  243.    default:
  244.       legal = GL_FALSE;
  245.    }
  246.  
  247.    if (!legal) {
  248.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
  249.       return;
  250.    }
  251.  
  252.    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  253.  
  254.    if (alpha)
  255.       texUnit->Combine.SourceA[term] = param;
  256.    else
  257.       texUnit->Combine.SourceRGB[term] = param;
  258. }
  259.  
  260.  
  261. /** Set an RGB or A combiner operand term */
  262. static void
  263. set_combiner_operand(struct gl_context *ctx,
  264.                      struct gl_texture_unit *texUnit,
  265.                      GLenum pname, GLenum param)
  266. {
  267.    GLuint term;
  268.    GLboolean alpha, legal;
  269.  
  270.    /* The enums were given sequential values for a reason.
  271.     */
  272.    switch (pname) {
  273.    case GL_OPERAND0_RGB:
  274.    case GL_OPERAND1_RGB:
  275.    case GL_OPERAND2_RGB:
  276.    case GL_OPERAND3_RGB_NV:
  277.       term = pname - GL_OPERAND0_RGB;
  278.       alpha = GL_FALSE;
  279.       break;
  280.    case GL_OPERAND0_ALPHA:
  281.    case GL_OPERAND1_ALPHA:
  282.    case GL_OPERAND2_ALPHA:
  283.    case GL_OPERAND3_ALPHA_NV:
  284.       term = pname - GL_OPERAND0_ALPHA;
  285.       alpha = GL_TRUE;
  286.       break;
  287.    default:
  288.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  289.       return;
  290.    }
  291.  
  292.    if ((term == 3) && (ctx->API != API_OPENGL_COMPAT
  293.                        || !ctx->Extensions.NV_texture_env_combine4)) {
  294.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  295.       return;
  296.    }
  297.  
  298.    assert(term < MAX_COMBINER_TERMS);
  299.  
  300.    /*
  301.     * Error-check param (the source operand)
  302.     */
  303.    switch (param) {
  304.    case GL_SRC_COLOR:
  305.    case GL_ONE_MINUS_SRC_COLOR:
  306.       /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT
  307.        * version.  In the ARB and NV versions and OpenGL ES 1.x they can be
  308.        * used for any RGB operand.
  309.        */
  310.       legal = !alpha
  311.          && ((term < 2) || ctx->Extensions.ARB_texture_env_combine
  312.              || ctx->Extensions.NV_texture_env_combine4);
  313.       break;
  314.    case GL_ONE_MINUS_SRC_ALPHA:
  315.       /* GL_ONE_MINUS_SRC_ALPHA can only be used with
  316.        * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version.  In the ARB and NV
  317.        * versions and OpenGL ES 1.x it can be used for any operand.
  318.        */
  319.       legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine
  320.          || ctx->Extensions.NV_texture_env_combine4;
  321.       break;
  322.    case GL_SRC_ALPHA:
  323.       legal = GL_TRUE;
  324.       break;
  325.    default:
  326.       legal = GL_FALSE;
  327.    }
  328.  
  329.    if (!legal) {
  330.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
  331.       return;
  332.    }
  333.  
  334.    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  335.  
  336.    if (alpha)
  337.       texUnit->Combine.OperandA[term] = param;
  338.    else
  339.       texUnit->Combine.OperandRGB[term] = param;
  340. }
  341.  
  342.  
  343. static void
  344. set_combiner_scale(struct gl_context *ctx,
  345.                    struct gl_texture_unit *texUnit,
  346.                    GLenum pname, GLfloat scale)
  347. {
  348.    GLuint shift;
  349.  
  350.    if (scale == 1.0F) {
  351.       shift = 0;
  352.    }
  353.    else if (scale == 2.0F) {
  354.       shift = 1;
  355.    }
  356.    else if (scale == 4.0F) {
  357.       shift = 2;
  358.    }
  359.    else {
  360.       _mesa_error( ctx, GL_INVALID_VALUE,
  361.                    "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
  362.       return;
  363.    }
  364.  
  365.    switch (pname) {
  366.    case GL_RGB_SCALE:
  367.       if (texUnit->Combine.ScaleShiftRGB == shift)
  368.          return;
  369.       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  370.       texUnit->Combine.ScaleShiftRGB = shift;
  371.       break;
  372.    case GL_ALPHA_SCALE:
  373.       if (texUnit->Combine.ScaleShiftA == shift)
  374.          return;
  375.       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  376.       texUnit->Combine.ScaleShiftA = shift;
  377.       break;
  378.    default:
  379.       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  380.    }
  381. }
  382.  
  383.  
  384.  
  385. void GLAPIENTRY
  386. _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
  387. {
  388.    const GLint iparam0 = (GLint) param[0];
  389.    struct gl_texture_unit *texUnit;
  390.    GLuint maxUnit;
  391.    GET_CURRENT_CONTEXT(ctx);
  392.  
  393.    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
  394.       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
  395.    if (ctx->Texture.CurrentUnit >= maxUnit) {
  396.       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
  397.       return;
  398.    }
  399.  
  400.    texUnit = _mesa_get_current_tex_unit(ctx);
  401.  
  402.    if (target == GL_TEXTURE_ENV) {
  403.       switch (pname) {
  404.       case GL_TEXTURE_ENV_MODE:
  405.          set_env_mode(ctx, texUnit, (GLenum) iparam0);
  406.          break;
  407.       case GL_TEXTURE_ENV_COLOR:
  408.          set_env_color(ctx, texUnit, param);
  409.          break;
  410.       case GL_COMBINE_RGB:
  411.       case GL_COMBINE_ALPHA:
  412.          set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0);
  413.          break;
  414.       case GL_SOURCE0_RGB:
  415.       case GL_SOURCE1_RGB:
  416.       case GL_SOURCE2_RGB:
  417.       case GL_SOURCE3_RGB_NV:
  418.       case GL_SOURCE0_ALPHA:
  419.       case GL_SOURCE1_ALPHA:
  420.       case GL_SOURCE2_ALPHA:
  421.       case GL_SOURCE3_ALPHA_NV:
  422.          set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0);
  423.          break;
  424.       case GL_OPERAND0_RGB:
  425.       case GL_OPERAND1_RGB:
  426.       case GL_OPERAND2_RGB:
  427.       case GL_OPERAND3_RGB_NV:
  428.       case GL_OPERAND0_ALPHA:
  429.       case GL_OPERAND1_ALPHA:
  430.       case GL_OPERAND2_ALPHA:
  431.       case GL_OPERAND3_ALPHA_NV:
  432.          set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0);
  433.          break;
  434.       case GL_RGB_SCALE:
  435.       case GL_ALPHA_SCALE:
  436.          set_combiner_scale(ctx, texUnit, pname, param[0]);
  437.          break;
  438.       default:
  439.          _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
  440.          return;
  441.       }
  442.    }
  443.    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
  444.       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
  445.          if (texUnit->LodBias == param[0])
  446.             return;
  447.          FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  448.          texUnit->LodBias = param[0];
  449.       }
  450.       else {
  451.          TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
  452.          return;
  453.       }
  454.    }
  455.    else if (target == GL_POINT_SPRITE_NV) {
  456.       /* GL_ARB_point_sprite / GL_NV_point_sprite */
  457.       if (!ctx->Extensions.NV_point_sprite
  458.           && !ctx->Extensions.ARB_point_sprite) {
  459.          _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
  460.          return;
  461.       }
  462.       if (pname == GL_COORD_REPLACE_NV) {
  463.          if (iparam0 == GL_TRUE || iparam0 == GL_FALSE) {
  464.             /* It's kind of weird to set point state via glTexEnv,
  465.              * but that's what the spec calls for.
  466.              */
  467.             const GLboolean state = (GLboolean) iparam0;
  468.             if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
  469.                return;
  470.             FLUSH_VERTICES(ctx, _NEW_POINT);
  471.             ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
  472.          }
  473.          else {
  474.             _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0);
  475.             return;
  476.          }
  477.       }
  478.       else {
  479.          _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
  480.          return;
  481.       }
  482.    }
  483.    else {
  484.       _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)",
  485.                   _mesa_lookup_enum_by_nr(target));
  486.       return;
  487.    }
  488.  
  489.    if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
  490.       _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
  491.                   _mesa_lookup_enum_by_nr(target),
  492.                   _mesa_lookup_enum_by_nr(pname),
  493.                   *param,
  494.                   _mesa_lookup_enum_by_nr((GLenum) iparam0));
  495.  
  496.    /* Tell device driver about the new texture environment */
  497.    if (ctx->Driver.TexEnv) {
  498.       (*ctx->Driver.TexEnv)( ctx, target, pname, param );
  499.    }
  500. }
  501.  
  502.  
  503. void GLAPIENTRY
  504. _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
  505. {
  506.    GLfloat p[4];
  507.    p[0] = param;
  508.    p[1] = p[2] = p[3] = 0.0;
  509.    _mesa_TexEnvfv( target, pname, p );
  510. }
  511.  
  512.  
  513.  
  514. void GLAPIENTRY
  515. _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
  516. {
  517.    GLfloat p[4];
  518.    p[0] = (GLfloat) param;
  519.    p[1] = p[2] = p[3] = 0.0;
  520.    _mesa_TexEnvfv( target, pname, p );
  521. }
  522.  
  523.  
  524. void GLAPIENTRY
  525. _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
  526. {
  527.    GLfloat p[4];
  528.    if (pname == GL_TEXTURE_ENV_COLOR) {
  529.       p[0] = INT_TO_FLOAT( param[0] );
  530.       p[1] = INT_TO_FLOAT( param[1] );
  531.       p[2] = INT_TO_FLOAT( param[2] );
  532.       p[3] = INT_TO_FLOAT( param[3] );
  533.    }
  534.    else {
  535.       p[0] = (GLfloat) param[0];
  536.       p[1] = p[2] = p[3] = 0;  /* init to zero, just to be safe */
  537.    }
  538.    _mesa_TexEnvfv( target, pname, p );
  539. }
  540.  
  541.  
  542.  
  543. /**
  544.  * Helper for glGetTexEnvi/f()
  545.  * \return  value of queried pname or -1 if error.
  546.  */
  547. static GLint
  548. get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit,
  549.             GLenum pname)
  550. {
  551.    switch (pname) {
  552.    case GL_TEXTURE_ENV_MODE:
  553.       return texUnit->EnvMode;
  554.       break;
  555.    case GL_COMBINE_RGB:
  556.       return texUnit->Combine.ModeRGB;
  557.    case GL_COMBINE_ALPHA:
  558.       return texUnit->Combine.ModeA;
  559.    case GL_SOURCE0_RGB:
  560.    case GL_SOURCE1_RGB:
  561.    case GL_SOURCE2_RGB: {
  562.       const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
  563.       return texUnit->Combine.SourceRGB[rgb_idx];
  564.    }
  565.    case GL_SOURCE3_RGB_NV:
  566.       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
  567.          return texUnit->Combine.SourceRGB[3];
  568.       }
  569.       else {
  570.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
  571.       }
  572.       break;
  573.    case GL_SOURCE0_ALPHA:
  574.    case GL_SOURCE1_ALPHA:
  575.    case GL_SOURCE2_ALPHA: {
  576.       const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
  577.       return texUnit->Combine.SourceA[alpha_idx];
  578.    }
  579.    case GL_SOURCE3_ALPHA_NV:
  580.       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
  581.          return texUnit->Combine.SourceA[3];
  582.       }
  583.       else {
  584.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
  585.       }
  586.       break;
  587.    case GL_OPERAND0_RGB:
  588.    case GL_OPERAND1_RGB:
  589.    case GL_OPERAND2_RGB: {
  590.       const unsigned op_rgb = pname - GL_OPERAND0_RGB;
  591.       return texUnit->Combine.OperandRGB[op_rgb];
  592.    }
  593.    case GL_OPERAND3_RGB_NV:
  594.       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
  595.          return texUnit->Combine.OperandRGB[3];
  596.       }
  597.       else {
  598.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
  599.       }
  600.       break;
  601.    case GL_OPERAND0_ALPHA:
  602.    case GL_OPERAND1_ALPHA:
  603.    case GL_OPERAND2_ALPHA: {
  604.       const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
  605.       return texUnit->Combine.OperandA[op_alpha];
  606.    }
  607.    case GL_OPERAND3_ALPHA_NV:
  608.       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
  609.          return texUnit->Combine.OperandA[3];
  610.       }
  611.       else {
  612.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
  613.       }
  614.       break;
  615.    case GL_RGB_SCALE:
  616.       return 1 << texUnit->Combine.ScaleShiftRGB;
  617.    case GL_ALPHA_SCALE:
  618.       return 1 << texUnit->Combine.ScaleShiftA;
  619.    default:
  620.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
  621.       break;
  622.    }
  623.  
  624.    return -1; /* error */
  625. }
  626.  
  627.  
  628.  
  629. void GLAPIENTRY
  630. _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
  631. {
  632.    GLuint maxUnit;
  633.    const struct gl_texture_unit *texUnit;
  634.    GET_CURRENT_CONTEXT(ctx);
  635.  
  636.    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
  637.       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
  638.    if (ctx->Texture.CurrentUnit >= maxUnit) {
  639.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
  640.       return;
  641.    }
  642.  
  643.    texUnit = _mesa_get_current_tex_unit(ctx);
  644.  
  645.    if (target == GL_TEXTURE_ENV) {
  646.       if (pname == GL_TEXTURE_ENV_COLOR) {
  647.          if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
  648.             _mesa_update_state(ctx);
  649.          if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
  650.             COPY_4FV( params, texUnit->EnvColor );
  651.          else
  652.             COPY_4FV( params, texUnit->EnvColorUnclamped );
  653.       }
  654.       else {
  655.          GLint val = get_texenvi(ctx, texUnit, pname);
  656.          if (val >= 0) {
  657.             *params = (GLfloat) val;
  658.          }
  659.       }
  660.    }
  661.    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
  662.       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
  663.          *params = texUnit->LodBias;
  664.       }
  665.       else {
  666.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  667.          return;
  668.       }
  669.    }
  670.    else if (target == GL_POINT_SPRITE_NV) {
  671.       /* GL_ARB_point_sprite / GL_NV_point_sprite */
  672.       if (!ctx->Extensions.NV_point_sprite
  673.           && !ctx->Extensions.ARB_point_sprite) {
  674.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  675.          return;
  676.       }
  677.       if (pname == GL_COORD_REPLACE_NV) {
  678.          *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
  679.       }
  680.       else {
  681.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  682.          return;
  683.       }
  684.    }
  685.    else {
  686.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  687.       return;
  688.    }
  689. }
  690.  
  691.  
  692. void GLAPIENTRY
  693. _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
  694. {
  695.    GLuint maxUnit;
  696.    const struct gl_texture_unit *texUnit;
  697.    GET_CURRENT_CONTEXT(ctx);
  698.  
  699.    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
  700.       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
  701.    if (ctx->Texture.CurrentUnit >= maxUnit) {
  702.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
  703.       return;
  704.    }
  705.  
  706.    texUnit = _mesa_get_current_tex_unit(ctx);
  707.  
  708.    if (target == GL_TEXTURE_ENV) {
  709.       if (pname == GL_TEXTURE_ENV_COLOR) {
  710.          params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
  711.          params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
  712.          params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
  713.          params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
  714.       }
  715.       else {
  716.          GLint val = get_texenvi(ctx, texUnit, pname);
  717.          if (val >= 0) {
  718.             *params = val;
  719.          }
  720.       }
  721.    }
  722.    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
  723.       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
  724.          *params = (GLint) texUnit->LodBias;
  725.       }
  726.       else {
  727.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
  728.          return;
  729.       }
  730.    }
  731.    else if (target == GL_POINT_SPRITE_NV) {
  732.       /* GL_ARB_point_sprite / GL_NV_point_sprite */
  733.       if (!ctx->Extensions.NV_point_sprite
  734.           && !ctx->Extensions.ARB_point_sprite) {
  735.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
  736.          return;
  737.       }
  738.       if (pname == GL_COORD_REPLACE_NV) {
  739.          *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
  740.       }
  741.       else {
  742.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
  743.          return;
  744.       }
  745.    }
  746.    else {
  747.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
  748.       return;
  749.    }
  750. }
  751.  
  752.