Home | History | Annotate | Line # | Download | only in lib
      1 /*
      2  * Copyright (C) 2019 Collabora, Ltd.
      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 FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  */
     23 
     24 #include "pan_device.h"
     25 #include "pan_bo.h"
     26 
     27 /* Sample positions are specified partially in hardware, partially in software
     28  * on Mali. On Midgard, sample positions are completely fixed but need to be
     29  * software accessible to implement gl_SamplePosition. On Bifrost, sample
     30  * positions are part fixed, part programmable, and again need to be accessible
     31  * for gl_SamplePosition. The mali_sample_position data structure is
     32  * hardware-defined on Bifrost as a packed 8:8 fixed point format. The
     33  * mali_sample_positions array is part-hardware, part-software-defined: it must
     34  * give the sample position when indexed by the sample index, as well as
     35  * reading back the origin when indexed by 32.
     36  *
     37  * The upshot is all of this is known at compile-time, so we can just hardcode
     38  * the LUT, upload it to GPU memory on device initialization, and forget about
     39  * it.
     40  */
     41 
     42 struct mali_sample_position {
     43         uint16_t x, y;
     44 } __attribute__((packed));
     45 
     46 struct mali_sample_positions {
     47         struct mali_sample_position positions[32];
     48         struct mali_sample_position origin;
     49         struct mali_sample_position padding[64 - (32 + 1)];
     50 } __attribute__((packed));
     51 
     52 /* SAMPLE16 constructs a single sample in terms of 1/16's of the grid, centered
     53  * at the origin. SAMPLE4/8 swap the units for legibility. */
     54 
     55 #define SAMPLE16(x, y) { \
     56         (((x) + 8) * (256 / 16)), \
     57         (((y) + 8) * (256 / 16)) \
     58 }
     59 
     60 #define SAMPLE8(x, y) SAMPLE16((x) * 2, (y) * 2)
     61 #define SAMPLE4(x, y) SAMPLE16((x) * 4, (y) * 4)
     62 
     63 const struct mali_sample_positions sample_position_lut[] = {
     64         [MALI_SAMPLE_PATTERN_SINGLE_SAMPLED] = {
     65                 .positions = {
     66                         SAMPLE4(0, 0)
     67                 },
     68                 .origin = SAMPLE4(0, 0)
     69         },
     70 
     71         [MALI_SAMPLE_PATTERN_ORDERED_4X_GRID] = {
     72                 .positions = {
     73                         SAMPLE4(-1, -1),
     74                         SAMPLE4( 1, -1),
     75                         SAMPLE4(-1,  1),
     76                         SAMPLE4( 1,  1),
     77                 },
     78                 .origin = SAMPLE4(0, 0)
     79         },
     80 
     81         [MALI_SAMPLE_PATTERN_ROTATED_4X_GRID] = {
     82                 .positions = {
     83                         SAMPLE8(-1, -3),
     84                         SAMPLE8( 3, -1),
     85                         SAMPLE8(-3,  1),
     86                         SAMPLE8( 1,  3),
     87                 },
     88                 .origin = SAMPLE8(0, 0)
     89         },
     90 
     91         [MALI_SAMPLE_PATTERN_D3D_8X_GRID] = {
     92                 .positions = {
     93                         SAMPLE16( 1, -3),
     94                         SAMPLE16(-1,  3),
     95                         SAMPLE16( 5,  1),
     96                         SAMPLE16(-3, -5),
     97                         SAMPLE16(-5,  5),
     98                         SAMPLE16(-7, -1),
     99                         SAMPLE16( 3,  7),
    100                         SAMPLE16( 7,  -7),
    101                 },
    102                 .origin = SAMPLE16(0, 0)
    103         },
    104 
    105         [MALI_SAMPLE_PATTERN_D3D_16X_GRID] = {
    106                 .positions = {
    107                         SAMPLE16( 1,  1),
    108                         SAMPLE16(-1, -3),
    109                         SAMPLE16(-3,  2),
    110                         SAMPLE16( 4, -1),
    111                         SAMPLE16(-5, -2),
    112                         SAMPLE16( 2,  5),
    113                         SAMPLE16( 5,  3),
    114                         SAMPLE16( 3, -5),
    115                         SAMPLE16(-2,  6),
    116                         SAMPLE16( 0,  7),
    117                         SAMPLE16(-4, -6),
    118                         SAMPLE16(-6,  4),
    119                         SAMPLE16(-8,  0),
    120                         SAMPLE16( 7, -4),
    121                         SAMPLE16( 6,  7),
    122                         SAMPLE16(-7, -8),
    123 
    124                 },
    125                 .origin = SAMPLE16(0, 0)
    126         }
    127 };
    128 
    129 mali_ptr
    130 panfrost_sample_positions(const struct panfrost_device *dev,
    131                 enum mali_sample_pattern pattern)
    132 {
    133         assert(pattern < ARRAY_SIZE(sample_position_lut));
    134         unsigned offset = (pattern * sizeof(sample_position_lut[0]));
    135         return dev->sample_positions->ptr.gpu + offset;
    136 }
    137 
    138 void
    139 panfrost_upload_sample_positions(struct panfrost_device *dev)
    140 {
    141         STATIC_ASSERT(sizeof(sample_position_lut) < 4096);
    142         dev->sample_positions = panfrost_bo_create(dev, 4096, 0, "Sample positions");
    143 
    144         memcpy(dev->sample_positions->ptr.cpu, sample_position_lut,
    145                         sizeof(sample_position_lut));
    146 }
    147 
    148 /* CPU side LUT query, to implement glGetMultisamplefv */
    149 
    150 void
    151 panfrost_query_sample_position(
    152                 enum mali_sample_pattern pattern,
    153                 unsigned sample_idx,
    154                 float *out)
    155 {
    156         struct mali_sample_position pos =
    157                 sample_position_lut[pattern].positions[sample_idx];
    158 
    159         out[0] = DECODE_FIXED_16(pos.x);
    160         out[1] = DECODE_FIXED_16(pos.y);
    161 }
    162