• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2012-2015 LunarG, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Chia-I Wu <olv@lunarg.com>
26  */
27 
28 #include "ilo_debug.h"
29 #include "ilo_state_cc.h"
30 
31 static bool
cc_validate_gen6_stencil(const struct ilo_dev * dev,const struct ilo_state_cc_info * info)32 cc_validate_gen6_stencil(const struct ilo_dev *dev,
33                          const struct ilo_state_cc_info *info)
34 {
35    const struct ilo_state_cc_stencil_info *stencil = &info->stencil;
36 
37    ILO_DEV_ASSERT(dev, 6, 8);
38 
39    /*
40     * From the Sandy Bridge PRM, volume 2 part 1, page 359:
41     *
42     *     "If the Depth Buffer is either undefined or does not have a surface
43     *      format of D32_FLOAT_S8X24_UINT or D24_UNORM_S8_UINT and separate
44     *      stencil buffer is disabled, Stencil Test Enable must be DISABLED"
45     *
46     * From the Sandy Bridge PRM, volume 2 part 1, page 370:
47     *
48     *     "This field (Stencil Test Enable) cannot be enabled if Surface
49     *      Format in 3DSTATE_DEPTH_BUFFER is set to D16_UNORM."
50     */
51    if (stencil->test_enable)
52       assert(stencil->cv_has_buffer);
53 
54    return true;
55 }
56 
57 static bool
cc_validate_gen6_depth(const struct ilo_dev * dev,const struct ilo_state_cc_info * info)58 cc_validate_gen6_depth(const struct ilo_dev *dev,
59                        const struct ilo_state_cc_info *info)
60 {
61    const struct ilo_state_cc_depth_info *depth = &info->depth;
62 
63    ILO_DEV_ASSERT(dev, 6, 8);
64 
65    /*
66     * From the Sandy Bridge PRM, volume 2 part 1, page 360:
67     *
68     *     "Enabling the Depth Test function without defining a Depth Buffer is
69     *      UNDEFINED."
70     *
71     * From the Sandy Bridge PRM, volume 2 part 1, page 375:
72     *
73     *     "A Depth Buffer must be defined before enabling writes to it, or
74     *      operation is UNDEFINED."
75     */
76    if (depth->test_enable || depth->write_enable)
77       assert(depth->cv_has_buffer);
78 
79    return true;
80 }
81 
82 static bool
cc_set_gen6_DEPTH_STENCIL_STATE(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)83 cc_set_gen6_DEPTH_STENCIL_STATE(struct ilo_state_cc *cc,
84                                 const struct ilo_dev *dev,
85                                 const struct ilo_state_cc_info *info)
86 {
87    const struct ilo_state_cc_stencil_info *stencil = &info->stencil;
88    const struct ilo_state_cc_depth_info *depth = &info->depth;
89    const struct ilo_state_cc_params_info *params = &info->params;
90    uint32_t dw0, dw1, dw2;
91 
92    ILO_DEV_ASSERT(dev, 6, 7.5);
93 
94    if (!cc_validate_gen6_stencil(dev, info) ||
95        !cc_validate_gen6_depth(dev, info))
96       return false;
97 
98    dw0 = 0;
99    dw1 = 0;
100    if (stencil->test_enable) {
101       const struct ilo_state_cc_stencil_op_info *front = &stencil->front;
102       const struct ilo_state_cc_stencil_params_info *front_p =
103          &params->stencil_front;
104       const struct ilo_state_cc_stencil_op_info *back;
105       const struct ilo_state_cc_stencil_params_info *back_p;
106 
107       dw0 |= GEN6_ZS_DW0_STENCIL_TEST_ENABLE;
108 
109       if (stencil->twosided_enable) {
110          dw0 |= GEN6_ZS_DW0_STENCIL1_ENABLE;
111 
112          back = &stencil->back;
113          back_p = &params->stencil_back;
114       } else {
115          back = &stencil->front;
116          back_p = &params->stencil_front;
117       }
118 
119       dw0 |= front->test_func << GEN6_ZS_DW0_STENCIL_FUNC__SHIFT |
120              front->fail_op << GEN6_ZS_DW0_STENCIL_FAIL_OP__SHIFT |
121              front->zfail_op << GEN6_ZS_DW0_STENCIL_ZFAIL_OP__SHIFT |
122              front->zpass_op << GEN6_ZS_DW0_STENCIL_ZPASS_OP__SHIFT |
123              back->test_func << GEN6_ZS_DW0_STENCIL1_FUNC__SHIFT |
124              back->fail_op << GEN6_ZS_DW0_STENCIL1_FAIL_OP__SHIFT |
125              back->zfail_op << GEN6_ZS_DW0_STENCIL1_ZFAIL_OP__SHIFT |
126              back->zpass_op << GEN6_ZS_DW0_STENCIL1_ZPASS_OP__SHIFT;
127 
128       /*
129        * From the Ivy Bridge PRM, volume 2 part 1, page 363:
130        *
131        *     "If this field (Stencil Buffer Write Enable) is enabled, Stencil
132        *      Test Enable must also be enabled."
133        *
134        * This is different from depth write enable, which is independent from
135        * depth test enable.
136        */
137       if (front_p->write_mask || back_p->write_mask)
138          dw0 |= GEN6_ZS_DW0_STENCIL_WRITE_ENABLE;
139 
140       dw1 |= front_p->test_mask << GEN6_ZS_DW1_STENCIL_TEST_MASK__SHIFT |
141              front_p->write_mask << GEN6_ZS_DW1_STENCIL_WRITE_MASK__SHIFT |
142              back_p->test_mask << GEN6_ZS_DW1_STENCIL1_TEST_MASK__SHIFT |
143              back_p->write_mask << GEN6_ZS_DW1_STENCIL1_WRITE_MASK__SHIFT;
144    }
145 
146    dw2 = 0;
147    if (depth->test_enable) {
148       dw2 |= GEN6_ZS_DW2_DEPTH_TEST_ENABLE |
149              depth->test_func << GEN6_ZS_DW2_DEPTH_FUNC__SHIFT;
150    } else {
151       dw2 |= GEN6_COMPAREFUNCTION_ALWAYS << GEN6_ZS_DW2_DEPTH_FUNC__SHIFT;
152    }
153 
154    /* independent from depth->test_enable */
155    if (depth->write_enable)
156       dw2 |= GEN6_ZS_DW2_DEPTH_WRITE_ENABLE;
157 
158    STATIC_ASSERT(ARRAY_SIZE(cc->ds) >= 3);
159    cc->ds[0] = dw0;
160    cc->ds[1] = dw1;
161    cc->ds[2] = dw2;
162 
163    return true;
164 }
165 
166 static bool
cc_set_gen8_3DSTATE_WM_DEPTH_STENCIL(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)167 cc_set_gen8_3DSTATE_WM_DEPTH_STENCIL(struct ilo_state_cc *cc,
168                                      const struct ilo_dev *dev,
169                                      const struct ilo_state_cc_info *info)
170 {
171    const struct ilo_state_cc_stencil_info *stencil = &info->stencil;
172    const struct ilo_state_cc_depth_info *depth = &info->depth;
173    const struct ilo_state_cc_params_info *params = &info->params;
174    uint32_t dw1, dw2;
175 
176    ILO_DEV_ASSERT(dev, 8, 8);
177 
178    if (!cc_validate_gen6_stencil(dev, info) ||
179        !cc_validate_gen6_depth(dev, info))
180       return false;
181 
182    dw1 = 0;
183    dw2 = 0;
184    if (stencil->test_enable) {
185       const struct ilo_state_cc_stencil_op_info *front = &stencil->front;
186       const struct ilo_state_cc_stencil_params_info *front_p =
187          &params->stencil_front;
188       const struct ilo_state_cc_stencil_op_info *back;
189       const struct ilo_state_cc_stencil_params_info *back_p;
190 
191       dw1 |= GEN8_ZS_DW1_STENCIL_TEST_ENABLE;
192 
193       if (stencil->twosided_enable) {
194          dw1 |= GEN8_ZS_DW1_STENCIL1_ENABLE;
195 
196          back = &stencil->back;
197          back_p = &params->stencil_back;
198       } else {
199          back = &stencil->front;
200          back_p = &params->stencil_front;
201       }
202 
203       dw1 |= front->fail_op << GEN8_ZS_DW1_STENCIL_FAIL_OP__SHIFT |
204              front->zfail_op << GEN8_ZS_DW1_STENCIL_ZFAIL_OP__SHIFT |
205              front->zpass_op << GEN8_ZS_DW1_STENCIL_ZPASS_OP__SHIFT |
206              back->test_func << GEN8_ZS_DW1_STENCIL1_FUNC__SHIFT |
207              back->fail_op << GEN8_ZS_DW1_STENCIL1_FAIL_OP__SHIFT |
208              back->zfail_op << GEN8_ZS_DW1_STENCIL1_ZFAIL_OP__SHIFT |
209              back->zpass_op << GEN8_ZS_DW1_STENCIL1_ZPASS_OP__SHIFT |
210              front->test_func << GEN8_ZS_DW1_STENCIL_FUNC__SHIFT;
211 
212       if (front_p->write_mask || back_p->write_mask)
213          dw1 |= GEN8_ZS_DW1_STENCIL_WRITE_ENABLE;
214 
215       dw2 |= front_p->test_mask << GEN8_ZS_DW2_STENCIL_TEST_MASK__SHIFT |
216              front_p->write_mask << GEN8_ZS_DW2_STENCIL_WRITE_MASK__SHIFT |
217              back_p->test_mask << GEN8_ZS_DW2_STENCIL1_TEST_MASK__SHIFT |
218              back_p->write_mask << GEN8_ZS_DW2_STENCIL1_WRITE_MASK__SHIFT;
219    }
220 
221    if (depth->test_enable) {
222       dw1 |= GEN8_ZS_DW1_DEPTH_TEST_ENABLE |
223              depth->test_func << GEN8_ZS_DW1_DEPTH_FUNC__SHIFT;
224    } else {
225       dw1 |= GEN6_COMPAREFUNCTION_ALWAYS << GEN8_ZS_DW1_DEPTH_FUNC__SHIFT;
226    }
227 
228    if (depth->write_enable)
229       dw1 |= GEN8_ZS_DW1_DEPTH_WRITE_ENABLE;
230 
231    STATIC_ASSERT(ARRAY_SIZE(cc->ds) >= 2);
232    cc->ds[0] = dw1;
233    cc->ds[1] = dw2;
234 
235    return true;
236 }
237 
238 static bool
is_dual_source_blend_factor(enum gen_blend_factor factor)239 is_dual_source_blend_factor(enum gen_blend_factor factor)
240 {
241    switch (factor) {
242    case GEN6_BLENDFACTOR_SRC1_COLOR:
243    case GEN6_BLENDFACTOR_SRC1_ALPHA:
244    case GEN6_BLENDFACTOR_INV_SRC1_COLOR:
245    case GEN6_BLENDFACTOR_INV_SRC1_ALPHA:
246       return true;
247    default:
248       return false;
249    }
250 }
251 
252 static bool
cc_get_gen6_dual_source_blending(const struct ilo_dev * dev,const struct ilo_state_cc_info * info)253 cc_get_gen6_dual_source_blending(const struct ilo_dev *dev,
254                                  const struct ilo_state_cc_info *info)
255 {
256    const struct ilo_state_cc_blend_info *blend = &info->blend;
257    bool dual_source_blending;
258    uint8_t i;
259 
260    ILO_DEV_ASSERT(dev, 6, 8);
261 
262    dual_source_blending = (blend->rt_count &&
263          (is_dual_source_blend_factor(blend->rt[0].rgb_src) ||
264           is_dual_source_blend_factor(blend->rt[0].rgb_dst) ||
265           is_dual_source_blend_factor(blend->rt[0].a_src) ||
266           is_dual_source_blend_factor(blend->rt[0].a_dst)));
267 
268    /*
269     * From the Ivy Bridge PRM, volume 2 part 1, page 356:
270     *
271     *     "Dual Source Blending: When using "Dual Source" Render Target
272     *      Write messages, the Source1 pixel color+alpha passed in the
273     *      message can be selected as a src/dst blend factor. See Color
274     *      Buffer Blending.  In single-source mode, those blend factor
275     *      selections are invalid. If SRC1 is included in a src/dst blend
276     *      factor and a DualSource RT Write message is not utilized,
277     *      results are UNDEFINED. (This reflects the same restriction in DX
278     *      APIs, where undefined results are produced if "o1" is not
279     *      written by a PS - there are no default values defined). If SRC1
280     *      is not included in a src/dst blend factor, dual source blending
281     *      must be disabled."
282     *
283     * From the Ivy Bridge PRM, volume 4 part 1, page 356:
284     *
285     *     "The single source message will not cause a write to the render
286     *      target if Dual Source Blend Enable in 3DSTATE_WM is enabled."
287     *
288     *     "The dual source message will revert to a single source message
289     *      using source 0 if Dual Source Blend Enable in 3DSTATE_WM is
290     *      disabled."
291     *
292     * Dual source blending must be enabled or disabled universally.
293     */
294    for (i = 1; i < blend->rt_count; i++) {
295       assert(dual_source_blending ==
296          (is_dual_source_blend_factor(blend->rt[i].rgb_src) ||
297           is_dual_source_blend_factor(blend->rt[i].rgb_dst) ||
298           is_dual_source_blend_factor(blend->rt[i].a_src) ||
299           is_dual_source_blend_factor(blend->rt[i].a_dst)));
300    }
301 
302    return dual_source_blending;
303 }
304 
305 static bool
cc_validate_gen6_alpha(const struct ilo_dev * dev,const struct ilo_state_cc_info * info)306 cc_validate_gen6_alpha(const struct ilo_dev *dev,
307                        const struct ilo_state_cc_info *info)
308 {
309    const struct ilo_state_cc_alpha_info *alpha = &info->alpha;
310 
311    ILO_DEV_ASSERT(dev, 6, 8);
312 
313    /*
314     * From the Sandy Bridge PRM, volume 2 part 1, page 356:
315     *
316     *     "Alpha values from the pixel shader are treated as FLOAT32 format
317     *      for computing the AlphaToCoverage Mask."
318     *
319     * From the Sandy Bridge PRM, volume 2 part 1, page 378:
320     *
321     *     "If set (AlphaToCoverage Enable), Source0 Alpha is converted to a
322     *      temporary 1/2/4-bit coverage mask and the mask bit corresponding to
323     *      the sample# ANDed with the sample mask bit. If set, sample coverage
324     *      is computed based on src0 alpha value. Value of 0 disables all
325     *      samples and value of 1 enables all samples for that pixel. The same
326     *      coverage needs to apply to all the RTs in MRT case. Further, any
327     *      value of src0 alpha between 0 and 1 monotonically increases the
328     *      number of enabled pixels.
329     *
330     *      The same coverage needs to be applied to all the RTs in MRT case."
331     *
332     *     "If set (AlphaToOne Enable), Source0 Alpha is set to 1.0f after
333     *      (possibly) being used to generate the AlphaToCoverage coverage
334     *      mask.
335     *
336     *      The same coverage needs to be applied to all the RTs in MRT case.
337     *
338     *      If Dual Source Blending is enabled, this bit must be disabled."
339     *
340     * From the Sandy Bridge PRM, volume 2 part 1, page 382:
341     *
342     *     "Alpha Test can only be enabled if Pixel Shader outputs a float
343     *      alpha value.
344     *
345     *      Alpha Test is applied independently on each render target by
346     *      comparing that render target's alpha value against the alpha
347     *      reference value. If the alpha test fails, the corresponding pixel
348     *      write will be supressed only for that render target. The
349     *      depth/stencil update will occur if alpha test passes for any render
350     *      target."
351     *
352     * From the Sandy Bridge PRM, volume 4 part 1, page 194:
353     *
354     *     "Multiple render targets are supported with the single source and
355     *      replicate data messages. Each render target is accessed with a
356     *      separate Render Target Write message, each with a different surface
357     *      indicated (different binding table index). The depth buffer is
358     *      written only by the message(s) to the last render target, indicated
359     *      by the Last Render Target Select bit set to clear the pixel
360     *      scoreboard bits."
361     *
362     * When AlphaToCoverage/AlphaToOne/AlphaTest is enabled, it is
363     * required/desirable for the RT write messages to set "Source0 Alpha
364     * Present to RenderTarget" in the MRT case.  It is also required/desirable
365     * for the alpha values to be FLOAT32.
366     */
367    if (alpha->alpha_to_coverage || alpha->alpha_to_one || alpha->test_enable)
368       assert(alpha->cv_float_source0_alpha);
369 
370    /*
371     * From the Sandy Bridge PRM, volume 2 part 1, page 356:
372     *
373     *     "[DevSNB]: When NumSamples = 1, AlphaToCoverage and AlphaTo
374     *      Coverage Dither both must be disabled."
375     */
376    if (ilo_dev_gen(dev) == ILO_GEN(6) && alpha->alpha_to_coverage)
377       assert(alpha->cv_sample_count_one);
378 
379    /*
380     * From the Sandy Bridge PRM, volume 2 part 1, page 378:
381     *
382     *     "If Dual Source Blending is enabled, this bit (AlphaToOne Enable)
383     *      must be disabled."
384     */
385    if (alpha->alpha_to_one)
386       assert(!cc_get_gen6_dual_source_blending(dev, info));
387 
388    return true;
389 }
390 
391 static bool
cc_validate_gen6_blend(const struct ilo_dev * dev,const struct ilo_state_cc_info * info)392 cc_validate_gen6_blend(const struct ilo_dev *dev,
393                        const struct ilo_state_cc_info *info)
394 {
395    const struct ilo_state_cc_blend_info *blend = &info->blend;
396 
397    ILO_DEV_ASSERT(dev, 6, 8);
398 
399    assert(blend->rt_count <= ILO_STATE_CC_BLEND_MAX_RT_COUNT);
400 
401    return true;
402 }
403 
404 static enum gen_blend_factor
get_dst_alpha_one_blend_factor(enum gen_blend_factor factor,bool is_rgb)405 get_dst_alpha_one_blend_factor(enum gen_blend_factor factor, bool is_rgb)
406 {
407    switch (factor) {
408    case GEN6_BLENDFACTOR_DST_ALPHA:
409       return GEN6_BLENDFACTOR_ONE;
410    case GEN6_BLENDFACTOR_INV_DST_ALPHA:
411       return GEN6_BLENDFACTOR_ZERO;
412    case GEN6_BLENDFACTOR_SRC_ALPHA_SATURATE:
413       return (is_rgb) ? GEN6_BLENDFACTOR_ZERO : GEN6_BLENDFACTOR_ONE;
414    default:
415       return factor;
416    }
417 }
418 
419 static void
cc_get_gen6_effective_rt(const struct ilo_dev * dev,const struct ilo_state_cc_info * info,uint8_t rt_index,struct ilo_state_cc_blend_rt_info * dst)420 cc_get_gen6_effective_rt(const struct ilo_dev *dev,
421                          const struct ilo_state_cc_info *info,
422                          uint8_t rt_index,
423                          struct ilo_state_cc_blend_rt_info *dst)
424 {
425    const struct ilo_state_cc_blend_rt_info *rt = &info->blend.rt[rt_index];
426 
427    if (rt->logicop_enable || rt->blend_enable ||
428        rt->argb_write_disables != 0xf)
429       assert(rt->cv_has_buffer);
430 
431    /*
432     * From the Sandy Bridge PRM, volume 2 part 1, page 365:
433     *
434     *     "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB
435     *      variants), otherwise Logic Ops must be DISABLED."
436     *
437     * From the Broadwell PRM, volume 7, page 671:
438     *
439     *     "Logic Ops are supported on all blendable render targets and render
440     *      targets with *INT formats."
441     */
442    if (ilo_dev_gen(dev) < ILO_GEN(8) && rt->logicop_enable)
443       assert(rt->cv_is_unorm);
444 
445    /*
446     * From the Sandy Bridge PRM, volume 2 part 1, page 361:
447     *
448     *     "Only certain surface formats support Color Buffer Blending.  Refer
449     *      to the Surface Format tables in Sampling Engine. Blending must be
450     *      disabled on a RenderTarget if blending is not supported."
451     *
452     * From the Sandy Bridge PRM, volume 2 part 1, page 365:
453     *
454     *     "Color Buffer Blending and Logic Ops must not be enabled
455     *      simultaneously, or behavior is UNDEFINED."
456     */
457    if (rt->blend_enable)
458       assert(!rt->cv_is_integer && !rt->logicop_enable);
459 
460    *dst = *rt;
461    if (rt->blend_enable) {
462       /* 0x0 is reserved in enum gen_blend_factor */
463       assert(rt->rgb_src && rt->rgb_dst && rt->a_src && rt->a_dst);
464 
465       if (rt->force_dst_alpha_one) {
466          dst->rgb_src = get_dst_alpha_one_blend_factor(rt->rgb_src, true);
467          dst->rgb_dst = get_dst_alpha_one_blend_factor(rt->rgb_dst, true);
468          dst->a_src = get_dst_alpha_one_blend_factor(rt->a_src, false);
469          dst->a_dst = get_dst_alpha_one_blend_factor(rt->a_dst, false);
470          dst->force_dst_alpha_one = false;
471       }
472    } else {
473       dst->rgb_src = GEN6_BLENDFACTOR_ONE;
474       dst->rgb_dst = GEN6_BLENDFACTOR_ZERO;
475       dst->rgb_func = GEN6_BLENDFUNCTION_ADD;
476       dst->a_src = dst->rgb_src;
477       dst->a_dst = dst->rgb_dst;
478       dst->a_func = dst->rgb_func;
479    }
480 }
481 
482 static bool
cc_set_gen6_BLEND_STATE(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)483 cc_set_gen6_BLEND_STATE(struct ilo_state_cc *cc,
484                         const struct ilo_dev *dev,
485                         const struct ilo_state_cc_info *info)
486 {
487    const struct ilo_state_cc_alpha_info *alpha = &info->alpha;
488    const struct ilo_state_cc_blend_info *blend = &info->blend;
489    uint32_t dw_rt[2 * ILO_STATE_CC_BLEND_MAX_RT_COUNT], dw1_invariant;
490    uint32_t dw0, dw1;
491    uint8_t i;
492 
493    ILO_DEV_ASSERT(dev, 6, 7.5);
494 
495    if (!cc_validate_gen6_alpha(dev, info) ||
496        !cc_validate_gen6_blend(dev, info))
497       return false;
498 
499    /*
500     * According to the Sandy Bridge PRM, volume 2 part 1, page 360, pre-blend
501     * and post-blend color clamps must be enabled in most cases.  For the
502     * other cases, they are either desirable or ignored.  We can enable them
503     * unconditionally.
504     */
505    dw1 = GEN6_RT_DW1_COLORCLAMP_RTFORMAT |
506          GEN6_RT_DW1_PRE_BLEND_CLAMP |
507          GEN6_RT_DW1_POST_BLEND_CLAMP;
508 
509    if (alpha->alpha_to_coverage) {
510       dw1 |= GEN6_RT_DW1_ALPHA_TO_COVERAGE;
511 
512       /*
513        * From the Sandy Bridge PRM, volume 2 part 1, page 379:
514        *
515        *     "[DevSNB]: This bit (AlphaToCoverage Dither Enable) must be
516        *      disabled."
517        */
518       if (ilo_dev_gen(dev) >= ILO_GEN(7))
519          dw1 |= GEN6_RT_DW1_ALPHA_TO_COVERAGE_DITHER;
520    }
521 
522    if (alpha->alpha_to_one)
523       dw1 |= GEN6_RT_DW1_ALPHA_TO_ONE;
524 
525    if (alpha->test_enable) {
526       dw1 |= GEN6_RT_DW1_ALPHA_TEST_ENABLE |
527              alpha->test_func << GEN6_RT_DW1_ALPHA_TEST_FUNC__SHIFT;
528    } else {
529       /*
530        * From the Ivy Bridge PRM, volume 2 part 1, page 371:
531        *
532        *     "When Alpha Test is disabled, Alpha Test Function must be
533        *      COMPAREFUNCTION_ALWAYS."
534        */
535       dw1 |= GEN6_COMPAREFUNCTION_ALWAYS <<
536          GEN6_RT_DW1_ALPHA_TEST_FUNC__SHIFT;
537    }
538 
539    if (blend->dither_enable)
540       dw1 |= GEN6_RT_DW1_DITHER_ENABLE;
541 
542    dw1_invariant = dw1;
543 
544    for (i = 0; i < blend->rt_count; i++) {
545       struct ilo_state_cc_blend_rt_info rt;
546 
547       cc_get_gen6_effective_rt(dev, info, i, &rt);
548 
549       /* 0x0 is reserved for blend factors and we have to set them all */
550       dw0 = rt.a_func << GEN6_RT_DW0_ALPHA_FUNC__SHIFT |
551             rt.a_src << GEN6_RT_DW0_SRC_ALPHA_FACTOR__SHIFT |
552             rt.a_dst << GEN6_RT_DW0_DST_ALPHA_FACTOR__SHIFT |
553             rt.rgb_func << GEN6_RT_DW0_COLOR_FUNC__SHIFT |
554             rt.rgb_src << GEN6_RT_DW0_SRC_COLOR_FACTOR__SHIFT |
555             rt.rgb_dst << GEN6_RT_DW0_DST_COLOR_FACTOR__SHIFT;
556 
557       if (rt.blend_enable) {
558          dw0 |= GEN6_RT_DW0_BLEND_ENABLE;
559 
560          if (rt.a_src != rt.rgb_src ||
561              rt.a_dst != rt.rgb_dst ||
562              rt.a_func != rt.rgb_func)
563             dw0 |= GEN6_RT_DW0_INDEPENDENT_ALPHA_ENABLE;
564       }
565 
566       dw1 = dw1_invariant |
567             rt.argb_write_disables << GEN6_RT_DW1_WRITE_DISABLES__SHIFT;
568 
569       if (rt.logicop_enable) {
570          dw1 |= GEN6_RT_DW1_LOGICOP_ENABLE |
571                 rt.logicop_func << GEN6_RT_DW1_LOGICOP_FUNC__SHIFT;
572       }
573 
574       dw_rt[2 * i + 0] = dw0;
575       dw_rt[2 * i + 1] = dw1;
576    }
577 
578 
579    STATIC_ASSERT(ARRAY_SIZE(cc->blend) >= ARRAY_SIZE(dw_rt));
580    memcpy(&cc->blend[0], dw_rt, sizeof(uint32_t) * 2 * blend->rt_count);
581    cc->blend_state_count = info->blend.rt_count;
582 
583    return true;
584 }
585 
586 static bool
cc_set_gen8_BLEND_STATE(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)587 cc_set_gen8_BLEND_STATE(struct ilo_state_cc *cc,
588                         const struct ilo_dev *dev,
589                         const struct ilo_state_cc_info *info)
590 {
591    const struct ilo_state_cc_alpha_info *alpha = &info->alpha;
592    const struct ilo_state_cc_blend_info *blend = &info->blend;
593    uint32_t dw_rt[2 * ILO_STATE_CC_BLEND_MAX_RT_COUNT], dw0, dw1;
594    bool indep_alpha_enable;
595    uint8_t i;
596 
597    ILO_DEV_ASSERT(dev, 8, 8);
598 
599    if (!cc_validate_gen6_alpha(dev, info) ||
600        !cc_validate_gen6_blend(dev, info))
601       return false;
602 
603    indep_alpha_enable = false;
604    for (i = 0; i < blend->rt_count; i++) {
605       struct ilo_state_cc_blend_rt_info rt;
606 
607       cc_get_gen6_effective_rt(dev, info, i, &rt);
608 
609       dw0 = rt.rgb_src << GEN8_RT_DW0_SRC_COLOR_FACTOR__SHIFT |
610             rt.rgb_dst << GEN8_RT_DW0_DST_COLOR_FACTOR__SHIFT |
611             rt.rgb_func << GEN8_RT_DW0_COLOR_FUNC__SHIFT |
612             rt.a_src << GEN8_RT_DW0_SRC_ALPHA_FACTOR__SHIFT |
613             rt.a_dst << GEN8_RT_DW0_DST_ALPHA_FACTOR__SHIFT |
614             rt.a_func << GEN8_RT_DW0_ALPHA_FUNC__SHIFT |
615             rt.argb_write_disables << GEN8_RT_DW0_WRITE_DISABLES__SHIFT;
616 
617       if (rt.blend_enable) {
618          dw0 |= GEN8_RT_DW0_BLEND_ENABLE;
619 
620          if (rt.a_src != rt.rgb_src ||
621              rt.a_dst != rt.rgb_dst ||
622              rt.a_func != rt.rgb_func)
623             indep_alpha_enable = true;
624       }
625 
626       dw1 = GEN8_RT_DW1_COLORCLAMP_RTFORMAT |
627             GEN8_RT_DW1_PRE_BLEND_CLAMP |
628             GEN8_RT_DW1_POST_BLEND_CLAMP;
629 
630       if (rt.logicop_enable) {
631          dw1 |= GEN8_RT_DW1_LOGICOP_ENABLE |
632                 rt.logicop_func << GEN8_RT_DW1_LOGICOP_FUNC__SHIFT;
633       }
634 
635       dw_rt[2 * i + 0] = dw0;
636       dw_rt[2 * i + 1] = dw1;
637    }
638 
639    dw0 = 0;
640 
641    if (alpha->alpha_to_coverage) {
642       dw0 |= GEN8_BLEND_DW0_ALPHA_TO_COVERAGE |
643              GEN8_BLEND_DW0_ALPHA_TO_COVERAGE_DITHER;
644    }
645 
646    if (indep_alpha_enable)
647       dw0 |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE;
648 
649    if (alpha->alpha_to_one)
650       dw0 |= GEN8_BLEND_DW0_ALPHA_TO_ONE;
651 
652    if (alpha->test_enable) {
653       dw0 |= GEN8_BLEND_DW0_ALPHA_TEST_ENABLE |
654              alpha->test_func << GEN8_BLEND_DW0_ALPHA_TEST_FUNC__SHIFT;
655    } else {
656       dw0 |= GEN6_COMPAREFUNCTION_ALWAYS <<
657          GEN8_BLEND_DW0_ALPHA_TEST_FUNC__SHIFT;
658    }
659 
660    if (blend->dither_enable)
661       dw0 |= GEN8_BLEND_DW0_DITHER_ENABLE;
662 
663    STATIC_ASSERT(ARRAY_SIZE(cc->blend) >= 2 + ARRAY_SIZE(dw_rt));
664    cc->blend[1] = dw0;
665    memcpy(&cc->blend[2], dw_rt, sizeof(uint32_t) * 2 * blend->rt_count);
666    cc->blend_state_count = info->blend.rt_count;
667 
668    return true;
669 }
670 
671 static bool
cc_set_gen8_3DSTATE_PS_BLEND(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)672 cc_set_gen8_3DSTATE_PS_BLEND(struct ilo_state_cc *cc,
673                              const struct ilo_dev *dev,
674                              const struct ilo_state_cc_info *info)
675 {
676    const struct ilo_state_cc_alpha_info *alpha = &info->alpha;
677    const struct ilo_state_cc_blend_info *blend = &info->blend;
678    uint32_t dw1;
679 
680    ILO_DEV_ASSERT(dev, 8, 8);
681 
682    dw1 = 0;
683 
684    if (alpha->alpha_to_coverage)
685       dw1 |= GEN8_PS_BLEND_DW1_ALPHA_TO_COVERAGE;
686 
687    if (alpha->test_enable)
688       dw1 |= GEN8_PS_BLEND_DW1_ALPHA_TEST_ENABLE;
689 
690    if (blend->rt_count) {
691       struct ilo_state_cc_blend_rt_info rt0;
692       uint8_t i;
693 
694       cc_get_gen6_effective_rt(dev, info, 0, &rt0);
695 
696       /* 0x0 is reserved for blend factors and we have to set them all */
697       dw1 |= rt0.a_src << GEN8_PS_BLEND_DW1_RT0_SRC_ALPHA_FACTOR__SHIFT |
698              rt0.a_dst << GEN8_PS_BLEND_DW1_RT0_DST_ALPHA_FACTOR__SHIFT |
699              rt0.rgb_src << GEN8_PS_BLEND_DW1_RT0_SRC_COLOR_FACTOR__SHIFT |
700              rt0.rgb_dst << GEN8_PS_BLEND_DW1_RT0_DST_COLOR_FACTOR__SHIFT;
701 
702       for (i = 0; i < blend->rt_count; i++) {
703          if (blend->rt[i].argb_write_disables != 0xf) {
704             dw1 |= GEN8_PS_BLEND_DW1_WRITABLE_RT;
705             break;
706          }
707       }
708 
709       if (rt0.blend_enable) {
710          dw1 |= GEN8_PS_BLEND_DW1_RT0_BLEND_ENABLE;
711 
712          if (rt0.a_src != rt0.rgb_src || rt0.a_dst != rt0.rgb_dst)
713             dw1 |= GEN8_PS_BLEND_DW1_RT0_INDEPENDENT_ALPHA_ENABLE;
714       }
715    }
716 
717    STATIC_ASSERT(ARRAY_SIZE(cc->blend) >= 1);
718    cc->blend[0] = dw1;
719 
720    return true;
721 }
722 
723 static bool
cc_params_set_gen6_COLOR_CALC_STATE(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_params_info * params)724 cc_params_set_gen6_COLOR_CALC_STATE(struct ilo_state_cc *cc,
725                                     const struct ilo_dev *dev,
726                                     const struct ilo_state_cc_params_info *params)
727 {
728    uint32_t dw0;
729 
730    ILO_DEV_ASSERT(dev, 6, 8);
731 
732    dw0 = params->stencil_front.test_ref << GEN6_CC_DW0_STENCIL_REF__SHIFT |
733          params->stencil_back.test_ref << GEN6_CC_DW0_STENCIL1_REF__SHIFT |
734          GEN6_CC_DW0_ALPHATEST_FLOAT32;
735 
736    STATIC_ASSERT(ARRAY_SIZE(cc->cc) >= 6);
737    cc->cc[0] = dw0;
738    cc->cc[1] = fui(params->alpha_ref);
739    cc->cc[2] = fui(params->blend_rgba[0]);
740    cc->cc[3] = fui(params->blend_rgba[1]);
741    cc->cc[4] = fui(params->blend_rgba[2]);
742    cc->cc[5] = fui(params->blend_rgba[3]);
743 
744    return true;
745 }
746 
747 bool
ilo_state_cc_init(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)748 ilo_state_cc_init(struct ilo_state_cc *cc,
749                   const struct ilo_dev *dev,
750                   const struct ilo_state_cc_info *info)
751 {
752    assert(ilo_is_zeroed(cc, sizeof(*cc)));
753    return ilo_state_cc_set_info(cc, dev, info);
754 }
755 
756 bool
ilo_state_cc_set_info(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_info * info)757 ilo_state_cc_set_info(struct ilo_state_cc *cc,
758                       const struct ilo_dev *dev,
759                       const struct ilo_state_cc_info *info)
760 {
761    bool ret = true;
762 
763    if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
764       ret &= cc_set_gen8_3DSTATE_WM_DEPTH_STENCIL(cc, dev, info);
765       ret &= cc_set_gen8_BLEND_STATE(cc, dev, info);
766       ret &= cc_set_gen8_3DSTATE_PS_BLEND(cc, dev, info);
767    } else {
768       ret &= cc_set_gen6_DEPTH_STENCIL_STATE(cc, dev, info);
769       ret &= cc_set_gen6_BLEND_STATE(cc, dev, info);
770    }
771 
772    ret &= cc_params_set_gen6_COLOR_CALC_STATE(cc, dev, &info->params);
773 
774    assert(ret);
775 
776    return ret;
777 }
778 
779 bool
ilo_state_cc_set_params(struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc_params_info * params)780 ilo_state_cc_set_params(struct ilo_state_cc *cc,
781                         const struct ilo_dev *dev,
782                         const struct ilo_state_cc_params_info *params)
783 {
784    /* modify stencil masks */
785    if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
786       uint32_t dw1 = cc->ds[0];
787       uint32_t dw2 = cc->ds[1];
788 
789       if (dw1 & GEN8_ZS_DW1_STENCIL_TEST_ENABLE) {
790          const bool twosided_enable = (dw1 & GEN8_ZS_DW1_STENCIL1_ENABLE);
791          const struct ilo_state_cc_stencil_params_info *front_p =
792             &params->stencil_front;
793          const struct ilo_state_cc_stencil_params_info *back_p =
794             (twosided_enable) ? &params->stencil_back :
795                                 &params->stencil_front;
796 
797          if (front_p->write_mask || back_p->write_mask)
798             dw1 |= GEN8_ZS_DW1_STENCIL_WRITE_ENABLE;
799          else
800             dw1 &= ~GEN8_ZS_DW1_STENCIL_WRITE_ENABLE;
801 
802          dw2 =
803             front_p->test_mask << GEN8_ZS_DW2_STENCIL_TEST_MASK__SHIFT |
804             front_p->write_mask << GEN8_ZS_DW2_STENCIL_WRITE_MASK__SHIFT |
805             back_p->test_mask << GEN8_ZS_DW2_STENCIL1_TEST_MASK__SHIFT |
806             back_p->write_mask << GEN8_ZS_DW2_STENCIL1_WRITE_MASK__SHIFT;
807       }
808 
809       cc->ds[0] = dw1;
810       cc->ds[1] = dw2;
811    } else {
812       uint32_t dw0 = cc->ds[0];
813       uint32_t dw1 = cc->ds[1];
814 
815       if (dw0 & GEN6_ZS_DW0_STENCIL_TEST_ENABLE) {
816          const bool twosided_enable = (dw0 & GEN6_ZS_DW0_STENCIL1_ENABLE);
817          const struct ilo_state_cc_stencil_params_info *front_p =
818             &params->stencil_front;
819          const struct ilo_state_cc_stencil_params_info *back_p =
820             (twosided_enable) ? &params->stencil_back :
821                                 &params->stencil_front;
822 
823          if (front_p->write_mask || back_p->write_mask)
824             dw0 |= GEN6_ZS_DW0_STENCIL_WRITE_ENABLE;
825          else
826             dw0 &= ~GEN6_ZS_DW0_STENCIL_WRITE_ENABLE;
827 
828          dw1 =
829             front_p->test_mask << GEN6_ZS_DW1_STENCIL_TEST_MASK__SHIFT |
830             front_p->write_mask << GEN6_ZS_DW1_STENCIL_WRITE_MASK__SHIFT |
831             back_p->test_mask << GEN6_ZS_DW1_STENCIL1_TEST_MASK__SHIFT |
832             back_p->write_mask << GEN6_ZS_DW1_STENCIL1_WRITE_MASK__SHIFT;
833       }
834 
835       cc->ds[0] = dw0;
836       cc->ds[1] = dw1;
837    }
838 
839    /* modify COLOR_CALC_STATE */
840    cc_params_set_gen6_COLOR_CALC_STATE(cc, dev, params);
841 
842    return true;
843 }
844 
845 void
ilo_state_cc_full_delta(const struct ilo_state_cc * cc,const struct ilo_dev * dev,struct ilo_state_cc_delta * delta)846 ilo_state_cc_full_delta(const struct ilo_state_cc *cc,
847                         const struct ilo_dev *dev,
848                         struct ilo_state_cc_delta *delta)
849 {
850    delta->dirty = ILO_STATE_CC_BLEND_STATE |
851                   ILO_STATE_CC_COLOR_CALC_STATE;
852 
853    if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
854       delta->dirty |= ILO_STATE_CC_3DSTATE_WM_DEPTH_STENCIL |
855                       ILO_STATE_CC_3DSTATE_PS_BLEND;
856    } else {
857       delta->dirty |= ILO_STATE_CC_DEPTH_STENCIL_STATE;
858    }
859 }
860 
861 void
ilo_state_cc_get_delta(const struct ilo_state_cc * cc,const struct ilo_dev * dev,const struct ilo_state_cc * old,struct ilo_state_cc_delta * delta)862 ilo_state_cc_get_delta(const struct ilo_state_cc *cc,
863                        const struct ilo_dev *dev,
864                        const struct ilo_state_cc *old,
865                        struct ilo_state_cc_delta *delta)
866 {
867    delta->dirty = 0;
868 
869    if (memcmp(cc->ds, old->ds, sizeof(cc->ds))) {
870       if (ilo_dev_gen(dev) >= ILO_GEN(8))
871          delta->dirty |= ILO_STATE_CC_3DSTATE_WM_DEPTH_STENCIL;
872       else
873          delta->dirty |= ILO_STATE_CC_DEPTH_STENCIL_STATE;
874    }
875 
876    if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
877       if (cc->blend[0] != old->blend[0])
878          delta->dirty |= ILO_STATE_CC_3DSTATE_PS_BLEND;
879 
880       if (memcmp(&cc->blend[1], &old->blend[1],
881                sizeof(uint32_t) * (1 + 2 * cc->blend_state_count)))
882          delta->dirty |= ILO_STATE_CC_BLEND_STATE;
883    } else if (memcmp(cc->blend, old->blend,
884             sizeof(uint32_t) * 2 * cc->blend_state_count)) {
885       delta->dirty |= ILO_STATE_CC_BLEND_STATE;
886    }
887 
888    if (memcmp(cc->cc, old->cc, sizeof(cc->cc)))
889       delta->dirty |= ILO_STATE_CC_COLOR_CALC_STATE;
890 }
891