1 /************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 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 VMWARE 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 <stdio.h> 30 #include "main/glheader.h" 31 #include "main/context.h" 32 33 #include "pipe/p_defines.h" 34 #include "st_context.h" 35 #include "st_atom.h" 36 #include "st_program.h" 37 #include "st_manager.h" 38 39 typedef void (*update_func_t)(struct st_context *st); 40 41 /* The list state update functions. */ 42 static const update_func_t update_functions[] = 43 { 44 #define ST_STATE(FLAG, st_update) st_update, 45 #include "st_atom_list.h" 46 #undef ST_STATE 47 }; 48 49 50 void st_init_atoms( struct st_context *st ) 51 { 52 STATIC_ASSERT(ARRAY_SIZE(update_functions) <= 64); 53 } 54 55 56 void st_destroy_atoms( struct st_context *st ) 57 { 58 /* no-op */ 59 } 60 61 62 /* Too complex to figure out, just check every time: 63 */ 64 static void check_program_state( struct st_context *st ) 65 { 66 struct gl_context *ctx = st->ctx; 67 struct st_vertex_program *old_vp = st->vp; 68 struct st_common_program *old_tcp = st->tcp; 69 struct st_common_program *old_tep = st->tep; 70 struct st_common_program *old_gp = st->gp; 71 struct st_fragment_program *old_fp = st->fp; 72 73 struct gl_program *new_vp = ctx->VertexProgram._Current; 74 struct gl_program *new_tcp = ctx->TessCtrlProgram._Current; 75 struct gl_program *new_tep = ctx->TessEvalProgram._Current; 76 struct gl_program *new_gp = ctx->GeometryProgram._Current; 77 struct gl_program *new_fp = ctx->FragmentProgram._Current; 78 uint64_t dirty = 0; 79 unsigned num_viewports = 1; 80 81 /* Flag states used by both new and old shaders to unbind shader resources 82 * properly when transitioning to shaders that don't use them. 83 */ 84 if (unlikely(new_vp != &old_vp->Base)) { 85 if (old_vp) 86 dirty |= old_vp->affected_states; 87 if (new_vp) 88 dirty |= ST_NEW_VERTEX_PROGRAM(st, st_vertex_program(new_vp)); 89 } 90 91 if (unlikely(new_tcp != &old_tcp->Base)) { 92 if (old_tcp) 93 dirty |= old_tcp->affected_states; 94 if (new_tcp) 95 dirty |= st_common_program(new_tcp)->affected_states; 96 } 97 98 if (unlikely(new_tep != &old_tep->Base)) { 99 if (old_tep) 100 dirty |= old_tep->affected_states; 101 if (new_tep) 102 dirty |= st_common_program(new_tep)->affected_states; 103 } 104 105 if (unlikely(new_gp != &old_gp->Base)) { 106 if (old_gp) 107 dirty |= old_gp->affected_states; 108 if (new_gp) 109 dirty |= st_common_program(new_gp)->affected_states; 110 } 111 112 if (unlikely(new_fp != &old_fp->Base)) { 113 if (old_fp) 114 dirty |= old_fp->affected_states; 115 if (new_fp) 116 dirty |= st_fragment_program(new_fp)->affected_states; 117 } 118 119 /* Find out the number of viewports. This determines how many scissors 120 * and viewport states we need to update. 121 */ 122 struct gl_program *last_prim_shader = new_gp ? new_gp : 123 new_tep ? new_tep : new_vp; 124 if (last_prim_shader && 125 last_prim_shader->info.outputs_written & VARYING_BIT_VIEWPORT) 126 num_viewports = ctx->Const.MaxViewports; 127 128 if (st->state.num_viewports != num_viewports) { 129 st->state.num_viewports = num_viewports; 130 dirty |= ST_NEW_VIEWPORT; 131 132 if (ctx->Scissor.EnableFlags & u_bit_consecutive(0, num_viewports)) 133 dirty |= ST_NEW_SCISSOR; 134 } 135 136 st->dirty |= dirty; 137 } 138 139 static void check_attrib_edgeflag(struct st_context *st) 140 { 141 const struct gl_vertex_array **arrays = st->ctx->Array._DrawArrays; 142 GLboolean vertdata_edgeflags, edgeflag_culls_prims, edgeflags_enabled; 143 struct gl_program *vp = st->ctx->VertexProgram._Current; 144 145 if (!arrays) 146 return; 147 148 edgeflags_enabled = st->ctx->Polygon.FrontMode != GL_FILL || 149 st->ctx->Polygon.BackMode != GL_FILL; 150 151 vertdata_edgeflags = edgeflags_enabled && 152 arrays[VERT_ATTRIB_EDGEFLAG]->StrideB != 0; 153 if (vertdata_edgeflags != st->vertdata_edgeflags) { 154 st->vertdata_edgeflags = vertdata_edgeflags; 155 if (vp) 156 st->dirty |= ST_NEW_VERTEX_PROGRAM(st, st_vertex_program(vp)); 157 } 158 159 edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags && 160 !st->ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0]; 161 if (edgeflag_culls_prims != st->edgeflag_culls_prims) { 162 st->edgeflag_culls_prims = edgeflag_culls_prims; 163 st->dirty |= ST_NEW_RASTERIZER; 164 } 165 } 166 167 168 /*********************************************************************** 169 * Update all derived state: 170 */ 171 172 void st_validate_state( struct st_context *st, enum st_pipeline pipeline ) 173 { 174 struct gl_context *ctx = st->ctx; 175 uint64_t dirty, pipeline_mask; 176 uint32_t dirty_lo, dirty_hi; 177 178 /* Get Mesa driver state. 179 * 180 * Inactive states are shader states not used by shaders at the moment. 181 */ 182 st->dirty |= ctx->NewDriverState & st->active_states & ST_ALL_STATES_MASK; 183 ctx->NewDriverState = 0; 184 185 /* Get pipeline state. */ 186 switch (pipeline) { 187 case ST_PIPELINE_RENDER: 188 if (st->ctx->API == API_OPENGL_COMPAT) 189 check_attrib_edgeflag(st); 190 191 if (st->gfx_shaders_may_be_dirty) { 192 check_program_state(st); 193 st->gfx_shaders_may_be_dirty = false; 194 } 195 196 st_manager_validate_framebuffers(st); 197 198 pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK; 199 break; 200 201 case ST_PIPELINE_CLEAR: 202 st_manager_validate_framebuffers(st); 203 pipeline_mask = ST_PIPELINE_CLEAR_STATE_MASK; 204 break; 205 206 case ST_PIPELINE_UPDATE_FRAMEBUFFER: 207 st_manager_validate_framebuffers(st); 208 pipeline_mask = ST_PIPELINE_UPDATE_FB_STATE_MASK; 209 break; 210 211 case ST_PIPELINE_COMPUTE: { 212 struct st_compute_program *old_cp = st->cp; 213 struct gl_program *new_cp = ctx->ComputeProgram._Current; 214 215 if (new_cp != &old_cp->Base) { 216 if (old_cp) 217 st->dirty |= old_cp->affected_states; 218 assert(new_cp); 219 st->dirty |= st_compute_program(new_cp)->affected_states; 220 } 221 222 st->compute_shader_may_be_dirty = false; 223 224 /* 225 * We add the ST_NEW_FB_STATE bit here as well, because glBindFramebuffer 226 * acts as a barrier that breaks feedback loops between the framebuffer 227 * and textures bound to the framebuffer, even when those textures are 228 * accessed by compute shaders; so we must inform the driver of new 229 * framebuffer state. 230 */ 231 pipeline_mask = ST_PIPELINE_COMPUTE_STATE_MASK | ST_NEW_FB_STATE; 232 break; 233 } 234 235 default: 236 unreachable("Invalid pipeline specified"); 237 } 238 239 dirty = st->dirty & pipeline_mask; 240 if (!dirty) 241 return; 242 243 dirty_lo = dirty; 244 dirty_hi = dirty >> 32; 245 246 /* Update states. 247 * 248 * Don't use u_bit_scan64, it may be slower on 32-bit. 249 */ 250 while (dirty_lo) 251 update_functions[u_bit_scan(&dirty_lo)](st); 252 while (dirty_hi) 253 update_functions[32 + u_bit_scan(&dirty_hi)](st); 254 255 /* Clear the render or compute state bits. */ 256 st->dirty &= ~pipeline_mask; 257 } 258