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 42struct mali_sample_position { 43 uint16_t x, y; 44} __attribute__((packed)); 45 46struct 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 63const 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 129mali_ptr 130panfrost_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 138void 139panfrost_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 150void 151panfrost_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