2 * Copyright © 2009 Intel Corporation
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:
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
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
24 * Eric Anholt <eric@anholt.net>
28 #include "brw_context.h"
29 #include "brw_state.h"
30 #include "brw_defines.h"
32 #include "intel_batchbuffer.h"
33 #include "main/macros.h"
35 struct gen6_blend_state_key
{
36 GLboolean color_blend
, alpha_enabled
;
38 GLboolean color_mask
[BRW_MAX_DRAW_BUFFERS
][4];
42 GLenum blend_eq_rgb
, blend_eq_a
;
43 GLenum blend_src_rgb
, blend_src_a
;
44 GLenum blend_dst_rgb
, blend_dst_a
;
50 blend_state_populate_key(struct brw_context
*brw
,
51 struct gen6_blend_state_key
*key
)
53 struct gl_context
*ctx
= &brw
->intel
.ctx
;
55 memset(key
, 0, sizeof(*key
));
58 memcpy(key
->color_mask
, ctx
->Color
.ColorMask
, sizeof(key
->color_mask
));
61 if (ctx
->Color
._LogicOpEnabled
)
62 key
->logic_op
= ctx
->Color
.LogicOp
;
64 key
->logic_op
= GL_COPY
;
67 key
->color_blend
= ctx
->Color
.BlendEnabled
;
68 if (key
->color_blend
) {
69 key
->blend_eq_rgb
= ctx
->Color
.BlendEquationRGB
;
70 key
->blend_eq_a
= ctx
->Color
.BlendEquationA
;
71 key
->blend_src_rgb
= ctx
->Color
.BlendSrcRGB
;
72 key
->blend_dst_rgb
= ctx
->Color
.BlendDstRGB
;
73 key
->blend_src_a
= ctx
->Color
.BlendSrcA
;
74 key
->blend_dst_a
= ctx
->Color
.BlendDstA
;
78 key
->alpha_enabled
= ctx
->Color
.AlphaEnabled
;
79 if (key
->alpha_enabled
) {
80 key
->alpha_func
= ctx
->Color
.AlphaFunc
;
84 key
->dither
= ctx
->Color
.DitherFlag
;
88 * Creates the state cache entry for the given CC unit key.
91 blend_state_create_from_key(struct brw_context
*brw
,
92 struct gen6_blend_state_key
*key
)
94 struct gen6_blend_state blend
[BRW_MAX_DRAW_BUFFERS
];
98 memset(&blend
, 0, sizeof(blend
));
100 for (b
= 0; b
< BRW_MAX_DRAW_BUFFERS
; b
++) {
101 if (key
->logic_op
!= GL_COPY
) {
102 blend
[b
].blend1
.logic_op_enable
= 1;
103 blend
[b
].blend1
.logic_op_func
= intel_translate_logic_op(key
->logic_op
);
104 } else if (key
->color_blend
& (1 << b
)) {
105 GLenum eqRGB
= key
->blend_eq_rgb
;
106 GLenum eqA
= key
->blend_eq_a
;
107 GLenum srcRGB
= key
->blend_src_rgb
;
108 GLenum dstRGB
= key
->blend_dst_rgb
;
109 GLenum srcA
= key
->blend_src_a
;
110 GLenum dstA
= key
->blend_dst_a
;
112 if (eqRGB
== GL_MIN
|| eqRGB
== GL_MAX
) {
113 srcRGB
= dstRGB
= GL_ONE
;
116 if (eqA
== GL_MIN
|| eqA
== GL_MAX
) {
117 srcA
= dstA
= GL_ONE
;
120 blend
[b
].blend0
.dest_blend_factor
= brw_translate_blend_factor(dstRGB
);
121 blend
[b
].blend0
.source_blend_factor
= brw_translate_blend_factor(srcRGB
);
122 blend
[b
].blend0
.blend_func
= brw_translate_blend_equation(eqRGB
);
124 blend
[b
].blend0
.ia_dest_blend_factor
= brw_translate_blend_factor(dstA
);
125 blend
[b
].blend0
.ia_source_blend_factor
= brw_translate_blend_factor(srcA
);
126 blend
[b
].blend0
.ia_blend_func
= brw_translate_blend_equation(eqA
);
128 blend
[b
].blend0
.blend_enable
= 1;
129 blend
[b
].blend0
.ia_blend_enable
= (srcA
!= srcRGB
||
134 if (key
->alpha_enabled
) {
135 blend
[b
].blend1
.alpha_test_enable
= 1;
136 blend
[b
].blend1
.alpha_test_func
= intel_translate_compare_func(key
->alpha_func
);
141 blend
[b
].blend1
.dither_enable
= 1;
142 blend
[b
].blend1
.y_dither_offset
= 0;
143 blend
[b
].blend1
.x_dither_offset
= 0;
146 blend
[b
].blend1
.write_disable_r
= !key
->color_mask
[b
][0];
147 blend
[b
].blend1
.write_disable_g
= !key
->color_mask
[b
][1];
148 blend
[b
].blend1
.write_disable_b
= !key
->color_mask
[b
][2];
149 blend
[b
].blend1
.write_disable_a
= !key
->color_mask
[b
][3];
152 bo
= brw_upload_cache(&brw
->cache
, BRW_BLEND_STATE
,
155 &blend
, sizeof(blend
));
161 prepare_blend_state(struct brw_context
*brw
)
163 struct gen6_blend_state_key key
;
165 blend_state_populate_key(brw
, &key
);
167 drm_intel_bo_unreference(brw
->cc
.blend_state_bo
);
168 brw
->cc
.blend_state_bo
= brw_search_cache(&brw
->cache
, BRW_BLEND_STATE
,
173 if (brw
->cc
.blend_state_bo
== NULL
)
174 brw
->cc
.blend_state_bo
= blend_state_create_from_key(brw
, &key
);
177 const struct brw_tracked_state gen6_blend_state
= {
183 .prepare
= prepare_blend_state
,
186 struct gen6_color_calc_state_key
{
187 float blend_constant_color
[4];
189 GLubyte stencil_ref
[2];
193 color_calc_state_populate_key(struct brw_context
*brw
,
194 struct gen6_color_calc_state_key
*key
)
196 struct gl_context
*ctx
= &brw
->intel
.ctx
;
198 memset(key
, 0, sizeof(*key
));
201 if (ctx
->Stencil
._Enabled
) {
202 const unsigned back
= ctx
->Stencil
._BackFace
;
204 key
->stencil_ref
[0] = ctx
->Stencil
.Ref
[0];
205 if (ctx
->Stencil
._TestTwoSide
)
206 key
->stencil_ref
[1] = ctx
->Stencil
.Ref
[back
];
210 if (ctx
->Color
.AlphaEnabled
)
211 key
->alpha_ref
= ctx
->Color
.AlphaRef
;
213 key
->blend_constant_color
[0] = ctx
->Color
.BlendColor
[0];
214 key
->blend_constant_color
[1] = ctx
->Color
.BlendColor
[1];
215 key
->blend_constant_color
[2] = ctx
->Color
.BlendColor
[2];
216 key
->blend_constant_color
[3] = ctx
->Color
.BlendColor
[3];
220 * Creates the state cache entry for the given CC state key.
222 static drm_intel_bo
*
223 color_calc_state_create_from_key(struct brw_context
*brw
,
224 struct gen6_color_calc_state_key
*key
)
226 struct gen6_color_calc_state cc
;
229 memset(&cc
, 0, sizeof(cc
));
231 cc
.cc0
.alpha_test_format
= BRW_ALPHATEST_FORMAT_UNORM8
;
232 UNCLAMPED_FLOAT_TO_UBYTE(cc
.cc1
.alpha_ref_fi
.ui
, key
->alpha_ref
);
234 cc
.cc0
.stencil_ref
= key
->stencil_ref
[0];
235 cc
.cc0
.bf_stencil_ref
= key
->stencil_ref
[1];
237 cc
.constant_r
= key
->blend_constant_color
[0];
238 cc
.constant_g
= key
->blend_constant_color
[1];
239 cc
.constant_b
= key
->blend_constant_color
[2];
240 cc
.constant_a
= key
->blend_constant_color
[3];
242 bo
= brw_upload_cache(&brw
->cache
, BRW_COLOR_CALC_STATE
,
251 prepare_color_calc_state(struct brw_context
*brw
)
253 struct gen6_color_calc_state_key key
;
255 color_calc_state_populate_key(brw
, &key
);
257 drm_intel_bo_unreference(brw
->cc
.state_bo
);
258 brw
->cc
.state_bo
= brw_search_cache(&brw
->cache
, BRW_COLOR_CALC_STATE
,
263 if (brw
->cc
.state_bo
== NULL
)
264 brw
->cc
.state_bo
= color_calc_state_create_from_key(brw
, &key
);
267 const struct brw_tracked_state gen6_color_calc_state
= {
269 .mesa
= _NEW_COLOR
| _NEW_STENCIL
,
273 .prepare
= prepare_color_calc_state
,
276 static void upload_cc_state_pointers(struct brw_context
*brw
)
278 struct intel_context
*intel
= &brw
->intel
;
281 OUT_BATCH(_3DSTATE_CC_STATE_POINTERS
<< 16 | (4 - 2));
282 OUT_RELOC(brw
->cc
.blend_state_bo
, I915_GEM_DOMAIN_INSTRUCTION
, 0, 1);
283 OUT_RELOC(brw
->cc
.depth_stencil_state_bo
, I915_GEM_DOMAIN_INSTRUCTION
, 0, 1);
284 OUT_RELOC(brw
->cc
.state_bo
, I915_GEM_DOMAIN_INSTRUCTION
, 0, 1);
289 static void prepare_cc_state_pointers(struct brw_context
*brw
)
291 brw_add_validated_bo(brw
, brw
->cc
.state_bo
);
292 brw_add_validated_bo(brw
, brw
->cc
.blend_state_bo
);
293 brw_add_validated_bo(brw
, brw
->cc
.depth_stencil_state_bo
);
296 const struct brw_tracked_state gen6_cc_state_pointers
= {
299 .brw
= BRW_NEW_BATCH
,
300 .cache
= (CACHE_NEW_BLEND_STATE
|
301 CACHE_NEW_COLOR_CALC_STATE
|
302 CACHE_NEW_DEPTH_STENCIL_STATE
)
304 .prepare
= prepare_cc_state_pointers
,
305 .emit
= upload_cc_state_pointers
,