1 /*
2  * Copyright © 2012 Intel Corporation
3  *
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:
10  *
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
13  * Software.
14  *
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
21  * IN THE SOFTWARE.
22  */
23 
24 #include "intel_batchbuffer.h"
25 
26 #include "brw_context.h"
27 #include "brw_defines.h"
28 
29 
30 /**
31  * 3DSTATE_MULTISAMPLE
32  */
33 void
gen6_emit_3dstate_multisample(struct brw_context * brw,unsigned num_samples)34 gen6_emit_3dstate_multisample(struct brw_context *brw,
35                               unsigned num_samples)
36 {
37    struct intel_context *intel = &brw->intel;
38 
39    uint32_t number_of_multisamples = 0;
40    uint32_t sample_positions_3210 = 0;
41    uint32_t sample_positions_7654 = 0;
42 
43    switch (num_samples) {
44    case 0:
45    case 1:
46       number_of_multisamples = MS_NUMSAMPLES_1;
47       break;
48    case 4:
49       number_of_multisamples = MS_NUMSAMPLES_4;
50       /* Sample positions:
51        *   2 6 a e
52        * 2   0
53        * 6       1
54        * a 2
55        * e     3
56        */
57       sample_positions_3210 = 0xae2ae662;
58       break;
59    case 8:
60       number_of_multisamples = MS_NUMSAMPLES_8;
61       /* Sample positions are based on a solution to the "8 queens" puzzle.
62        * Rationale: in a solution to the 8 queens puzzle, no two queens share
63        * a row, column, or diagonal.  This is a desirable property for samples
64        * in a multisampling pattern, because it ensures that the samples are
65        * relatively uniformly distributed through the pixel.
66        *
67        * There are several solutions to the 8 queens puzzle (see
68        * http://en.wikipedia.org/wiki/Eight_queens_puzzle).  This solution was
69        * chosen because it has a queen close to the center; this should
70        * improve the accuracy of centroid interpolation, since the hardware
71        * implements centroid interpolation by choosing the centermost sample
72        * that overlaps with the primitive being drawn.
73        *
74        * Note: from the Ivy Bridge PRM, Vol2 Part1 p304 (3DSTATE_MULTISAMPLE:
75        * Programming Notes):
76        *
77        *     "When programming the sample offsets (for NUMSAMPLES_4 or _8 and
78        *     MSRASTMODE_xxx_PATTERN), the order of the samples 0 to 3 (or 7
79        *     for 8X) must have monotonically increasing distance from the
80        *     pixel center. This is required to get the correct centroid
81        *     computation in the device."
82        *
83        * Sample positions:
84        *   1 3 5 7 9 b d f
85        * 1     5
86        * 3           2
87        * 5               6
88        * 7 4
89        * 9       0
90        * b             3
91        * d         1
92        * f   7
93        */
94       sample_positions_3210 = 0xdbb39d79;
95       sample_positions_7654 = 0x3ff55117;
96       break;
97    default:
98       assert(!"Unrecognized num_samples in gen6_emit_3dstate_multisample");
99       break;
100    }
101 
102    int len = intel->gen >= 7 ? 4 : 3;
103    BEGIN_BATCH(len);
104    OUT_BATCH(_3DSTATE_MULTISAMPLE << 16 | (len - 2));
105    OUT_BATCH(MS_PIXEL_LOCATION_CENTER | number_of_multisamples);
106    OUT_BATCH(sample_positions_3210);
107    if (intel->gen >= 7)
108       OUT_BATCH(sample_positions_7654);
109    ADVANCE_BATCH();
110 }
111 
112 
113 /**
114  * 3DSTATE_SAMPLE_MASK
115  */
116 void
gen6_emit_3dstate_sample_mask(struct brw_context * brw,unsigned num_samples,float coverage,bool coverage_invert)117 gen6_emit_3dstate_sample_mask(struct brw_context *brw,
118                               unsigned num_samples, float coverage,
119                               bool coverage_invert)
120 {
121    struct intel_context *intel = &brw->intel;
122 
123    BEGIN_BATCH(2);
124    OUT_BATCH(_3DSTATE_SAMPLE_MASK << 16 | (2 - 2));
125    if (num_samples > 1) {
126       int coverage_int = (int) (num_samples * coverage + 0.5);
127       uint32_t coverage_bits = (1 << coverage_int) - 1;
128       if (coverage_invert)
129          coverage_bits ^= (1 << num_samples) - 1;
130       OUT_BATCH(coverage_bits);
131    } else {
132       OUT_BATCH(1);
133    }
134    ADVANCE_BATCH();
135 }
136 
137 
upload_multisample_state(struct brw_context * brw)138 static void upload_multisample_state(struct brw_context *brw)
139 {
140    struct intel_context *intel = &brw->intel;
141    struct gl_context *ctx = &intel->ctx;
142    float coverage = 1.0;
143    float coverage_invert = false;
144 
145    /* _NEW_BUFFERS */
146    unsigned num_samples = ctx->DrawBuffer->Visual.samples;
147 
148    /* _NEW_MULTISAMPLE */
149    if (ctx->Multisample._Enabled && ctx->Multisample.SampleCoverage) {
150       coverage = ctx->Multisample.SampleCoverageValue;
151       coverage_invert = ctx->Multisample.SampleCoverageInvert;
152    }
153 
154    /* 3DSTATE_MULTISAMPLE is nonpipelined. */
155    intel_emit_post_sync_nonzero_flush(intel);
156 
157    gen6_emit_3dstate_multisample(brw, num_samples);
158    gen6_emit_3dstate_sample_mask(brw, num_samples, coverage, coverage_invert);
159 }
160 
161 
162 const struct brw_tracked_state gen6_multisample_state = {
163    .dirty = {
164       .mesa = _NEW_BUFFERS |
165               _NEW_MULTISAMPLE,
166       .brw = BRW_NEW_CONTEXT,
167       .cache = 0
168    },
169    .emit = upload_multisample_state
170 };
171