1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2019 Collabora, Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "pan_device.h"
25bf215546Sopenharmony_ci#include "pan_bo.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci/* Sample positions are specified partially in hardware, partially in software
28bf215546Sopenharmony_ci * on Mali. On Midgard, sample positions are completely fixed but need to be
29bf215546Sopenharmony_ci * software accessible to implement gl_SamplePosition. On Bifrost, sample
30bf215546Sopenharmony_ci * positions are part fixed, part programmable, and again need to be accessible
31bf215546Sopenharmony_ci * for gl_SamplePosition. The mali_sample_position data structure is
32bf215546Sopenharmony_ci * hardware-defined on Bifrost as a packed 8:8 fixed point format. The
33bf215546Sopenharmony_ci * mali_sample_positions array is part-hardware, part-software-defined: it must
34bf215546Sopenharmony_ci * give the sample position when indexed by the sample index, as well as
35bf215546Sopenharmony_ci * reading back the origin when indexed by 32.
36bf215546Sopenharmony_ci *
37bf215546Sopenharmony_ci * The upshot is all of this is known at compile-time, so we can just hardcode
38bf215546Sopenharmony_ci * the LUT, upload it to GPU memory on device initialization, and forget about
39bf215546Sopenharmony_ci * it.
40bf215546Sopenharmony_ci */
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistruct mali_sample_position {
43bf215546Sopenharmony_ci        uint16_t x, y;
44bf215546Sopenharmony_ci} __attribute__((packed));
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistruct mali_sample_positions {
47bf215546Sopenharmony_ci        struct mali_sample_position positions[32];
48bf215546Sopenharmony_ci        struct mali_sample_position origin;
49bf215546Sopenharmony_ci        struct mali_sample_position padding[64 - (32 + 1)];
50bf215546Sopenharmony_ci} __attribute__((packed));
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci/* SAMPLE16 constructs a single sample in terms of 1/16's of the grid, centered
53bf215546Sopenharmony_ci * at the origin. SAMPLE4/8 swap the units for legibility. */
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci#define SAMPLE16(x, y) { \
56bf215546Sopenharmony_ci        (((x) + 8) * (256 / 16)), \
57bf215546Sopenharmony_ci        (((y) + 8) * (256 / 16)) \
58bf215546Sopenharmony_ci}
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci#define SAMPLE8(x, y) SAMPLE16((x) * 2, (y) * 2)
61bf215546Sopenharmony_ci#define SAMPLE4(x, y) SAMPLE16((x) * 4, (y) * 4)
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ciconst struct mali_sample_positions sample_position_lut[] = {
64bf215546Sopenharmony_ci        [MALI_SAMPLE_PATTERN_SINGLE_SAMPLED] = {
65bf215546Sopenharmony_ci                .positions = {
66bf215546Sopenharmony_ci                        SAMPLE4(0, 0)
67bf215546Sopenharmony_ci                },
68bf215546Sopenharmony_ci                .origin = SAMPLE4(0, 0)
69bf215546Sopenharmony_ci        },
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci        [MALI_SAMPLE_PATTERN_ORDERED_4X_GRID] = {
72bf215546Sopenharmony_ci                .positions = {
73bf215546Sopenharmony_ci                        SAMPLE4(-1, -1),
74bf215546Sopenharmony_ci                        SAMPLE4( 1, -1),
75bf215546Sopenharmony_ci                        SAMPLE4(-1,  1),
76bf215546Sopenharmony_ci                        SAMPLE4( 1,  1),
77bf215546Sopenharmony_ci                },
78bf215546Sopenharmony_ci                .origin = SAMPLE4(0, 0)
79bf215546Sopenharmony_ci        },
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci        [MALI_SAMPLE_PATTERN_ROTATED_4X_GRID] = {
82bf215546Sopenharmony_ci                .positions = {
83bf215546Sopenharmony_ci                        SAMPLE8(-1, -3),
84bf215546Sopenharmony_ci                        SAMPLE8( 3, -1),
85bf215546Sopenharmony_ci                        SAMPLE8(-3,  1),
86bf215546Sopenharmony_ci                        SAMPLE8( 1,  3),
87bf215546Sopenharmony_ci                },
88bf215546Sopenharmony_ci                .origin = SAMPLE8(0, 0)
89bf215546Sopenharmony_ci        },
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci        [MALI_SAMPLE_PATTERN_D3D_8X_GRID] = {
92bf215546Sopenharmony_ci                .positions = {
93bf215546Sopenharmony_ci                        SAMPLE16( 1, -3),
94bf215546Sopenharmony_ci                        SAMPLE16(-1,  3),
95bf215546Sopenharmony_ci                        SAMPLE16( 5,  1),
96bf215546Sopenharmony_ci                        SAMPLE16(-3, -5),
97bf215546Sopenharmony_ci                        SAMPLE16(-5,  5),
98bf215546Sopenharmony_ci                        SAMPLE16(-7, -1),
99bf215546Sopenharmony_ci                        SAMPLE16( 3,  7),
100bf215546Sopenharmony_ci                        SAMPLE16( 7,  -7),
101bf215546Sopenharmony_ci                },
102bf215546Sopenharmony_ci                .origin = SAMPLE16(0, 0)
103bf215546Sopenharmony_ci        },
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci        [MALI_SAMPLE_PATTERN_D3D_16X_GRID] = {
106bf215546Sopenharmony_ci                .positions = {
107bf215546Sopenharmony_ci                        SAMPLE16( 1,  1),
108bf215546Sopenharmony_ci                        SAMPLE16(-1, -3),
109bf215546Sopenharmony_ci                        SAMPLE16(-3,  2),
110bf215546Sopenharmony_ci                        SAMPLE16( 4, -1),
111bf215546Sopenharmony_ci                        SAMPLE16(-5, -2),
112bf215546Sopenharmony_ci                        SAMPLE16( 2,  5),
113bf215546Sopenharmony_ci                        SAMPLE16( 5,  3),
114bf215546Sopenharmony_ci                        SAMPLE16( 3, -5),
115bf215546Sopenharmony_ci                        SAMPLE16(-2,  6),
116bf215546Sopenharmony_ci                        SAMPLE16( 0,  7),
117bf215546Sopenharmony_ci                        SAMPLE16(-4, -6),
118bf215546Sopenharmony_ci                        SAMPLE16(-6,  4),
119bf215546Sopenharmony_ci                        SAMPLE16(-8,  0),
120bf215546Sopenharmony_ci                        SAMPLE16( 7, -4),
121bf215546Sopenharmony_ci                        SAMPLE16( 6,  7),
122bf215546Sopenharmony_ci                        SAMPLE16(-7, -8),
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci                },
125bf215546Sopenharmony_ci                .origin = SAMPLE16(0, 0)
126bf215546Sopenharmony_ci        }
127bf215546Sopenharmony_ci};
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_cimali_ptr
130bf215546Sopenharmony_cipanfrost_sample_positions(const struct panfrost_device *dev,
131bf215546Sopenharmony_ci                enum mali_sample_pattern pattern)
132bf215546Sopenharmony_ci{
133bf215546Sopenharmony_ci        assert(pattern < ARRAY_SIZE(sample_position_lut));
134bf215546Sopenharmony_ci        unsigned offset = (pattern * sizeof(sample_position_lut[0]));
135bf215546Sopenharmony_ci        return dev->sample_positions->ptr.gpu + offset;
136bf215546Sopenharmony_ci}
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_civoid
139bf215546Sopenharmony_cipanfrost_upload_sample_positions(struct panfrost_device *dev)
140bf215546Sopenharmony_ci{
141bf215546Sopenharmony_ci        STATIC_ASSERT(sizeof(sample_position_lut) < 4096);
142bf215546Sopenharmony_ci        dev->sample_positions = panfrost_bo_create(dev, 4096, 0, "Sample positions");
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci        memcpy(dev->sample_positions->ptr.cpu, sample_position_lut,
145bf215546Sopenharmony_ci                        sizeof(sample_position_lut));
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci/* CPU side LUT query, to implement glGetMultisamplefv */
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_civoid
151bf215546Sopenharmony_cipanfrost_query_sample_position(
152bf215546Sopenharmony_ci                enum mali_sample_pattern pattern,
153bf215546Sopenharmony_ci                unsigned sample_idx,
154bf215546Sopenharmony_ci                float *out)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci        struct mali_sample_position pos =
157bf215546Sopenharmony_ci                sample_position_lut[pattern].positions[sample_idx];
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci        out[0] = DECODE_FIXED_16(pos.x);
160bf215546Sopenharmony_ci        out[1] = DECODE_FIXED_16(pos.y);
161bf215546Sopenharmony_ci}
162