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