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