i965: Giant pile of flushing to track down SNB bringup issues.
[mesa.git] / src / mesa / drivers / dri / i965 / gen6_cc.c
1 /*
2 * Copyright © 2009 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 *
26 */
27
28 #include "brw_context.h"
29 #include "brw_state.h"
30 #include "brw_defines.h"
31 #include "brw_util.h"
32 #include "intel_batchbuffer.h"
33 #include "main/macros.h"
34 #include "main/enums.h"
35
36 struct brw_blend_state_key {
37 GLboolean color_blend, alpha_enabled;
38
39 GLenum logic_op;
40
41 GLenum blend_eq_rgb, blend_eq_a;
42 GLenum blend_src_rgb, blend_src_a;
43 GLenum blend_dst_rgb, blend_dst_a;
44
45 GLenum alpha_func;
46
47 GLboolean dither;
48 };
49
50 static void
51 blend_state_populate_key(struct brw_context *brw,
52 struct brw_blend_state_key *key)
53 {
54 GLcontext *ctx = &brw->intel.ctx;
55
56 memset(key, 0, sizeof(*key));
57
58 /* _NEW_COLOR */
59 if (ctx->Color._LogicOpEnabled)
60 key->logic_op = ctx->Color.LogicOp;
61 else
62 key->logic_op = GL_COPY;
63
64 /* _NEW_COLOR */
65 key->color_blend = ctx->Color.BlendEnabled;
66 if (key->color_blend) {
67 key->blend_eq_rgb = ctx->Color.BlendEquationRGB;
68 key->blend_eq_a = ctx->Color.BlendEquationA;
69 key->blend_src_rgb = ctx->Color.BlendSrcRGB;
70 key->blend_dst_rgb = ctx->Color.BlendDstRGB;
71 key->blend_src_a = ctx->Color.BlendSrcA;
72 key->blend_dst_a = ctx->Color.BlendDstA;
73 }
74
75 /* _NEW_COLOR */
76 key->alpha_enabled = ctx->Color.AlphaEnabled;
77 if (key->alpha_enabled) {
78 key->alpha_func = ctx->Color.AlphaFunc;
79 }
80
81 /* _NEW_COLOR */
82 key->dither = ctx->Color.DitherFlag;
83 }
84
85 /**
86 * Creates the state cache entry for the given CC unit key.
87 */
88 static drm_intel_bo *
89 blend_state_create_from_key(struct brw_context *brw,
90 struct brw_blend_state_key *key)
91 {
92 struct gen6_blend_state blend;
93 drm_intel_bo *bo;
94
95 memset(&blend, 0, sizeof(blend));
96
97 if (key->logic_op != GL_COPY) {
98 blend.blend1.logic_op_enable = 1;
99 blend.blend1.logic_op_func = intel_translate_logic_op(key->logic_op);
100 } else if (key->color_blend) {
101 GLenum eqRGB = key->blend_eq_rgb;
102 GLenum eqA = key->blend_eq_a;
103 GLenum srcRGB = key->blend_src_rgb;
104 GLenum dstRGB = key->blend_dst_rgb;
105 GLenum srcA = key->blend_src_a;
106 GLenum dstA = key->blend_dst_a;
107
108 if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
109 srcRGB = dstRGB = GL_ONE;
110 }
111
112 if (eqA == GL_MIN || eqA == GL_MAX) {
113 srcA = dstA = GL_ONE;
114 }
115
116 blend.blend0.dest_blend_factor = brw_translate_blend_factor(dstRGB);
117 blend.blend0.source_blend_factor = brw_translate_blend_factor(srcRGB);
118 blend.blend0.blend_func = brw_translate_blend_equation(eqRGB);
119
120 blend.blend0.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
121 blend.blend0.ia_source_blend_factor = brw_translate_blend_factor(srcA);
122 blend.blend0.ia_blend_func = brw_translate_blend_equation(eqA);
123
124 blend.blend0.blend_enable = 1;
125 blend.blend0.ia_blend_enable = (srcA != srcRGB ||
126 dstA != dstRGB ||
127 eqA != eqRGB);
128 }
129
130 if (key->alpha_enabled) {
131 blend.blend1.alpha_test_enable = 1;
132 blend.blend1.alpha_test_func = intel_translate_compare_func(key->alpha_func);
133
134 }
135
136 if (key->dither) {
137 blend.blend1.dither_enable = 1;
138 blend.blend1.y_dither_offset = 0;
139 blend.blend1.x_dither_offset = 0;
140 }
141
142 bo = brw_upload_cache(&brw->cache, BRW_BLEND_STATE,
143 key, sizeof(*key),
144 NULL, 0,
145 &blend, sizeof(blend));
146
147 return bo;
148 }
149
150 static void
151 prepare_blend_state(struct brw_context *brw)
152 {
153 struct brw_blend_state_key key;
154
155 blend_state_populate_key(brw, &key);
156
157 drm_intel_bo_unreference(brw->cc.blend_state_bo);
158 brw->cc.blend_state_bo = brw_search_cache(&brw->cache, BRW_BLEND_STATE,
159 &key, sizeof(key),
160 NULL, 0,
161 NULL);
162
163 if (brw->cc.blend_state_bo == NULL)
164 brw->cc.blend_state_bo = blend_state_create_from_key(brw, &key);
165 }
166
167 const struct brw_tracked_state gen6_blend_state = {
168 .dirty = {
169 .mesa = _NEW_COLOR,
170 .brw = 0,
171 .cache = 0,
172 },
173 .prepare = prepare_blend_state,
174 };
175
176 struct brw_color_calc_state_key {
177 GLubyte blend_constant_color[4];
178 GLclampf alpha_ref;
179 GLubyte stencil_ref[2];
180 };
181
182 static void
183 color_calc_state_populate_key(struct brw_context *brw,
184 struct brw_color_calc_state_key *key)
185 {
186 GLcontext *ctx = &brw->intel.ctx;
187
188 memset(key, 0, sizeof(*key));
189
190 /* _NEW_STENCIL */
191 if (ctx->Stencil._Enabled) {
192 const unsigned back = ctx->Stencil._BackFace;
193
194 key->stencil_ref[0] = ctx->Stencil.Ref[0];
195 if (ctx->Stencil._TestTwoSide)
196 key->stencil_ref[1] = ctx->Stencil.Ref[back];
197 }
198
199 /* _NEW_COLOR */
200 if (ctx->Color.AlphaEnabled)
201 key->alpha_ref = ctx->Color.AlphaRef;
202
203 key->blend_constant_color[0] = ctx->Color.BlendColor[0];
204 key->blend_constant_color[1] = ctx->Color.BlendColor[1];
205 key->blend_constant_color[2] = ctx->Color.BlendColor[2];
206 key->blend_constant_color[3] = ctx->Color.BlendColor[3];
207 }
208
209 /**
210 * Creates the state cache entry for the given CC state key.
211 */
212 static drm_intel_bo *
213 color_calc_state_create_from_key(struct brw_context *brw,
214 struct brw_color_calc_state_key *key)
215 {
216 struct gen6_color_calc_state cc;
217 drm_intel_bo *bo;
218
219 memset(&cc, 0, sizeof(cc));
220
221 cc.cc0.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
222 UNCLAMPED_FLOAT_TO_UBYTE(cc.cc1.alpha_ref_fi.ui, key->alpha_ref);
223
224 cc.cc0.stencil_ref = key->stencil_ref[0];
225 cc.cc0.bf_stencil_ref = key->stencil_ref[1];
226
227 cc.constant_r = key->blend_constant_color[0];
228 cc.constant_g = key->blend_constant_color[1];
229 cc.constant_b = key->blend_constant_color[2];
230 cc.constant_a = key->blend_constant_color[3];
231
232 bo = brw_upload_cache(&brw->cache, BRW_COLOR_CALC_STATE,
233 key, sizeof(*key),
234 NULL, 0,
235 &cc, sizeof(cc));
236
237 return bo;
238 }
239
240 static void
241 prepare_color_calc_state(struct brw_context *brw)
242 {
243 struct brw_color_calc_state_key key;
244
245 color_calc_state_populate_key(brw, &key);
246
247 drm_intel_bo_unreference(brw->cc.state_bo);
248 brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE,
249 &key, sizeof(key),
250 NULL, 0,
251 NULL);
252
253 if (brw->cc.state_bo == NULL)
254 brw->cc.state_bo = color_calc_state_create_from_key(brw, &key);
255 }
256
257 const struct brw_tracked_state gen6_color_calc_state = {
258 .dirty = {
259 .mesa = _NEW_COLOR,
260 .brw = 0,
261 .cache = 0,
262 },
263 .prepare = prepare_color_calc_state,
264 };
265
266 static void upload_cc_state_pointers(struct brw_context *brw)
267 {
268 struct intel_context *intel = &brw->intel;
269
270 BEGIN_BATCH(4);
271 OUT_BATCH(CMD_3D_CC_STATE_POINTERS << 16 | (4 - 2));
272 OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
273 OUT_RELOC(brw->cc.blend_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
274 OUT_RELOC(brw->cc.depth_stencil_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
275 ADVANCE_BATCH();
276
277 intel_batchbuffer_emit_mi_flush(intel->batch);
278 }
279
280
281 static void prepare_cc_state_pointers(struct brw_context *brw)
282 {
283 brw_add_validated_bo(brw, brw->cc.state_bo);
284 brw_add_validated_bo(brw, brw->cc.blend_state_bo);
285 brw_add_validated_bo(brw, brw->cc.depth_stencil_state_bo);
286 }
287
288 const struct brw_tracked_state gen6_cc_state_pointers = {
289 .dirty = {
290 .mesa = 0,
291 .brw = BRW_NEW_BATCH,
292 .cache = (CACHE_NEW_BLEND_STATE |
293 CACHE_NEW_COLOR_CALC_STATE |
294 CACHE_NEW_DEPTH_STENCIL_STATE)
295 },
296 .prepare = prepare_cc_state_pointers,
297 .emit = upload_cc_state_pointers,
298 };