i965: Stream out CC unit state.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_cc.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
36 #include "brw_util.h"
37 #include "main/macros.h"
38
39 void
40 brw_update_cc_vp(struct brw_context *brw)
41 {
42 GLcontext *ctx = &brw->intel.ctx;
43 struct brw_cc_viewport ccv;
44
45 memset(&ccv, 0, sizeof(ccv));
46
47 /* _NEW_TRANSOFORM */
48 if (ctx->Transform.DepthClamp) {
49 /* _NEW_VIEWPORT */
50 ccv.min_depth = MIN2(ctx->Viewport.Near, ctx->Viewport.Far);
51 ccv.max_depth = MAX2(ctx->Viewport.Near, ctx->Viewport.Far);
52 } else {
53 ccv.min_depth = 0.0;
54 ccv.max_depth = 1.0;
55 }
56
57 drm_intel_bo_unreference(brw->cc.vp_bo);
58 brw->cc.vp_bo = brw_cache_data(&brw->cache, BRW_CC_VP, &ccv, sizeof(ccv));
59 }
60
61 /**
62 * Modify blend function to force destination alpha to 1.0
63 *
64 * If \c function specifies a blend function that uses destination alpha,
65 * replace it with a function that hard-wires destination alpha to 1.0. This
66 * is used when rendering to xRGB targets.
67 */
68 static GLenum
69 fix_xRGB_alpha(GLenum function)
70 {
71 switch (function) {
72 case GL_DST_ALPHA:
73 return GL_ONE;
74
75 case GL_ONE_MINUS_DST_ALPHA:
76 case GL_SRC_ALPHA_SATURATE:
77 return GL_ZERO;
78 }
79
80 return function;
81 }
82
83 static void prepare_cc_unit(struct brw_context *brw)
84 {
85 brw_add_validated_bo(brw, brw->cc.vp_bo);
86 }
87
88 /**
89 * Creates the state cache entry for the given CC unit key.
90 */
91 static void upload_cc_unit(struct brw_context *brw)
92 {
93 GLcontext *ctx = &brw->intel.ctx;
94 struct brw_cc_unit_state cc;
95 void *map;
96
97 memset(&cc, 0, sizeof(cc));
98
99 /* _NEW_STENCIL */
100 if (ctx->Stencil._Enabled) {
101 const unsigned back = ctx->Stencil._BackFace;
102
103 cc.cc0.stencil_enable = 1;
104 cc.cc0.stencil_func =
105 intel_translate_compare_func(ctx->Stencil.Function[0]);
106 cc.cc0.stencil_fail_op =
107 intel_translate_stencil_op(ctx->Stencil.FailFunc[0]);
108 cc.cc0.stencil_pass_depth_fail_op =
109 intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]);
110 cc.cc0.stencil_pass_depth_pass_op =
111 intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]);
112 cc.cc1.stencil_ref = ctx->Stencil.Ref[0];
113 cc.cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
114 cc.cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
115
116 if (ctx->Stencil._TestTwoSide) {
117 cc.cc0.bf_stencil_enable = 1;
118 cc.cc0.bf_stencil_func =
119 intel_translate_compare_func(ctx->Stencil.Function[back]);
120 cc.cc0.bf_stencil_fail_op =
121 intel_translate_stencil_op(ctx->Stencil.FailFunc[back]);
122 cc.cc0.bf_stencil_pass_depth_fail_op =
123 intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]);
124 cc.cc0.bf_stencil_pass_depth_pass_op =
125 intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]);
126 cc.cc1.bf_stencil_ref = ctx->Stencil.Ref[back];
127 cc.cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back];
128 cc.cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back];
129 }
130
131 /* Not really sure about this:
132 */
133 if (ctx->Stencil.WriteMask[0] ||
134 (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back]))
135 cc.cc0.stencil_write_enable = 1;
136 }
137
138 /* _NEW_COLOR */
139 if (ctx->Color._LogicOpEnabled && ctx->Color.LogicOp != GL_COPY) {
140 cc.cc2.logicop_enable = 1;
141 cc.cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp);
142 } else if (ctx->Color.BlendEnabled) {
143 GLenum eqRGB = ctx->Color.BlendEquationRGB;
144 GLenum eqA = ctx->Color.BlendEquationA;
145 GLenum srcRGB = ctx->Color.BlendSrcRGB;
146 GLenum dstRGB = ctx->Color.BlendDstRGB;
147 GLenum srcA = ctx->Color.BlendSrcA;
148 GLenum dstA = ctx->Color.BlendDstA;
149
150 /* If the renderbuffer is XRGB, we have to frob the blend function to
151 * force the destination alpha to 1.0. This means replacing GL_DST_ALPHA
152 * with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO.
153 */
154 if (ctx->DrawBuffer->Visual.alphaBits == 0) {
155 srcRGB = fix_xRGB_alpha(srcRGB);
156 srcA = fix_xRGB_alpha(srcA);
157 dstRGB = fix_xRGB_alpha(dstRGB);
158 dstA = fix_xRGB_alpha(dstA);
159 }
160
161 if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
162 srcRGB = dstRGB = GL_ONE;
163 }
164
165 if (eqA == GL_MIN || eqA == GL_MAX) {
166 srcA = dstA = GL_ONE;
167 }
168
169 cc.cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
170 cc.cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
171 cc.cc6.blend_function = brw_translate_blend_equation(eqRGB);
172
173 cc.cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
174 cc.cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
175 cc.cc5.ia_blend_function = brw_translate_blend_equation(eqA);
176
177 cc.cc3.blend_enable = 1;
178 cc.cc3.ia_blend_enable = (srcA != srcRGB ||
179 dstA != dstRGB ||
180 eqA != eqRGB);
181 }
182
183 if (ctx->Color.AlphaEnabled) {
184 cc.cc3.alpha_test = 1;
185 cc.cc3.alpha_test_func =
186 intel_translate_compare_func(ctx->Color.AlphaFunc);
187 cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
188
189 UNCLAMPED_FLOAT_TO_UBYTE(cc.cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
190 }
191
192 if (ctx->Color.DitherFlag) {
193 cc.cc5.dither_enable = 1;
194 cc.cc6.y_dither_offset = 0;
195 cc.cc6.x_dither_offset = 0;
196 }
197
198 /* _NEW_DEPTH */
199 if (ctx->Depth.Test) {
200 cc.cc2.depth_test = 1;
201 cc.cc2.depth_test_function =
202 intel_translate_compare_func(ctx->Depth.Func);
203 cc.cc2.depth_write_enable = ctx->Depth.Mask;
204 }
205
206 /* CACHE_NEW_CC_VP */
207 cc.cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
208
209 if (INTEL_DEBUG & DEBUG_STATS)
210 cc.cc5.statistics_enable = 1;
211
212 map = brw_state_batch(brw, sizeof(cc), 64,
213 &brw->cc.state_bo, &brw->cc.state_offset);
214 memcpy(map, &cc, sizeof(cc));
215 brw->state.dirty.cache |= CACHE_NEW_CC_UNIT;
216
217 /* Emit CC viewport relocation */
218 drm_intel_bo_emit_reloc(brw->cc.state_bo, (brw->cc.state_offset +
219 offsetof(struct brw_cc_unit_state,
220 cc4)),
221 brw->cc.vp_bo, 0,
222 I915_GEM_DOMAIN_INSTRUCTION, 0);
223 }
224
225 const struct brw_tracked_state brw_cc_unit = {
226 .dirty = {
227 .mesa = _NEW_STENCIL | _NEW_COLOR | _NEW_DEPTH,
228 .brw = BRW_NEW_BATCH,
229 .cache = CACHE_NEW_CC_VP
230 },
231 .prepare = prepare_cc_unit,
232 .emit = upload_cc_unit,
233 };