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: Daniel Stone <daniels@collabora.com>
Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Daniel Stone
7 years ago
0 | 0 | /* |
1 | 1 | * Copyright (c) 2017 Rob Clark <rclark@redhat.com> |
2 | * Copyright © 2013 Intel Corporation | |
2 | 3 | * |
3 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
4 | 5 | * copy of this software and associated documentation files (the "Software"), |
22 | 23 | |
23 | 24 | #include <errno.h> |
24 | 25 | #include <fcntl.h> |
26 | #include <stdbool.h> | |
25 | 27 | #include <stdio.h> |
26 | 28 | #include <stdlib.h> |
27 | 29 | #include <string.h> |
77 | 79 | return &gbm; |
78 | 80 | } |
79 | 81 | |
82 | static bool has_ext(const char *extension_list, const char *ext) | |
83 | { | |
84 | const char *ptr = extension_list; | |
85 | int len = strlen(ext); | |
86 | ||
87 | if (ptr == NULL || *ptr == '\0') | |
88 | return false; | |
89 | ||
90 | while (true) { | |
91 | ptr = strstr(ptr, ext); | |
92 | if (!ptr) | |
93 | return false; | |
94 | ||
95 | if (ptr[len] == ' ' || ptr[len] == '\0') | |
96 | return true; | |
97 | ||
98 | ptr += len; | |
99 | } | |
100 | } | |
101 | ||
80 | 102 | int init_egl(struct egl *egl, const struct gbm *gbm) |
81 | 103 | { |
82 | 104 | EGLint major, minor, n; |
95 | 117 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
96 | 118 | EGL_NONE |
97 | 119 | }; |
98 | ||
99 | #define get_proc(name) do { \ | |
100 | egl->name = (void *)eglGetProcAddress(#name); \ | |
120 | const char *egl_exts_client, *egl_exts_dpy, *gl_exts; | |
121 | ||
122 | #define get_proc_client(ext, name) do { \ | |
123 | if (has_ext(egl_exts_client, #ext)) \ | |
124 | egl->name = (void *)eglGetProcAddress(#name); \ | |
101 | 125 | } while (0) |
102 | ||
103 | get_proc(eglGetPlatformDisplayEXT); | |
104 | get_proc(eglCreateImageKHR); | |
105 | get_proc(eglDestroyImageKHR); | |
106 | get_proc(glEGLImageTargetTexture2DOES); | |
107 | get_proc(eglCreateSyncKHR); | |
108 | get_proc(eglDestroySyncKHR); | |
109 | get_proc(eglWaitSyncKHR); | |
110 | get_proc(eglDupNativeFenceFDANDROID); | |
126 | #define get_proc_dpy(ext, name) do { \ | |
127 | if (has_ext(egl_exts_dpy, #ext)) \ | |
128 | egl->name = (void *)eglGetProcAddress(#name); \ | |
129 | } while (0) | |
130 | ||
131 | #define get_proc_gl(ext, name) do { \ | |
132 | if (has_ext(gl_exts, #ext)) \ | |
133 | egl->name = (void *)eglGetProcAddress(#name); \ | |
134 | } while (0) | |
135 | ||
136 | egl_exts_client = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | |
137 | get_proc_client(EGL_EXT_platform_base, eglGetPlatformDisplayEXT); | |
111 | 138 | |
112 | 139 | if (egl->eglGetPlatformDisplayEXT) { |
113 | 140 | egl->display = egl->eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, |
121 | 148 | return -1; |
122 | 149 | } |
123 | 150 | |
151 | egl_exts_dpy = eglQueryString(egl->display, EGL_EXTENSIONS); | |
152 | get_proc_dpy(EGL_KHR_image_base, eglCreateImageKHR); | |
153 | get_proc_dpy(EGL_KHR_image_base, eglDestroyImageKHR); | |
154 | get_proc_dpy(EGL_KHR_fence_sync, eglCreateSyncKHR); | |
155 | get_proc_dpy(EGL_KHR_fence_sync, eglDestroySyncKHR); | |
156 | get_proc_dpy(EGL_KHR_fence_sync, eglWaitSyncKHR); | |
157 | get_proc_dpy(EGL_ANDROID_native_fence_sync, eglDupNativeFenceFDANDROID); | |
158 | ||
124 | 159 | printf("Using display %p with EGL version %d.%d\n", |
125 | 160 | egl->display, major, minor); |
126 | 161 | |
128 | 163 | printf("EGL information:\n"); |
129 | 164 | printf(" version: \"%s\"\n", eglQueryString(egl->display, EGL_VERSION)); |
130 | 165 | printf(" vendor: \"%s\"\n", eglQueryString(egl->display, EGL_VENDOR)); |
131 | printf(" extensions: \"%s\"\n", eglQueryString(egl->display, EGL_EXTENSIONS)); | |
166 | printf(" client extensions: \"%s\"\n", egl_exts_client); | |
167 | printf(" display extensions: \"%s\"\n", egl_exts_dpy); | |
132 | 168 | printf("===================================\n"); |
133 | 169 | |
134 | 170 | if (!eglBindAPI(EGL_OPENGL_ES_API)) { |
158 | 194 | /* connect the context to the surface */ |
159 | 195 | eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context); |
160 | 196 | |
197 | gl_exts = (char *) glGetString(GL_EXTENSIONS); | |
161 | 198 | printf("OpenGL ES 2.x information:\n"); |
162 | 199 | printf(" version: \"%s\"\n", glGetString(GL_VERSION)); |
163 | 200 | printf(" shading language version: \"%s\"\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); |
164 | 201 | printf(" vendor: \"%s\"\n", glGetString(GL_VENDOR)); |
165 | 202 | printf(" renderer: \"%s\"\n", glGetString(GL_RENDERER)); |
166 | printf(" extensions: \"%s\"\n", glGetString(GL_EXTENSIONS)); | |
203 | printf(" extensions: \"%s\"\n", gl_exts); | |
167 | 204 | printf("===================================\n"); |
205 | ||
206 | get_proc_gl(GL_OES_EGL_image, glEGLImageTargetTexture2DOES); | |
168 | 207 | |
169 | 208 | return 0; |
170 | 209 | } |