Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2009-2010 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_gldefs.h"
  30. #include "nv10_3d.xml.h"
  31. #include "nouveau_util.h"
  32. #include "nv10_driver.h"
  33. #include "nv20_driver.h"
  34.  
  35. #define RC_IN_SHIFT_A   24
  36. #define RC_IN_SHIFT_B   16
  37. #define RC_IN_SHIFT_C   8
  38. #define RC_IN_SHIFT_D   0
  39. #define RC_IN_SHIFT_E   56
  40. #define RC_IN_SHIFT_F   48
  41. #define RC_IN_SHIFT_G   40
  42.  
  43. #define RC_IN_SOURCE(source)                            \
  44.         ((uint64_t)NV10_3D_RC_IN_RGB_D_INPUT_##source)
  45. #define RC_IN_USAGE(usage)                                      \
  46.         ((uint64_t)NV10_3D_RC_IN_RGB_D_COMPONENT_USAGE_##usage)
  47. #define RC_IN_MAPPING(mapping)                                  \
  48.         ((uint64_t)NV10_3D_RC_IN_RGB_D_MAPPING_##mapping)
  49.  
  50. #define RC_OUT_BIAS     NV10_3D_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF
  51. #define RC_OUT_SCALE_1  NV10_3D_RC_OUT_RGB_SCALE_NONE
  52. #define RC_OUT_SCALE_2  NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_TWO
  53. #define RC_OUT_SCALE_4  NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_FOUR
  54.  
  55. /* Make the combiner do: spare0_i = A_i * B_i */
  56. #define RC_OUT_AB       NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0
  57. /* spare0_i = dot3(A, B) */
  58. #define RC_OUT_DOT_AB   (NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0 |  \
  59.                          NV10_3D_RC_OUT_RGB_AB_DOT_PRODUCT)
  60. /* spare0_i = A_i * B_i + C_i * D_i */
  61. #define RC_OUT_SUM      NV10_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0
  62.  
  63. struct combiner_state {
  64.         struct gl_context *ctx;
  65.         int unit;
  66.         GLboolean premodulate;
  67.  
  68.         /* GL state */
  69.         GLenum mode;
  70.         GLenum *source;
  71.         GLenum *operand;
  72.         GLuint logscale;
  73.  
  74.         /* Derived HW state */
  75.         uint64_t in;
  76.         uint32_t out;
  77. };
  78.  
  79. /* Initialize a combiner_state struct from the texture unit
  80.  * context. */
  81. #define INIT_COMBINER(chan, ctx, rc, i) do {                    \
  82.                 struct gl_tex_env_combine_state *c =            \
  83.                         ctx->Texture.Unit[i]._CurrentCombine;   \
  84.                 (rc)->ctx = ctx;                                \
  85.                 (rc)->unit = i;                                 \
  86.                 (rc)->premodulate = c->_NumArgs##chan == 4;     \
  87.                 (rc)->mode = c->Mode##chan;                     \
  88.                 (rc)->source = c->Source##chan;                 \
  89.                 (rc)->operand = c->Operand##chan;               \
  90.                 (rc)->logscale = c->ScaleShift##chan;           \
  91.                 (rc)->in = (rc)->out = 0;                       \
  92.         } while (0)
  93.  
  94. /* Get the RC input source for the specified EXT_texture_env_combine
  95.  * source. */
  96. static uint32_t
  97. get_input_source(struct combiner_state *rc, int source)
  98. {
  99.         switch (source) {
  100.         case GL_ZERO:
  101.                 return RC_IN_SOURCE(ZERO);
  102.  
  103.         case GL_TEXTURE:
  104.                 return RC_IN_SOURCE(TEXTURE0) + rc->unit;
  105.  
  106.         case GL_TEXTURE0:
  107.                 return RC_IN_SOURCE(TEXTURE0);
  108.  
  109.         case GL_TEXTURE1:
  110.                 return RC_IN_SOURCE(TEXTURE1);
  111.  
  112.         case GL_TEXTURE2:
  113.                 return RC_IN_SOURCE(TEXTURE2);
  114.  
  115.         case GL_TEXTURE3:
  116.                 return RC_IN_SOURCE(TEXTURE3);
  117.  
  118.         case GL_CONSTANT:
  119.                 return context_chipset(rc->ctx) >= 0x20 ?
  120.                         RC_IN_SOURCE(CONSTANT_COLOR0) :
  121.                         RC_IN_SOURCE(CONSTANT_COLOR0) + rc->unit;
  122.  
  123.         case GL_PRIMARY_COLOR:
  124.                 return RC_IN_SOURCE(PRIMARY_COLOR);
  125.  
  126.         case GL_PREVIOUS:
  127.                 return rc->unit ? RC_IN_SOURCE(SPARE0)
  128.                         : RC_IN_SOURCE(PRIMARY_COLOR);
  129.  
  130.         default:
  131.                 assert(0);
  132.         }
  133. }
  134.  
  135. /* Get the RC input mapping for the specified texture_env_combine
  136.  * operand, possibly inverted or biased. */
  137. #define INVERT 0x1
  138. #define HALF_BIAS 0x2
  139.  
  140. static uint32_t
  141. get_input_mapping(struct combiner_state *rc, int operand, int flags)
  142. {
  143.         int map = 0;
  144.  
  145.         if (is_color_operand(operand))
  146.                 map |= RC_IN_USAGE(RGB);
  147.         else
  148.                 map |= RC_IN_USAGE(ALPHA);
  149.  
  150.         if (is_negative_operand(operand) == !(flags & INVERT))
  151.                 map |= flags & HALF_BIAS ?
  152.                         RC_IN_MAPPING(HALF_BIAS_NEGATE) :
  153.                         RC_IN_MAPPING(UNSIGNED_INVERT);
  154.         else
  155.                 map |= flags & HALF_BIAS ?
  156.                         RC_IN_MAPPING(HALF_BIAS_NORMAL) :
  157.                         RC_IN_MAPPING(UNSIGNED_IDENTITY);
  158.  
  159.         return map;
  160. }
  161.  
  162. static uint32_t
  163. get_input_arg(struct combiner_state *rc, int arg, int flags)
  164. {
  165.         int source = rc->source[arg];
  166.         int operand = rc->operand[arg];
  167.  
  168.         /* Fake several unsupported texture formats. */
  169.         if (is_texture_source(source)) {
  170.                 int i = (source == GL_TEXTURE ?
  171.                          rc->unit : source - GL_TEXTURE0);
  172.                 struct gl_texture_object *t = rc->ctx->Texture.Unit[i]._Current;
  173.                 mesa_format format = t->Image[0][t->BaseLevel]->TexFormat;
  174.  
  175.                 if (format == MESA_FORMAT_A_UNORM8) {
  176.                         /* Emulated using I8. */
  177.                         if (is_color_operand(operand))
  178.                                 return RC_IN_SOURCE(ZERO) |
  179.                                         get_input_mapping(rc, operand, flags);
  180.  
  181.                 } else if (format == MESA_FORMAT_L_UNORM8) {
  182.                         /* Sometimes emulated using I8. */
  183.                         if (!is_color_operand(operand))
  184.                                 return RC_IN_SOURCE(ZERO) |
  185.                                         get_input_mapping(rc, operand,
  186.                                                           flags ^ INVERT);
  187.  
  188.                 } else if (format == MESA_FORMAT_B8G8R8X8_UNORM) {
  189.                         /* Sometimes emulated using ARGB8888. */
  190.                         if (!is_color_operand(operand))
  191.                                 return RC_IN_SOURCE(ZERO) |
  192.                                         get_input_mapping(rc, operand,
  193.                                                           flags ^ INVERT);
  194.                 }
  195.         }
  196.  
  197.         return get_input_source(rc, source) |
  198.                 get_input_mapping(rc, operand, flags);
  199. }
  200.  
  201. /* Bind the RC input variable <var> to the EXT_texture_env_combine
  202.  * argument <arg>, possibly inverted or biased. */
  203. #define INPUT_ARG(rc, var, arg, flags)                                  \
  204.         (rc)->in |= get_input_arg(rc, arg, flags) << RC_IN_SHIFT_##var
  205.  
  206. /* Bind the RC input variable <var> to the RC source <src>. */
  207. #define INPUT_SRC(rc, var, src, chan)                                   \
  208.         (rc)->in |= (RC_IN_SOURCE(src) |                                \
  209.                      RC_IN_USAGE(chan)) << RC_IN_SHIFT_##var
  210.  
  211. /* Bind the RC input variable <var> to a constant +/-1 */
  212. #define INPUT_ONE(rc, var, flags)                                       \
  213.         (rc)->in |= (RC_IN_SOURCE(ZERO) |                               \
  214.                      (flags & INVERT ? RC_IN_MAPPING(EXPAND_NORMAL) :   \
  215.                       RC_IN_MAPPING(UNSIGNED_INVERT))) << RC_IN_SHIFT_##var
  216.  
  217. static void
  218. setup_combiner(struct combiner_state *rc)
  219. {
  220.         switch (rc->mode) {
  221.         case GL_REPLACE:
  222.                 INPUT_ARG(rc, A, 0, 0);
  223.                 INPUT_ONE(rc, B, 0);
  224.  
  225.                 rc->out = RC_OUT_AB;
  226.                 break;
  227.  
  228.         case GL_MODULATE:
  229.                 INPUT_ARG(rc, A, 0, 0);
  230.                 INPUT_ARG(rc, B, 1, 0);
  231.  
  232.                 rc->out = RC_OUT_AB;
  233.                 break;
  234.  
  235.         case GL_ADD:
  236.         case GL_ADD_SIGNED:
  237.                 if (rc->premodulate) {
  238.                         INPUT_ARG(rc, A, 0, 0);
  239.                         INPUT_ARG(rc, B, 1, 0);
  240.                         INPUT_ARG(rc, C, 2, 0);
  241.                         INPUT_ARG(rc, D, 3, 0);
  242.                 } else {
  243.                         INPUT_ARG(rc, A, 0, 0);
  244.                         INPUT_ONE(rc, B, 0);
  245.                         INPUT_ARG(rc, C, 1, 0);
  246.                         INPUT_ONE(rc, D, 0);
  247.                 }
  248.  
  249.                 rc->out = RC_OUT_SUM |
  250.                         (rc->mode == GL_ADD_SIGNED ? RC_OUT_BIAS : 0);
  251.                 break;
  252.  
  253.         case GL_INTERPOLATE:
  254.                 INPUT_ARG(rc, A, 0, 0);
  255.                 INPUT_ARG(rc, B, 2, 0);
  256.                 INPUT_ARG(rc, C, 1, 0);
  257.                 INPUT_ARG(rc, D, 2, INVERT);
  258.  
  259.                 rc->out = RC_OUT_SUM;
  260.                 break;
  261.  
  262.         case GL_SUBTRACT:
  263.                 INPUT_ARG(rc, A, 0, 0);
  264.                 INPUT_ONE(rc, B, 0);
  265.                 INPUT_ARG(rc, C, 1, 0);
  266.                 INPUT_ONE(rc, D, INVERT);
  267.  
  268.                 rc->out = RC_OUT_SUM;
  269.                 break;
  270.  
  271.         case GL_DOT3_RGB:
  272.         case GL_DOT3_RGBA:
  273.                 INPUT_ARG(rc, A, 0, HALF_BIAS);
  274.                 INPUT_ARG(rc, B, 1, HALF_BIAS);
  275.  
  276.                 rc->out = RC_OUT_DOT_AB | RC_OUT_SCALE_4;
  277.  
  278.                 assert(!rc->logscale);
  279.                 break;
  280.  
  281.         default:
  282.                 assert(0);
  283.         }
  284.  
  285.         switch (rc->logscale) {
  286.         case 0:
  287.                 rc->out |= RC_OUT_SCALE_1;
  288.                 break;
  289.         case 1:
  290.                 rc->out |= RC_OUT_SCALE_2;
  291.                 break;
  292.         case 2:
  293.                 rc->out |= RC_OUT_SCALE_4;
  294.                 break;
  295.         default:
  296.                 assert(0);
  297.         }
  298. }
  299.  
  300. void
  301. nv10_get_general_combiner(struct gl_context *ctx, int i,
  302.                           uint32_t *a_in, uint32_t *a_out,
  303.                           uint32_t *c_in, uint32_t *c_out, uint32_t *k)
  304. {
  305.         struct combiner_state rc_a, rc_c;
  306.  
  307.         if (ctx->Texture.Unit[i]._Current) {
  308.                 INIT_COMBINER(RGB, ctx, &rc_c, i);
  309.  
  310.                 if (rc_c.mode == GL_DOT3_RGBA)
  311.                         rc_a = rc_c;
  312.                 else
  313.                         INIT_COMBINER(A, ctx, &rc_a, i);
  314.  
  315.                 setup_combiner(&rc_c);
  316.                 setup_combiner(&rc_a);
  317.  
  318.         } else {
  319.                 rc_a.in = rc_a.out = rc_c.in = rc_c.out = 0;
  320.         }
  321.  
  322.         *k = pack_rgba_f(MESA_FORMAT_B8G8R8A8_UNORM,
  323.                          ctx->Texture.Unit[i].EnvColor);
  324.         *a_in = rc_a.in;
  325.         *a_out = rc_a.out;
  326.         *c_in = rc_c.in;
  327.         *c_out = rc_c.out;
  328. }
  329.  
  330. void
  331. nv10_get_final_combiner(struct gl_context *ctx, uint64_t *in, int *n)
  332. {
  333.         struct combiner_state rc = {};
  334.  
  335.         /*
  336.          * The final fragment value equation is something like:
  337.          *      x_i = A_i * B_i + (1 - A_i) * C_i + D_i
  338.          *      x_alpha = G_alpha
  339.          * where D_i = E_i * F_i, i one of {red, green, blue}.
  340.          */
  341.         if (ctx->Fog.ColorSumEnabled || ctx->Light.Enabled) {
  342.                 INPUT_SRC(&rc, D, E_TIMES_F, RGB);
  343.                 INPUT_SRC(&rc, F, SECONDARY_COLOR, RGB);
  344.         }
  345.  
  346.         if (ctx->Fog.Enabled) {
  347.                 INPUT_SRC(&rc, A, FOG, ALPHA);
  348.                 INPUT_SRC(&rc, C, FOG, RGB);
  349.                 INPUT_SRC(&rc, E, FOG, ALPHA);
  350.         } else {
  351.                 INPUT_ONE(&rc, A, 0);
  352.                 INPUT_ONE(&rc, C, 0);
  353.                 INPUT_ONE(&rc, E, 0);
  354.         }
  355.  
  356.         if (ctx->Texture._MaxEnabledTexImageUnit != -1) {
  357.                 INPUT_SRC(&rc, B, SPARE0, RGB);
  358.                 INPUT_SRC(&rc, G, SPARE0, ALPHA);
  359.         } else {
  360.                 INPUT_SRC(&rc, B, PRIMARY_COLOR, RGB);
  361.                 INPUT_SRC(&rc, G, PRIMARY_COLOR, ALPHA);
  362.         }
  363.  
  364.         *in = rc.in;
  365.         *n = ctx->Texture._MaxEnabledTexImageUnit + 1;
  366. }
  367.  
  368. void
  369. nv10_emit_tex_env(struct gl_context *ctx, int emit)
  370. {
  371.         const int i = emit - NOUVEAU_STATE_TEX_ENV0;
  372.         struct nouveau_pushbuf *push = context_push(ctx);
  373.         uint32_t a_in, a_out, c_in, c_out, k;
  374.  
  375.         nv10_get_general_combiner(ctx, i, &a_in, &a_out, &c_in, &c_out, &k);
  376.  
  377.         /* Enable the combiners we're going to need. */
  378.         if (i == 1) {
  379.                 if (c_out || a_out)
  380.                         c_out |= 0x5 << 27;
  381.                 else
  382.                         c_out |= 0x3 << 27;
  383.         }
  384.  
  385.         BEGIN_NV04(push, NV10_3D(RC_IN_ALPHA(i)), 1);
  386.         PUSH_DATA (push, a_in);
  387.         BEGIN_NV04(push, NV10_3D(RC_IN_RGB(i)), 1);
  388.         PUSH_DATA (push, c_in);
  389.         BEGIN_NV04(push, NV10_3D(RC_COLOR(i)), 1);
  390.         PUSH_DATA (push, k);
  391.         BEGIN_NV04(push, NV10_3D(RC_OUT_ALPHA(i)), 1);
  392.         PUSH_DATA (push, a_out);
  393.         BEGIN_NV04(push, NV10_3D(RC_OUT_RGB(i)), 1);
  394.         PUSH_DATA (push, c_out);
  395.  
  396.         context_dirty(ctx, FRAG);
  397. }
  398.  
  399. void
  400. nv10_emit_frag(struct gl_context *ctx, int emit)
  401. {
  402.         struct nouveau_pushbuf *push = context_push(ctx);
  403.         uint64_t in;
  404.         int n;
  405.  
  406.         nv10_get_final_combiner(ctx, &in, &n);
  407.  
  408.         BEGIN_NV04(push, NV10_3D(RC_FINAL0), 2);
  409.         PUSH_DATA (push, in);
  410.         PUSH_DATA (push, in >> 32);
  411. }
  412.