Home | History | Annotate | Download | only in state_tracker
      1 /**************************************************************************
      2  *
      3  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 
     29 #include "main/glheader.h"
     30 #include "main/context.h"
     31 
     32 #include "pipe/p_defines.h"
     33 #include "st_context.h"
     34 #include "st_atom.h"
     35 #include "st_cb_bitmap.h"
     36 #include "st_program.h"
     37 #include "st_manager.h"
     38 
     39 
     40 /**
     41  * This is used to initialize st->atoms[].
     42  */
     43 static const struct st_tracked_state *atoms[] =
     44 {
     45    &st_update_depth_stencil_alpha,
     46    &st_update_clip,
     47 
     48    &st_finalize_textures,
     49    &st_update_fp,
     50    &st_update_gp,
     51    &st_update_vp,
     52 
     53    &st_update_rasterizer,
     54    &st_update_polygon_stipple,
     55    &st_update_viewport,
     56    &st_update_scissor,
     57    &st_update_blend,
     58    &st_update_sampler,
     59    &st_update_vertex_texture,
     60    &st_update_fragment_texture,
     61    &st_update_geometry_texture,
     62    &st_update_framebuffer,
     63    &st_update_msaa,
     64    &st_update_vs_constants,
     65    &st_update_gs_constants,
     66    &st_update_fs_constants,
     67    &st_update_pixel_transfer,
     68 
     69    /* this must be done after the vertex program update */
     70    &st_update_array
     71 };
     72 
     73 
     74 void st_init_atoms( struct st_context *st )
     75 {
     76    /* no-op */
     77 }
     78 
     79 
     80 void st_destroy_atoms( struct st_context *st )
     81 {
     82    /* no-op */
     83 }
     84 
     85 
     86 /***********************************************************************
     87  */
     88 
     89 static GLboolean check_state( const struct st_state_flags *a,
     90 			      const struct st_state_flags *b )
     91 {
     92    return ((a->mesa & b->mesa) ||
     93 	   (a->st & b->st));
     94 }
     95 
     96 static void accumulate_state( struct st_state_flags *a,
     97 			      const struct st_state_flags *b )
     98 {
     99    a->mesa |= b->mesa;
    100    a->st |= b->st;
    101 }
    102 
    103 
    104 static void xor_states( struct st_state_flags *result,
    105 			     const struct st_state_flags *a,
    106 			      const struct st_state_flags *b )
    107 {
    108    result->mesa = a->mesa ^ b->mesa;
    109    result->st = a->st ^ b->st;
    110 }
    111 
    112 
    113 /* Too complex to figure out, just check every time:
    114  */
    115 static void check_program_state( struct st_context *st )
    116 {
    117    struct gl_context *ctx = st->ctx;
    118 
    119    if (ctx->VertexProgram._Current != &st->vp->Base)
    120       st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
    121 
    122    if (ctx->FragmentProgram._Current != &st->fp->Base)
    123       st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
    124 
    125    if (ctx->GeometryProgram._Current != &st->gp->Base)
    126       st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
    127 }
    128 
    129 static void check_attrib_edgeflag(struct st_context *st)
    130 {
    131    const struct gl_client_array **arrays = st->ctx->Array._DrawArrays;
    132    GLboolean vertDataEdgeFlags;
    133 
    134    if (!arrays)
    135       return;
    136 
    137    vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
    138                        arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
    139    if (vertDataEdgeFlags != st->vertdata_edgeflags) {
    140       st->vertdata_edgeflags = vertDataEdgeFlags;
    141       st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
    142    }
    143 }
    144 
    145 
    146 /***********************************************************************
    147  * Update all derived state:
    148  */
    149 
    150 void st_validate_state( struct st_context *st )
    151 {
    152    struct st_state_flags *state = &st->dirty;
    153    GLuint i;
    154 
    155    /* Get Mesa driver state. */
    156    st->dirty.st |= st->ctx->NewDriverState;
    157    st->ctx->NewDriverState = 0;
    158 
    159    check_attrib_edgeflag(st);
    160 
    161    /* The bitmap cache is immune to pixel unpack changes.
    162     * Note that GLUT makes several calls to glPixelStore for each
    163     * bitmap char it draws so this is an important check.
    164     */
    165    if (state->mesa & ~_NEW_PACKUNPACK)
    166       st_flush_bitmap_cache(st);
    167 
    168    check_program_state( st );
    169 
    170    st_manager_validate_framebuffers(st);
    171 
    172    if (state->st == 0)
    173       return;
    174 
    175    /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/
    176 
    177 #ifdef DEBUG
    178    if (1) {
    179 #else
    180    if (0) {
    181 #endif
    182       /* Debug version which enforces various sanity checks on the
    183        * state flags which are generated and checked to help ensure
    184        * state atoms are ordered correctly in the list.
    185        */
    186       struct st_state_flags examined, prev;
    187       memset(&examined, 0, sizeof(examined));
    188       prev = *state;
    189 
    190       for (i = 0; i < Elements(atoms); i++) {
    191 	 const struct st_tracked_state *atom = atoms[i];
    192 	 struct st_state_flags generated;
    193 
    194 	 /*printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);*/
    195 
    196 	 if (!(atom->dirty.mesa || atom->dirty.st) ||
    197 	     !atom->update) {
    198 	    printf("malformed atom %s\n", atom->name);
    199 	    assert(0);
    200 	 }
    201 
    202 	 if (check_state(state, &atom->dirty)) {
    203 	    atoms[i]->update( st );
    204 	    /*printf("after: %x\n", atom->dirty.mesa);*/
    205 	 }
    206 
    207 	 accumulate_state(&examined, &atom->dirty);
    208 
    209 	 /* generated = (prev ^ state)
    210 	  * if (examined & generated)
    211 	  *     fail;
    212 	  */
    213 	 xor_states(&generated, &prev, state);
    214 	 assert(!check_state(&examined, &generated));
    215 	 prev = *state;
    216       }
    217       /*printf("\n");*/
    218 
    219    }
    220    else {
    221       for (i = 0; i < Elements(atoms); i++) {
    222 	 if (check_state(state, &atoms[i]->dirty))
    223 	    atoms[i]->update( st );
    224       }
    225    }
    226 
    227    memset(state, 0, sizeof(*state));
    228 }
    229 
    230 
    231 
    232