remove unneeded includes
[mesa.git] / src / mesa / pipe / i915simple / i915_state_dynamic.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 #include "i915_batch.h"
29 #include "i915_state_inlines.h"
30 #include "i915_context.h"
31 #include "i915_reg.h"
32 #include "i915_state.h"
33 #include "pipe/p_util.h"
34
35 #define FILE_DEBUG_FLAG DEBUG_STATE
36
37 /* State that we have chosen to store in the DYNAMIC segment of the
38 * i915 indirect state mechanism.
39 *
40 * Can't cache these in the way we do the static state, as there is no
41 * start/size in the command packet, instead an 'end' value that gets
42 * incremented.
43 *
44 * Additionally, there seems to be a requirement to re-issue the full
45 * (active) state every time a 4kb boundary is crossed.
46 */
47
48 static inline void set_dynamic_indirect( struct i915_context *i915,
49 unsigned offset,
50 const unsigned *src,
51 unsigned dwords )
52 {
53 int i;
54
55 for (i = 0; i < dwords; i++)
56 i915->current.dynamic[offset + i] = src[i];
57
58 i915->hardware_dirty |= I915_HW_DYNAMIC;
59 }
60
61
62 /***********************************************************************
63 * Modes4: stencil masks and logicop
64 */
65 static void upload_MODES4( struct i915_context *i915 )
66 {
67 unsigned modes4 = 0;
68
69 /* I915_NEW_STENCIL */
70 {
71 int testmask = i915->stencil.value_mask[0] & 0xff;
72 int writemask = i915->stencil.write_mask[0] & 0xff;
73
74 modes4 |= (_3DSTATE_MODES_4_CMD |
75 ENABLE_STENCIL_TEST_MASK |
76 STENCIL_TEST_MASK(testmask) |
77 ENABLE_STENCIL_WRITE_MASK |
78 STENCIL_WRITE_MASK(writemask));
79 }
80
81 /* I915_NEW_BLEND */
82 {
83 modes4 |= (_3DSTATE_MODES_4_CMD |
84 ENABLE_LOGIC_OP_FUNC |
85 LOGIC_OP_FUNC(i915_translate_logic_op(i915->blend.logicop_func)));
86 }
87
88 /* Always, so that we know when state is in-active:
89 */
90 set_dynamic_indirect( i915,
91 I915_DYNAMIC_MODES4,
92 &modes4,
93 1 );
94 }
95
96 const struct i915_tracked_state i915_upload_MODES4 = {
97 .dirty = I915_NEW_BLEND | I915_NEW_STENCIL,
98 .update = upload_MODES4
99 };
100
101
102
103
104 /***********************************************************************
105 */
106
107 static void upload_BFO( struct i915_context *i915 )
108 {
109 unsigned bf[2];
110
111 memset( bf, 0, sizeof(bf) );
112
113 /* _NEW_STENCIL
114 */
115 if (i915->stencil.back_enabled) {
116 int test = i915_translate_compare_func(i915->stencil.back_func);
117 int fop = i915_translate_stencil_op(i915->stencil.back_fail_op);
118 int dfop = i915_translate_stencil_op(i915->stencil.back_zfail_op);
119 int dpop = i915_translate_stencil_op(i915->stencil.back_zpass_op);
120 int ref = i915->stencil.ref_value[1] & 0xff;
121 int tmask = i915->stencil.value_mask[1] & 0xff;
122 int wmask = i915->stencil.write_mask[1] & 0xff;
123
124 bf[0] = (_3DSTATE_BACKFACE_STENCIL_OPS |
125 BFO_ENABLE_STENCIL_FUNCS |
126 BFO_ENABLE_STENCIL_TWO_SIDE |
127 BFO_ENABLE_STENCIL_REF |
128 BFO_STENCIL_TWO_SIDE |
129 (ref << BFO_STENCIL_REF_SHIFT) |
130 (test << BFO_STENCIL_TEST_SHIFT) |
131 (fop << BFO_STENCIL_FAIL_SHIFT) |
132 (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
133 (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT));
134
135 bf[1] = (_3DSTATE_BACKFACE_STENCIL_MASKS |
136 BFM_ENABLE_STENCIL_TEST_MASK |
137 BFM_ENABLE_STENCIL_WRITE_MASK |
138 (tmask << BFM_STENCIL_TEST_MASK_SHIFT) |
139 (wmask << BFM_STENCIL_WRITE_MASK_SHIFT));
140 }
141 else {
142 /* This actually disables two-side stencil: The bit set is a
143 * modify-enable bit to indicate we are changing the two-side
144 * setting. Then there is a symbolic zero to show that we are
145 * setting the flag to zero/off.
146 */
147 bf[0] = (_3DSTATE_BACKFACE_STENCIL_OPS |
148 BFO_ENABLE_STENCIL_TWO_SIDE |
149 0);
150 bf[1] = 0;
151 }
152
153 set_dynamic_indirect( i915,
154 I915_DYNAMIC_BFO_0,
155 &bf[0],
156 2 );
157 }
158
159 const struct i915_tracked_state i915_upload_BFO = {
160 .dirty = I915_NEW_STENCIL,
161 .update = upload_BFO
162 };
163
164
165 /***********************************************************************
166 */
167
168
169 static void upload_BLENDCOLOR( struct i915_context *i915 )
170 {
171 unsigned bc[2];
172
173 memset( bc, 0, sizeof(bc) );
174
175 /* I915_NEW_BLEND {_COLOR}
176 */
177 {
178 const float *color = i915->blend_color.color;
179
180 bc[0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
181 bc[1] = pack_ui32_float4( color[0],
182 color[1],
183 color[2],
184 color[3] );
185 }
186
187 set_dynamic_indirect( i915,
188 I915_DYNAMIC_BC_0,
189 bc,
190 2 );
191 }
192
193 const struct i915_tracked_state i915_upload_BLENDCOLOR = {
194 .dirty = I915_NEW_BLEND,
195 .update = upload_BLENDCOLOR
196 };
197
198 /***********************************************************************
199 */
200
201
202 static void upload_IAB( struct i915_context *i915 )
203 {
204 unsigned iab = 0;
205
206 {
207 unsigned eqRGB = i915->blend.rgb_func;
208 unsigned srcRGB = i915->blend.rgb_src_factor;
209 unsigned dstRGB = i915->blend.rgb_dst_factor;
210
211 unsigned eqA = i915->blend.alpha_func;
212 unsigned srcA = i915->blend.alpha_src_factor;
213 unsigned dstA = i915->blend.alpha_dst_factor;
214
215 /* Special handling for MIN/MAX filter modes handled at
216 * state_tracker level.
217 */
218
219 if (srcA != srcRGB ||
220 dstA != dstRGB ||
221 eqA != eqRGB) {
222
223 iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
224 IAB_MODIFY_ENABLE |
225 IAB_ENABLE |
226 IAB_MODIFY_FUNC |
227 IAB_MODIFY_SRC_FACTOR |
228 IAB_MODIFY_DST_FACTOR |
229 SRC_ABLND_FACT(i915_translate_blend_factor(srcA)) |
230 DST_ABLND_FACT(i915_translate_blend_factor(dstA)) |
231 (i915_translate_blend_func(eqA) << IAB_FUNC_SHIFT));
232 }
233 else {
234 iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
235 IAB_MODIFY_ENABLE |
236 0);
237 }
238 }
239
240
241 set_dynamic_indirect( i915,
242 I915_DYNAMIC_IAB,
243 &iab,
244 1 );
245 }
246
247 const struct i915_tracked_state i915_upload_IAB = {
248 .dirty = I915_NEW_BLEND,
249 .update = upload_IAB
250 };
251
252
253 /***********************************************************************
254 */
255
256
257
258 static void upload_DEPTHSCALE( struct i915_context *i915 )
259 {
260 union { float f; unsigned u; } ds[2];
261
262 memset( ds, 0, sizeof(ds) );
263
264 /* I915_NEW_SETUP
265 */
266 ds[0].u = _3DSTATE_DEPTH_OFFSET_SCALE;
267 ds[1].f = i915->setup.offset_scale;
268
269 set_dynamic_indirect( i915,
270 I915_DYNAMIC_DEPTHSCALE_0,
271 &ds[0].u,
272 2 );
273 }
274
275 const struct i915_tracked_state i915_upload_DEPTHSCALE = {
276 .dirty = I915_NEW_SETUP,
277 .update = upload_DEPTHSCALE
278 };
279
280
281
282 /***********************************************************************
283 * Polygon stipple
284 *
285 * The i915 supports a 4x4 stipple natively, GL wants 32x32.
286 * Fortunately stipple is usually a repeating pattern.
287 *
288 * XXX: does stipple pattern need to be adjusted according to
289 * the window position?
290 *
291 * XXX: possibly need workaround for conform paths test.
292 */
293
294 static void upload_STIPPLE( struct i915_context *i915 )
295 {
296 unsigned st[2];
297
298 st[0] = _3DSTATE_STIPPLE;
299 st[1] = 0;
300
301 /* I915_NEW_SETUP
302 */
303 if (i915->setup.poly_stipple_enable) {
304 st[1] |= ST1_ENABLE;
305 }
306
307
308 /* I915_NEW_STIPPLE
309 */
310 {
311 const ubyte *mask = (const ubyte *)i915->poly_stipple.stipple;
312 ubyte p[4];
313
314 p[0] = mask[12] & 0xf;
315 p[1] = mask[8] & 0xf;
316 p[2] = mask[4] & 0xf;
317 p[3] = mask[0] & 0xf;
318
319 /* Not sure what to do about fallbacks, so for now just dont:
320 */
321 st[1] |= ((p[0] << 0) |
322 (p[1] << 4) |
323 (p[2] << 8) |
324 (p[3] << 12));
325 }
326
327
328 set_dynamic_indirect( i915,
329 I915_DYNAMIC_STP_0,
330 &st[0],
331 2 );
332 }
333
334
335 const struct i915_tracked_state i915_upload_STIPPLE = {
336 .dirty = I915_NEW_SETUP | I915_NEW_STIPPLE,
337 .update = upload_STIPPLE
338 };
339
340
341
342 /***********************************************************************
343 * Scissor.
344 */
345 static void upload_SCISSOR_ENABLE( struct i915_context *i915 )
346 {
347 unsigned sc[1];
348
349 if (i915->setup.scissor)
350 sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT;
351 else
352 sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT;
353
354 set_dynamic_indirect( i915,
355 I915_DYNAMIC_SC_ENA_0,
356 &sc[0],
357 1 );
358 }
359
360 const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = {
361 .dirty = I915_NEW_SETUP,
362 .update = upload_SCISSOR_ENABLE
363 };
364
365
366
367 static void upload_SCISSOR_RECT( struct i915_context *i915 )
368 {
369 unsigned x1 = i915->scissor.minx;
370 unsigned y1 = i915->scissor.miny;
371 unsigned x2 = i915->scissor.maxx;
372 unsigned y2 = i915->scissor.maxy;
373 unsigned sc[3];
374
375 sc[0] = _3DSTATE_SCISSOR_RECT_0_CMD;
376 sc[1] = (y1 << 16) | (x1 & 0xffff);
377 sc[2] = (y2 << 16) | (x2 & 0xffff);
378
379 set_dynamic_indirect( i915,
380 I915_DYNAMIC_SC_RECT_0,
381 &sc[0],
382 3 );
383 }
384
385
386 const struct i915_tracked_state i915_upload_SCISSOR_RECT = {
387 .dirty = I915_NEW_SCISSOR,
388 .update = upload_SCISSOR_RECT
389 };
390
391
392
393
394
395
396 static const struct i915_tracked_state *atoms[] = {
397 &i915_upload_MODES4,
398 &i915_upload_BFO,
399 &i915_upload_BLENDCOLOR,
400 &i915_upload_IAB,
401 &i915_upload_DEPTHSCALE,
402 &i915_upload_STIPPLE,
403 &i915_upload_SCISSOR_ENABLE,
404 &i915_upload_SCISSOR_RECT
405 };
406
407 /* These will be dynamic indirect state commands, but for now just end
408 * up on the batch buffer with everything else.
409 */
410 void i915_update_dynamic( struct i915_context *i915 )
411 {
412 int i;
413
414 for (i = 0; i < Elements(atoms); i++)
415 if (i915->dirty & atoms[i]->dirty)
416 atoms[i]->update( i915 );
417 }
418