14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2003 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg 2901e04c3fSmrg#include <stdio.h> 3001e04c3fSmrg#include "main/arrayobj.h" 314a49301eSmrg#include "main/glheader.h" 324a49301eSmrg#include "main/context.h" 334a49301eSmrg 344a49301eSmrg#include "pipe/p_defines.h" 354a49301eSmrg#include "st_context.h" 364a49301eSmrg#include "st_atom.h" 374a49301eSmrg#include "st_program.h" 383464ebd5Sriastradh#include "st_manager.h" 39b9abf16eSmaya#include "st_util.h" 40b9abf16eSmaya 41cdc920a0Smrg 4201e04c3fSmrgtypedef void (*update_func_t)(struct st_context *st); 434a49301eSmrg 4401e04c3fSmrg/* The list state update functions. */ 4501e04c3fSmrgstatic const update_func_t update_functions[] = 464a49301eSmrg{ 4701e04c3fSmrg#define ST_STATE(FLAG, st_update) st_update, 4801e04c3fSmrg#include "st_atom_list.h" 4901e04c3fSmrg#undef ST_STATE 504a49301eSmrg}; 514a49301eSmrg 524a49301eSmrg 534a49301eSmrgvoid st_init_atoms( struct st_context *st ) 544a49301eSmrg{ 5501e04c3fSmrg STATIC_ASSERT(ARRAY_SIZE(update_functions) <= 64); 564a49301eSmrg} 574a49301eSmrg 584a49301eSmrg 594a49301eSmrgvoid st_destroy_atoms( struct st_context *st ) 604a49301eSmrg{ 614a49301eSmrg /* no-op */ 624a49301eSmrg} 634a49301eSmrg 644a49301eSmrg 654a49301eSmrg/* Too complex to figure out, just check every time: 664a49301eSmrg */ 674a49301eSmrgstatic void check_program_state( struct st_context *st ) 684a49301eSmrg{ 693464ebd5Sriastradh struct gl_context *ctx = st->ctx; 707ec681f3Smrg struct st_program *old_vp = st->vp; 717ec681f3Smrg struct st_program *old_tcp = st->tcp; 727ec681f3Smrg struct st_program *old_tep = st->tep; 737ec681f3Smrg struct st_program *old_gp = st->gp; 747ec681f3Smrg struct st_program *old_fp = st->fp; 7501e04c3fSmrg 7601e04c3fSmrg struct gl_program *new_vp = ctx->VertexProgram._Current; 7701e04c3fSmrg struct gl_program *new_tcp = ctx->TessCtrlProgram._Current; 7801e04c3fSmrg struct gl_program *new_tep = ctx->TessEvalProgram._Current; 7901e04c3fSmrg struct gl_program *new_gp = ctx->GeometryProgram._Current; 8001e04c3fSmrg struct gl_program *new_fp = ctx->FragmentProgram._Current; 8101e04c3fSmrg uint64_t dirty = 0; 8201e04c3fSmrg unsigned num_viewports = 1; 8301e04c3fSmrg 8401e04c3fSmrg /* Flag states used by both new and old shaders to unbind shader resources 8501e04c3fSmrg * properly when transitioning to shaders that don't use them. 8601e04c3fSmrg */ 877ec681f3Smrg if (unlikely(new_vp != (old_vp ? &old_vp->Base : NULL))) { 8801e04c3fSmrg if (old_vp) 8901e04c3fSmrg dirty |= old_vp->affected_states; 9001e04c3fSmrg if (new_vp) 917ec681f3Smrg dirty |= ST_NEW_VERTEX_PROGRAM(st, st_program(new_vp)); 9201e04c3fSmrg } 9301e04c3fSmrg 9401e04c3fSmrg if (unlikely(new_tcp != &old_tcp->Base)) { 9501e04c3fSmrg if (old_tcp) 9601e04c3fSmrg dirty |= old_tcp->affected_states; 9701e04c3fSmrg if (new_tcp) 987ec681f3Smrg dirty |= st_program(new_tcp)->affected_states; 9901e04c3fSmrg } 10001e04c3fSmrg 10101e04c3fSmrg if (unlikely(new_tep != &old_tep->Base)) { 10201e04c3fSmrg if (old_tep) 10301e04c3fSmrg dirty |= old_tep->affected_states; 10401e04c3fSmrg if (new_tep) 1057ec681f3Smrg dirty |= st_program(new_tep)->affected_states; 10601e04c3fSmrg } 1074a49301eSmrg 10801e04c3fSmrg if (unlikely(new_gp != &old_gp->Base)) { 10901e04c3fSmrg if (old_gp) 11001e04c3fSmrg dirty |= old_gp->affected_states; 11101e04c3fSmrg if (new_gp) 1127ec681f3Smrg dirty |= st_program(new_gp)->affected_states; 11301e04c3fSmrg } 1144a49301eSmrg 11501e04c3fSmrg if (unlikely(new_fp != &old_fp->Base)) { 11601e04c3fSmrg if (old_fp) 11701e04c3fSmrg dirty |= old_fp->affected_states; 11801e04c3fSmrg if (new_fp) 1197ec681f3Smrg dirty |= st_program(new_fp)->affected_states; 12001e04c3fSmrg } 12101e04c3fSmrg 12201e04c3fSmrg /* Find out the number of viewports. This determines how many scissors 12301e04c3fSmrg * and viewport states we need to update. 12401e04c3fSmrg */ 12501e04c3fSmrg struct gl_program *last_prim_shader = new_gp ? new_gp : 12601e04c3fSmrg new_tep ? new_tep : new_vp; 12701e04c3fSmrg if (last_prim_shader && 1287ec681f3Smrg last_prim_shader->info.outputs_written & ( 1297ec681f3Smrg VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK)) 13001e04c3fSmrg num_viewports = ctx->Const.MaxViewports; 13101e04c3fSmrg 13201e04c3fSmrg if (st->state.num_viewports != num_viewports) { 13301e04c3fSmrg st->state.num_viewports = num_viewports; 13401e04c3fSmrg dirty |= ST_NEW_VIEWPORT; 13501e04c3fSmrg 13601e04c3fSmrg if (ctx->Scissor.EnableFlags & u_bit_consecutive(0, num_viewports)) 13701e04c3fSmrg dirty |= ST_NEW_SCISSOR; 13801e04c3fSmrg } 1394a49301eSmrg 14001e04c3fSmrg st->dirty |= dirty; 1414a49301eSmrg} 1424a49301eSmrg 1437ec681f3Smrgvoid st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags) 144af69d88dSmrg{ 1457ec681f3Smrg bool edgeflags_enabled = st->ctx->Polygon.FrontMode != GL_FILL || 1467ec681f3Smrg st->ctx->Polygon.BackMode != GL_FILL; 1477ec681f3Smrg bool vertdata_edgeflags = edgeflags_enabled && per_vertex_edgeflags; 14801e04c3fSmrg 149af69d88dSmrg if (vertdata_edgeflags != st->vertdata_edgeflags) { 150af69d88dSmrg st->vertdata_edgeflags = vertdata_edgeflags; 1517ec681f3Smrg 1527ec681f3Smrg struct gl_program *vp = st->ctx->VertexProgram._Current; 15301e04c3fSmrg if (vp) 1547ec681f3Smrg st->dirty |= ST_NEW_VERTEX_PROGRAM(st, st_program(vp)); 155af69d88dSmrg } 156af69d88dSmrg 1577ec681f3Smrg bool edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags && 1587ec681f3Smrg !st->ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0]; 159af69d88dSmrg if (edgeflag_culls_prims != st->edgeflag_culls_prims) { 160af69d88dSmrg st->edgeflag_culls_prims = edgeflag_culls_prims; 16101e04c3fSmrg st->dirty |= ST_NEW_RASTERIZER; 162af69d88dSmrg } 163af69d88dSmrg} 164af69d88dSmrg 1657ec681f3Smrgstatic void check_attrib_edgeflag(struct st_context *st) 1667ec681f3Smrg{ 1677ec681f3Smrg st_update_edgeflags(st, _mesa_draw_edge_flag_array_enabled(st->ctx)); 1687ec681f3Smrg} 1697ec681f3Smrg 1704a49301eSmrg 1714a49301eSmrg/*********************************************************************** 1724a49301eSmrg * Update all derived state: 1734a49301eSmrg */ 1744a49301eSmrg 17501e04c3fSmrgvoid st_validate_state( struct st_context *st, enum st_pipeline pipeline ) 1764a49301eSmrg{ 17701e04c3fSmrg struct gl_context *ctx = st->ctx; 17801e04c3fSmrg uint64_t dirty, pipeline_mask; 17901e04c3fSmrg uint32_t dirty_lo, dirty_hi; 18001e04c3fSmrg 18101e04c3fSmrg /* Get Mesa driver state. 18201e04c3fSmrg * 18301e04c3fSmrg * Inactive states are shader states not used by shaders at the moment. 18401e04c3fSmrg */ 18501e04c3fSmrg st->dirty |= ctx->NewDriverState & st->active_states & ST_ALL_STATES_MASK; 1867ec681f3Smrg ctx->NewDriverState &= ~st->dirty; 18701e04c3fSmrg 18801e04c3fSmrg /* Get pipeline state. */ 18901e04c3fSmrg switch (pipeline) { 19001e04c3fSmrg case ST_PIPELINE_RENDER: 1917ec681f3Smrg case ST_PIPELINE_RENDER_NO_VARRAYS: 19201e04c3fSmrg if (st->ctx->API == API_OPENGL_COMPAT) 19301e04c3fSmrg check_attrib_edgeflag(st); 19401e04c3fSmrg 19501e04c3fSmrg if (st->gfx_shaders_may_be_dirty) { 19601e04c3fSmrg check_program_state(st); 19701e04c3fSmrg st->gfx_shaders_may_be_dirty = false; 19801e04c3fSmrg } 1994a49301eSmrg 20001e04c3fSmrg st_manager_validate_framebuffers(st); 201af69d88dSmrg 2027ec681f3Smrg if (pipeline == ST_PIPELINE_RENDER) 2037ec681f3Smrg pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK; 2047ec681f3Smrg else 2057ec681f3Smrg pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK_NO_VARRAYS; 20601e04c3fSmrg break; 207af69d88dSmrg 20801e04c3fSmrg case ST_PIPELINE_CLEAR: 20901e04c3fSmrg st_manager_validate_framebuffers(st); 21001e04c3fSmrg pipeline_mask = ST_PIPELINE_CLEAR_STATE_MASK; 21101e04c3fSmrg break; 2124a49301eSmrg 21301e04c3fSmrg case ST_PIPELINE_META: 21401e04c3fSmrg if (st->gfx_shaders_may_be_dirty) { 21501e04c3fSmrg check_program_state(st); 21601e04c3fSmrg st->gfx_shaders_may_be_dirty = false; 21701e04c3fSmrg } 2184a49301eSmrg 21901e04c3fSmrg st_manager_validate_framebuffers(st); 22001e04c3fSmrg pipeline_mask = ST_PIPELINE_META_STATE_MASK; 22101e04c3fSmrg break; 222cdc920a0Smrg 22301e04c3fSmrg case ST_PIPELINE_UPDATE_FRAMEBUFFER: 22401e04c3fSmrg st_manager_validate_framebuffers(st); 22501e04c3fSmrg pipeline_mask = ST_PIPELINE_UPDATE_FB_STATE_MASK; 22601e04c3fSmrg break; 2274a49301eSmrg 22801e04c3fSmrg case ST_PIPELINE_COMPUTE: { 2297ec681f3Smrg struct st_program *old_cp = st->cp; 23001e04c3fSmrg struct gl_program *new_cp = ctx->ComputeProgram._Current; 2314a49301eSmrg 23201e04c3fSmrg if (new_cp != &old_cp->Base) { 23301e04c3fSmrg if (old_cp) 23401e04c3fSmrg st->dirty |= old_cp->affected_states; 23501e04c3fSmrg assert(new_cp); 2367ec681f3Smrg st->dirty |= st_program(new_cp)->affected_states; 2374a49301eSmrg } 2384a49301eSmrg 23901e04c3fSmrg st->compute_shader_may_be_dirty = false; 24001e04c3fSmrg 24101e04c3fSmrg /* 24201e04c3fSmrg * We add the ST_NEW_FB_STATE bit here as well, because glBindFramebuffer 24301e04c3fSmrg * acts as a barrier that breaks feedback loops between the framebuffer 24401e04c3fSmrg * and textures bound to the framebuffer, even when those textures are 24501e04c3fSmrg * accessed by compute shaders; so we must inform the driver of new 24601e04c3fSmrg * framebuffer state. 24701e04c3fSmrg */ 24801e04c3fSmrg pipeline_mask = ST_PIPELINE_COMPUTE_STATE_MASK | ST_NEW_FB_STATE; 24901e04c3fSmrg break; 2504a49301eSmrg } 25101e04c3fSmrg 25201e04c3fSmrg default: 25301e04c3fSmrg unreachable("Invalid pipeline specified"); 2544a49301eSmrg } 2554a49301eSmrg 25601e04c3fSmrg dirty = st->dirty & pipeline_mask; 25701e04c3fSmrg if (!dirty) 25801e04c3fSmrg return; 2594a49301eSmrg 26001e04c3fSmrg dirty_lo = dirty; 26101e04c3fSmrg dirty_hi = dirty >> 32; 2624a49301eSmrg 26301e04c3fSmrg /* Update states. 26401e04c3fSmrg * 26501e04c3fSmrg * Don't use u_bit_scan64, it may be slower on 32-bit. 26601e04c3fSmrg */ 26701e04c3fSmrg while (dirty_lo) 26801e04c3fSmrg update_functions[u_bit_scan(&dirty_lo)](st); 26901e04c3fSmrg while (dirty_hi) 27001e04c3fSmrg update_functions[32 + u_bit_scan(&dirty_hi)](st); 2714a49301eSmrg 27201e04c3fSmrg /* Clear the render or compute state bits. */ 27301e04c3fSmrg st->dirty &= ~pipeline_mask; 27401e04c3fSmrg} 275