Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright (C) 2009 Francisco Jerez.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining
  6.  * a copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sublicense, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the
  14.  * next paragraph) shall be included in all copies or substantial
  15.  * portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  */
  26.  
  27. #include "nouveau_driver.h"
  28. #include "nouveau_context.h"
  29. #include "nouveau_util.h"
  30. #include "nv_object.xml.h"
  31. #include "nv04_3d.xml.h"
  32. #include "nv04_driver.h"
  33.  
  34. #define COMBINER_SHIFT(in)                                              \
  35.         (NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT##in##__SHIFT     \
  36.          - NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0__SHIFT)
  37. #define COMBINER_SOURCE(reg)                                    \
  38.         NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_##reg
  39. #define COMBINER_INVERT                                 \
  40.         NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE0
  41. #define COMBINER_ALPHA                                  \
  42.         NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA0
  43.  
  44. struct combiner_state {
  45.         struct gl_context *ctx;
  46.         int unit;
  47.         GLboolean alpha;
  48.         GLboolean premodulate;
  49.  
  50.         /* GL state */
  51.         GLenum mode;
  52.         GLenum *source;
  53.         GLenum *operand;
  54.         GLuint logscale;
  55.  
  56.         /* Derived HW state */
  57.         uint32_t hw;
  58. };
  59.  
  60. #define __INIT_COMBINER_ALPHA_A GL_TRUE
  61. #define __INIT_COMBINER_ALPHA_RGB GL_FALSE
  62.  
  63. /* Initialize a combiner_state struct from the texture unit
  64.  * context. */
  65. #define INIT_COMBINER(chan, ctx, rc, i) do {                    \
  66.                 struct gl_tex_env_combine_state *c =            \
  67.                         ctx->Texture.Unit[i]._CurrentCombine;   \
  68.                 (rc)->ctx = ctx;                                \
  69.                 (rc)->unit = i;                                 \
  70.                 (rc)->alpha = __INIT_COMBINER_ALPHA_##chan;     \
  71.                 (rc)->premodulate = c->_NumArgs##chan == 4;     \
  72.                 (rc)->mode = c->Mode##chan;                     \
  73.                 (rc)->source = c->Source##chan;                 \
  74.                 (rc)->operand = c->Operand##chan;               \
  75.                 (rc)->logscale = c->ScaleShift##chan;           \
  76.                 (rc)->hw = 0;                                   \
  77.         } while (0)
  78.  
  79. /* Get the combiner source for the specified EXT_texture_env_combine
  80.  * source. */
  81. static uint32_t
  82. get_input_source(struct combiner_state *rc, int source)
  83. {
  84.         switch (source) {
  85.         case GL_ZERO:
  86.                 return COMBINER_SOURCE(ZERO);
  87.  
  88.         case GL_TEXTURE:
  89.                 return rc->unit ? COMBINER_SOURCE(TEXTURE1) :
  90.                         COMBINER_SOURCE(TEXTURE0);
  91.  
  92.         case GL_TEXTURE0:
  93.                 return COMBINER_SOURCE(TEXTURE0);
  94.  
  95.         case GL_TEXTURE1:
  96.                 return COMBINER_SOURCE(TEXTURE1);
  97.  
  98.         case GL_CONSTANT:
  99.                 return COMBINER_SOURCE(CONSTANT);
  100.  
  101.         case GL_PRIMARY_COLOR:
  102.                 return COMBINER_SOURCE(PRIMARY_COLOR);
  103.  
  104.         case GL_PREVIOUS:
  105.                 return rc->unit ? COMBINER_SOURCE(PREVIOUS) :
  106.                         COMBINER_SOURCE(PRIMARY_COLOR);
  107.  
  108.         default:
  109.                 assert(0);
  110.         }
  111. }
  112.  
  113. /* Get the (possibly inverted) combiner input mapping for the
  114.  * specified EXT_texture_env_combine operand. */
  115. #define INVERT 0x1
  116.  
  117. static uint32_t
  118. get_input_mapping(struct combiner_state *rc, int operand, int flags)
  119. {
  120.         int map = 0;
  121.  
  122.         if (!is_color_operand(operand) && !rc->alpha)
  123.                 map |= COMBINER_ALPHA;
  124.  
  125.         if (is_negative_operand(operand) == !(flags & INVERT))
  126.                 map |= COMBINER_INVERT;
  127.  
  128.         return map;
  129. }
  130.  
  131. static uint32_t
  132. get_input_arg(struct combiner_state *rc, int arg, int flags)
  133. {
  134.         int source = rc->source[arg];
  135.         int operand = rc->operand[arg];
  136.  
  137.         /* Fake several unsupported texture formats. */
  138.         if (is_texture_source(source)) {
  139.                 int i = (source == GL_TEXTURE ?
  140.                          rc->unit : source - GL_TEXTURE0);
  141.                 struct gl_texture_object *t = rc->ctx->Texture.Unit[i]._Current;
  142.                 gl_format format = t->Image[0][t->BaseLevel]->TexFormat;
  143.  
  144.                 if (format == MESA_FORMAT_A8) {
  145.                         /* Emulated using I8. */
  146.                         if (is_color_operand(operand))
  147.                                 return COMBINER_SOURCE(ZERO) |
  148.                                         get_input_mapping(rc, operand, flags);
  149.  
  150.                 } else if (format == MESA_FORMAT_L8) {
  151.                         /* Emulated using I8. */
  152.                         if (!is_color_operand(operand))
  153.                                 return COMBINER_SOURCE(ZERO) |
  154.                                         get_input_mapping(rc, operand,
  155.                                                           flags ^ INVERT);
  156.                 }
  157.         }
  158.  
  159.         return get_input_source(rc, source) |
  160.                 get_input_mapping(rc, operand, flags);
  161. }
  162.  
  163. /* Bind the combiner input <in> to the combiner source <src>,
  164.  * possibly inverted. */
  165. #define INPUT_SRC(rc, in, src, flags)                                   \
  166.         (rc)->hw |= ((flags & INVERT ? COMBINER_INVERT : 0) |           \
  167.                    COMBINER_SOURCE(src)) << COMBINER_SHIFT(in)
  168.  
  169. /* Bind the combiner input <in> to the EXT_texture_env_combine
  170.  * argument <arg>, possibly inverted. */
  171. #define INPUT_ARG(rc, in, arg, flags)                                   \
  172.         (rc)->hw |= get_input_arg(rc, arg, flags) << COMBINER_SHIFT(in)
  173.  
  174. #define UNSIGNED_OP(rc)                                                 \
  175.         (rc)->hw |= ((rc)->logscale ?                                   \
  176.                      NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_SCALE2 :  \
  177.                      NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_IDENTITY)
  178. #define SIGNED_OP(rc)                                                   \
  179.         (rc)->hw |= ((rc)->logscale ?                                   \
  180.                      NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS_SCALE2 : \
  181.                      NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS)
  182.  
  183. static void
  184. setup_combiner(struct combiner_state *rc)
  185. {
  186.         switch (rc->mode) {
  187.         case GL_REPLACE:
  188.                 INPUT_ARG(rc, 0, 0, 0);
  189.                 INPUT_SRC(rc, 1, ZERO, INVERT);
  190.                 INPUT_SRC(rc, 2, ZERO, 0);
  191.                 INPUT_SRC(rc, 3, ZERO, 0);
  192.                 UNSIGNED_OP(rc);
  193.                 break;
  194.  
  195.         case GL_MODULATE:
  196.                 INPUT_ARG(rc, 0, 0, 0);
  197.                 INPUT_ARG(rc, 1, 1, 0);
  198.                 INPUT_SRC(rc, 2, ZERO, 0);
  199.                 INPUT_SRC(rc, 3, ZERO, 0);
  200.                 UNSIGNED_OP(rc);
  201.                 break;
  202.  
  203.         case GL_ADD:
  204.         case GL_ADD_SIGNED:
  205.                 if (rc->premodulate) {
  206.                         INPUT_ARG(rc, 0, 0, 0);
  207.                         INPUT_ARG(rc, 1, 1, 0);
  208.                         INPUT_ARG(rc, 2, 2, 0);
  209.                         INPUT_ARG(rc, 3, 3, 0);
  210.                 } else {
  211.                         INPUT_ARG(rc, 0, 0, 0);
  212.                         INPUT_SRC(rc, 1, ZERO, INVERT);
  213.                         INPUT_ARG(rc, 2, 1, 0);
  214.                         INPUT_SRC(rc, 3, ZERO, INVERT);
  215.                 }
  216.  
  217.                 if (rc->mode == GL_ADD_SIGNED)
  218.                         SIGNED_OP(rc);
  219.                 else
  220.                         UNSIGNED_OP(rc);
  221.  
  222.                 break;
  223.  
  224.         case GL_INTERPOLATE:
  225.                 INPUT_ARG(rc, 0, 0, 0);
  226.                 INPUT_ARG(rc, 1, 2, 0);
  227.                 INPUT_ARG(rc, 2, 1, 0);
  228.                 INPUT_ARG(rc, 3, 2, INVERT);
  229.                 UNSIGNED_OP(rc);
  230.                 break;
  231.  
  232.         default:
  233.                 assert(0);
  234.         }
  235. }
  236.  
  237. static unsigned
  238. get_texenv_mode(unsigned mode)
  239. {
  240.         switch (mode) {
  241.         case GL_REPLACE:
  242.                 return 0x1;
  243.         case GL_DECAL:
  244.                 return 0x3;
  245.         case GL_MODULATE:
  246.                 return 0x4;
  247.         default:
  248.                 assert(0);
  249.         }
  250. }
  251.  
  252. void
  253. nv04_emit_tex_env(struct gl_context *ctx, int emit)
  254. {
  255.         struct nv04_context *nv04 = to_nv04_context(ctx);
  256.         const int i = emit - NOUVEAU_STATE_TEX_ENV0;
  257.         struct combiner_state rc_a = {}, rc_c = {};
  258.  
  259.         /* Compute the new combiner state. */
  260.         if (ctx->Texture.Unit[i]._ReallyEnabled) {
  261.                 INIT_COMBINER(A, ctx, &rc_a, i);
  262.                 setup_combiner(&rc_a);
  263.  
  264.                 INIT_COMBINER(RGB, ctx, &rc_c, i);
  265.                 setup_combiner(&rc_c);
  266.  
  267.         } else {
  268.                 if (i == 0) {
  269.                         INPUT_SRC(&rc_a, 0, PRIMARY_COLOR, 0);
  270.                         INPUT_SRC(&rc_c, 0, PRIMARY_COLOR, 0);
  271.                 } else {
  272.                         INPUT_SRC(&rc_a, 0, PREVIOUS, 0);
  273.                         INPUT_SRC(&rc_c, 0, PREVIOUS, 0);
  274.                 }
  275.  
  276.                 INPUT_SRC(&rc_a, 1, ZERO, INVERT);
  277.                 INPUT_SRC(&rc_c, 1, ZERO, INVERT);
  278.                 INPUT_SRC(&rc_a, 2, ZERO, 0);
  279.                 INPUT_SRC(&rc_c, 2, ZERO, 0);
  280.                 INPUT_SRC(&rc_a, 3, ZERO, 0);
  281.                 INPUT_SRC(&rc_c, 3, ZERO, 0);
  282.  
  283.                 UNSIGNED_OP(&rc_a);
  284.                 UNSIGNED_OP(&rc_c);
  285.         }
  286.  
  287.         /* calculate non-multitex state */
  288.         nv04->blend &= ~NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK;
  289.         if (ctx->Texture._EnabledUnits)
  290.                 nv04->blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode);
  291.         else
  292.                 nv04->blend |= get_texenv_mode(GL_MODULATE);
  293.  
  294.         /* update calculated multitex state */
  295.         nv04->alpha[i] = rc_a.hw;
  296.         nv04->color[i] = rc_c.hw;
  297.         nv04->factor   = pack_rgba_f(MESA_FORMAT_ARGB8888,
  298.                                      ctx->Texture.Unit[0].EnvColor);
  299. }
  300.