1 /**************************************************************************
3 * Copyright 2003 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 #include "main/arrayobj.h"
31 #include "main/glheader.h"
32 #include "main/context.h"
34 #include "pipe/p_defines.h"
35 #include "st_context.h"
37 #include "st_program.h"
38 #include "st_manager.h"
40 typedef void (*update_func_t
)(struct st_context
*st
);
42 /* The list state update functions. */
43 static const update_func_t update_functions
[] =
45 #define ST_STATE(FLAG, st_update) st_update,
46 #include "st_atom_list.h"
51 void st_init_atoms( struct st_context
*st
)
53 STATIC_ASSERT(ARRAY_SIZE(update_functions
) <= 64);
57 void st_destroy_atoms( struct st_context
*st
)
63 /* Too complex to figure out, just check every time:
65 static void check_program_state( struct st_context
*st
)
67 struct gl_context
*ctx
= st
->ctx
;
68 struct st_vertex_program
*old_vp
= st
->vp
;
69 struct st_common_program
*old_tcp
= st
->tcp
;
70 struct st_common_program
*old_tep
= st
->tep
;
71 struct st_common_program
*old_gp
= st
->gp
;
72 struct st_fragment_program
*old_fp
= st
->fp
;
74 struct gl_program
*new_vp
= ctx
->VertexProgram
._Current
;
75 struct gl_program
*new_tcp
= ctx
->TessCtrlProgram
._Current
;
76 struct gl_program
*new_tep
= ctx
->TessEvalProgram
._Current
;
77 struct gl_program
*new_gp
= ctx
->GeometryProgram
._Current
;
78 struct gl_program
*new_fp
= ctx
->FragmentProgram
._Current
;
80 unsigned num_viewports
= 1;
82 /* Flag states used by both new and old shaders to unbind shader resources
83 * properly when transitioning to shaders that don't use them.
85 if (unlikely(new_vp
!= &old_vp
->Base
)) {
87 dirty
|= old_vp
->affected_states
;
89 dirty
|= ST_NEW_VERTEX_PROGRAM(st
, st_vertex_program(new_vp
));
92 if (unlikely(new_tcp
!= &old_tcp
->Base
)) {
94 dirty
|= old_tcp
->affected_states
;
96 dirty
|= st_common_program(new_tcp
)->affected_states
;
99 if (unlikely(new_tep
!= &old_tep
->Base
)) {
101 dirty
|= old_tep
->affected_states
;
103 dirty
|= st_common_program(new_tep
)->affected_states
;
106 if (unlikely(new_gp
!= &old_gp
->Base
)) {
108 dirty
|= old_gp
->affected_states
;
110 dirty
|= st_common_program(new_gp
)->affected_states
;
113 if (unlikely(new_fp
!= &old_fp
->Base
)) {
115 dirty
|= old_fp
->affected_states
;
117 dirty
|= st_fragment_program(new_fp
)->affected_states
;
120 /* Find out the number of viewports. This determines how many scissors
121 * and viewport states we need to update.
123 struct gl_program
*last_prim_shader
= new_gp
? new_gp
:
124 new_tep
? new_tep
: new_vp
;
125 if (last_prim_shader
&&
126 last_prim_shader
->info
.outputs_written
& VARYING_BIT_VIEWPORT
)
127 num_viewports
= ctx
->Const
.MaxViewports
;
129 if (st
->state
.num_viewports
!= num_viewports
) {
130 st
->state
.num_viewports
= num_viewports
;
131 dirty
|= ST_NEW_VIEWPORT
;
133 if (ctx
->Scissor
.EnableFlags
& u_bit_consecutive(0, num_viewports
))
134 dirty
|= ST_NEW_SCISSOR
;
140 static void check_attrib_edgeflag(struct st_context
*st
)
142 GLboolean vertdata_edgeflags
, edgeflag_culls_prims
, edgeflags_enabled
;
143 struct gl_program
*vp
= st
->ctx
->VertexProgram
._Current
;
145 edgeflags_enabled
= st
->ctx
->Polygon
.FrontMode
!= GL_FILL
||
146 st
->ctx
->Polygon
.BackMode
!= GL_FILL
;
148 vertdata_edgeflags
= edgeflags_enabled
&&
149 _mesa_draw_edge_flag_array_enabled(st
->ctx
);
151 if (vertdata_edgeflags
!= st
->vertdata_edgeflags
) {
152 st
->vertdata_edgeflags
= vertdata_edgeflags
;
154 st
->dirty
|= ST_NEW_VERTEX_PROGRAM(st
, st_vertex_program(vp
));
157 edgeflag_culls_prims
= edgeflags_enabled
&& !vertdata_edgeflags
&&
158 !st
->ctx
->Current
.Attrib
[VERT_ATTRIB_EDGEFLAG
][0];
159 if (edgeflag_culls_prims
!= st
->edgeflag_culls_prims
) {
160 st
->edgeflag_culls_prims
= edgeflag_culls_prims
;
161 st
->dirty
|= ST_NEW_RASTERIZER
;
166 /***********************************************************************
167 * Update all derived state:
170 void st_validate_state( struct st_context
*st
, enum st_pipeline pipeline
)
172 struct gl_context
*ctx
= st
->ctx
;
173 uint64_t dirty
, pipeline_mask
;
174 uint32_t dirty_lo
, dirty_hi
;
176 /* Get Mesa driver state.
178 * Inactive states are shader states not used by shaders at the moment.
180 st
->dirty
|= ctx
->NewDriverState
& st
->active_states
& ST_ALL_STATES_MASK
;
181 ctx
->NewDriverState
= 0;
183 /* Get pipeline state. */
185 case ST_PIPELINE_RENDER
:
186 if (st
->ctx
->API
== API_OPENGL_COMPAT
)
187 check_attrib_edgeflag(st
);
189 if (st
->gfx_shaders_may_be_dirty
) {
190 check_program_state(st
);
191 st
->gfx_shaders_may_be_dirty
= false;
194 st_manager_validate_framebuffers(st
);
196 pipeline_mask
= ST_PIPELINE_RENDER_STATE_MASK
;
199 case ST_PIPELINE_CLEAR
:
200 st_manager_validate_framebuffers(st
);
201 pipeline_mask
= ST_PIPELINE_CLEAR_STATE_MASK
;
204 case ST_PIPELINE_META
:
205 if (st
->gfx_shaders_may_be_dirty
) {
206 check_program_state(st
);
207 st
->gfx_shaders_may_be_dirty
= false;
210 st_manager_validate_framebuffers(st
);
211 pipeline_mask
= ST_PIPELINE_META_STATE_MASK
;
214 case ST_PIPELINE_UPDATE_FRAMEBUFFER
:
215 st_manager_validate_framebuffers(st
);
216 pipeline_mask
= ST_PIPELINE_UPDATE_FB_STATE_MASK
;
219 case ST_PIPELINE_COMPUTE
: {
220 struct st_compute_program
*old_cp
= st
->cp
;
221 struct gl_program
*new_cp
= ctx
->ComputeProgram
._Current
;
223 if (new_cp
!= &old_cp
->Base
) {
225 st
->dirty
|= old_cp
->affected_states
;
227 st
->dirty
|= st_compute_program(new_cp
)->affected_states
;
230 st
->compute_shader_may_be_dirty
= false;
233 * We add the ST_NEW_FB_STATE bit here as well, because glBindFramebuffer
234 * acts as a barrier that breaks feedback loops between the framebuffer
235 * and textures bound to the framebuffer, even when those textures are
236 * accessed by compute shaders; so we must inform the driver of new
239 pipeline_mask
= ST_PIPELINE_COMPUTE_STATE_MASK
| ST_NEW_FB_STATE
;
244 unreachable("Invalid pipeline specified");
247 dirty
= st
->dirty
& pipeline_mask
;
252 dirty_hi
= dirty
>> 32;
256 * Don't use u_bit_scan64, it may be slower on 32-bit.
259 update_functions
[u_bit_scan(&dirty_lo
)](st
);
261 update_functions
[32 + u_bit_scan(&dirty_hi
)](st
);
263 /* Clear the render or compute state bits. */
264 st
->dirty
&= ~pipeline_mask
;