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