Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "nouveau_util.h"
  31. #include "nv10_3d.xml.h"
  32. #include "nv10_driver.h"
  33.  
  34. void
  35. nv10_emit_clip_plane(struct gl_context *ctx, int emit)
  36. {
  37. }
  38.  
  39. static inline unsigned
  40. get_material_bitmask(unsigned m)
  41. {
  42.         unsigned ret = 0;
  43.  
  44.         if (m & MAT_BIT_FRONT_EMISSION)
  45.                 ret |= NV10_3D_COLOR_MATERIAL_EMISSION;
  46.         if (m & MAT_BIT_FRONT_AMBIENT)
  47.                 ret |= NV10_3D_COLOR_MATERIAL_AMBIENT;
  48.         if (m & MAT_BIT_FRONT_DIFFUSE)
  49.                 ret |= NV10_3D_COLOR_MATERIAL_DIFFUSE;
  50.         if (m & MAT_BIT_FRONT_SPECULAR)
  51.                 ret |= NV10_3D_COLOR_MATERIAL_SPECULAR;
  52.  
  53.         return ret;
  54. }
  55.  
  56. void
  57. nv10_emit_color_material(struct gl_context *ctx, int emit)
  58. {
  59.         struct nouveau_pushbuf *push = context_push(ctx);
  60.         unsigned mask = get_material_bitmask(ctx->Light._ColorMaterialBitmask);
  61.  
  62.         BEGIN_NV04(push, NV10_3D(COLOR_MATERIAL), 1);
  63.         PUSH_DATA (push, ctx->Light.ColorMaterialEnabled ? mask : 0);
  64. }
  65.  
  66. static unsigned
  67. get_fog_mode(unsigned mode)
  68. {
  69.         switch (mode) {
  70.         case GL_LINEAR:
  71.                 return NV10_3D_FOG_MODE_LINEAR;
  72.         case GL_EXP:
  73.                 return NV10_3D_FOG_MODE_EXP;
  74.         case GL_EXP2:
  75.                 return NV10_3D_FOG_MODE_EXP2;
  76.         default:
  77.                 assert(0);
  78.         }
  79. }
  80.  
  81. static unsigned
  82. get_fog_source(unsigned source, unsigned distance_mode)
  83. {
  84.         switch (source) {
  85.         case GL_FOG_COORDINATE_EXT:
  86.                 return NV10_3D_FOG_COORD_FOG;
  87.         case GL_FRAGMENT_DEPTH_EXT:
  88.                 switch (distance_mode) {
  89.                 case GL_EYE_PLANE_ABSOLUTE_NV:
  90.                         return NV10_3D_FOG_COORD_DIST_ORTHOGONAL_ABS;
  91.                 case GL_EYE_PLANE:
  92.                         return NV10_3D_FOG_COORD_DIST_ORTHOGONAL;
  93.                 case GL_EYE_RADIAL_NV:
  94.                         return NV10_3D_FOG_COORD_DIST_RADIAL;
  95.                 default:
  96.                         assert(0);
  97.                 }
  98.         default:
  99.                 assert(0);
  100.         }
  101. }
  102.  
  103. void
  104. nv10_get_fog_coeff(struct gl_context *ctx, float k[3])
  105. {
  106.         struct gl_fog_attrib *f = &ctx->Fog;
  107.  
  108.         switch (f->Mode) {
  109.         case GL_LINEAR:
  110.                 k[0] = 2 + f->Start / (f->End - f->Start);
  111.                 k[1] = -1 / (f->End - f->Start);
  112.                 break;
  113.  
  114.         case GL_EXP:
  115.                 k[0] = 1.5;
  116.                 k[1] = -0.09 * f->Density;
  117.                 break;
  118.  
  119.         case GL_EXP2:
  120.                 k[0] = 1.5;
  121.                 k[1] = -0.21 * f->Density;
  122.                 break;
  123.  
  124.         default:
  125.                 assert(0);
  126.         }
  127.  
  128.         k[2] = 0;
  129. }
  130.  
  131. void
  132. nv10_emit_fog(struct gl_context *ctx, int emit)
  133. {
  134.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  135.         struct nouveau_pushbuf *push = context_push(ctx);
  136.         struct gl_fog_attrib *f = &ctx->Fog;
  137.         unsigned source = nctx->fallback == HWTNL ?
  138.                 f->FogCoordinateSource : GL_FOG_COORDINATE_EXT;
  139.         float k[3];
  140.  
  141.         nv10_get_fog_coeff(ctx, k);
  142.  
  143.         BEGIN_NV04(push, NV10_3D(FOG_MODE), 4);
  144.         PUSH_DATA (push, get_fog_mode(f->Mode));
  145.         PUSH_DATA (push, get_fog_source(source, f->FogDistanceMode));
  146.         PUSH_DATAb(push, f->Enabled);
  147.         PUSH_DATA (push, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color));
  148.  
  149.         BEGIN_NV04(push, NV10_3D(FOG_COEFF(0)), 3);
  150.         PUSH_DATAp(push, k, 3);
  151.  
  152.         context_dirty(ctx, FRAG);
  153. }
  154.  
  155. static inline unsigned
  156. get_light_mode(struct gl_light *l)
  157. {
  158.         if (l->Enabled) {
  159.                 if (l->_Flags & LIGHT_SPOT)
  160.                         return NV10_3D_ENABLED_LIGHTS_0_DIRECTIONAL;
  161.                 else if (l->_Flags & LIGHT_POSITIONAL)
  162.                         return NV10_3D_ENABLED_LIGHTS_0_POSITIONAL;
  163.                 else
  164.                         return NV10_3D_ENABLED_LIGHTS_0_NONPOSITIONAL;
  165.         } else {
  166.                 return NV10_3D_ENABLED_LIGHTS_0_DISABLED;
  167.         }
  168. }
  169.  
  170. void
  171. nv10_emit_light_enable(struct gl_context *ctx, int emit)
  172. {
  173.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  174.         struct nouveau_pushbuf *push = context_push(ctx);
  175.         uint32_t en_lights = 0;
  176.         int i;
  177.  
  178.         if (nctx->fallback != HWTNL) {
  179.                 BEGIN_NV04(push, NV10_3D(LIGHTING_ENABLE), 1);
  180.                 PUSH_DATA (push, 0);
  181.                 return;
  182.         }
  183.  
  184.         for (i = 0; i < MAX_LIGHTS; i++)
  185.                 en_lights |= get_light_mode(&ctx->Light.Light[i]) << 2 * i;
  186.  
  187.         BEGIN_NV04(push, NV10_3D(ENABLED_LIGHTS), 1);
  188.         PUSH_DATA (push, en_lights);
  189.         BEGIN_NV04(push, NV10_3D(LIGHTING_ENABLE), 1);
  190.         PUSH_DATAb(push, ctx->Light.Enabled);
  191.         BEGIN_NV04(push, NV10_3D(NORMALIZE_ENABLE), 1);
  192.         PUSH_DATAb(push, ctx->Transform.Normalize);
  193. }
  194.  
  195. void
  196. nv10_emit_light_model(struct gl_context *ctx, int emit)
  197. {
  198.         struct nouveau_pushbuf *push = context_push(ctx);
  199.         struct gl_lightmodel *m = &ctx->Light.Model;
  200.  
  201.         BEGIN_NV04(push, NV10_3D(SEPARATE_SPECULAR_ENABLE), 1);
  202.         PUSH_DATAb(push, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR);
  203.  
  204.         BEGIN_NV04(push, NV10_3D(LIGHT_MODEL), 1);
  205.         PUSH_DATA (push, ((m->LocalViewer ?
  206.                          NV10_3D_LIGHT_MODEL_LOCAL_VIEWER : 0) |
  207.                         (_mesa_need_secondary_color(ctx) ?
  208.                          NV10_3D_LIGHT_MODEL_SEPARATE_SPECULAR : 0) |
  209.                         (!ctx->Light.Enabled && ctx->Fog.ColorSumEnabled ?
  210.                          NV10_3D_LIGHT_MODEL_VERTEX_SPECULAR : 0)));
  211. }
  212.  
  213. static float
  214. get_shine(const float p[], float x)
  215. {
  216.         const int n = 15;
  217.         const float *y = &p[1];
  218.         float f = (n - 1) * (1 - 1 / (1 + p[0] * x))
  219.                 / (1 - 1 / (1 + p[0] * 1024));
  220.         int i = f;
  221.  
  222.         /* Linear interpolation in f-space (Faster and somewhat more
  223.          * accurate than x-space). */
  224.         if (x == 0)
  225.                 return y[0];
  226.         else if (i > n - 2)
  227.                 return y[n - 1];
  228.         else
  229.                 return y[i] + (y[i + 1] - y[i]) * (f - i);
  230. }
  231.  
  232. static const float nv10_spot_params[2][16] = {
  233.         { 0.02, -3.80e-05, -1.77, -2.41, -2.71, -2.88, -2.98, -3.06,
  234.           -3.11, -3.17, -3.23, -3.28, -3.37, -3.47, -3.83, -5.11 },
  235.         { 0.02, -0.01, 1.77, 2.39, 2.70, 2.87, 2.98, 3.06,
  236.           3.10, 3.16, 3.23, 3.27, 3.37, 3.47, 3.83, 5.11 },
  237. };
  238.  
  239. void
  240. nv10_get_spot_coeff(struct gl_light *l, float k[7])
  241. {
  242.         float e = l->SpotExponent;
  243.         float a0, b0, a1, a2, b2, a3;
  244.  
  245.         if (e > 0)
  246.                 a0 = -1 - 5.36e-3 / sqrt(e);
  247.         else
  248.                 a0 = -1;
  249.         b0 = 1 / (1 + 0.273 * e);
  250.  
  251.         a1 = get_shine(nv10_spot_params[0], e);
  252.  
  253.         a2 = get_shine(nv10_spot_params[1], e);
  254.         b2 = 1 / (1 + 0.273 * e);
  255.  
  256.         a3 = 0.9 + 0.278 * e;
  257.  
  258.         if (l->SpotCutoff > 0) {
  259.                 float cutoff = MAX2(a3, 1 / (1 - l->_CosCutoff));
  260.  
  261.                 k[0] = MAX2(0, a0 + b0 * cutoff);
  262.                 k[1] = a1;
  263.                 k[2] = a2 + b2 * cutoff;
  264.                 k[3] = - cutoff * l->_NormSpotDirection[0];
  265.                 k[4] = - cutoff * l->_NormSpotDirection[1];
  266.                 k[5] = - cutoff * l->_NormSpotDirection[2];
  267.                 k[6] = 1 - cutoff;
  268.  
  269.         } else {
  270.                 k[0] = b0;
  271.                 k[1] = a1;
  272.                 k[2] = a2 + b2;
  273.                 k[3] = - l->_NormSpotDirection[0];
  274.                 k[4] = - l->_NormSpotDirection[1];
  275.                 k[5] = - l->_NormSpotDirection[2];
  276.                 k[6] = -1;
  277.         }
  278. }
  279.  
  280. void
  281. nv10_emit_light_source(struct gl_context *ctx, int emit)
  282. {
  283.         const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0;
  284.         struct nouveau_pushbuf *push = context_push(ctx);
  285.         struct gl_light *l = &ctx->Light.Light[i];
  286.  
  287.         if (l->_Flags & LIGHT_POSITIONAL) {
  288.                 BEGIN_NV04(push, NV10_3D(LIGHT_POSITION_X(i)), 3);
  289.                 PUSH_DATAp(push, l->_Position, 3);
  290.  
  291.                 BEGIN_NV04(push, NV10_3D(LIGHT_ATTENUATION_CONSTANT(i)), 3);
  292.                 PUSH_DATAf(push, l->ConstantAttenuation);
  293.                 PUSH_DATAf(push, l->LinearAttenuation);
  294.                 PUSH_DATAf(push, l->QuadraticAttenuation);
  295.  
  296.         } else {
  297.                 BEGIN_NV04(push, NV10_3D(LIGHT_DIRECTION_X(i)), 3);
  298.                 PUSH_DATAp(push, l->_VP_inf_norm, 3);
  299.  
  300.                 BEGIN_NV04(push, NV10_3D(LIGHT_HALF_VECTOR_X(i)), 3);
  301.                 PUSH_DATAp(push, l->_h_inf_norm, 3);
  302.         }
  303.  
  304.         if (l->_Flags & LIGHT_SPOT) {
  305.                 float k[7];
  306.  
  307.                 nv10_get_spot_coeff(l, k);
  308.  
  309.                 BEGIN_NV04(push, NV10_3D(LIGHT_SPOT_CUTOFF(i, 0)), 7);
  310.                 PUSH_DATAp(push, k, 7);
  311.         }
  312. }
  313.  
  314. #define USE_COLOR_MATERIAL(attr)                                        \
  315.         (ctx->Light.ColorMaterialEnabled &&                             \
  316.          ctx->Light._ColorMaterialBitmask & (1 << MAT_ATTRIB_FRONT_##attr))
  317.  
  318. void
  319. nv10_emit_material_ambient(struct gl_context *ctx, int emit)
  320. {
  321.         struct nouveau_pushbuf *push = context_push(ctx);
  322.         float (*mat)[4] = ctx->Light.Material.Attrib;
  323.         float c_scene[3], c_factor[3];
  324.         struct gl_light *l;
  325.  
  326.         if (USE_COLOR_MATERIAL(AMBIENT)) {
  327.                 COPY_3V(c_scene, ctx->Light.Model.Ambient);
  328.                 COPY_3V(c_factor, mat[MAT_ATTRIB_FRONT_EMISSION]);
  329.  
  330.         } else if (USE_COLOR_MATERIAL(EMISSION)) {
  331.                 SCALE_3V(c_scene, mat[MAT_ATTRIB_FRONT_AMBIENT],
  332.                          ctx->Light.Model.Ambient);
  333.                 ZERO_3V(c_factor);
  334.  
  335.         } else {
  336.                 COPY_3V(c_scene, ctx->Light._BaseColor[0]);
  337.                 ZERO_3V(c_factor);
  338.         }
  339.  
  340.         BEGIN_NV04(push, NV10_3D(LIGHT_MODEL_AMBIENT_R), 3);
  341.         PUSH_DATAp(push, c_scene, 3);
  342.  
  343.         if (ctx->Light.ColorMaterialEnabled) {
  344.                 BEGIN_NV04(push, NV10_3D(MATERIAL_FACTOR_R), 3);
  345.                 PUSH_DATAp(push, c_factor, 3);
  346.         }
  347.  
  348.         foreach(l, &ctx->Light.EnabledList) {
  349.                 const int i = l - ctx->Light.Light;
  350.                 float *c_light = (USE_COLOR_MATERIAL(AMBIENT) ?
  351.                                   l->Ambient :
  352.                                   l->_MatAmbient[0]);
  353.  
  354.                 BEGIN_NV04(push, NV10_3D(LIGHT_AMBIENT_R(i)), 3);
  355.                 PUSH_DATAp(push, c_light, 3);
  356.         }
  357. }
  358.  
  359. void
  360. nv10_emit_material_diffuse(struct gl_context *ctx, int emit)
  361. {
  362.         struct nouveau_pushbuf *push = context_push(ctx);
  363.         GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
  364.         struct gl_light *l;
  365.  
  366.         BEGIN_NV04(push, NV10_3D(MATERIAL_FACTOR_A), 1);
  367.         PUSH_DATAf(push, mat[MAT_ATTRIB_FRONT_DIFFUSE][3]);
  368.  
  369.         foreach(l, &ctx->Light.EnabledList) {
  370.                 const int i = l - ctx->Light.Light;
  371.                 float *c_light = (USE_COLOR_MATERIAL(DIFFUSE) ?
  372.                                   l->Diffuse :
  373.                                   l->_MatDiffuse[0]);
  374.  
  375.                 BEGIN_NV04(push, NV10_3D(LIGHT_DIFFUSE_R(i)), 3);
  376.                 PUSH_DATAp(push, c_light, 3);
  377.         }
  378. }
  379.  
  380. void
  381. nv10_emit_material_specular(struct gl_context *ctx, int emit)
  382. {
  383.         struct nouveau_pushbuf *push = context_push(ctx);
  384.         struct gl_light *l;
  385.  
  386.         foreach(l, &ctx->Light.EnabledList) {
  387.                 const int i = l - ctx->Light.Light;
  388.                 float *c_light = (USE_COLOR_MATERIAL(SPECULAR) ?
  389.                                   l->Specular :
  390.                                   l->_MatSpecular[0]);
  391.  
  392.                 BEGIN_NV04(push, NV10_3D(LIGHT_SPECULAR_R(i)), 3);
  393.                 PUSH_DATAp(push, c_light, 3);
  394.         }
  395. }
  396.  
  397. static const float nv10_shininess_param[6][16] = {
  398.         { 0.70, 0.00, 0.06, 0.06, 0.05, 0.04, 0.02, 0.00,
  399.           -0.06, -0.13, -0.24, -0.36, -0.51, -0.66, -0.82, -1.00 },
  400.         { 0.01, 1.00, -2.29, -2.77, -2.96, -3.06, -3.12, -3.18,
  401.           -3.24, -3.29, -3.36, -3.43, -3.51, -3.75, -4.33, -5.11 },
  402.         { 0.02, 0.00, 2.28, 2.75, 2.94, 3.04, 3.1, 3.15,
  403.           3.18, 3.22, 3.27, 3.32, 3.39, 3.48, 3.84, 5.11 },
  404.         { 0.70, 0.00, 0.05, 0.06, 0.06, 0.06, 0.05, 0.04,
  405.           0.02, 0.01, -0.03, -0.12, -0.25, -0.43, -0.68, -0.99 },
  406.         { 0.01, 1.00, -1.61, -2.35, -2.67, -2.84, -2.96, -3.05,
  407.           -3.08, -3.14, -3.2, -3.26, -3.32, -3.42, -3.54, -4.21 },
  408.         { 0.01, 0.00, 2.25, 2.73, 2.92, 3.03, 3.09, 3.15,
  409.           3.16, 3.21, 3.25, 3.29, 3.35, 3.43, 3.56, 4.22 },
  410. };
  411.  
  412. void
  413. nv10_get_shininess_coeff(float s, float k[6])
  414. {
  415.         int i;
  416.  
  417.         for (i = 0; i < 6; i++)
  418.                 k[i] = get_shine(nv10_shininess_param[i], s);
  419. }
  420.  
  421. void
  422. nv10_emit_material_shininess(struct gl_context *ctx, int emit)
  423. {
  424.         struct nouveau_pushbuf *push = context_push(ctx);
  425.         float (*mat)[4] = ctx->Light.Material.Attrib;
  426.         float k[6];
  427.  
  428.         nv10_get_shininess_coeff(
  429.                 CLAMP(mat[MAT_ATTRIB_FRONT_SHININESS][0], 0, 1024),
  430.                 k);
  431.  
  432.         BEGIN_NV04(push, NV10_3D(MATERIAL_SHININESS(0)), 6);
  433.         PUSH_DATAp(push, k, 6);
  434. }
  435.  
  436. void
  437. nv10_emit_modelview(struct gl_context *ctx, int emit)
  438. {
  439.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  440.         struct nouveau_pushbuf *push = context_push(ctx);
  441.         GLmatrix *m = ctx->ModelviewMatrixStack.Top;
  442.  
  443.         if (nctx->fallback != HWTNL)
  444.                 return;
  445.  
  446.         if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled ||
  447.             (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) {
  448.                 BEGIN_NV04(push, NV10_3D(MODELVIEW_MATRIX(0, 0)), 16);
  449.                 PUSH_DATAm(push, m->m);
  450.         }
  451.  
  452.         if (ctx->Light.Enabled ||
  453.             (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) {
  454.                 int i, j;
  455.  
  456.                 BEGIN_NV04(push, NV10_3D(INVERSE_MODELVIEW_MATRIX(0, 0)), 12);
  457.                 for (i = 0; i < 3; i++)
  458.                         for (j = 0; j < 4; j++)
  459.                                 PUSH_DATAf(push, m->inv[4*i + j]);
  460.         }
  461. }
  462.  
  463. void
  464. nv10_emit_point_parameter(struct gl_context *ctx, int emit)
  465. {
  466. }
  467.  
  468. void
  469. nv10_emit_projection(struct gl_context *ctx, int emit)
  470. {
  471.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  472.         struct nouveau_pushbuf *push = context_push(ctx);
  473.         GLmatrix m;
  474.  
  475.         _math_matrix_ctr(&m);
  476.         get_viewport_scale(ctx, m.m);
  477.  
  478.         if (nv10_use_viewport_zclear(ctx))
  479.                 m.m[MAT_SZ] /= 8;
  480.  
  481.         if (nctx->fallback == HWTNL)
  482.                 _math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix);
  483.  
  484.         BEGIN_NV04(push, NV10_3D(PROJECTION_MATRIX(0)), 16);
  485.         PUSH_DATAm(push, m.m);
  486.  
  487.         _math_matrix_dtr(&m);
  488. }
  489.