brw_cc.c revision aac120977d1ead319141d48d65c9bba626ec03b8
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#include "intel_batchbuffer.h"
39
40void
41brw_update_cc_vp(struct brw_context *brw)
42{
43   struct gl_context *ctx = &brw->intel.ctx;
44   struct brw_cc_viewport ccv;
45
46   memset(&ccv, 0, sizeof(ccv));
47
48   /* _NEW_TRANSOFORM */
49   if (ctx->Transform.DepthClamp) {
50      /* _NEW_VIEWPORT */
51      ccv.min_depth = MIN2(ctx->Viewport.Near, ctx->Viewport.Far);
52      ccv.max_depth = MAX2(ctx->Viewport.Near, ctx->Viewport.Far);
53   } else {
54      ccv.min_depth = 0.0;
55      ccv.max_depth = 1.0;
56   }
57
58   drm_intel_bo_unreference(brw->cc.vp_bo);
59   brw->cc.vp_bo = brw_cache_data(&brw->cache, BRW_CC_VP, &ccv, sizeof(ccv));
60}
61
62/**
63 * Modify blend function to force destination alpha to 1.0
64 *
65 * If \c function specifies a blend function that uses destination alpha,
66 * replace it with a function that hard-wires destination alpha to 1.0.  This
67 * is used when rendering to xRGB targets.
68 */
69static GLenum
70fix_xRGB_alpha(GLenum function)
71{
72   switch (function) {
73   case GL_DST_ALPHA:
74      return GL_ONE;
75
76   case GL_ONE_MINUS_DST_ALPHA:
77   case GL_SRC_ALPHA_SATURATE:
78      return GL_ZERO;
79   }
80
81   return function;
82}
83
84static void prepare_cc_unit(struct brw_context *brw)
85{
86   brw_add_validated_bo(brw, brw->cc.vp_bo);
87}
88
89/**
90 * Creates the state cache entry for the given CC unit key.
91 */
92static void upload_cc_unit(struct brw_context *brw)
93{
94   struct intel_context *intel = &brw->intel;
95   struct gl_context *ctx = &brw->intel.ctx;
96   struct brw_cc_unit_state *cc;
97
98   cc = brw_state_batch(brw, sizeof(*cc), 64, &brw->cc.state_offset);
99   memset(cc, 0, sizeof(*cc));
100
101   /* _NEW_STENCIL */
102   if (ctx->Stencil._Enabled) {
103      const unsigned back = ctx->Stencil._BackFace;
104
105      cc->cc0.stencil_enable = 1;
106      cc->cc0.stencil_func =
107	 intel_translate_compare_func(ctx->Stencil.Function[0]);
108      cc->cc0.stencil_fail_op =
109	 intel_translate_stencil_op(ctx->Stencil.FailFunc[0]);
110      cc->cc0.stencil_pass_depth_fail_op =
111	 intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]);
112      cc->cc0.stencil_pass_depth_pass_op =
113	 intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]);
114      cc->cc1.stencil_ref = ctx->Stencil.Ref[0];
115      cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
116      cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
117
118      if (ctx->Stencil._TestTwoSide) {
119	 cc->cc0.bf_stencil_enable = 1;
120	 cc->cc0.bf_stencil_func =
121	    intel_translate_compare_func(ctx->Stencil.Function[back]);
122	 cc->cc0.bf_stencil_fail_op =
123	    intel_translate_stencil_op(ctx->Stencil.FailFunc[back]);
124	 cc->cc0.bf_stencil_pass_depth_fail_op =
125	    intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]);
126	 cc->cc0.bf_stencil_pass_depth_pass_op =
127	    intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]);
128	 cc->cc1.bf_stencil_ref = ctx->Stencil.Ref[back];
129	 cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back];
130	 cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back];
131      }
132
133      /* Not really sure about this:
134       */
135      if (ctx->Stencil.WriteMask[0] ||
136	  (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back]))
137	 cc->cc0.stencil_write_enable = 1;
138   }
139
140   /* _NEW_COLOR */
141   if (ctx->Color._LogicOpEnabled && ctx->Color.LogicOp != GL_COPY) {
142      cc->cc2.logicop_enable = 1;
143      cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp);
144   } else if (ctx->Color.BlendEnabled) {
145      GLenum eqRGB = ctx->Color.Blend[0].EquationRGB;
146      GLenum eqA = ctx->Color.Blend[0].EquationA;
147      GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
148      GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
149      GLenum srcA = ctx->Color.Blend[0].SrcA;
150      GLenum dstA = ctx->Color.Blend[0].DstA;
151
152      /* If the renderbuffer is XRGB, we have to frob the blend function to
153       * force the destination alpha to 1.0.  This means replacing GL_DST_ALPHA
154       * with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO.
155       */
156      if (ctx->DrawBuffer->Visual.alphaBits == 0) {
157	 srcRGB = fix_xRGB_alpha(srcRGB);
158	 srcA   = fix_xRGB_alpha(srcA);
159	 dstRGB = fix_xRGB_alpha(dstRGB);
160	 dstA   = fix_xRGB_alpha(dstA);
161      }
162
163      if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
164	 srcRGB = dstRGB = GL_ONE;
165      }
166
167      if (eqA == GL_MIN || eqA == GL_MAX) {
168	 srcA = dstA = GL_ONE;
169      }
170
171      cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
172      cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
173      cc->cc6.blend_function = brw_translate_blend_equation(eqRGB);
174
175      cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
176      cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
177      cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA);
178
179      cc->cc3.blend_enable = 1;
180      cc->cc3.ia_blend_enable = (srcA != srcRGB ||
181				dstA != dstRGB ||
182				eqA != eqRGB);
183   }
184
185   if (ctx->Color.AlphaEnabled) {
186      cc->cc3.alpha_test = 1;
187      cc->cc3.alpha_test_func =
188	 intel_translate_compare_func(ctx->Color.AlphaFunc);
189      cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
190
191      UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
192   }
193
194   if (ctx->Color.DitherFlag) {
195      cc->cc5.dither_enable = 1;
196      cc->cc6.y_dither_offset = 0;
197      cc->cc6.x_dither_offset = 0;
198   }
199
200   /* _NEW_DEPTH */
201   if (ctx->Depth.Test) {
202      cc->cc2.depth_test = 1;
203      cc->cc2.depth_test_function =
204	 intel_translate_compare_func(ctx->Depth.Func);
205      cc->cc2.depth_write_enable = ctx->Depth.Mask;
206   }
207
208   if (intel->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS))
209      cc->cc5.statistics_enable = 1;
210
211   /* CACHE_NEW_CC_VP */
212   cc->cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
213
214   brw->state.dirty.cache |= CACHE_NEW_CC_UNIT;
215
216   /* Emit CC viewport relocation */
217   drm_intel_bo_emit_reloc(brw->intel.batch.bo,
218			   (brw->cc.state_offset +
219			    offsetof(struct brw_cc_unit_state, cc4)),
220			   brw->cc.vp_bo, 0,
221			   I915_GEM_DOMAIN_INSTRUCTION, 0);
222}
223
224const struct brw_tracked_state brw_cc_unit = {
225   .dirty = {
226      .mesa = _NEW_STENCIL | _NEW_COLOR | _NEW_DEPTH,
227      .brw = BRW_NEW_BATCH,
228      .cache = CACHE_NEW_CC_VP
229   },
230   .prepare = prepare_cc_unit,
231   .emit = upload_cc_unit,
232};
233
234static void upload_blend_constant_color(struct brw_context *brw)
235{
236   struct intel_context *intel = &brw->intel;
237   struct gl_context *ctx = &intel->ctx;
238
239   BEGIN_BATCH(5);
240   OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2));
241   OUT_BATCH(ctx->Color.BlendColor[0]);
242   OUT_BATCH(ctx->Color.BlendColor[1]);
243   OUT_BATCH(ctx->Color.BlendColor[2]);
244   OUT_BATCH(ctx->Color.BlendColor[3]);
245   CACHED_BATCH();
246}
247
248const struct brw_tracked_state brw_blend_constant_color = {
249   .dirty = {
250      .mesa = _NEW_COLOR,
251      .brw = BRW_NEW_CONTEXT,
252      .cache = 0
253   },
254   .emit = upload_blend_constant_color
255};
256