Commit c84b17c5 authored by Daniel Stone's avatar Daniel Stone

common: Check for extensions before resolving symbols

eglGetProcAddress is allowed to return any old garbage for symbols it
doesn't know about. To avoid any mishaps, check for the appropriate
extension presence (split into EGL client extension, EGL display
extension, and GL extension, checks) before we look up any symbols
through it.

The walk through the extension list is taken from libepoxy.
Signed-off-by: 's avatarDaniel Stone <daniels@collabora.com>
Reviewed-by: 's avatarEric Engestrom <eric.engestrom@imgtec.com>
Reviewed-by: 's avatarEmil Velikov <emil.velikov@collabora.com>
parent d8bb1379
/*
* Copyright (c) 2017 Rob Clark <rclark@redhat.com>
* Copyright © 2013 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
......@@ -23,6 +24,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -78,6 +80,26 @@ const struct gbm * init_gbm(int drm_fd, int w, int h, uint64_t modifier)
return &gbm;
}
static bool has_ext(const char *extension_list, const char *ext)
{
const char *ptr = extension_list;
int len = strlen(ext);
if (ptr == NULL || *ptr == '\0')
return false;
while (true) {
ptr = strstr(ptr, ext);
if (!ptr)
return false;
if (ptr[len] == ' ' || ptr[len] == '\0')
return true;
ptr += len;
}
}
int init_egl(struct egl *egl, const struct gbm *gbm)
{
EGLint major, minor, n;
......@@ -96,19 +118,24 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
const char *egl_exts_client, *egl_exts_dpy, *gl_exts;
#define get_proc_client(ext, name) do { \
if (has_ext(egl_exts_client, #ext)) \
egl->name = (void *)eglGetProcAddress(#name); \
} while (0)
#define get_proc_dpy(ext, name) do { \
if (has_ext(egl_exts_dpy, #ext)) \
egl->name = (void *)eglGetProcAddress(#name); \
} while (0)
#define get_proc(name) do { \
egl->name = (void *)eglGetProcAddress(#name); \
#define get_proc_gl(ext, name) do { \
if (has_ext(gl_exts, #ext)) \
egl->name = (void *)eglGetProcAddress(#name); \
} while (0)
get_proc(eglGetPlatformDisplayEXT);
get_proc(eglCreateImageKHR);
get_proc(eglDestroyImageKHR);
get_proc(glEGLImageTargetTexture2DOES);
get_proc(eglCreateSyncKHR);
get_proc(eglDestroySyncKHR);
get_proc(eglWaitSyncKHR);
get_proc(eglDupNativeFenceFDANDROID);
egl_exts_client = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
get_proc_client(EGL_EXT_platform_base, eglGetPlatformDisplayEXT);
if (egl->eglGetPlatformDisplayEXT) {
egl->display = egl->eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR,
......@@ -122,6 +149,14 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
return -1;
}
egl_exts_dpy = eglQueryString(egl->display, EGL_EXTENSIONS);
get_proc_dpy(EGL_KHR_image_base, eglCreateImageKHR);
get_proc_dpy(EGL_KHR_image_base, eglDestroyImageKHR);
get_proc_dpy(EGL_KHR_fence_sync, eglCreateSyncKHR);
get_proc_dpy(EGL_KHR_fence_sync, eglDestroySyncKHR);
get_proc_dpy(EGL_KHR_fence_sync, eglWaitSyncKHR);
get_proc_dpy(EGL_ANDROID_native_fence_sync, eglDupNativeFenceFDANDROID);
printf("Using display %p with EGL version %d.%d\n",
egl->display, major, minor);
......@@ -129,7 +164,8 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
printf("EGL information:\n");
printf(" version: \"%s\"\n", eglQueryString(egl->display, EGL_VERSION));
printf(" vendor: \"%s\"\n", eglQueryString(egl->display, EGL_VENDOR));
printf(" extensions: \"%s\"\n", eglQueryString(egl->display, EGL_EXTENSIONS));
printf(" client extensions: \"%s\"\n", egl_exts_client);
printf(" display extensions: \"%s\"\n", egl_exts_dpy);
printf("===================================\n");
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
......@@ -159,14 +195,17 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
/* connect the context to the surface */
eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context);
gl_exts = (char *) glGetString(GL_EXTENSIONS);
printf("OpenGL ES 2.x information:\n");
printf(" version: \"%s\"\n", glGetString(GL_VERSION));
printf(" shading language version: \"%s\"\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
printf(" vendor: \"%s\"\n", glGetString(GL_VENDOR));
printf(" renderer: \"%s\"\n", glGetString(GL_RENDERER));
printf(" extensions: \"%s\"\n", glGetString(GL_EXTENSIONS));
printf(" extensions: \"%s\"\n", gl_exts);
printf("===================================\n");
get_proc_gl(GL_OES_EGL_image, glEGLImageTargetTexture2DOES);
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment