You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							599 lines
						
					
					
						
							15 KiB
						
					
					
				
			
		
		
	
	
							599 lines
						
					
					
						
							15 KiB
						
					
					
				/*
 | 
						|
 * Copyright © 2012 Intel Corporation
 | 
						|
 * Copyright © 2015, 2019 Collabora, Ltd.
 | 
						|
 * Copyright © 2016 NVIDIA Corporation
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining
 | 
						|
 * a copy of this software and associated documentation files (the
 | 
						|
 * "Software"), to deal in the Software without restriction, including
 | 
						|
 * without limitation the rights to use, copy, modify, merge, publish,
 | 
						|
 * distribute, sublicense, and/or sell copies of the Software, and to
 | 
						|
 * permit persons to whom the Software is furnished to do so, subject to
 | 
						|
 * the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the
 | 
						|
 * next paragraph) shall be included in all copies or substantial
 | 
						|
 * portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
						|
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
						|
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
						|
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
						|
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
#include "shared/helpers.h"
 | 
						|
#include "shared/platform.h"
 | 
						|
 | 
						|
#include "gl-renderer.h"
 | 
						|
#include "gl-renderer-internal.h"
 | 
						|
#include "pixel-formats.h"
 | 
						|
#include "shared/weston-egl-ext.h"
 | 
						|
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
struct egl_config_print_info {
 | 
						|
	const EGLint *attrs;
 | 
						|
	unsigned attrs_count;
 | 
						|
	const char *prefix;
 | 
						|
	const char *separator;
 | 
						|
	int field_width;
 | 
						|
};
 | 
						|
 | 
						|
static const char *
 | 
						|
egl_error_string(EGLint code)
 | 
						|
{
 | 
						|
#define MYERRCODE(x) case x: return #x;
 | 
						|
	switch (code) {
 | 
						|
	MYERRCODE(EGL_SUCCESS)
 | 
						|
	MYERRCODE(EGL_NOT_INITIALIZED)
 | 
						|
	MYERRCODE(EGL_BAD_ACCESS)
 | 
						|
	MYERRCODE(EGL_BAD_ALLOC)
 | 
						|
	MYERRCODE(EGL_BAD_ATTRIBUTE)
 | 
						|
	MYERRCODE(EGL_BAD_CONTEXT)
 | 
						|
	MYERRCODE(EGL_BAD_CONFIG)
 | 
						|
	MYERRCODE(EGL_BAD_CURRENT_SURFACE)
 | 
						|
	MYERRCODE(EGL_BAD_DISPLAY)
 | 
						|
	MYERRCODE(EGL_BAD_SURFACE)
 | 
						|
	MYERRCODE(EGL_BAD_MATCH)
 | 
						|
	MYERRCODE(EGL_BAD_PARAMETER)
 | 
						|
	MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
 | 
						|
	MYERRCODE(EGL_BAD_NATIVE_WINDOW)
 | 
						|
	MYERRCODE(EGL_CONTEXT_LOST)
 | 
						|
	default:
 | 
						|
		return "unknown";
 | 
						|
	}
 | 
						|
#undef MYERRCODE
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gl_renderer_print_egl_error_state(void)
 | 
						|
{
 | 
						|
	EGLint code;
 | 
						|
 | 
						|
	code = eglGetError();
 | 
						|
	weston_log("EGL error state: %s (0x%04lx)\n",
 | 
						|
		egl_error_string(code), (long)code);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
print_egl_surface_type_bits(FILE *fp, EGLint egl_surface_type)
 | 
						|
{
 | 
						|
	const char *sep = "";
 | 
						|
	unsigned i;
 | 
						|
 | 
						|
	static const struct {
 | 
						|
		EGLint bit;
 | 
						|
		const char *str;
 | 
						|
	} egl_surf_bits[] = {
 | 
						|
		{ EGL_WINDOW_BIT, "win" },
 | 
						|
		{ EGL_PIXMAP_BIT, "pix" },
 | 
						|
		{ EGL_PBUFFER_BIT, "pbf" },
 | 
						|
		{ EGL_MULTISAMPLE_RESOLVE_BOX_BIT, "ms_resolve_box" },
 | 
						|
		{ EGL_SWAP_BEHAVIOR_PRESERVED_BIT, "swap_preserved" },
 | 
						|
	};
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_LENGTH(egl_surf_bits); i++) {
 | 
						|
		if (egl_surface_type & egl_surf_bits[i].bit) {
 | 
						|
			fprintf(fp, "%s%s", sep, egl_surf_bits[i].str);
 | 
						|
			sep = "|";
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static const struct egl_config_print_info config_info_ints[] = {
 | 
						|
#define ARRAY(...) ((const EGLint[]) { __VA_ARGS__ })
 | 
						|
 | 
						|
	{ ARRAY(EGL_CONFIG_ID), 1, "id: ", "", 3 },
 | 
						|
	{ ARRAY(EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, EGL_ALPHA_SIZE), 4,
 | 
						|
	  "rgba: ", " ", 1 },
 | 
						|
	{ ARRAY(EGL_BUFFER_SIZE), 1, "buf: ", "", 2 },
 | 
						|
	{ ARRAY(EGL_DEPTH_SIZE), 1, "dep: ", "", 2 },
 | 
						|
	{ ARRAY(EGL_STENCIL_SIZE), 1, "stcl: ", "", 1 },
 | 
						|
	{ ARRAY(EGL_MIN_SWAP_INTERVAL, EGL_MAX_SWAP_INTERVAL), 2,
 | 
						|
	  "int: ", "-", 1 },
 | 
						|
 | 
						|
#undef ARRAY
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
print_egl_config_ints(FILE *fp, EGLDisplay egldpy, EGLConfig eglconfig)
 | 
						|
{
 | 
						|
	unsigned i;
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_LENGTH(config_info_ints); i++) {
 | 
						|
		const struct egl_config_print_info *info = &config_info_ints[i];
 | 
						|
		unsigned j;
 | 
						|
		const char *sep = "";
 | 
						|
 | 
						|
		fputs(info->prefix, fp);
 | 
						|
		for (j = 0; j < info->attrs_count; j++) {
 | 
						|
			EGLint value;
 | 
						|
 | 
						|
			if (eglGetConfigAttrib(egldpy, eglconfig,
 | 
						|
					       info->attrs[j], &value)) {
 | 
						|
				fprintf(fp, "%s%*d",
 | 
						|
					sep, info->field_width, value);
 | 
						|
			} else {
 | 
						|
				fprintf(fp, "%s!", sep);
 | 
						|
			}
 | 
						|
			sep = info->separator;
 | 
						|
		}
 | 
						|
 | 
						|
		fputs(" ", fp);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
print_egl_config_info(FILE *fp, EGLDisplay egldpy, EGLConfig eglconfig)
 | 
						|
{
 | 
						|
	EGLint value;
 | 
						|
 | 
						|
	print_egl_config_ints(fp, egldpy, eglconfig);
 | 
						|
 | 
						|
	fputs("type: ", fp);
 | 
						|
	if (eglGetConfigAttrib(egldpy, eglconfig, EGL_SURFACE_TYPE, &value))
 | 
						|
		print_egl_surface_type_bits(fp, value);
 | 
						|
	else
 | 
						|
		fputs("-", fp);
 | 
						|
 | 
						|
	fputs(" vis_id: ", fp);
 | 
						|
	if (eglGetConfigAttrib(egldpy, eglconfig, EGL_NATIVE_VISUAL_ID, &value)) {
 | 
						|
		if (value != 0) {
 | 
						|
			const struct pixel_format_info *p;
 | 
						|
 | 
						|
			p = pixel_format_get_info(value);
 | 
						|
			if (p) {
 | 
						|
				fprintf(fp, "%s (0x%x)",
 | 
						|
					p->drm_format_name, (unsigned)value);
 | 
						|
			} else {
 | 
						|
				fprintf(fp, "0x%x", (unsigned)value);
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			fputs("0", fp);
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		fputs("-", fp);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
log_all_egl_configs(EGLDisplay egldpy)
 | 
						|
{
 | 
						|
	EGLint count = 0;
 | 
						|
	EGLConfig *configs;
 | 
						|
	int i;
 | 
						|
	char *strbuf = NULL;
 | 
						|
	size_t strsize = 0;
 | 
						|
	FILE *fp;
 | 
						|
 | 
						|
	weston_log("All available EGLConfigs:\n");
 | 
						|
 | 
						|
	if (!eglGetConfigs(egldpy, NULL, 0, &count) || count < 1)
 | 
						|
		return;
 | 
						|
 | 
						|
	configs = calloc(count, sizeof *configs);
 | 
						|
	if (!configs)
 | 
						|
		return;
 | 
						|
 | 
						|
	if (!eglGetConfigs(egldpy, configs, count, &count))
 | 
						|
		return;
 | 
						|
 | 
						|
	fp = open_memstream(&strbuf, &strsize);
 | 
						|
	if (!fp)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	for (i = 0; i < count; i++) {
 | 
						|
		print_egl_config_info(fp, egldpy, configs[i]);
 | 
						|
		fputc(0, fp);
 | 
						|
		fflush(fp);
 | 
						|
		weston_log_continue(STAMP_SPACE "%s\n", strbuf);
 | 
						|
		rewind(fp);
 | 
						|
	}
 | 
						|
 | 
						|
	fclose(fp);
 | 
						|
	free(strbuf);
 | 
						|
 | 
						|
out:
 | 
						|
	free(configs);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
 | 
						|
{
 | 
						|
	char *strbuf = NULL;
 | 
						|
	size_t strsize = 0;
 | 
						|
	FILE *fp;
 | 
						|
 | 
						|
	fp = open_memstream(&strbuf, &strsize);
 | 
						|
	if (fp) {
 | 
						|
		print_egl_config_info(fp, egldpy, eglconfig);
 | 
						|
		fclose(fp);
 | 
						|
	}
 | 
						|
 | 
						|
	weston_log("Chosen EGL config details: %s\n", strbuf ? strbuf : "?");
 | 
						|
	free(strbuf);
 | 
						|
}
 | 
						|
 | 
						|
static bool
 | 
						|
egl_config_pixel_format_matches(struct gl_renderer *gr,
 | 
						|
				EGLConfig config,
 | 
						|
				const struct pixel_format_info *pinfo)
 | 
						|
{
 | 
						|
	static const EGLint attribs[4] = {
 | 
						|
		EGL_ALPHA_SIZE, EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE
 | 
						|
	};
 | 
						|
	const int *argb[4] = {
 | 
						|
		&pinfo->bits.a, &pinfo->bits.r, &pinfo->bits.g, &pinfo->bits.b
 | 
						|
	};
 | 
						|
	unsigned i;
 | 
						|
	EGLint value;
 | 
						|
 | 
						|
	if (gr->platform == EGL_PLATFORM_GBM_KHR) {
 | 
						|
		if (!eglGetConfigAttrib(gr->egl_display, config,
 | 
						|
					EGL_NATIVE_VISUAL_ID, &value))
 | 
						|
			return false;
 | 
						|
 | 
						|
		return ((uint32_t)value) == pinfo->format;
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = 0; i < 4; i++) {
 | 
						|
		if (!eglGetConfigAttrib(gr->egl_display, config,
 | 
						|
					attribs[i], &value))
 | 
						|
			return false;
 | 
						|
		if (value != *argb[i])
 | 
						|
			return false;
 | 
						|
	}
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
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)
 | 
						|
{
 | 
						|
	EGLint count = 0;
 | 
						|
	EGLint matched = 0;
 | 
						|
	EGLConfig *configs;
 | 
						|
	unsigned i;
 | 
						|
	EGLint j;
 | 
						|
	int config_index = -1;
 | 
						|
 | 
						|
	if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1) {
 | 
						|
		weston_log("No EGL configs to choose from.\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	configs = calloc(count, sizeof *configs);
 | 
						|
	if (!configs)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	if (!eglChooseConfig(gr->egl_display, attribs, configs,
 | 
						|
			      count, &matched) || !matched) {
 | 
						|
		weston_log("No EGL configs with appropriate attributes.\n");
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	if (pinfo_count == 0)
 | 
						|
		config_index = 0;
 | 
						|
 | 
						|
	for (i = 0; config_index == -1 && i < pinfo_count; i++)
 | 
						|
		for (j = 0; config_index == -1 && j < matched; j++)
 | 
						|
			if (egl_config_pixel_format_matches(gr, configs[j],
 | 
						|
							    pinfo[i]))
 | 
						|
				config_index = j;
 | 
						|
 | 
						|
	if (config_index != -1)
 | 
						|
		*config_out = configs[config_index];
 | 
						|
 | 
						|
out:
 | 
						|
	free(configs);
 | 
						|
	if (config_index == -1)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	if (i > 1)
 | 
						|
		weston_log("Unable to use first choice EGL config with"
 | 
						|
			   " %s, succeeded with alternate %s.\n",
 | 
						|
			   pinfo[0]->drm_format_name,
 | 
						|
			   pinfo[i - 1]->drm_format_name);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
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)
 | 
						|
{
 | 
						|
	EGLint value;
 | 
						|
	unsigned i;
 | 
						|
 | 
						|
	if (config == EGL_NO_CONFIG_KHR)
 | 
						|
		return false;
 | 
						|
 | 
						|
	if (!eglGetConfigAttrib(gr->egl_display, config,
 | 
						|
				EGL_SURFACE_TYPE, &value))
 | 
						|
		return false;
 | 
						|
	if ((value & egl_surface_type) != egl_surface_type)
 | 
						|
		return false;
 | 
						|
 | 
						|
	for (i = 0; i < pinfo_count; i++) {
 | 
						|
		if (egl_config_pixel_format_matches(gr, config, pinfo[i]))
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
/* The caller must free() the string */
 | 
						|
static char *
 | 
						|
explain_egl_config_criteria(EGLint egl_surface_type,
 | 
						|
			    const struct pixel_format_info *const *pinfo,
 | 
						|
			    unsigned pinfo_count)
 | 
						|
{
 | 
						|
	FILE *fp;
 | 
						|
	char *str = NULL;
 | 
						|
	size_t size = 0;
 | 
						|
	const char *sep;
 | 
						|
	unsigned i;
 | 
						|
 | 
						|
	fp = open_memstream(&str, &size);
 | 
						|
	if (!fp)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	fputs("{ ", fp);
 | 
						|
 | 
						|
	print_egl_surface_type_bits(fp, egl_surface_type);
 | 
						|
	fputs("; ", fp);
 | 
						|
 | 
						|
	sep = "";
 | 
						|
	for (i = 0; i < pinfo_count; i++) {
 | 
						|
		fprintf(fp, "%s%s", sep, pinfo[i]->drm_format_name);
 | 
						|
		sep = ", ";
 | 
						|
	}
 | 
						|
 | 
						|
	fputs(" }", fp);
 | 
						|
 | 
						|
	fclose(fp);
 | 
						|
 | 
						|
	return str;
 | 
						|
}
 | 
						|
 | 
						|
EGLConfig
 | 
						|
