1/* 2 * © Copyright 2018 Alyssa Rosenzweig 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 25#include "pan_format.h" 26 27/* From panwrap/panwrap-decoder, but we don't want to bring in all those headers */ 28char *panwrap_format_name(enum mali_format format); 29 30/* Construct a default swizzle based on the number of components */ 31 32static unsigned 33panfrost_translate_swizzle(enum pipe_swizzle s) 34{ 35 switch (s) { 36 case PIPE_SWIZZLE_X: 37 return MALI_CHANNEL_RED; 38 39 case PIPE_SWIZZLE_Y: 40 return MALI_CHANNEL_GREEN; 41 42 case PIPE_SWIZZLE_Z: 43 return MALI_CHANNEL_BLUE; 44 45 case PIPE_SWIZZLE_W: 46 return MALI_CHANNEL_ALPHA; 47 48 case PIPE_SWIZZLE_0: 49 case PIPE_SWIZZLE_NONE: 50 return MALI_CHANNEL_ZERO; 51 52 case PIPE_SWIZZLE_1: 53 return MALI_CHANNEL_ONE; 54 55 default: 56 assert(0); 57 return 0; 58 } 59} 60 61/* Translate a Gallium swizzle quad to a 12-bit Mali swizzle code */ 62 63unsigned 64panfrost_translate_swizzle_4(const unsigned char swizzle[4]) 65{ 66 unsigned out = 0; 67 68 for (unsigned i = 0; i < 4; ++i) { 69 unsigned translated = panfrost_translate_swizzle(swizzle[i]); 70 out |= (translated << (3*i)); 71 } 72 73 return out; 74} 75 76unsigned 77panfrost_get_default_swizzle(unsigned components) 78{ 79 unsigned char default_swizzles[4][4] = { 80 {PIPE_SWIZZLE_X, PIPE_SWIZZLE_0, PIPE_SWIZZLE_0, PIPE_SWIZZLE_1}, 81 {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_0, PIPE_SWIZZLE_1}, 82 {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_1}, 83 {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W}, 84 }; 85 86 assert(components >= 1 && components <= 4); 87 return panfrost_translate_swizzle_4(default_swizzles[components - 1]); 88} 89 90static unsigned 91panfrost_translate_channel_width(unsigned size) 92{ 93 switch (size) { 94 case 4: 95 return MALI_CHANNEL_4; 96 case 8: 97 return MALI_CHANNEL_8; 98 case 16: 99 return MALI_CHANNEL_16; 100 case 32: 101 return MALI_CHANNEL_32; 102 default: 103 fprintf(stderr, "Unknown width %d\n", size); 104 assert(0); 105 return 0; 106 } 107} 108 109static unsigned 110panfrost_translate_channel_type(unsigned type, unsigned size, bool norm) { 111 switch (type) { 112 case UTIL_FORMAT_TYPE_UNSIGNED: 113 return norm ? MALI_FORMAT_UNORM : MALI_FORMAT_UINT; 114 115 case UTIL_FORMAT_TYPE_SIGNED: 116 return norm ? MALI_FORMAT_SNORM : MALI_FORMAT_SINT; 117 118 case UTIL_FORMAT_TYPE_FLOAT: 119 if (size == 16) { 120 /* With FLOAT, fp16 */ 121 return MALI_FORMAT_SINT; 122 } else if (size == 32) { 123 /* With FLOAT< fp32 */ 124 return MALI_FORMAT_UNORM; 125 } else { 126 assert(0); 127 return 0; 128 } 129 130 default: 131 assert(0); 132 return 0; 133 } 134} 135 136/* Constructs a mali_format satisfying the specified Gallium format 137 * description */ 138 139enum mali_format 140panfrost_find_format(const struct util_format_description *desc) 141{ 142 /* Find first non-VOID channel */ 143 struct util_format_channel_description chan = desc->channel[0]; 144 145 for (unsigned c = 0; c < 4; ++c) { 146 if (desc->channel[c].type == UTIL_FORMAT_TYPE_VOID) 147 continue; 148 149 chan = desc->channel[c]; 150 break; 151 } 152 153 /* Check for special formats */ 154 switch (desc->format) { 155 case PIPE_FORMAT_YV12: 156 case PIPE_FORMAT_YV16: 157 case PIPE_FORMAT_IYUV: 158 case PIPE_FORMAT_NV21: 159 fprintf(stderr, "YUV format type %s (%d) is not yet supported, but it's probably close to NV12!\n", desc->name, desc->format); 160 assert(0); 161 break; 162 163 case PIPE_FORMAT_NV12: 164 return MALI_NV12; 165 166 case PIPE_FORMAT_R10G10B10X2_UNORM: 167 case PIPE_FORMAT_B10G10R10X2_UNORM: 168 case PIPE_FORMAT_R10G10B10A2_UNORM: 169 case PIPE_FORMAT_B10G10R10A2_UNORM: 170 return MALI_RGB10_A2_UNORM; 171 172 case PIPE_FORMAT_R10G10B10X2_SNORM: 173 case PIPE_FORMAT_R10G10B10A2_SNORM: 174 case PIPE_FORMAT_B10G10R10A2_SNORM: 175 return MALI_RGB10_A2_SNORM; 176 177 case PIPE_FORMAT_R10G10B10A2_UINT: 178 case PIPE_FORMAT_B10G10R10A2_UINT: 179 return MALI_RGB10_A2UI; 180 181 /* TODO: ZS isn't really special case */ 182 case PIPE_FORMAT_Z32_UNORM: 183 return MALI_Z32_UNORM; 184 185 case PIPE_FORMAT_B5G6R5_UNORM: 186 return MALI_RGB565; 187 188 case PIPE_FORMAT_B5G5R5A1_UNORM: 189 return MALI_RGB5_A1_UNORM; 190 191 case PIPE_FORMAT_A1B5G5R5_UNORM: 192 case PIPE_FORMAT_X1B5G5R5_UNORM: 193 /* Not supported - this is backwards from OpenGL! */ 194 assert(0); 195 break; 196 197 case PIPE_FORMAT_R32_FIXED: 198 return MALI_R32_FIXED; 199 case PIPE_FORMAT_R32G32_FIXED: 200 return MALI_RG32_FIXED; 201 case PIPE_FORMAT_R32G32B32_FIXED: 202 return MALI_RGB32_FIXED; 203 case PIPE_FORMAT_R32G32B32A32_FIXED: 204 return MALI_RGBA32_FIXED; 205 206 default: 207 /* Fallthrough to default */ 208 break; 209 } 210 211 /* Formats must match in channel count */ 212 assert(desc->nr_channels >= 1 && desc->nr_channels <= 4); 213 unsigned format = MALI_NR_CHANNELS(desc->nr_channels); 214 215 switch (chan.type) { 216 case UTIL_FORMAT_TYPE_UNSIGNED: 217 case UTIL_FORMAT_TYPE_SIGNED: 218 case UTIL_FORMAT_TYPE_FIXED: 219 /* Channel width */ 220 format |= panfrost_translate_channel_width(chan.size); 221 222 /* Channel type */ 223 format |= panfrost_translate_channel_type(chan.type, chan.size, chan.normalized); 224 break; 225 226 case UTIL_FORMAT_TYPE_FLOAT: 227 /* Float formats use a special width and encode width 228 * with type mixed */ 229 230 format |= MALI_CHANNEL_FLOAT; 231 format |= panfrost_translate_channel_type(chan.type, chan.size, chan.normalized); 232 break; 233 234 default: 235 fprintf(stderr, "Unknown format type in %s\n", desc->name); 236 assert(0); 237 break; 238 } 239 240 return (enum mali_format) format; 241} 242 243 244