1 #include "util/format/u_format.h"
2 #include "zink_format.h"
3 #include "util/u_math.h"
4
5 enum pipe_format
zink_decompose_vertex_format(enum pipe_format format)6 zink_decompose_vertex_format(enum pipe_format format)
7 {
8 const struct util_format_description *desc = util_format_description(format);
9 unsigned first_non_void = util_format_get_first_non_void_channel(format);
10 enum pipe_format new_format;
11 assert(first_non_void == 0);
12 if (!desc->is_array)
13 return PIPE_FORMAT_NONE;
14 if (desc->is_unorm) {
15 enum pipe_format unorm_formats[] = {
16 PIPE_FORMAT_R8_UNORM,
17 PIPE_FORMAT_R16_UNORM,
18 PIPE_FORMAT_R32_UNORM
19 };
20 return unorm_formats[desc->channel[first_non_void].size >> 4];
21 } else if (desc->is_snorm) {
22 enum pipe_format snorm_formats[] = {
23 PIPE_FORMAT_R8_SNORM,
24 PIPE_FORMAT_R16_SNORM,
25 PIPE_FORMAT_R32_SNORM
26 };
27 return snorm_formats[desc->channel[first_non_void].size >> 4];
28 } else {
29 enum pipe_format uint_formats[][3] = {
30 {PIPE_FORMAT_R8_USCALED, PIPE_FORMAT_R16_USCALED, PIPE_FORMAT_R32_USCALED},
31 {PIPE_FORMAT_R8_UINT, PIPE_FORMAT_R16_UINT, PIPE_FORMAT_R32_UINT},
32 };
33 enum pipe_format sint_formats[][3] = {
34 {PIPE_FORMAT_R8_SSCALED, PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R32_SSCALED},
35 {PIPE_FORMAT_R8_SINT, PIPE_FORMAT_R16_SINT, PIPE_FORMAT_R32_SINT},
36 };
37 switch (desc->channel[first_non_void].type) {
38 case UTIL_FORMAT_TYPE_UNSIGNED:
39 return uint_formats[desc->channel[first_non_void].pure_integer][desc->channel[first_non_void].size >> 4];
40 case UTIL_FORMAT_TYPE_SIGNED:
41 return sint_formats[desc->channel[first_non_void].pure_integer][desc->channel[first_non_void].size >> 4];
42 case UTIL_FORMAT_TYPE_FLOAT:
43 return desc->channel[first_non_void].size == 16 ? PIPE_FORMAT_R16_FLOAT : PIPE_FORMAT_R32_FLOAT;
44 break;
45 default:
46 return PIPE_FORMAT_NONE;
47 }
48 }
49 return new_format;
50 }
51
52 bool
zink_format_is_red_alpha(enum pipe_format format)53 zink_format_is_red_alpha(enum pipe_format format)
54 {
55 switch (format) {
56 case PIPE_FORMAT_R4A4_UNORM:
57 case PIPE_FORMAT_R8A8_SINT:
58 case PIPE_FORMAT_R8A8_SNORM:
59 case PIPE_FORMAT_R8A8_UINT:
60 case PIPE_FORMAT_R8A8_UNORM:
61 case PIPE_FORMAT_R16A16_SINT:
62 case PIPE_FORMAT_R16A16_SNORM:
63 case PIPE_FORMAT_R16A16_UINT:
64 case PIPE_FORMAT_R16A16_UNORM:
65 case PIPE_FORMAT_R16A16_FLOAT:
66 case PIPE_FORMAT_R32A32_SINT:
67 case PIPE_FORMAT_R32A32_UINT:
68 case PIPE_FORMAT_R32A32_FLOAT:
69 return true;
70 default: break;
71 }
72 return false;
73 }
74
75 bool
zink_format_is_emulated_alpha(enum pipe_format format)76 zink_format_is_emulated_alpha(enum pipe_format format)
77 {
78 return util_format_is_alpha(format) ||
79 util_format_is_luminance(format) ||
80 util_format_is_luminance_alpha(format) ||
81 zink_format_is_red_alpha(format);
82 }
83
84 static enum pipe_format
emulate_alpha(enum pipe_format format)85 emulate_alpha(enum pipe_format format)
86 {
87 if (format == PIPE_FORMAT_A8_UNORM)
88 return PIPE_FORMAT_R8_UNORM;
89 if (format == PIPE_FORMAT_A8_UINT)
90 return PIPE_FORMAT_R8_UINT;
91 if (format == PIPE_FORMAT_A8_SNORM)
92 return PIPE_FORMAT_R8_SNORM;
93 if (format == PIPE_FORMAT_A8_SINT)
94 return PIPE_FORMAT_R8_SINT;
95 if (format == PIPE_FORMAT_A16_UNORM)
96 return PIPE_FORMAT_R16_UNORM;
97 if (format == PIPE_FORMAT_A16_UINT)
98 return PIPE_FORMAT_R16_UINT;
99 if (format == PIPE_FORMAT_A16_SNORM)
100 return PIPE_FORMAT_R16_SNORM;
101 if (format == PIPE_FORMAT_A16_SINT)
102 return PIPE_FORMAT_R16_SINT;
103 if (format == PIPE_FORMAT_A16_FLOAT)
104 return PIPE_FORMAT_R16_FLOAT;
105 if (format == PIPE_FORMAT_A32_UINT)
106 return PIPE_FORMAT_R32_UINT;
107 if (format == PIPE_FORMAT_A32_SINT)
108 return PIPE_FORMAT_R32_SINT;
109 if (format == PIPE_FORMAT_A32_FLOAT)
110 return PIPE_FORMAT_R32_FLOAT;
111 return format;
112 }
113
114 static enum pipe_format
emulate_red_alpha(enum pipe_format format)115 emulate_red_alpha(enum pipe_format format)
116 {
117 switch (format) {
118 case PIPE_FORMAT_R8A8_SINT:
119 return PIPE_FORMAT_R8G8_SINT;
120 case PIPE_FORMAT_R8A8_SNORM:
121 return PIPE_FORMAT_R8G8_SNORM;
122 case PIPE_FORMAT_R8A8_UINT:
123 return PIPE_FORMAT_R8G8_UINT;
124 case PIPE_FORMAT_R8A8_UNORM:
125 return PIPE_FORMAT_R8G8_UNORM;
126 case PIPE_FORMAT_R16A16_SINT:
127 return PIPE_FORMAT_R16G16_SINT;
128 case PIPE_FORMAT_R16A16_SNORM:
129 return PIPE_FORMAT_R16G16_SNORM;
130 case PIPE_FORMAT_R16A16_UINT:
131 return PIPE_FORMAT_R16G16_UINT;
132 case PIPE_FORMAT_R16A16_UNORM:
133 return PIPE_FORMAT_R16G16_UNORM;
134 case PIPE_FORMAT_R16A16_FLOAT:
135 return PIPE_FORMAT_R16G16_FLOAT;
136 case PIPE_FORMAT_R32A32_SINT:
137 return PIPE_FORMAT_R32G32_SINT;
138 case PIPE_FORMAT_R32A32_UINT:
139 return PIPE_FORMAT_R32G32_UINT;
140 case PIPE_FORMAT_R32A32_FLOAT:
141 return PIPE_FORMAT_R32G32_FLOAT;
142 default: break;
143 }
144 return format;
145 }
146
147 enum pipe_format
zink_format_get_emulated_alpha(enum pipe_format format)148 zink_format_get_emulated_alpha(enum pipe_format format)
149 {
150 if (util_format_is_alpha(format))
151 return emulate_alpha(format);
152 if (util_format_is_luminance(format))
153 return util_format_luminance_to_red(format);
154 if (util_format_is_luminance_alpha(format)) {
155 if (util_format_is_srgb(format))
156 return format;
157 if (format == PIPE_FORMAT_LATC2_UNORM)
158 return PIPE_FORMAT_RGTC2_UNORM;
159 if (format == PIPE_FORMAT_LATC2_SNORM)
160 return PIPE_FORMAT_RGTC2_SNORM;
161
162 format = util_format_luminance_to_red(format);
163 }
164
165 return emulate_red_alpha(format);
166 }
167
168
169 enum pipe_format
zink_format_emulate_x8(enum pipe_format format)170 zink_format_emulate_x8(enum pipe_format format)
171 {
172 /* convert missing Xn variants to An */
173 switch (format) {
174 case PIPE_FORMAT_B8G8R8X8_UNORM:
175 return PIPE_FORMAT_B8G8R8A8_UNORM;
176
177 case PIPE_FORMAT_B8G8R8X8_SRGB:
178 return PIPE_FORMAT_B8G8R8A8_SRGB;
179 case PIPE_FORMAT_R8G8B8X8_SRGB:
180 return PIPE_FORMAT_R8G8B8A8_SRGB;
181
182 case PIPE_FORMAT_R8G8B8X8_SINT:
183 return PIPE_FORMAT_R8G8B8A8_SINT;
184 case PIPE_FORMAT_R8G8B8X8_SNORM:
185 return PIPE_FORMAT_R8G8B8A8_SNORM;
186 case PIPE_FORMAT_R8G8B8X8_UNORM:
187 return PIPE_FORMAT_R8G8B8A8_UNORM;
188
189 case PIPE_FORMAT_R16G16B16X16_FLOAT:
190 return PIPE_FORMAT_R16G16B16A16_FLOAT;
191 case PIPE_FORMAT_R16G16B16X16_SINT:
192 return PIPE_FORMAT_R16G16B16A16_SINT;
193 case PIPE_FORMAT_R16G16B16X16_SNORM:
194 return PIPE_FORMAT_R16G16B16A16_SNORM;
195 case PIPE_FORMAT_R16G16B16X16_UNORM:
196 return PIPE_FORMAT_R16G16B16A16_UNORM;
197
198 case PIPE_FORMAT_R32G32B32X32_FLOAT:
199 return PIPE_FORMAT_R32G32B32A32_FLOAT;
200 case PIPE_FORMAT_R32G32B32X32_SINT:
201 return PIPE_FORMAT_R32G32B32A32_SINT;
202
203 case PIPE_FORMAT_R10G10B10X2_SINT:
204 return PIPE_FORMAT_R10G10B10A2_SINT;
205 case PIPE_FORMAT_R10G10B10X2_SNORM:
206 return PIPE_FORMAT_R10G10B10A2_SNORM;
207 case PIPE_FORMAT_R10G10B10X2_UNORM:
208 return PIPE_FORMAT_R10G10B10A2_UNORM;
209
210 case PIPE_FORMAT_B10G10R10X2_SINT:
211 return PIPE_FORMAT_B10G10R10A2_SINT;
212 case PIPE_FORMAT_B10G10R10X2_SNORM:
213 return PIPE_FORMAT_B10G10R10A2_SNORM;
214 case PIPE_FORMAT_B10G10R10X2_UNORM:
215 return PIPE_FORMAT_B10G10R10A2_UNORM;
216
217 case PIPE_FORMAT_R5G5B5X1_UNORM:
218 return PIPE_FORMAT_R5G5B5A1_UNORM;
219 case PIPE_FORMAT_B5G5R5X1_UNORM:
220 return PIPE_FORMAT_B5G5R5A1_UNORM;
221
222 default:
223 return format;
224 }
225 }
226
227 bool
zink_format_is_voidable_rgba_variant(enum pipe_format format)228 zink_format_is_voidable_rgba_variant(enum pipe_format format)
229 {
230 return format != zink_format_emulate_x8(format);
231 }
232
233 void
zink_format_clamp_channel_color(const struct util_format_description * desc,union pipe_color_union * dst,const union pipe_color_union * src,unsigned i)234 zink_format_clamp_channel_color(const struct util_format_description *desc, union pipe_color_union *dst, const union pipe_color_union *src, unsigned i)
235 {
236 int non_void = util_format_get_first_non_void_channel(desc->format);
237 unsigned channel = desc->swizzle[i];
238
239 if (channel > PIPE_SWIZZLE_W || desc->channel[channel].type == UTIL_FORMAT_TYPE_VOID) {
240 if (non_void != -1) {
241 if (desc->channel[non_void].type == UTIL_FORMAT_TYPE_FLOAT) {
242 dst->f[i] = uif(UINT32_MAX);
243 } else {
244 if (desc->channel[non_void].normalized)
245 dst->f[i] = 1.0;
246 else if (desc->channel[non_void].type == UTIL_FORMAT_TYPE_SIGNED)
247 dst->i[i] = INT32_MAX;
248 else
249 dst->ui[i] = UINT32_MAX;
250 }
251 } else {
252 dst->ui[i] = src->ui[i];
253 }
254 return;
255 }
256
257 switch (desc->channel[channel].type) {
258 case UTIL_FORMAT_TYPE_VOID:
259 unreachable("handled above");
260 break;
261 case UTIL_FORMAT_TYPE_SIGNED:
262 if (desc->channel[channel].normalized)
263 dst->i[i] = src->i[i];
264 else {
265 dst->i[i] = MAX2(src->i[i], -(1<<(desc->channel[channel].size - 1)));
266 dst->i[i] = MIN2(dst->i[i], (1 << (desc->channel[channel].size - 1)) - 1);
267 }
268 break;
269 case UTIL_FORMAT_TYPE_UNSIGNED:
270 if (desc->channel[channel].normalized)
271 dst->ui[i] = src->ui[i];
272 else
273 dst->ui[i] = MIN2(src->ui[i], BITFIELD_MASK(desc->channel[channel].size));
274 break;
275 case UTIL_FORMAT_TYPE_FIXED:
276 case UTIL_FORMAT_TYPE_FLOAT:
277 dst->ui[i] = src->ui[i];
278 break;
279 }
280 }
281
282 void
zink_format_clamp_channel_srgb(const struct util_format_description * desc,union pipe_color_union * dst,const union pipe_color_union * src,unsigned i)283 zink_format_clamp_channel_srgb(const struct util_format_description *desc, union pipe_color_union *dst, const union pipe_color_union *src, unsigned i)
284 {
285 unsigned channel = desc->swizzle[i];
286 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB &&
287 channel <= PIPE_SWIZZLE_W) {
288 switch (desc->channel[channel].type) {
289 case UTIL_FORMAT_TYPE_SIGNED:
290 case UTIL_FORMAT_TYPE_UNSIGNED:
291 dst->f[i] = CLAMP(src->f[i], 0.0, 1.0);
292 return;
293 default:
294 break;
295 }
296 }
297
298 dst->ui[i] = src->ui[i];
299 }
300