1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2003 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg 29b8e80941Smrg#include <stdio.h> 30b8e80941Smrg#include "main/arrayobj.h" 31848b8605Smrg#include "main/glheader.h" 32848b8605Smrg#include "main/context.h" 33848b8605Smrg 34848b8605Smrg#include "pipe/p_defines.h" 35848b8605Smrg#include "st_context.h" 36848b8605Smrg#include "st_atom.h" 37848b8605Smrg#include "st_program.h" 38848b8605Smrg#include "st_manager.h" 39b8e80941Smrg#include "st_util.h" 40848b8605Smrg 41848b8605Smrg 42b8e80941Smrgtypedef void (*update_func_t)(struct st_context *st); 43b8e80941Smrg 44b8e80941Smrg/* The list state update functions. */ 45b8e80941Smrgstatic const update_func_t update_functions[] = 46848b8605Smrg{ 47b8e80941Smrg#define ST_STATE(FLAG, st_update) st_update, 48b8e80941Smrg#include "st_atom_list.h" 49b8e80941Smrg#undef ST_STATE 50848b8605Smrg}; 51848b8605Smrg 52848b8605Smrg 53848b8605Smrgvoid st_init_atoms( struct st_context *st ) 54848b8605Smrg{ 55b8e80941Smrg STATIC_ASSERT(ARRAY_SIZE(update_functions) <= 64); 56848b8605Smrg} 57848b8605Smrg 58848b8605Smrg 59848b8605Smrgvoid st_destroy_atoms( struct st_context *st ) 60848b8605Smrg{ 61848b8605Smrg /* no-op */ 62848b8605Smrg} 63848b8605Smrg 64848b8605Smrg 65848b8605Smrg/* Too complex to figure out, just check every time: 66848b8605Smrg */ 67848b8605Smrgstatic void check_program_state( struct st_context *st ) 68848b8605Smrg{ 69848b8605Smrg struct gl_context *ctx = st->ctx; 70b8e80941Smrg struct st_vertex_program *old_vp = st->vp; 71b8e80941Smrg struct st_common_program *old_tcp = st->tcp; 72b8e80941Smrg struct st_common_program *old_tep = st->tep; 73b8e80941Smrg struct st_common_program *old_gp = st->gp; 74b8e80941Smrg struct st_fragment_program *old_fp = st->fp; 75b8e80941Smrg 76b8e80941Smrg struct gl_program *new_vp = ctx->VertexProgram._Current; 77b8e80941Smrg struct gl_program *new_tcp = ctx->TessCtrlProgram._Current; 78b8e80941Smrg struct gl_program *new_tep = ctx->TessEvalProgram._Current; 79b8e80941Smrg struct gl_program *new_gp = ctx->GeometryProgram._Current; 80b8e80941Smrg struct gl_program *new_fp = ctx->FragmentProgram._Current; 81b8e80941Smrg uint64_t dirty = 0; 82b8e80941Smrg unsigned num_viewports = 1; 83b8e80941Smrg 84b8e80941Smrg /* Flag states used by both new and old shaders to unbind shader resources 85b8e80941Smrg * properly when transitioning to shaders that don't use them. 86b8e80941Smrg */ 87b8e80941Smrg if (unlikely(new_vp != &old_vp->Base)) { 88b8e80941Smrg if (old_vp) 89b8e80941Smrg dirty |= old_vp->affected_states; 90b8e80941Smrg if (new_vp) 91b8e80941Smrg dirty |= ST_NEW_VERTEX_PROGRAM(st, st_vertex_program(new_vp)); 92b8e80941Smrg } 93848b8605Smrg 94b8e80941Smrg if (unlikely(new_tcp != &old_tcp->Base)) { 95b8e80941Smrg if (old_tcp) 96b8e80941Smrg dirty |= old_tcp->affected_states; 97b8e80941Smrg if (new_tcp) 98b8e80941Smrg dirty |= st_common_program(new_tcp)->affected_states; 99b8e80941Smrg } 100848b8605Smrg 101b8e80941Smrg if (unlikely(new_tep != &old_tep->Base)) { 102b8e80941Smrg if (old_tep) 103b8e80941Smrg dirty |= old_tep->affected_states; 104b8e80941Smrg if (new_tep) 105b8e80941Smrg dirty |= st_common_program(new_tep)->affected_states; 106b8e80941Smrg } 107848b8605Smrg 108b8e80941Smrg if (unlikely(new_gp != &old_gp->Base)) { 109b8e80941Smrg if (old_gp) 110b8e80941Smrg dirty |= old_gp->affected_states; 111b8e80941Smrg if (new_gp) 112b8e80941Smrg dirty |= st_common_program(new_gp)->affected_states; 113b8e80941Smrg } 114b8e80941Smrg 115b8e80941Smrg if (unlikely(new_fp != &old_fp->Base)) { 116b8e80941Smrg if (old_fp) 117b8e80941Smrg dirty |= old_fp->affected_states; 118b8e80941Smrg if (new_fp) 119b8e80941Smrg dirty |= st_fragment_program(new_fp)->affected_states; 120b8e80941Smrg } 121b8e80941Smrg 122b8e80941Smrg /* Find out the number of viewports. This determines how many scissors 123b8e80941Smrg * and viewport states we need to update. 124b8e80941Smrg */ 125b8e80941Smrg struct gl_program *last_prim_shader = new_gp ? new_gp : 126b8e80941Smrg new_tep ? new_tep : new_vp; 127b8e80941Smrg if (last_prim_shader && 128b8e80941Smrg last_prim_shader->info.outputs_written & VARYING_BIT_VIEWPORT) 129b8e80941Smrg num_viewports = ctx->Const.MaxViewports; 130b8e80941Smrg 131b8e80941Smrg if (st->state.num_viewports != num_viewports) { 132b8e80941Smrg st->state.num_viewports = num_viewports; 133b8e80941Smrg dirty |= ST_NEW_VIEWPORT; 134b8e80941Smrg 135b8e80941Smrg if (ctx->Scissor.EnableFlags & u_bit_consecutive(0, num_viewports)) 136b8e80941Smrg dirty |= ST_NEW_SCISSOR; 137b8e80941Smrg } 138b8e80941Smrg 139b8e80941Smrg st->dirty |= dirty; 140848b8605Smrg} 141848b8605Smrg 142848b8605Smrgstatic void check_attrib_edgeflag(struct st_context *st) 143848b8605Smrg{ 144848b8605Smrg GLboolean vertdata_edgeflags, edgeflag_culls_prims, edgeflags_enabled; 145b8e80941Smrg struct gl_program *vp = st->ctx->VertexProgram._Current; 146848b8605Smrg 147848b8605Smrg edgeflags_enabled = st->ctx->Polygon.FrontMode != GL_FILL || 148848b8605Smrg st->ctx->Polygon.BackMode != GL_FILL; 149848b8605Smrg 150848b8605Smrg vertdata_edgeflags = edgeflags_enabled && 151b8e80941Smrg _mesa_draw_edge_flag_array_enabled(st->ctx); 152b8e80941Smrg 153848b8605Smrg if (vertdata_edgeflags != st->vertdata_edgeflags) { 154848b8605Smrg st->vertdata_edgeflags = vertdata_edgeflags; 155b8e80941Smrg if (vp) 156b8e80941Smrg st->dirty |= ST_NEW_VERTEX_PROGRAM(st, st_vertex_program(vp)); 157848b8605Smrg } 158848b8605Smrg 159848b8605Smrg edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags && 160848b8605Smrg !st->ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0]; 161848b8605Smrg if (edgeflag_culls_prims != st->edgeflag_culls_prims) { 162848b8605Smrg st->edgeflag_culls_prims = edgeflag_culls_prims; 163b8e80941Smrg st->dirty |= ST_NEW_RASTERIZER; 164848b8605Smrg } 165848b8605Smrg} 166848b8605Smrg 167848b8605Smrg 168848b8605Smrg/*********************************************************************** 169848b8605Smrg * Update all derived state: 170848b8605Smrg */ 171848b8605Smrg 172b8e80941Smrgvoid st_validate_state( struct st_context *st, enum st_pipeline pipeline ) 173848b8605Smrg{ 174b8e80941Smrg struct gl_context *ctx = st->ctx; 175b8e80941Smrg uint64_t dirty, pipeline_mask; 176b8e80941Smrg uint32_t dirty_lo, dirty_hi; 177b8e80941Smrg 178b8e80941Smrg /* Get Mesa driver state. 179b8e80941Smrg * 180b8e80941Smrg * Inactive states are shader states not used by shaders at the moment. 181b8e80941Smrg */ 182b8e80941Smrg st->dirty |= ctx->NewDriverState & st->active_states & ST_ALL_STATES_MASK; 183b8e80941Smrg ctx->NewDriverState = 0; 184b8e80941Smrg 185b8e80941Smrg /* Get pipeline state. */ 186b8e80941Smrg switch (pipeline) { 187b8e80941Smrg case ST_PIPELINE_RENDER: 188b8e80941Smrg if (st->ctx->API == API_OPENGL_COMPAT) 189b8e80941Smrg check_attrib_edgeflag(st); 190b8e80941Smrg 191b8e80941Smrg if (st->gfx_shaders_may_be_dirty) { 192b8e80941Smrg check_program_state(st); 193b8e80941Smrg st->gfx_shaders_may_be_dirty = false; 194b8e80941Smrg } 195848b8605Smrg 196b8e80941Smrg st_manager_validate_framebuffers(st); 197848b8605Smrg 198b8e80941Smrg pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK; 199b8e80941Smrg break; 200848b8605Smrg 201b8e80941Smrg case ST_PIPELINE_CLEAR: 202b8e80941Smrg st_manager_validate_framebuffers(st); 203b8e80941Smrg pipeline_mask = ST_PIPELINE_CLEAR_STATE_MASK; 204b8e80941Smrg break; 205848b8605Smrg 206b8e80941Smrg case ST_PIPELINE_META: 207b8e80941Smrg if (st->gfx_shaders_may_be_dirty) { 208b8e80941Smrg check_program_state(st); 209b8e80941Smrg st->gfx_shaders_may_be_dirty = false; 210b8e80941Smrg } 211848b8605Smrg 212b8e80941Smrg st_manager_validate_framebuffers(st); 213b8e80941Smrg pipeline_mask = ST_PIPELINE_META_STATE_MASK; 214b8e80941Smrg break; 215848b8605Smrg 216b8e80941Smrg case ST_PIPELINE_UPDATE_FRAMEBUFFER: 217b8e80941Smrg st_manager_validate_framebuffers(st); 218b8e80941Smrg pipeline_mask = ST_PIPELINE_UPDATE_FB_STATE_MASK; 219b8e80941Smrg break; 220848b8605Smrg 221b8e80941Smrg case ST_PIPELINE_COMPUTE: { 222b8e80941Smrg struct st_compute_program *old_cp = st->cp; 223b8e80941Smrg struct gl_program *new_cp = ctx->ComputeProgram._Current; 224848b8605Smrg 225b8e80941Smrg if (new_cp != &old_cp->Base) { 226b8e80941Smrg if (old_cp) 227b8e80941Smrg st->dirty |= old_cp->affected_states; 228b8e80941Smrg assert(new_cp); 229b8e80941Smrg st->dirty |= st_compute_program(new_cp)->affected_states; 230848b8605Smrg } 231848b8605Smrg 232b8e80941Smrg st->compute_shader_may_be_dirty = false; 233b8e80941Smrg 234b8e80941Smrg /* 235b8e80941Smrg * We add the ST_NEW_FB_STATE bit here as well, because glBindFramebuffer 236b8e80941Smrg * acts as a barrier that breaks feedback loops between the framebuffer 237b8e80941Smrg * and textures bound to the framebuffer, even when those textures are 238b8e80941Smrg * accessed by compute shaders; so we must inform the driver of new 239b8e80941Smrg * framebuffer state. 240b8e80941Smrg */ 241b8e80941Smrg pipeline_mask = ST_PIPELINE_COMPUTE_STATE_MASK | ST_NEW_FB_STATE; 242b8e80941Smrg break; 243848b8605Smrg } 244b8e80941Smrg 245b8e80941Smrg default: 246b8e80941Smrg unreachable("Invalid pipeline specified"); 247848b8605Smrg } 248848b8605Smrg 249b8e80941Smrg dirty = st->dirty & pipeline_mask; 250b8e80941Smrg if (!dirty) 251b8e80941Smrg return; 252848b8605Smrg 253b8e80941Smrg dirty_lo = dirty; 254b8e80941Smrg dirty_hi = dirty >> 32; 255848b8605Smrg 256b8e80941Smrg /* Update states. 257b8e80941Smrg * 258b8e80941Smrg * Don't use u_bit_scan64, it may be slower on 32-bit. 259b8e80941Smrg */ 260b8e80941Smrg while (dirty_lo) 261b8e80941Smrg update_functions[u_bit_scan(&dirty_lo)](st); 262b8e80941Smrg while (dirty_hi) 263b8e80941Smrg update_functions[32 + u_bit_scan(&dirty_hi)](st); 264848b8605Smrg 265b8e80941Smrg /* Clear the render or compute state bits. */ 266b8e80941Smrg st->dirty &= ~pipeline_mask; 267b8e80941Smrg} 268