• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2015, 2019 Collabora, Ltd.
4  * Copyright © 2016 NVIDIA Corporation
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #include "config.h"
29 
30 #include <assert.h>
31 
32 #include "shared/helpers.h"
33 #include "shared/platform.h"
34 
35 #include "gl-renderer.h"
36 #include "gl-renderer-internal.h"
37 #include "pixel-formats.h"
38 #include "shared/weston-egl-ext.h"
39 
40 #include <assert.h>
41 
42 struct egl_config_print_info {
43 	const EGLint *attrs;
44 	unsigned attrs_count;
45 	const char *prefix;
46 	const char *separator;
47 	int field_width;
48 };
49 
50 static const char *
egl_error_string(EGLint code)51 egl_error_string(EGLint code)
52 {
53 #define MYERRCODE(x) case x: return #x;
54 	switch (code) {
55 	MYERRCODE(EGL_SUCCESS)
56 	MYERRCODE(EGL_NOT_INITIALIZED)
57 	MYERRCODE(EGL_BAD_ACCESS)
58 	MYERRCODE(EGL_BAD_ALLOC)
59 	MYERRCODE(EGL_BAD_ATTRIBUTE)
60 	MYERRCODE(EGL_BAD_CONTEXT)
61 	MYERRCODE(EGL_BAD_CONFIG)
62 	MYERRCODE(EGL_BAD_CURRENT_SURFACE)
63 	MYERRCODE(EGL_BAD_DISPLAY)
64 	MYERRCODE(EGL_BAD_SURFACE)
65 	MYERRCODE(EGL_BAD_MATCH)
66 	MYERRCODE(EGL_BAD_PARAMETER)
67 	MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
68 	MYERRCODE(EGL_BAD_NATIVE_WINDOW)
69 	MYERRCODE(EGL_CONTEXT_LOST)
70 	default:
71 		return "unknown";
72 	}
73 #undef MYERRCODE
74 }
75 
76 void
gl_renderer_print_egl_error_state(void)77 gl_renderer_print_egl_error_state(void)
78 {
79 	EGLint code;
80 
81 	code = eglGetError();
82 	weston_log("EGL error state: %s (0x%04lx)\n",
83 		egl_error_string(code), (long)code);
84 }
85 
86 static void
print_egl_surface_type_bits(FILE * fp,EGLint egl_surface_type)87 print_egl_surface_type_bits(FILE *fp, EGLint egl_surface_type)
88 {
89 	const char *sep = "";
90 	unsigned i;
91 
92 	static const struct {
93 		EGLint bit;
94 		const char *str;
95 	} egl_surf_bits[] = {
96 		{ EGL_WINDOW_BIT, "win" },
97 		{ EGL_PIXMAP_BIT, "pix" },
98 		{ EGL_PBUFFER_BIT, "pbf" },
99 		{ EGL_MULTISAMPLE_RESOLVE_BOX_BIT, "ms_resolve_box" },
100 		{ EGL_SWAP_BEHAVIOR_PRESERVED_BIT, "swap_preserved" },
101 	};
102 
103 	for (i = 0; i < ARRAY_LENGTH(egl_surf_bits); i++) {
104 		if (egl_surface_type & egl_surf_bits[i].bit) {
105 			fprintf(fp, "%s%s", sep, egl_surf_bits[i].str);
106 			sep = "|";
107 		}
108 	}
109 }
110 
111 static const struct egl_config_print_info config_info_ints[] = {
112 #define ARRAY(...) ((const EGLint[]) { __VA_ARGS__ })
113 
114 	{ ARRAY(EGL_CONFIG_ID), 1, "id: ", "", 3 },
115 	{ ARRAY(EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, EGL_ALPHA_SIZE), 4,
116 	  "rgba: ", " ", 1 },
117 	{ ARRAY(EGL_BUFFER_SIZE), 1, "buf: ", "", 2 },
118 	{ ARRAY(EGL_DEPTH_SIZE), 1, "dep: ", "", 2 },
119 	{ ARRAY(EGL_STENCIL_SIZE), 1, "stcl: ", "", 1 },
120 	{ ARRAY(EGL_MIN_SWAP_INTERVAL, EGL_MAX_SWAP_INTERVAL), 2,
121 	  "int: ", "-", 1 },
122 
123 #undef ARRAY
124 };
125 
126 static void
print_egl_config_ints(FILE * fp,EGLDisplay egldpy,EGLConfig eglconfig)127 print_egl_config_ints(FILE *fp, EGLDisplay egldpy, EGLConfig eglconfig)
128 {
129 	unsigned i;
130 
131 	for (i = 0; i < ARRAY_LENGTH(config_info_ints); i++) {
132 		const struct egl_config_print_info *info = &config_info_ints[i];
133 		unsigned j;
134 		const char *sep = "";
135 
136 		fputs(info->prefix, fp);
137 		for (j = 0; j < info->attrs_count; j++) {
138 			EGLint value;
139 
140 			if (eglGetConfigAttrib(egldpy, eglconfig,
141 					       info->attrs[j], &value)) {
142 				fprintf(fp, "%s%*d",
143 					sep, info->field_width, value);
144 			} else {
145 				fprintf(fp, "%s!", sep);
146 			}
147 			sep = info->separator;
148 		}
149 
150 		fputs(" ", fp);
151 	}
152 }
153 
154 static void
print_egl_config_info(FILE * fp,EGLDisplay egldpy,EGLConfig eglconfig)155 print_egl_config_info(FILE *fp, EGLDisplay egldpy, EGLConfig eglconfig)
156 {
157 	EGLint value;
158 
159 	print_egl_config_ints(fp, egldpy, eglconfig);
160 
161 	fputs("type: ", fp);
162 	if (eglGetConfigAttrib(egldpy, eglconfig, EGL_SURFACE_TYPE, &value))
163 		print_egl_surface_type_bits(fp, value);
164 	else
165 		fputs("-", fp);
166 
167 	fputs(" vis_id: ", fp);
168 	if (eglGetConfigAttrib(egldpy, eglconfig, EGL_NATIVE_VISUAL_ID, &value)) {
169 		if (value != 0) {
170 			const struct pixel_format_info *p;
171 
172 			p = pixel_format_get_info(value);
173 			if (p) {
174 				fprintf(fp, "%s (0x%x)",
175 					p->drm_format_name, (unsigned)value);
176 			} else {
177 				fprintf(fp, "0x%x", (unsigned)value);
178 			}
179 		} else {
180 			fputs("0", fp);
181 		}
182 	} else {
183 		fputs("-", fp);
184 	}
185 }
186 
187 static void
log_all_egl_configs(EGLDisplay egldpy)188 log_all_egl_configs(EGLDisplay egldpy)
189 {
190 	EGLint count = 0;
191 	EGLConfig *configs;
192 	int i;
193 	char *strbuf = NULL;
194 	size_t strsize = 0;
195 	FILE *fp;
196 
197 	weston_log("All available EGLConfigs:\n");
198 
199 	if (!eglGetConfigs(egldpy, NULL, 0, &count) || count < 1)
200 		return;
201 
202 	configs = calloc(count, sizeof *configs);
203 	if (!configs)
204 		return;
205 
206 	if (!eglGetConfigs(egldpy, configs, count, &count))
207 		return;
208 
209 	fp = open_memstream(&strbuf, &strsize);
210 	if (!fp)
211 		goto out;
212 
213 	for (i = 0; i < count; i++) {
214 		print_egl_config_info(fp, egldpy, configs[i]);
215 		fputc(0, fp);
216 		fflush(fp);
217 		weston_log_continue(STAMP_SPACE "%s\n", strbuf);
218 		rewind(fp);
219 	}
220 
221 	fclose(fp);
222 	free(strbuf);
223 
224 out:
225 	free(configs);
226 }
227 
228 void
log_egl_config_info(EGLDisplay egldpy,EGLConfig eglconfig)229 log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
230 {
231 	char *strbuf = NULL;
232 	size_t strsize = 0;
233 	FILE *fp;
234 
235 	fp = open_memstream(&strbuf, &strsize);
236 	if (fp) {
237 		print_egl_config_info(fp, egldpy, eglconfig);
238 		fclose(fp);
239 	}
240 
241 	weston_log("Chosen EGL config details: %s\n", strbuf ? strbuf : "?");
242 	free(strbuf);
243 }
244 
245 static bool
egl_config_pixel_format_matches(struct gl_renderer * gr,EGLConfig config,const struct pixel_format_info * pinfo)246 egl_config_pixel_format_matches(struct gl_renderer *gr,
247 				EGLConfig config,
248 				const struct pixel_format_info *pinfo)
249 {
250 	static const EGLint attribs[4] = {
251 		EGL_ALPHA_SIZE, EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE
252 	};
253 	const int *argb[4] = {
254 		&pinfo->bits.a, &pinfo->bits.r, &pinfo->bits.g, &pinfo->bits.b
255 	};
256 	unsigned i;
257 	EGLint value;
258 
259 	if (gr->platform == EGL_PLATFORM_GBM_KHR) {
260 		if (!eglGetConfigAttrib(gr->egl_display, config,
261 					EGL_NATIVE_VISUAL_ID, &value))
262 			return false;
263 
264 		return ((uint32_t)value) == pinfo->format;
265 	}
266 
267 	for (i = 0; i < 4; i++) {
268 		if (!eglGetConfigAttrib(gr->egl_display, config,
269 					attribs[i], &value))
270 			return false;
271 		if (value != *argb[i])
272 			return false;
273 	}
274 
275 	return true;
276 }
277 
278 static int
egl_choose_config(struct gl_renderer * gr,const EGLint * attribs,const struct pixel_format_info * const * pinfo,unsigned pinfo_count,EGLConfig * config_out)279 egl_choose_config(struct gl_renderer *gr,
280 		  const EGLint *attribs,
281 		  const struct pixel_format_info *const *pinfo,
282 		  unsigned pinfo_count,
283 		  EGLConfig *config_out)
284 {
285 	EGLint count = 0;
286 	EGLint matched = 0;
287 	EGLConfig *configs;
288 	unsigned i;
289 	EGLint j;
290 	int config_index = -1;
291 
292 	if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1) {
293 		weston_log("No EGL configs to choose from.\n");
294 		return -1;
295 	}
296 	configs = calloc(count, sizeof *configs);
297 	if (!configs)
298 		return -1;
299 
300 	if (!eglChooseConfig(gr->egl_display, attribs, configs,
301 			      count, &matched) || !matched) {
302 		weston_log("No EGL configs with appropriate attributes.\n");
303 		goto out;
304 	}
305 
306 	if (pinfo_count == 0)
307 		config_index = 0;
308 
309 	for (i = 0; config_index == -1 && i < pinfo_count; i++)
310 		for (j = 0; config_index == -1 && j < matched; j++)
311 			if (egl_config_pixel_format_matches(gr, configs[j],
312 							    pinfo[i]))
313 				config_index = j;
314 
315 	if (config_index != -1)
316 		*config_out = configs[config_index];
317 
318 out:
319 	free(configs);
320 	if (config_index == -1)
321 		return -1;
322 
323 	if (i > 1)
324 		weston_log("Unable to use first choice EGL config with"
325 			   " %s, succeeded with alternate %s.\n",
326 			   pinfo[0]->drm_format_name,
327 			   pinfo[i - 1]->drm_format_name);
328 	return 0;
329 }
330 
331 static bool
egl_config_is_compatible(struct gl_renderer * gr,EGLConfig config,EGLint egl_surface_type,const struct pixel_format_info * const * pinfo,unsigned pinfo_count)332 egl_config_is_compatible(struct gl_renderer *gr,
333 			 EGLConfig config,
334 			 EGLint egl_surface_type,
335 			 const struct pixel_format_info *const *pinfo,
336 			 unsigned pinfo_count)
337 {
338 	EGLint value;
339 	unsigned i;
340 
341 	if (config == EGL_NO_CONFIG_KHR)
342 		return false;
343 
344 	if (!eglGetConfigAttrib(gr->egl_display, config,
345 				EGL_SURFACE_TYPE, &value))
346 		return false;
347 	if ((value & egl_surface_type) != egl_surface_type)
348 		return false;
349 
350 	for (i = 0; i < pinfo_count; i++) {
351 		if (egl_config_pixel_format_matches(gr, config, pinfo[i]))
352 			return true;
353 	}
354 	return false;
355 }
356 
357 /* The caller must free() the string */
358 static char *
explain_egl_config_criteria(EGLint egl_surface_type,const struct pixel_format_info * const * pinfo,unsigned pinfo_count)359 explain_egl_config_criteria(EGLint egl_surface_type,
360 			    const struct pixel_format_info *const *pinfo,
361 			    unsigned pinfo_count)
362 {
363 	FILE *fp;
364 	char *str = NULL;
365 	size_t size = 0;
366 	const char *sep;
367 	unsigned i;
368 
369 	fp = open_memstream(&str, &size);
370 	if (!fp)
371 		return NULL;
372 
373 	fputs("{ ", fp);
374 
375 	print_egl_surface_type_bits(fp, egl_surface_type);
376 	fputs("; ", fp);
377 
378 	sep = "";
379 	for (i = 0; i < pinfo_count; i++) {
380 		fprintf(fp, "%s%s", sep, pinfo[i]->drm_format_name);
381 		sep = ", ";
382 	}
383 
384 	fputs(" }", fp);
385 
386 	fclose(fp);
387 
388 	return str;
389 }
390 
391 EGLConfig
gl_renderer_get_egl_config(struct gl_renderer * gr,EGLint egl_surface_type,const uint32_t * drm_formats,unsigned drm_formats_count)392 gl_renderer_get_egl_config(struct gl_renderer *gr,
393 			   EGLint egl_surface_type,
394 			   const uint32_t *drm_formats,
395 			   unsigned drm_formats_count)
396 {
397 	EGLConfig egl_config;
398 	const struct pixel_format_info *pinfo[16];
399 	unsigned pinfo_count;
400 	unsigned i;
401 	char *what;
402 	EGLint config_attribs[] = {
403 		EGL_SURFACE_TYPE,    egl_surface_type,
404 		EGL_RED_SIZE,        1,
405 		EGL_GREEN_SIZE,      1,
406 		EGL_BLUE_SIZE,       1,
407 		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
408 		EGL_NONE
409 	};
410 
411 	assert(drm_formats_count < ARRAY_LENGTH(pinfo));
412 	drm_formats_count = MIN(drm_formats_count, ARRAY_LENGTH(pinfo));
413 
414 	for (pinfo_count = 0, i = 0; i < drm_formats_count; i++) {
415 		pinfo[pinfo_count] = pixel_format_get_info(drm_formats[i]);
416 		if (!pinfo[pinfo_count]) {
417 			weston_log("Bad/unknown DRM format code 0x%08x.\n",
418 				   drm_formats[i]);
419 			continue;
420 		}
421 		pinfo_count++;
422 	}
423 
424 	if (egl_config_is_compatible(gr, gr->egl_config, egl_surface_type,
425 				     pinfo, pinfo_count))
426 		return gr->egl_config;
427 
428 	if (egl_choose_config(gr, config_attribs, pinfo, pinfo_count,
429 			      &egl_config) < 0) {
430 		what = explain_egl_config_criteria(egl_surface_type,
431 						   pinfo, pinfo_count);
432 		weston_log("No EGLConfig matches %s.\n", what);
433 		free(what);
434 		log_all_egl_configs(gr->egl_display);
435 		return EGL_NO_CONFIG_KHR;
436 	}
437 
438 	/*
439 	 * If we do not have configless context support, all EGLConfigs must
440 	 * be the one and the same, because we use just one GL context for
441 	 * everything.
442 	 */
443 	if (gr->egl_config != EGL_NO_CONFIG_KHR &&
444 	    egl_config != gr->egl_config) {
445 		what = explain_egl_config_criteria(egl_surface_type,
446 						   pinfo, pinfo_count);
447 		weston_log("Found an EGLConfig matching %s but it is not usable"
448 			   " because neither EGL_KHR_no_config_context nor "
449 			   "EGL_MESA_configless_context are supported by EGL.\n",
450 			   what);
451 		free(what);
452 		return EGL_NO_CONFIG_KHR;
453 	}
454 
455 	return egl_config;
456 }
457 
458 int
gl_renderer_setup_egl_display(struct gl_renderer * gr,void * native_display)459 gl_renderer_setup_egl_display(struct gl_renderer *gr,
460 			      void *native_display)
461 {
462 	gr->egl_display = NULL;
463 
464 	/* extension_suffix is supported */
465 	if (gr->has_platform_base)
466 		gr->egl_display = gr->get_platform_display(gr->platform,
467 							   native_display,
468 							   NULL);
469 
470 	if (!gr->egl_display) {
471 		weston_log("warning: either no EGL_EXT_platform_base "
472 			   "support or specific platform support; "
473 			   "falling back to eglGetDisplay.\n");
474 		gr->egl_display = eglGetDisplay(native_display);
475 	}
476 
477 	if (!gr->egl_display) {
478 		weston_log("failed to create display\n");
479 		return -1;
480 	}
481 
482 	if (!eglInitialize(gr->egl_display, NULL, NULL)) {
483 		weston_log("failed to initialize display\n");
484 		goto fail;
485 	}
486 
487 	return 0;
488 
489 fail:
490 	gl_renderer_print_egl_error_state();
491 	return -1;
492 }
493 
494 static const char *
platform_to_extension(EGLenum platform)495 platform_to_extension(EGLenum platform)
496 {
497 	switch (platform) {
498 	case EGL_PLATFORM_GBM_KHR:
499 		return "gbm";
500 	case EGL_PLATFORM_WAYLAND_KHR:
501 		return "wayland";
502 	case EGL_PLATFORM_X11_KHR:
503 		return "x11";
504 	case EGL_PLATFORM_SURFACELESS_MESA:
505 		return "surfaceless";
506 	default:
507 		assert(0 && "bad EGL platform enum");
508 	}
509 }
510 
511 /** Checks for EGL client extensions (i.e. independent of EGL display),
512  * loads the function pointers, and checks if the platform is supported.
513  *
514  * \param gr The OpenGL renderer
515  * \return 0 for success, -1 if platform is unsupported
516  *
517  * This function checks whether a specific platform_* extension is supported
518  * by EGL by checking in order "EGL_KHR_platform_foo", "EGL_EXT_platform_foo",
519  * and "EGL_MESA_platform_foo" in order, for some platform "foo".
520  */
521 int
gl_renderer_setup_egl_client_extensions(struct gl_renderer * gr)522 gl_renderer_setup_egl_client_extensions(struct gl_renderer *gr)
523 {
524 	const char *extensions;
525 	const char *extension_suffix = platform_to_extension(gr->platform);
526 	char s[64];
527 
528 	extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
529 	if (!extensions) {
530 		weston_log("Retrieving EGL client extension string failed.\n");
531 		return 0;
532 	}
533 
534 	gl_renderer_log_extensions("EGL client extensions",
535 				   extensions);
536 
537 	if (weston_check_egl_extension(extensions, "EGL_EXT_platform_base")) {
538 		gr->get_platform_display =
539 			(void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
540 		gr->create_platform_window =
541 			(void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
542 		gr->has_platform_base = true;
543 	} else {
544 		weston_log("warning: EGL_EXT_platform_base not supported.\n");
545 
546 		/* Surfaceless is unusable without platform_base extension */
547 		if (gr->platform == EGL_PLATFORM_SURFACELESS_MESA)
548 			return -1;
549 
550 		return 0;
551 	}
552 
553 	snprintf(s, sizeof s, "EGL_KHR_platform_%s", extension_suffix);
554 	if (weston_check_egl_extension(extensions, s))
555 		return 0;
556 
557 	snprintf(s, sizeof s, "EGL_EXT_platform_%s", extension_suffix);
558 	if (weston_check_egl_extension(extensions, s))
559 		return 0;
560 
561 	snprintf(s, sizeof s, "EGL_MESA_platform_%s", extension_suffix);
562 	if (weston_check_egl_extension(extensions, s))
563 		return 0;
564 
565 	/* at this point we definitely have some platform extensions but
566 	 * haven't found the supplied platform, so chances are it's
567 	 * not supported. */
568 
569 	return -1;
570 }
571 
572 int
gl_renderer_setup_egl_extensions(struct weston_compositor * ec)573 gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
574 {
575 	static const struct {
576 		char *extension, *entrypoint;
577 	} swap_damage_ext_to_entrypoint[] = {
578 		{
579 			.extension = "EGL_EXT_swap_buffers_with_damage",
580 			.entrypoint = "eglSwapBuffersWithDamageEXT",
581 		},
582 		{
583 			.extension = "EGL_KHR_swap_buffers_with_damage",
584 			.entrypoint = "eglSwapBuffersWithDamageKHR",
585 		},
586 	};
587 	struct gl_renderer *gr = get_renderer(ec);
588 	const char *extensions;
589 	EGLBoolean ret;
590 	unsigned i;
591 
592 	gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
593 	gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
594 
595 	gr->bind_display =
596 		(void *) eglGetProcAddress("eglBindWaylandDisplayWL");
597 	gr->unbind_display =
598 		(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
599 	gr->query_buffer =
600 		(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
601 	gr->set_damage_region =
602 		(void *) eglGetProcAddress("eglSetDamageRegionKHR");
603 
604 	extensions =
605 		(const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
606 	if (!extensions) {
607 		weston_log("Retrieving EGL extension string failed.\n");
608 		return -1;
609 	}
610 
611 	if (weston_check_egl_extension(extensions, "EGL_IMG_context_priority"))
612 		gr->has_context_priority = true;
613 
614 	if (weston_check_egl_extension(extensions, "EGL_WL_bind_wayland_display"))
615 		gr->has_bind_display = true;
616 	if (gr->has_bind_display) {
617 		assert(gr->bind_display);
618 		assert(gr->unbind_display);
619 		assert(gr->query_buffer);
620 		ret = gr->bind_display(gr->egl_display, ec->wl_display);
621 		if (!ret)
622 			gr->has_bind_display = false;
623 	}
624 
625 	if (weston_check_egl_extension(extensions, "EGL_EXT_buffer_age"))
626 		gr->has_egl_buffer_age = true;
627 
628 	if (weston_check_egl_extension(extensions, "EGL_KHR_partial_update")) {
629 		assert(gr->set_damage_region);
630 		gr->has_egl_partial_update = true;
631 	}
632 
633 	for (i = 0; i < ARRAY_LENGTH(swap_damage_ext_to_entrypoint); i++) {
634 		if (weston_check_egl_extension(extensions,
635 				swap_damage_ext_to_entrypoint[i].extension)) {
636 			gr->swap_buffers_with_damage =
637 				(void *) eglGetProcAddress(
638 						swap_damage_ext_to_entrypoint[i].entrypoint);
639 			assert(gr->swap_buffers_with_damage);
640 			break;
641 		}
642 	}
643 
644 	if (weston_check_egl_extension(extensions, "EGL_KHR_no_config_context") ||
645 	    weston_check_egl_extension(extensions, "EGL_MESA_configless_context"))
646 		gr->has_configless_context = true;
647 
648 	if (weston_check_egl_extension(extensions, "EGL_KHR_surfaceless_context"))
649 		gr->has_surfaceless_context = true;
650 
651 	if (weston_check_egl_extension(extensions, "EGL_EXT_image_dma_buf_import"))
652 		gr->has_dmabuf_import = true;
653 
654 	if (weston_check_egl_extension(extensions,
655 				"EGL_EXT_image_dma_buf_import_modifiers")) {
656 		gr->query_dmabuf_formats =
657 			(void *) eglGetProcAddress("eglQueryDmaBufFormatsEXT");
658 		gr->query_dmabuf_modifiers =
659 			(void *) eglGetProcAddress("eglQueryDmaBufModifiersEXT");
660 		assert(gr->query_dmabuf_formats);
661 		assert(gr->query_dmabuf_modifiers);
662 		gr->has_dmabuf_import_modifiers = true;
663 	}
664 
665 	if (weston_check_egl_extension(extensions, "EGL_KHR_fence_sync")) {
666 		gr->create_sync =
667 			(void *) eglGetProcAddress("eglCreateSyncKHR");
668 		gr->destroy_sync =
669 			(void *) eglGetProcAddress("eglDestroySyncKHR");
670 		gr->dup_native_fence_fd =
671 			(void *) eglGetProcAddress("eglDupNativeFenceFDANDROID");
672 		assert(gr->create_sync);
673 		assert(gr->destroy_sync);
674 		assert(gr->dup_native_fence_fd);
675 		gr->has_native_fence_sync = true;
676 	} else {
677 		weston_log("warning: Disabling render GPU timeline and explicit "
678 			   "synchronization due to missing "
679 			   "EGL_ANDROID_native_fence_sync extension\n");
680 	}
681 
682 	if (weston_check_egl_extension(extensions, "EGL_KHR_wait_sync")) {
683 		gr->wait_sync = (void *) eglGetProcAddress("eglWaitSyncKHR");
684 		assert(gr->wait_sync);
685 		gr->has_wait_sync = true;
686 	} else {
687 		weston_log("warning: Disabling explicit synchronization due"
688 			   "to missing EGL_KHR_wait_sync extension\n");
689 	}
690 
691 	return 0;
692 }
693