Branch data Line data Source code
1 : : /*
2 : : * This file is part of libplacebo.
3 : : *
4 : : * libplacebo is free software; you can redistribute it and/or
5 : : * modify it under the terms of the GNU Lesser General Public
6 : : * License as published by the Free Software Foundation; either
7 : : * version 2.1 of the License, or (at your option) any later version.
8 : : *
9 : : * libplacebo is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : * GNU Lesser General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU Lesser General Public
15 : : * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #include "gpu.h"
19 : : #include "common.h"
20 : : #include "formats.h"
21 : : #include "utils.h"
22 : :
23 : : #ifdef PL_HAVE_UNIX
24 : : static bool supported_fourcc(struct pl_gl *p, EGLint fourcc)
25 : : {
26 [ + + ]: 540 : for (int i = 0; i < p->egl_formats.num; ++i)
27 [ + + ]: 536 : if (fourcc == p->egl_formats.elem[i])
28 : : return true;
29 : : return false;
30 : : }
31 : : #endif
32 : :
33 : : #define FMT(_name, bits, ftype, _caps) \
34 : : (struct pl_fmt_t) { \
35 : : .name = _name, \
36 : : .type = PL_FMT_##ftype, \
37 : : .caps = (enum pl_fmt_caps) (_caps), \
38 : : .sample_order = {0, 1, 2, 3}, \
39 : : .component_depth = {bits, bits, bits, bits}, \
40 : : }
41 : :
42 : : // Convenience to make the names simpler
43 : : enum {
44 : : // Type aliases
45 : : U8 = GL_UNSIGNED_BYTE,
46 : : U16 = GL_UNSIGNED_SHORT,
47 : : U32 = GL_UNSIGNED_INT,
48 : : I8 = GL_BYTE,
49 : : I16 = GL_SHORT,
50 : : I32 = GL_INT,
51 : : FLT = GL_FLOAT,
52 : : HALF = GL_HALF_FLOAT,
53 : :
54 : : // Component aliases
55 : : R = GL_RED,
56 : : RG = GL_RG,
57 : : RGB = GL_RGB,
58 : : RGBA = GL_RGBA,
59 : : BGRA = GL_BGRA,
60 : : RI = GL_RED_INTEGER,
61 : : RGI = GL_RG_INTEGER,
62 : : RGBI = GL_RGB_INTEGER,
63 : : RGBAI = GL_RGBA_INTEGER,
64 : :
65 : : // Capability aliases
66 : : S = PL_FMT_CAP_SAMPLEABLE,
67 : : L = PL_FMT_CAP_LINEAR,
68 : : F = PL_FMT_CAP_RENDERABLE | PL_FMT_CAP_BLITTABLE, // FBO support
69 : : V = PL_FMT_CAP_VERTEX,
70 : : };
71 : :
72 : : // Basic 8-bit formats
73 : : const struct gl_format formats_norm8[] = {
74 : : {GL_R8, R, U8, FMT("r8", 8, UNORM, S|L|F|V)},
75 : : {GL_RG8, RG, U8, FMT("rg8", 8, UNORM, S|L|F|V)},
76 : : {GL_RGB8, RGB, U8, FMT("rgb8", 8, UNORM, S|L|F|V)},
77 : : {GL_RGBA8, RGBA, U8, FMT("rgba8", 8, UNORM, S|L|F|V)},
78 : : };
79 : :
80 : : // Signed variants
81 : : /* TODO: these are broken in mesa
82 : : const struct gl_format formats_snorm8[] = {
83 : : {GL_R8_SNORM, R, I8, FMT("r8s", 8, SNORM, S|L|F|V)},
84 : : {GL_RG8_SNORM, RG, I8, FMT("rg8s", 8, SNORM, S|L|F|V)},
85 : : {GL_RGB8_SNORM, RGB, I8, FMT("rgb8s", 8, SNORM, S|L|F|V)},
86 : : {GL_RGBA8_SNORM, RGBA, I8, FMT("rgba8s", 8, SNORM, S|L|F|V)},
87 : : };
88 : : */
89 : :
90 : : // BGRA 8-bit
91 : : const struct gl_format formats_bgra8[] = {
92 : : {GL_RGBA8, BGRA, U8, {
93 : : .name = "bgra8",
94 : : .type = PL_FMT_UNORM,
95 : : .caps = S|L|F|V,
96 : : .sample_order = {2, 1, 0, 3},
97 : : .component_depth = {8, 8, 8, 8},
98 : : }},
99 : : };
100 : :
101 : : // Basic 16-bit formats, excluding rgb16 (special cased below)
102 : : const struct gl_format formats_norm16[] = {
103 : : {GL_R16, R, U16, FMT("r16", 16, UNORM, S|L|F|V)},
104 : : {GL_RG16, RG, U16, FMT("rg16", 16, UNORM, S|L|F|V)},
105 : : {GL_RGBA16, RGBA, U16, FMT("rgba16", 16, UNORM, S|L|F|V)},
106 : : };
107 : :
108 : : // Renderable version of rgb16
109 : : const struct gl_format formats_rgb16_fbo[] = {
110 : : {GL_RGB16, RGB, U16, FMT("rgb16", 16, UNORM, S|L|F|V)},
111 : : };
112 : :
113 : : // Non-renderable version of rgb16
114 : : const struct gl_format formats_rgb16_fallback[] = {
115 : : {GL_RGB16, RGB, U16, FMT("rgb16", 16, UNORM, S|L|V)},
116 : : };
117 : :
118 : : // Signed 16-bit variants
119 : : /* TODO: these are broken in mesa and nvidia
120 : : const struct gl_format formats_snorm16[] = {
121 : : {GL_R16_SNORM, R, I16, FMT("r16s", 16, SNORM, S|L|F|V)},
122 : : {GL_RG16_SNORM, RG, I16, FMT("rg16s", 16, SNORM, S|L|F|V)},
123 : : {GL_RGB16_SNORM, RGB, I16, FMT("rgb16s", 16, SNORM, S|L|F|V)},
124 : : {GL_RGBA16_SNORM, RGBA, I16, FMT("rgba16s", 16, SNORM, S|L|F|V)},
125 : : };
126 : : */
127 : :
128 : : // 32-bit floating point texture formats
129 : : const struct gl_format formats_float32[] = {
130 : : {GL_R32F, R, FLT, FMT("r32f", 32, FLOAT, S|L|F|V)},
131 : : {GL_RG32F, RG, FLT, FMT("rg32f", 32, FLOAT, S|L|F|V)},
132 : : {GL_RGB32F, RGB, FLT, FMT("rgb32f", 32, FLOAT, S|L|F|V)},
133 : : {GL_RGBA32F, RGBA, FLT, FMT("rgba32f", 32, FLOAT, S|L|F|V)},
134 : : };
135 : :
136 : : // 16-bit floating point texture formats
137 : : const struct gl_format formats_float16[] = {
138 : : {GL_R16F, R, FLT, FMT("r16f", 16, FLOAT, S|L|F)},
139 : : {GL_RG16F, RG, FLT, FMT("rg16f", 16, FLOAT, S|L|F)},
140 : : {GL_RGB16F, RGB, FLT, FMT("rgb16f", 16, FLOAT, S|L|F)},
141 : : {GL_RGBA16F, RGBA, FLT, FMT("rgba16f", 16, FLOAT, S|L|F)},
142 : : };
143 : :
144 : : // 16-bit half float texture formats
145 : : const struct gl_format formats_half16[] = {
146 : : {GL_R16F, R, HALF, FMT("r16hf", 16, FLOAT, S|L|F)},
147 : : {GL_RG16F, RG, HALF, FMT("rg16hf", 16, FLOAT, S|L|F)},
148 : : {GL_RGB16F, RGB, HALF, FMT("rgb16hf", 16, FLOAT, S|L|F)},
149 : : {GL_RGBA16F, RGBA, HALF, FMT("rgba16hf",16, FLOAT, S|L|F)},
150 : : };
151 : :
152 : : // Renderable 16-bit float formats (excluding rgb16f)
153 : : const struct gl_format formats_float16_fbo[] = {
154 : : {GL_R16F, R, HALF, FMT("r16hf", 16, FLOAT, S|L|F)},
155 : : {GL_RG16F, RG, HALF, FMT("rg16hf", 16, FLOAT, S|L|F)},
156 : : {GL_RGB16F, RGB, HALF, FMT("rgb16hf", 16, FLOAT, S|L)},
157 : : {GL_RGBA16F, RGBA, HALF, FMT("rgba16hf",16, FLOAT, S|L|F)},
158 : : {GL_R16F, R, FLT, FMT("r16f", 16, FLOAT, S|L|F)},
159 : : {GL_RG16F, RG, FLT, FMT("rg16f", 16, FLOAT, S|L|F)},
160 : : {GL_RGB16F, RGB, FLT, FMT("rgb16f", 16, FLOAT, S|L)},
161 : : {GL_RGBA16F, RGBA, FLT, FMT("rgba16f", 16, FLOAT, S|L|F)},
162 : : };
163 : :
164 : : // Non-renderable 16-bit float formats
165 : : const struct gl_format formats_float16_fallback[] = {
166 : : {GL_R16F, R, HALF, FMT("r16hf", 16, FLOAT, S|L)},
167 : : {GL_RG16F, RG, HALF, FMT("rg16hf", 16, FLOAT, S|L)},
168 : : {GL_RGB16F, RGB, HALF, FMT("rgb16hf", 16, FLOAT, S|L)},
169 : : {GL_RGBA16F, RGBA, HALF, FMT("rgba16hf",16, FLOAT, S|L)},
170 : : {GL_R16F, R, FLT, FMT("r16f", 16, FLOAT, S|L)},
171 : : {GL_RG16F, RG, FLT, FMT("rg16f", 16, FLOAT, S|L)},
172 : : {GL_RGB16F, RGB, FLT, FMT("rgb16f", 16, FLOAT, S|L)},
173 : : {GL_RGBA16F, RGBA, FLT, FMT("rgba16f", 16, FLOAT, S|L)},
174 : : };
175 : :
176 : : // (Unsigned) integer formats
177 : : const struct gl_format formats_uint[] = {
178 : : {GL_R8UI, RI, U8, FMT("r8u", 8, UINT, S|F|V)},
179 : : {GL_RG8UI, RGI, U8, FMT("rg8u", 8, UINT, S|F|V)},
180 : : {GL_RGB8UI, RGBI, U8, FMT("rgb8u", 8, UINT, S|V)},
181 : : {GL_RGBA8UI, RGBAI, U8, FMT("rgba8u", 8, UINT, S|F|V)},
182 : : {GL_R16UI, RI, U16, FMT("r16u", 16, UINT, S|F|V)},
183 : : {GL_RG16UI, RGI, U16, FMT("rg16u", 16, UINT, S|F|V)},
184 : : {GL_RGB16UI, RGBI, U16, FMT("rgb16u", 16, UINT, S|V)},
185 : : {GL_RGBA16UI, RGBAI, U16, FMT("rgba16u", 16, UINT, S|F|V)},
186 : : };
187 : :
188 : : /* TODO
189 : : {GL_R32UI, RI, U32, FMT("r32u", 32, UINT)},
190 : : {GL_RG32UI, RGI, U32, FMT("rg32u", 32, UINT)},
191 : : {GL_RGB32UI, RGBI, U32, FMT("rgb32u", 32, UINT)},
192 : : {GL_RGBA32UI, RGBAI, U32, FMT("rgba32u", 32, UINT)},
193 : :
194 : : {GL_R8I, RI, I8, FMT("r8i", 8, SINT)},
195 : : {GL_RG8I, RGI, I8, FMT("rg8i", 8, SINT)},
196 : : {GL_RGB8I, RGBI, I8, FMT("rgb8i", 8, SINT)},
197 : : {GL_RGBA8I, RGBAI, I8, FMT("rgba8i", 8, SINT)},
198 : : {GL_R16I, RI, I16, FMT("r16i", 16, SINT)},
199 : : {GL_RG16I, RGI, I16, FMT("rg16i", 16, SINT)},
200 : : {GL_RGB16I, RGBI, I16, FMT("rgb16i", 16, SINT)},
201 : : {GL_RGBA16I, RGBAI, I16, FMT("rgba16i", 16, SINT)},
202 : : {GL_R32I, RI, I32, FMT("r32i", 32, SINT)},
203 : : {GL_RG32I, RGI, I32, FMT("rg32i", 32, SINT)},
204 : : {GL_RGB32I, RGBI, I32, FMT("rgb32i", 32, SINT)},
205 : : {GL_RGBA32I, RGBAI, I32, FMT("rgba32i", 32, SINT)},
206 : : */
207 : :
208 : : // GL2 legacy formats
209 : : const struct gl_format formats_legacy_gl2[] = {
210 : : {GL_RGB8, RGB, U8, FMT("rgb8", 8, UNORM, S|L|V)},
211 : : {GL_RGBA8, RGBA, U8, FMT("rgba8", 8, UNORM, S|L|V)},
212 : : {GL_RGB16, RGB, U16, FMT("rgb16", 16, UNORM, S|L|V)},
213 : : {GL_RGBA16, RGBA, U16, FMT("rgba16", 16, UNORM, S|L|V)},
214 : : };
215 : :
216 : : // GLES2 legacy formats
217 : : const struct gl_format formats_legacy_gles2[] = {
218 : : {GL_RGB, RGB, U8, FMT("rgb", 8, UNORM, S|L)},
219 : : {GL_RGBA, RGBA, U8, FMT("rgba", 8, UNORM, S|L)},
220 : : };
221 : :
222 : : // GLES BGRA
223 : : const struct gl_format formats_bgra_gles[] = {
224 : : {GL_BGRA, BGRA, U8, {
225 : : .name = "bgra8",
226 : : .type = PL_FMT_UNORM,
227 : : .caps = S|L|F|V,
228 : : .sample_order = {2, 1, 0, 3},
229 : : .component_depth = {8, 8, 8, 8},
230 : : }},
231 : : };
232 : :
233 : : // Fallback for vertex-only formats, as a last resort
234 : : const struct gl_format formats_basic_vertex[] = {
235 : : {GL_R32F, R, FLT, FMT("r32f", 32, FLOAT, V)},
236 : : {GL_RG32F, RG, FLT, FMT("rg32f", 32, FLOAT, V)},
237 : : {GL_RGB32F, RGB, FLT, FMT("rgb32f", 32, FLOAT, V)},
238 : : {GL_RGBA32F, RGBA, FLT, FMT("rgba32f", 32, FLOAT, V)},
239 : : };
240 : :
241 : 116 : static void add_format(pl_gpu pgpu, const struct gl_format *gl_fmt)
242 : : {
243 : : struct pl_gpu_t *gpu = (struct pl_gpu_t *) pgpu;
244 : 116 : struct pl_gl *p = PL_PRIV(gpu);
245 : :
246 : 116 : struct pl_fmt_t *fmt = pl_alloc_obj(gpu, fmt, gl_fmt);
247 : 116 : const struct gl_format **fmtp = PL_PRIV(fmt);
248 : 116 : *fmt = gl_fmt->tmpl;
249 : 116 : *fmtp = gl_fmt;
250 : :
251 : : // Calculate the host size and number of components
252 [ + + + + : 116 : switch (gl_fmt->fmt) {
- ]
253 : 28 : case GL_RED:
254 : : case GL_RED_INTEGER:
255 : 28 : fmt->num_components = 1;
256 : 28 : break;
257 : 28 : case GL_RG:
258 : : case GL_RG_INTEGER:
259 : 28 : fmt->num_components = 2;
260 : 28 : break;
261 : 28 : case GL_RGB:
262 : : case GL_RGB_INTEGER:
263 : 28 : fmt->num_components = 3;
264 : 28 : break;
265 : 32 : case GL_RGBA:
266 : : case GL_RGBA_INTEGER:
267 : : case GL_BGRA:
268 : 32 : fmt->num_components = 4;
269 : 32 : break;
270 : : default:
271 : 0 : pl_unreachable();
272 : : }
273 : :
274 : : int size;
275 [ + + - + ]: 116 : switch (gl_fmt->type) {
276 : : case GL_BYTE:
277 : : case GL_UNSIGNED_BYTE:
278 : : size = 1;
279 : : break;
280 : 48 : case GL_SHORT:
281 : : case GL_UNSIGNED_SHORT:
282 : : case GL_HALF_FLOAT:
283 : : size = 2;
284 : 48 : break;
285 : 32 : case GL_INT:
286 : : case GL_UNSIGNED_INT:
287 : : case GL_FLOAT:
288 : : size = 4;
289 : 32 : break;
290 : : default:
291 : 0 : pl_unreachable();
292 : : }
293 : :
294 : : // Host visible representation
295 : 116 : fmt->texel_size = fmt->num_components * size;
296 : 116 : fmt->texel_align = 1;
297 [ + + ]: 412 : for (int i = 0; i < fmt->num_components; i++)
298 : 296 : fmt->host_bits[i] = size * 8;
299 : :
300 : : // Compute internal size by summing up the depth
301 : : int ibits = 0;
302 [ + + ]: 412 : for (int i = 0; i < fmt->num_components; i++)
303 : 296 : ibits += fmt->component_depth[i];
304 : 116 : fmt->internal_size = (ibits + 7) / 8;
305 : :
306 : : // We're not the ones actually emulating these texture format - the
307 : : // driver is - but we might as well set the hint.
308 : 116 : fmt->emulated = fmt->texel_size != fmt->internal_size;
309 : :
310 : : // 3-component formats are almost surely also emulated
311 [ + + ]: 116 : if (fmt->num_components == 3)
312 : 28 : fmt->emulated = true;
313 : :
314 : : // Older OpenGL most likely emulates 32-bit float formats as well
315 [ + + + + ]: 116 : if (p->gl_ver < 30 && fmt->component_depth[0] >= 32)
316 : 4 : fmt->emulated = true;
317 : :
318 : : // For sanity, clear the superfluous fields
319 [ + + ]: 284 : for (int i = fmt->num_components; i < 4; i++) {
320 : 168 : fmt->component_depth[i] = 0;
321 : 168 : fmt->sample_order[i] = 0;
322 : 168 : fmt->host_bits[i] = 0;
323 : : }
324 : :
325 : 116 : fmt->glsl_type = pl_var_glsl_type_name(pl_var_from_fmt(fmt, ""));
326 : 116 : fmt->glsl_format = pl_fmt_glsl_format(fmt, fmt->num_components);
327 : 116 : fmt->fourcc = pl_fmt_fourcc(fmt);
328 [ - + ]: 116 : pl_assert(fmt->glsl_type);
329 : :
330 : : #ifdef PL_HAVE_UNIX
331 [ + - + + : 152 : if (p->has_modifiers && fmt->fourcc && supported_fourcc(p, fmt->fourcc)) {
+ + ]
332 : 32 : int num_mods = 0;
333 : 32 : bool ok = eglQueryDmaBufModifiersEXT(p->egl_dpy, fmt->fourcc,
334 : : 0, NULL, NULL, &num_mods);
335 [ + - + - ]: 32 : if (ok && num_mods) {
336 : : // On my system eglQueryDmaBufModifiersEXT seems to never return
337 : : // MOD_INVALID even though eglExportDMABUFImageQueryMESA happily
338 : : // returns such modifiers. Since we handle INVALID by not
339 : : // requiring modifiers at all, always add this value to the
340 : : // list of supported modifiers. May result in duplicates, but
341 : : // whatever.
342 : 32 : uint64_t *mods = pl_calloc(fmt, num_mods + 1, sizeof(uint64_t));
343 : 32 : mods[0] = DRM_FORMAT_MOD_INVALID;
344 : 32 : ok = eglQueryDmaBufModifiersEXT(p->egl_dpy, fmt->fourcc, num_mods,
345 : 32 : &mods[1], NULL, &num_mods);
346 : :
347 [ + - ]: 32 : if (ok) {
348 : 32 : fmt->modifiers = mods;
349 : 32 : fmt->num_modifiers = num_mods + 1;
350 : : } else {
351 : 0 : pl_free(mods);
352 : : }
353 : : }
354 : :
355 : 32 : eglGetError(); // ignore probing errors
356 : : }
357 : :
358 [ + + ]: 116 : if (!fmt->num_modifiers) {
359 : : // Hacky fallback for older drivers that don't support properly
360 : : // querying modifiers
361 : : static const uint64_t static_mods[] = {
362 : : DRM_FORMAT_MOD_INVALID,
363 : : DRM_FORMAT_MOD_LINEAR,
364 : : };
365 : :
366 : 84 : fmt->num_modifiers = PL_ARRAY_SIZE(static_mods);
367 : 84 : fmt->modifiers = static_mods;
368 : : }
369 : : #endif
370 : :
371 : : // Gathering requires checking the format type (and extension presence)
372 [ + + ]: 116 : if (fmt->caps & PL_FMT_CAP_SAMPLEABLE)
373 : 112 : fmt->gatherable = p->gather_comps >= fmt->num_components;
374 : :
375 : : bool host_readable = false;
376 [ + + ]: 116 : if (p->gl_ver && p->has_readback)
377 : : host_readable = true;
378 : : // Reading from textures on GLES requires FBO support for this fmt
379 [ + + ]: 116 : if (fmt->caps & PL_FMT_CAP_RENDERABLE) {
380 : : // this combination always works in glReadPixels
381 [ + + + + ]: 101 : if ((gl_fmt->fmt == GL_RGBA && gl_fmt->type == GL_UNSIGNED_BYTE) ||
382 [ - + ]: 97 : p->has_readback)
383 : : host_readable = true;
384 : : }
385 [ + + ]: 15 : if (host_readable)
386 : 107 : fmt->caps |= PL_FMT_CAP_HOST_READABLE;
387 : :
388 [ + + + + : 116 : if (gpu->glsl.compute && fmt->glsl_format && p->has_storage)
+ - ]
389 : 22 : fmt->caps |= PL_FMT_CAP_STORABLE | PL_FMT_CAP_READWRITE;
390 : :
391 : : // GLES 2 can't do blitting
392 [ - + ]: 116 : if (p->gles_ver && p->gles_ver < 30)
393 : 0 : fmt->caps &= ~PL_FMT_CAP_BLITTABLE;
394 : :
395 : : // Only float-type formats are considered blendable in OpenGL
396 [ + - + ]: 116 : switch (fmt->type) {
397 : : case PL_FMT_UNKNOWN:
398 : : case PL_FMT_UINT:
399 : : case PL_FMT_SINT:
400 : : break;
401 : 84 : case PL_FMT_FLOAT:
402 : : case PL_FMT_UNORM:
403 : : case PL_FMT_SNORM:
404 [ + + ]: 84 : if (fmt->caps & PL_FMT_CAP_RENDERABLE)
405 : 77 : fmt->caps |= PL_FMT_CAP_BLENDABLE;
406 : : break;
407 : : case PL_FMT_TYPE_COUNT:
408 : 0 : pl_unreachable();
409 : : }
410 : :
411 : : // TODO: Texel buffers
412 : :
413 [ + + + + : 116 : PL_ARRAY_APPEND_RAW(gpu, gpu->formats, gpu->num_formats, fmt);
- + ]
414 : 116 : }
415 : :
416 : : #define DO_FORMATS(formats) \
417 : : do { \
418 : : for (int i = 0; i < PL_ARRAY_SIZE(formats); i++) \
419 : : add_format(gpu, &formats[i]); \
420 : : } while (0)
421 : :
422 : 4 : bool gl_setup_formats(struct pl_gpu_t *gpu)
423 : : {
424 : 4 : struct pl_gl *p = PL_PRIV(gpu);
425 : :
426 : : #ifdef PL_HAVE_UNIX
427 [ + - ]: 4 : if (p->has_modifiers) {
428 : 4 : EGLint num_formats = 0;
429 : 4 : bool ok = eglQueryDmaBufFormatsEXT(p->egl_dpy, 0, NULL,
430 : : &num_formats);
431 [ + - + - ]: 4 : if (ok && num_formats) {
432 : 4 : p->egl_formats.elem = pl_calloc(gpu, num_formats, sizeof(EGLint));
433 : 4 : p->egl_formats.num = num_formats;
434 : 4 : ok = eglQueryDmaBufFormatsEXT(p->egl_dpy, num_formats,
435 : : p->egl_formats.elem, &num_formats);
436 [ - + ]: 4 : pl_assert(ok);
437 : :
438 : 4 : PL_DEBUG(gpu, "EGL formats supported:");
439 [ + + ]: 192 : for (int i = 0; i < num_formats; ++i) {
440 [ + - ]: 188 : PL_DEBUG(gpu, " 0x%08x(%.4s)", p->egl_formats.elem[i],
441 : : PRINT_FOURCC(p->egl_formats.elem[i]));
442 : : }
443 : : }
444 : : }
445 : : #endif
446 : :
447 [ + + ]: 4 : if (p->gl_ver >= 30) {
448 : : // Desktop GL3+ has everything
449 [ + + ]: 15 : DO_FORMATS(formats_norm8);
450 [ + + ]: 6 : DO_FORMATS(formats_bgra8);
451 [ + + ]: 12 : DO_FORMATS(formats_norm16);
452 [ + + ]: 6 : DO_FORMATS(formats_rgb16_fbo);
453 [ + + ]: 15 : DO_FORMATS(formats_float32);
454 [ + + ]: 15 : DO_FORMATS(formats_float16);
455 [ + + ]: 15 : DO_FORMATS(formats_half16);
456 [ + + ]: 27 : DO_FORMATS(formats_uint);
457 : 3 : goto done;
458 : : }
459 : :
460 [ - + ]: 1 : if (p->gl_ver >= 21) {
461 : : // If we have a reasonable set of extensions, we can enable most
462 : : // things. Otherwise, pick simple fallback formats
463 [ # # ]: 0 : if (pl_opengl_has_ext(p->gl, "GL_ARB_texture_float") &&
464 [ # # ]: 0 : pl_opengl_has_ext(p->gl, "GL_ARB_texture_rg") &&
465 [ # # ]: 0 : pl_opengl_has_ext(p->gl, "GL_ARB_framebuffer_object"))
466 : : {
467 [ # # ]: 0 : DO_FORMATS(formats_norm8);
468 [ # # ]: 0 : DO_FORMATS(formats_bgra8);
469 [ # # ]: 0 : DO_FORMATS(formats_norm16);
470 [ # # ]: 0 : DO_FORMATS(formats_rgb16_fbo);
471 [ # # ]: 0 : DO_FORMATS(formats_float32);
472 [ # # ]: 0 : DO_FORMATS(formats_float16);
473 [ # # ]: 0 : if (pl_opengl_has_ext(p->gl, "GL_ARB_half_float_pixel"))
474 : : {
475 [ # # ]: 0 : DO_FORMATS(formats_half16);
476 : : }
477 : : } else {
478 : : // Fallback for GL2
479 [ # # ]: 0 : DO_FORMATS(formats_legacy_gl2);
480 [ # # ]: 0 : DO_FORMATS(formats_basic_vertex);
481 : : }
482 : 0 : goto done;
483 : : }
484 : :
485 [ + - ]: 1 : if (p->gles_ver >= 30) {
486 : : // GLES 3.0 has some basic formats, with framebuffers for float16
487 : : // depending on GL_EXT_color_buffer_(half_)float support
488 [ + + ]: 5 : DO_FORMATS(formats_norm8);
489 [ + - ]: 1 : if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_norm16")) {
490 [ + + ]: 4 : DO_FORMATS(formats_norm16);
491 [ + + ]: 2 : DO_FORMATS(formats_rgb16_fallback);
492 : : }
493 [ + - ]: 1 : if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_format_BGRA8888"))
494 [ + + ]: 2 : DO_FORMATS(formats_bgra_gles);
495 [ + + ]: 9 : DO_FORMATS(formats_uint);
496 [ + + ]: 5 : DO_FORMATS(formats_basic_vertex);
497 [ - + - - ]: 1 : if (p->gles_ver >= 32 || pl_opengl_has_ext(p->gl, "GL_EXT_color_buffer_float")) {
498 [ + + ]: 9 : DO_FORMATS(formats_float16_fbo);
499 : : } else {
500 [ # # ]: 0 : DO_FORMATS(formats_float16_fallback);
501 : : }
502 : 1 : goto done;
503 : : }
504 : :
505 [ # # ]: 0 : if (p->gles_ver >= 20) {
506 : : // GLES 2.0 only has some legacy fallback formats, with support for
507 : : // float16 depending on GL_EXT_texture_norm16 being present
508 [ # # ]: 0 : DO_FORMATS(formats_legacy_gles2);
509 [ # # ]: 0 : DO_FORMATS(formats_basic_vertex);
510 [ # # ]: 0 : if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_rg")) {
511 [ # # ]: 0 : DO_FORMATS(formats_norm8);
512 : : }
513 [ # # ]: 0 : if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_format_BGRA8888")) {
514 [ # # ]: 0 : DO_FORMATS(formats_bgra_gles);
515 : : }
516 : 0 : goto done;
517 : : }
518 : :
519 : : // Last resort fallback. Probably not very useful
520 [ # # ]: 0 : DO_FORMATS(formats_basic_vertex);
521 : 0 : goto done;
522 : :
523 : 4 : done:
524 : 4 : return gl_check_err(gpu, "gl_setup_formats");
525 : : }
|