brw_cc.c revision 34474fa4119378ef9fbb9fb557cc19c0a1ca1f7e
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
39static void prepare_cc_vp( struct brw_context *brw )
40{
41   GLcontext *ctx = &brw->intel.ctx;
42   struct brw_cc_viewport ccv;
43
44   memset(&ccv, 0, sizeof(ccv));
45
46   /* _NEW_TRANSOFORM */
47   if (ctx->Transform.DepthClamp) {
48      /* _NEW_VIEWPORT */
49      ccv.min_depth = MIN2(ctx->Viewport.Near, ctx->Viewport.Far);
50      ccv.max_depth = MAX2(ctx->Viewport.Near, ctx->Viewport.Far);
51   } else {
52      ccv.min_depth = 0.0;
53      ccv.max_depth = 1.0;
54   }
55
56   drm_intel_bo_unreference(brw->cc.vp_bo);
57   brw->cc.vp_bo = brw_cache_data(&brw->cache, BRW_CC_VP, &ccv, sizeof(ccv),
58				  NULL, 0);
59}
60
61const struct brw_tracked_state brw_cc_vp = {
62   .dirty = {
63      .mesa = _NEW_VIEWPORT | _NEW_TRANSFORM,
64      .brw = BRW_NEW_CONTEXT,
65      .cache = 0
66   },
67   .prepare = prepare_cc_vp
68};
69
70struct brw_cc_unit_key {
71   GLboolean stencil, stencil_two_side, color_blend, alpha_enabled;
72
73   GLenum stencil_func[2], stencil_fail_op[2];
74   GLenum stencil_pass_depth_fail_op[2], stencil_pass_depth_pass_op[2];
75   GLubyte stencil_ref[2], stencil_write_mask[2], stencil_test_mask[2];
76   GLenum logic_op;
77
78   GLenum blend_eq_rgb, blend_eq_a;
79   GLenum blend_src_rgb, blend_src_a;
80   GLenum blend_dst_rgb, blend_dst_a;
81
82   GLenum alpha_func;
83   GLclampf alpha_ref;
84
85   GLboolean dither;
86
87   GLboolean depth_test, depth_write;
88   GLenum depth_func;
89};
90
91/**
92 * Modify blend function to force destination alpha to 1.0
93 *
94 * If \c function specifies a blend function that uses destination alpha,
95 * replace it with a function that hard-wires destination alpha to 1.0.  This
96 * is used when rendering to xRGB targets.
97 */
98static GLenum
99fix_xRGB_alpha(GLenum function)
100{
101   switch (function) {
102   case GL_DST_ALPHA:
103      return GL_ONE;
104
105   case GL_ONE_MINUS_DST_ALPHA:
106   case GL_SRC_ALPHA_SATURATE:
107      return GL_ZERO;
108   }
109
110   return function;
111}
112
113static void
114cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
115{
116   GLcontext *ctx = &brw->intel.ctx;
117   const unsigned back = ctx->Stencil._BackFace;
118
119   memset(key, 0, sizeof(*key));
120
121   key->stencil = ctx->Stencil._Enabled;
122   key->stencil_two_side = ctx->Stencil._TestTwoSide;
123
124   if (key->stencil) {
125      key->stencil_func[0] = ctx->Stencil.Function[0];
126      key->stencil_fail_op[0] = ctx->Stencil.FailFunc[0];
127      key->stencil_pass_depth_fail_op[0] = ctx->Stencil.ZFailFunc[0];
128      key->stencil_pass_depth_pass_op[0] = ctx->Stencil.ZPassFunc[0];
129      key->stencil_ref[0] = ctx->Stencil.Ref[0];
130      key->stencil_write_mask[0] = ctx->Stencil.WriteMask[0];
131      key->stencil_test_mask[0] = ctx->Stencil.ValueMask[0];
132   }
133   if (key->stencil_two_side) {
134      key->stencil_func[1] = ctx->Stencil.Function[back];
135      key->stencil_fail_op[1] = ctx->Stencil.FailFunc[back];
136      key->stencil_pass_depth_fail_op[1] = ctx->Stencil.ZFailFunc[back];
137      key->stencil_pass_depth_pass_op[1] = ctx->Stencil.ZPassFunc[back];
138      key->stencil_ref[1] = ctx->Stencil.Ref[back];
139      key->stencil_write_mask[1] = ctx->Stencil.WriteMask[back];
140      key->stencil_test_mask[1] = ctx->Stencil.ValueMask[back];
141   }
142
143   if (ctx->Color._LogicOpEnabled)
144      key->logic_op = ctx->Color.LogicOp;
145   else
146      key->logic_op = GL_COPY;
147
148   key->color_blend = ctx->Color.BlendEnabled;
149   if (key->color_blend) {
150      key->blend_eq_rgb = ctx->Color.BlendEquationRGB;
151      key->blend_eq_a = ctx->Color.BlendEquationA;
152      key->blend_src_rgb = ctx->Color.BlendSrcRGB;
153      key->blend_dst_rgb = ctx->Color.BlendDstRGB;
154      key->blend_src_a = ctx->Color.BlendSrcA;
155      key->blend_dst_a = ctx->Color.BlendDstA;
156
157      /* If the renderbuffer is XRGB, we have to frob the blend function to
158       * force the destination alpha to 1.0.  This means replacing GL_DST_ALPHA
159       * with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO.
160       */
161      if (ctx->DrawBuffer->Visual.alphaBits == 0) {
162	 key->blend_src_rgb = fix_xRGB_alpha(key->blend_src_rgb);
163	 key->blend_src_a   = fix_xRGB_alpha(key->blend_src_a);
164	 key->blend_dst_rgb = fix_xRGB_alpha(key->blend_dst_rgb);
165	 key->blend_dst_a   = fix_xRGB_alpha(key->blend_dst_a);
166      }
167   }
168
169   key->alpha_enabled = ctx->Color.AlphaEnabled;
170   if (key->alpha_enabled) {
171      key->alpha_func = ctx->Color.AlphaFunc;
172      key->alpha_ref = ctx->Color.AlphaRef;
173   }
174
175   key->dither = ctx->Color.DitherFlag;
176
177   key->depth_test = ctx->Depth.Test;
178   if (key->depth_test) {
179      key->depth_func = ctx->Depth.Func;
180      key->depth_write = ctx->Depth.Mask;
181   }
182}
183
184/**
185 * Creates the state cache entry for the given CC unit key.
186 */
187static drm_intel_bo *
188cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key)
189{
190   struct brw_cc_unit_state cc;
191   drm_intel_bo *bo;
192
193   memset(&cc, 0, sizeof(cc));
194
195   /* _NEW_STENCIL */
196   if (key->stencil) {
197      cc.cc0.stencil_enable = 1;
198      cc.cc0.stencil_func =
199	 intel_translate_compare_func(key->stencil_func[0]);
200      cc.cc0.stencil_fail_op =
201	 intel_translate_stencil_op(key->stencil_fail_op[0]);
202      cc.cc0.stencil_pass_depth_fail_op =
203	 intel_translate_stencil_op(key->stencil_pass_depth_fail_op[0]);
204      cc.cc0.stencil_pass_depth_pass_op =
205	 intel_translate_stencil_op(key->stencil_pass_depth_pass_op[0]);
206      cc.cc1.stencil_ref = key->stencil_ref[0];
207      cc.cc1.stencil_write_mask = key->stencil_write_mask[0];
208      cc.cc1.stencil_test_mask = key->stencil_test_mask[0];
209
210      if (key->stencil_two_side) {
211	 cc.cc0.bf_stencil_enable = 1;
212	 cc.cc0.bf_stencil_func =
213	    intel_translate_compare_func(key->stencil_func[1]);
214	 cc.cc0.bf_stencil_fail_op =
215	    intel_translate_stencil_op(key->stencil_fail_op[1]);
216	 cc.cc0.bf_stencil_pass_depth_fail_op =
217	    intel_translate_stencil_op(key->stencil_pass_depth_fail_op[1]);
218	 cc.cc0.bf_stencil_pass_depth_pass_op =
219	    intel_translate_stencil_op(key->stencil_pass_depth_pass_op[1]);
220	 cc.cc1.bf_stencil_ref = key->stencil_ref[1];
221	 cc.cc2.bf_stencil_write_mask = key->stencil_write_mask[1];
222	 cc.cc2.bf_stencil_test_mask = key->stencil_test_mask[1];
223      }
224
225      /* Not really sure about this:
226       */
227      if (key->stencil_write_mask[0] ||
228	  (key->stencil_two_side && key->stencil_write_mask[1]))
229	 cc.cc0.stencil_write_enable = 1;
230   }
231
232   /* _NEW_COLOR */
233   if (key->logic_op != GL_COPY) {
234      cc.cc2.logicop_enable = 1;
235      cc.cc5.logicop_func = intel_translate_logic_op(key->logic_op);
236   } else if (key->color_blend) {
237      GLenum eqRGB = key->blend_eq_rgb;
238      GLenum eqA = key->blend_eq_a;
239      GLenum srcRGB = key->blend_src_rgb;
240      GLenum dstRGB = key->blend_dst_rgb;
241      GLenum srcA = key->blend_src_a;
242      GLenum dstA = key->blend_dst_a;
243
244      if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
245	 srcRGB = dstRGB = GL_ONE;
246      }
247
248      if (eqA == GL_MIN || eqA == GL_MAX) {
249	 srcA = dstA = GL_ONE;
250      }
251
252      cc.cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
253      cc.cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
254      cc.cc6.blend_function = brw_translate_blend_equation(eqRGB);
255
256      cc.cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
257      cc.cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
258      cc.cc5.ia_blend_function = brw_translate_blend_equation(eqA);
259
260      cc.cc3.blend_enable = 1;
261      cc.cc3.ia_blend_enable = (srcA != srcRGB ||
262				dstA != dstRGB ||
263				eqA != eqRGB);
264   }
265
266   if (key->alpha_enabled) {
267      cc.cc3.alpha_test = 1;
268      cc.cc3.alpha_test_func = intel_translate_compare_func(key->alpha_func);
269      cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
270
271      UNCLAMPED_FLOAT_TO_UBYTE(cc.cc7.alpha_ref.ub[0], key->alpha_ref);
272   }
273
274   if (key->dither) {
275      cc.cc5.dither_enable = 1;
276      cc.cc6.y_dither_offset = 0;
277      cc.cc6.x_dither_offset = 0;
278   }
279
280   /* _NEW_DEPTH */
281   if (key->depth_test) {
282      cc.cc2.depth_test = 1;
283      cc.cc2.depth_test_function = intel_translate_compare_func(key->depth_func);
284      cc.cc2.depth_write_enable = key->depth_write;
285   }
286
287   /* CACHE_NEW_CC_VP */
288   cc.cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
289
290   if (INTEL_DEBUG & DEBUG_STATS)
291      cc.cc5.statistics_enable = 1;
292
293   bo = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
294			 key, sizeof(*key),
295			 &brw->cc.vp_bo, 1,
296			 &cc, sizeof(cc));
297
298   /* Emit CC viewport relocation */
299   dri_bo_emit_reloc(bo,
300		     I915_GEM_DOMAIN_INSTRUCTION,
301		     0,
302		     0,
303		     offsetof(struct brw_cc_unit_state, cc4),
304		     brw->cc.vp_bo);
305
306   return bo;
307}
308
309static void prepare_cc_unit( struct brw_context *brw )
310{
311   struct brw_cc_unit_key key;
312
313   cc_unit_populate_key(brw, &key);
314
315   drm_intel_bo_unreference(brw->cc.state_bo);
316   brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_CC_UNIT,
317				       &key, sizeof(key),
318				       &brw->cc.vp_bo, 1,
319				       NULL);
320
321   if (brw->cc.state_bo == NULL)
322      brw->cc.state_bo = cc_unit_create_from_key(brw, &key);
323}
324
325const struct brw_tracked_state brw_cc_unit = {
326   .dirty = {
327      .mesa = _NEW_STENCIL | _NEW_COLOR | _NEW_DEPTH,
328      .brw = 0,
329      .cache = CACHE_NEW_CC_VP
330   },
331   .prepare = prepare_cc_unit,
332};
333
334
335
336