gl_renderer_get_egl_config(struct gl_renderer *gr,
 | 
						|
			   EGLint egl_surface_type,
 | 
						|
			   const uint32_t *drm_formats,
 | 
						|
			   unsigned drm_formats_count)
 | 
						|
{
 | 
						|
	EGLConfig egl_config;
 | 
						|
	const struct pixel_format_info *pinfo[16];
 | 
						|
	unsigned pinfo_count;
 | 
						|
	unsigned i;
 | 
						|
	char *what;
 | 
						|
	EGLint config_attribs[] = {
 | 
						|
		EGL_SURFACE_TYPE,    egl_surface_type,
 | 
						|
		EGL_RED_SIZE,        1,
 | 
						|
		EGL_GREEN_SIZE,      1,
 | 
						|
		EGL_BLUE_SIZE,       1,
 | 
						|
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
 | 
						|
		EGL_NONE
 | 
						|
	};
 | 
						|
 | 
						|
	assert(drm_formats_count < ARRAY_LENGTH(pinfo));
 | 
						|
	drm_formats_count = MIN(drm_formats_count, ARRAY_LENGTH(pinfo));
 | 
						|
 | 
						|
	for (pinfo_count = 0, i = 0; i < drm_formats_count; i++) {
 | 
						|
		pinfo[pinfo_count] = pixel_format_get_info(drm_formats[i]);
 | 
						|
		if (!pinfo[pinfo_count]) {
 | 
						|
			weston_log("Bad/unknown DRM format code 0x%08x.\n",
 | 
						|
				   drm_formats[i]);
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		pinfo_count++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (egl_config_is_compatible(gr, gr->egl_config, egl_surface_type,
 | 
						|
				     pinfo, pinfo_count))
 | 
						|
		return gr->egl_config;
 | 
						|
 | 
						|
	if (egl_choose_config(gr, config_attribs, pinfo, pinfo_count,
 | 
						|
			      &egl_config) < 0) {
 | 
						|
		what = explain_egl_config_criteria(egl_surface_type,
 | 
						|
						   pinfo, pinfo_count);
 | 
						|
		weston_log("No EGLConfig matches %s.\n", what);
 | 
						|
		free(what);
 | 
						|
		log_all_egl_configs(gr->egl_display);
 | 
						|
		return EGL_NO_CONFIG_KHR;
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * If we do not have configless context support, all EGLConfigs must
 | 
						|
	 * be the one and the same, because we use just one GL context for
 | 
						|
	 * everything.
 | 
						|
	 */
 | 
						|
	if (gr->egl_config != EGL_NO_CONFIG_KHR &&
 | 
						|
	    egl_config != gr->egl_config) {
 | 
						|
		what = explain_egl_config_criteria(egl_surface_type,
 | 
						|
						   pinfo, pinfo_count);
 | 
						|
		weston_log("Found an EGLConfig matching %s but it is not usable"
 | 
						|
			   " because neither EGL_KHR_no_config_context nor "
 | 
						|
			   "EGL_MESA_configless_context are supported by EGL.\n",
 | 
						|
			   what);
 | 
						|
		free(what);
 | 
						|
		return EGL_NO_CONFIG_KHR;
 | 
						|
	}
 | 
						|
 | 
						|
	return egl_config;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
renderer_setup_egl_client_extensions(struct gl_renderer *gr)
 | 
						|
{
 | 
						|
	const char *extensions;
 | 
						|
 | 
						|
	extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
 | 
						|
	if (!extensions) {
 | 
						|
		weston_log("Retrieving EGL client extension string failed.\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_EXT_platform_base"))
 | 
						|
		gr->create_platform_window =
 | 
						|
			(void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
 | 
						|
	else
 | 
						|
		weston_log("warning: EGL_EXT_platform_base not supported.\n");
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
 | 
						|
{
 | 
						|
	static const struct {
 | 
						|
		char *extension, *entrypoint;
 | 
						|
	} swap_damage_ext_to_entrypoint[] = {
 | 
						|
		{
 | 
						|
			.extension = "EGL_EXT_swap_buffers_with_damage",
 | 
						|
			.entrypoint = "eglSwapBuffersWithDamageEXT",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			.extension = "EGL_KHR_swap_buffers_with_damage",
 | 
						|
			.entrypoint = "eglSwapBuffersWithDamageKHR",
 | 
						|
		},
 | 
						|
	};
 | 
						|
	struct gl_renderer *gr = get_renderer(ec);
 | 
						|
	const char *extensions;
 | 
						|
	EGLBoolean ret;
 | 
						|
	unsigned i;
 | 
						|
 | 
						|
	gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
 | 
						|
	gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
 | 
						|
 | 
						|
	gr->bind_display =
 | 
						|
		(void *) eglGetProcAddress("eglBindWaylandDisplayWL");
 | 
						|
	gr->unbind_display =
 | 
						|
		(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
 | 
						|
	gr->query_buffer =
 | 
						|
		(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
 | 
						|
	gr->set_damage_region =
 | 
						|
		(void *) eglGetProcAddress("eglSetDamageRegionKHR");
 | 
						|
 | 
						|
	extensions =
 | 
						|
		(const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
 | 
						|
	if (!extensions) {
 | 
						|
		weston_log("Retrieving EGL extension string failed.\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_IMG_context_priority"))
 | 
						|
		gr->has_context_priority = true;
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_WL_bind_wayland_display"))
 | 
						|
		gr->has_bind_display = true;
 | 
						|
	if (gr->has_bind_display) {
 | 
						|
		assert(gr->bind_display);
 | 
						|
		assert(gr->unbind_display);
 | 
						|
		assert(gr->query_buffer);
 | 
						|
		ret = gr->bind_display(gr->egl_display, ec->wl_display);
 | 
						|
		if (!ret)
 | 
						|
			gr->has_bind_display = false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_EXT_buffer_age"))
 | 
						|
		gr->has_egl_buffer_age = true;
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_KHR_partial_update")) {
 | 
						|
		assert(gr->set_damage_region);
 | 
						|
		gr->has_egl_partial_update = true;
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_LENGTH(swap_damage_ext_to_entrypoint); i++) {
 | 
						|
		if (weston_check_egl_extension(extensions,
 | 
						|
				swap_damage_ext_to_entrypoint[i].extension)) {
 | 
						|
			gr->swap_buffers_with_damage =
 | 
						|
				(void *) eglGetProcAddress(
 | 
						|
						swap_damage_ext_to_entrypoint[i].entrypoint);
 | 
						|
			assert(gr->swap_buffers_with_damage);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_KHR_no_config_context") ||
 | 
						|
	    weston_check_egl_extension(extensions, "EGL_MESA_configless_context"))
 | 
						|
		gr->has_configless_context = true;
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_KHR_surfaceless_context"))
 | 
						|
		gr->has_surfaceless_context = true;
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_EXT_image_dma_buf_import"))
 | 
						|
		gr->has_dmabuf_import = true;
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions,
 | 
						|
				"EGL_EXT_image_dma_buf_import_modifiers")) {
 | 
						|
		gr->query_dmabuf_formats =
 | 
						|
			(void *) eglGetProcAddress("eglQueryDmaBufFormatsEXT");
 | 
						|
		gr->query_dmabuf_modifiers =
 | 
						|
			(void *) eglGetProcAddress("eglQueryDmaBufModifiersEXT");
 | 
						|
		assert(gr->query_dmabuf_formats);
 | 
						|
		assert(gr->query_dmabuf_modifiers);
 | 
						|
		gr->has_dmabuf_import_modifiers = true;
 | 
						|
	}
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_KHR_fence_sync") &&
 | 
						|
	    weston_check_egl_extension(extensions, "EGL_ANDROID_native_fence_sync")) {
 | 
						|
		gr->create_sync =
 | 
						|
			(void *) eglGetProcAddress("eglCreateSyncKHR");
 | 
						|
		gr->destroy_sync =
 | 
						|
			(void *) eglGetProcAddress("eglDestroySyncKHR");
 | 
						|
		gr->dup_native_fence_fd =
 | 
						|
			(void *) eglGetProcAddress("eglDupNativeFenceFDANDROID");
 | 
						|
		assert(gr->create_sync);
 | 
						|
		assert(gr->destroy_sync);
 | 
						|
		assert(gr->dup_native_fence_fd);
 | 
						|
		gr->has_native_fence_sync = true;
 | 
						|
	} else {
 | 
						|
		weston_log("warning: Disabling render GPU timeline and explicit "
 | 
						|
			   "synchronization due to missing "
 | 
						|
			   "EGL_ANDROID_native_fence_sync extension\n");
 | 
						|
	}
 | 
						|
 | 
						|
	if (weston_check_egl_extension(extensions, "EGL_KHR_wait_sync")) {
 | 
						|
		gr->wait_sync = (void *) eglGetProcAddress("eglWaitSyncKHR");
 | 
						|
		assert(gr->wait_sync);
 | 
						|
		gr->has_wait_sync = true;
 | 
						|
	} else {
 | 
						|
		weston_log("warning: Disabling explicit synchronization due"
 | 
						|
			   "to missing EGL_KHR_wait_sync extension\n");
 | 
						|
	}
 | 
						|
 | 
						|
	renderer_setup_egl_client_extensions(gr);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 |