Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  6.5
  4.  *
  5.  * Copyright (C) 1999-2006  Brian Paul   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.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26.  
  27. #include "main/glheader.h"
  28. #include "main/colormac.h"
  29. #include "main/light.h"
  30. #include "main/macros.h"
  31. #include "main/imports.h"
  32. #include "main/simple_list.h"
  33. #include "main/mtypes.h"
  34.  
  35. #include "math/m_translate.h"
  36.  
  37. #include "t_context.h"
  38. #include "t_pipeline.h"
  39.  
  40. #define LIGHT_TWOSIDE       0x1
  41. #define LIGHT_MATERIAL      0x2
  42. #define MAX_LIGHT_FUNC      0x4
  43.  
  44. typedef void (*light_func)( struct gl_context *ctx,
  45.                             struct vertex_buffer *VB,
  46.                             struct tnl_pipeline_stage *stage,
  47.                             GLvector4f *input );
  48.  
  49. /**
  50.  * Information for updating current material attributes from vertex color,
  51.  * for GL_COLOR_MATERIAL.
  52.  */
  53. struct material_cursor {
  54.    const GLfloat *ptr;    /* points to src vertex color (in VB array) */
  55.    GLuint stride;         /* stride to next vertex color (bytes) */
  56.    GLfloat *current;      /* points to material attribute to update */
  57.    GLuint size;           /* vertex/color size: 1, 2, 3 or 4 */
  58. };
  59.  
  60. /**
  61.  * Data private to this pipeline stage.
  62.  */
  63. struct light_stage_data {
  64.    GLvector4f Input;
  65.    GLvector4f LitColor[2];
  66.    GLvector4f LitSecondary[2];
  67.    light_func *light_func_tab;
  68.  
  69.    struct material_cursor mat[MAT_ATTRIB_MAX];
  70.    GLuint mat_count;
  71.    GLuint mat_bitmask;
  72. };
  73.  
  74.  
  75. #define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr))
  76.  
  77.  
  78.  
  79. /**
  80.  * In the case of colormaterial, the effected material attributes
  81.  * should already have been bound to point to the incoming color data,
  82.  * prior to running the pipeline.
  83.  * This function copies the vertex's color to the material attributes
  84.  * which are tracking glColor.
  85.  * It's called per-vertex in the lighting loop.
  86.  */
  87. static void
  88. update_materials(struct gl_context *ctx, struct light_stage_data *store)
  89. {
  90.    GLuint i;
  91.  
  92.    for (i = 0 ; i < store->mat_count ; i++) {
  93.       /* update the material */
  94.       COPY_CLEAN_4V(store->mat[i].current, store->mat[i].size, store->mat[i].ptr);
  95.       /* increment src vertex color pointer */
  96.       STRIDE_F(store->mat[i].ptr, store->mat[i].stride);
  97.    }
  98.      
  99.    /* recompute derived light/material values */
  100.    _mesa_update_material( ctx, store->mat_bitmask );
  101.    /* XXX we should only call this if we're tracking/changing the specular
  102.     * exponent.
  103.     */
  104.    _mesa_validate_all_lighting_tables( ctx );
  105. }
  106.  
  107.  
  108. /**
  109.  * Prepare things prior to running the lighting stage.
  110.  * Return number of material attributes which will track vertex color.
  111.  */
  112. static GLuint
  113. prepare_materials(struct gl_context *ctx,
  114.                   struct vertex_buffer *VB, struct light_stage_data *store)
  115. {
  116.    GLuint i;
  117.    
  118.    store->mat_count = 0;
  119.    store->mat_bitmask = 0;
  120.  
  121.    /* Examine the ColorMaterialBitmask to determine which materials
  122.     * track vertex color.  Override the material attribute's pointer
  123.     * with the color pointer for each one.
  124.     */
  125.    if (ctx->Light.ColorMaterialEnabled) {
  126.       const GLuint bitmask = ctx->Light.ColorMaterialBitmask;
  127.       for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
  128.          if (bitmask & (1<<i))
  129.             VB->AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
  130.    }
  131.  
  132.    /* Now, for each material attribute that's tracking vertex color, save
  133.     * some values (ptr, stride, size, current) that we'll need in
  134.     * update_materials(), above, that'll actually copy the vertex color to
  135.     * the material attribute(s).
  136.     */
  137.    for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
  138.       if (VB->AttribPtr[i]->stride) {
  139.          const GLuint j = store->mat_count++;
  140.          const GLuint attr = i - _TNL_ATTRIB_MAT_FRONT_AMBIENT;
  141.          store->mat[j].ptr    = VB->AttribPtr[i]->start;
  142.          store->mat[j].stride = VB->AttribPtr[i]->stride;
  143.          store->mat[j].size   = VB->AttribPtr[i]->size;
  144.          store->mat[j].current = ctx->Light.Material.Attrib[attr];
  145.          store->mat_bitmask |= (1<<attr);
  146.       }
  147.    }
  148.  
  149.    /* FIXME: Is this already done?
  150.     */
  151.    _mesa_update_material( ctx, ~0 );
  152.    _mesa_validate_all_lighting_tables( ctx );
  153.  
  154.    return store->mat_count;
  155. }
  156.  
  157. /* Tables for all the shading functions.
  158.  */
  159. static light_func _tnl_light_tab[MAX_LIGHT_FUNC];
  160. static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC];
  161. static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC];
  162. static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC];
  163.  
  164. #define TAG(x)           x
  165. #define IDX              (0)
  166. #include "t_vb_lighttmp.h"
  167.  
  168. #define TAG(x)           x##_twoside
  169. #define IDX              (LIGHT_TWOSIDE)
  170. #include "t_vb_lighttmp.h"
  171.  
  172. #define TAG(x)           x##_material
  173. #define IDX              (LIGHT_MATERIAL)
  174. #include "t_vb_lighttmp.h"
  175.  
  176. #define TAG(x)           x##_twoside_material
  177. #define IDX              (LIGHT_TWOSIDE|LIGHT_MATERIAL)
  178. #include "t_vb_lighttmp.h"
  179.  
  180.  
  181. static void init_lighting_tables( void )
  182. {
  183.    static int done;
  184.  
  185.    if (!done) {
  186.       init_light_tab();
  187.       init_light_tab_twoside();
  188.       init_light_tab_material();
  189.       init_light_tab_twoside_material();
  190.       done = 1;
  191.    }
  192. }
  193.  
  194.  
  195. static GLboolean run_lighting( struct gl_context *ctx,
  196.                                struct tnl_pipeline_stage *stage )
  197. {
  198.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  199.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  200.    struct vertex_buffer *VB = &tnl->vb;
  201.    GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->AttribPtr[_TNL_ATTRIB_POS];
  202.    GLuint idx;
  203.  
  204.    if (!ctx->Light.Enabled || ctx->VertexProgram._Current)
  205.       return GL_TRUE;
  206.  
  207.    /* Make sure we can talk about position x,y and z:
  208.     */
  209.    if (input->size <= 2 && input == VB->AttribPtr[_TNL_ATTRIB_POS]) {
  210.  
  211.       _math_trans_4f( store->Input.data,
  212.                       VB->AttribPtr[_TNL_ATTRIB_POS]->data,
  213.                       VB->AttribPtr[_TNL_ATTRIB_POS]->stride,
  214.                       GL_FLOAT,
  215.                       VB->AttribPtr[_TNL_ATTRIB_POS]->size,
  216.                       0,
  217.                       VB->Count );
  218.  
  219.       if (input->size <= 2) {
  220.          /* Clean z.
  221.           */
  222.          _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2);
  223.       }
  224.          
  225.       if (input->size <= 1) {
  226.          /* Clean y.
  227.           */
  228.          _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1);
  229.       }
  230.  
  231.       input = &store->Input;
  232.    }
  233.    
  234.    idx = 0;
  235.  
  236.    if (prepare_materials( ctx, VB, store ))
  237.       idx |= LIGHT_MATERIAL;
  238.  
  239.    if (ctx->Light.Model.TwoSide)
  240.       idx |= LIGHT_TWOSIDE;
  241.  
  242.    /* The individual functions know about replaying side-effects
  243.     * vs. full re-execution.
  244.     */
  245.    store->light_func_tab[idx]( ctx, VB, stage, input );
  246.  
  247.    return GL_TRUE;
  248. }
  249.  
  250.  
  251. /* Called in place of do_lighting when the light table may have changed.
  252.  */
  253. static void validate_lighting( struct gl_context *ctx,
  254.                                         struct tnl_pipeline_stage *stage )
  255. {
  256.    light_func *tab;
  257.  
  258.    if (!ctx->Light.Enabled || ctx->VertexProgram._Current)
  259.       return;
  260.  
  261.    if (ctx->Light._NeedVertices) {
  262.       if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  263.          tab = _tnl_light_spec_tab;
  264.       else
  265.          tab = _tnl_light_tab;
  266.    }
  267.    else {
  268.       if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
  269.          tab = _tnl_light_fast_single_tab;
  270.       else
  271.          tab = _tnl_light_fast_tab;
  272.    }
  273.  
  274.  
  275.    LIGHT_STAGE_DATA(stage)->light_func_tab = tab;
  276.  
  277.    /* This and the above should only be done on _NEW_LIGHT:
  278.     */
  279.    TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  280. }
  281.  
  282.  
  283.  
  284. /* Called the first time stage->run is called.  In effect, don't
  285.  * allocate data until the first time the stage is run.
  286.  */
  287. static GLboolean init_lighting( struct gl_context *ctx,
  288.                                 struct tnl_pipeline_stage *stage )
  289. {
  290.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  291.    struct light_stage_data *store;
  292.    GLuint size = tnl->vb.Size;
  293.  
  294.    stage->privatePtr = MALLOC(sizeof(*store));
  295.    store = LIGHT_STAGE_DATA(stage);
  296.    if (!store)
  297.       return GL_FALSE;
  298.  
  299.    /* Do onetime init.
  300.     */
  301.    init_lighting_tables();
  302.  
  303.    _mesa_vector4f_alloc( &store->Input, 0, size, 32 );
  304.    _mesa_vector4f_alloc( &store->LitColor[0], 0, size, 32 );
  305.    _mesa_vector4f_alloc( &store->LitColor[1], 0, size, 32 );
  306.    _mesa_vector4f_alloc( &store->LitSecondary[0], 0, size, 32 );
  307.    _mesa_vector4f_alloc( &store->LitSecondary[1], 0, size, 32 );
  308.  
  309.    store->LitColor[0].size = 4;
  310.    store->LitColor[1].size = 4;
  311.    store->LitSecondary[0].size = 3;
  312.    store->LitSecondary[1].size = 3;
  313.  
  314.    return GL_TRUE;
  315. }
  316.  
  317.  
  318.  
  319.  
  320. static void dtr( struct tnl_pipeline_stage *stage )
  321. {
  322.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  323.  
  324.    if (store) {
  325.       _mesa_vector4f_free( &store->Input );
  326.       _mesa_vector4f_free( &store->LitColor[0] );
  327.       _mesa_vector4f_free( &store->LitColor[1] );
  328.       _mesa_vector4f_free( &store->LitSecondary[0] );
  329.       _mesa_vector4f_free( &store->LitSecondary[1] );
  330.       FREE( store );
  331.       stage->privatePtr = NULL;
  332.    }
  333. }
  334.  
  335. const struct tnl_pipeline_stage _tnl_lighting_stage =
  336. {
  337.    "lighting",                  /* name */
  338.    NULL,                        /* private_data */
  339.    init_lighting,
  340.    dtr,                         /* destroy */
  341.    validate_lighting,
  342.    run_lighting
  343. };
  344.