1/* 2 * Copyright © 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24/** 25 * @file egl_without_glx.c 26 * 27 * Tries to test operation of the library on a GL stack with EGL and 28 * GLES but no GLX or desktop GL (such as Arm's Mali GLES3 drivers). 29 * This test is varied by the GLES_VERSION defined at compile time to 30 * test either a GLES1-only or a GLES2-only system. 31 */ 32 33#define _GNU_SOURCE 34 35#include <stdio.h> 36#include <string.h> 37#include <stdlib.h> 38#include <assert.h> 39#include <err.h> 40#include <dlfcn.h> 41#include "epoxy/gl.h" 42#include "epoxy/egl.h" 43 44#include "egl_common.h" 45 46/** 47 * Wraps the system dlopen(), which libepoxy will end up calling when 48 * it tries to dlopen() the API libraries, and errors out the 49 * libraries we're trying to simulate not being installed on the 50 * system. 51 */ 52void * 53dlopen(const char *filename, int flag) 54{ 55 void * (*dlopen_unwrapped)(const char *filename, int flag); 56 57 if (filename) { 58 if (!strcmp(filename, "libGL.so.1")) 59 return NULL; 60#if GLES_VERSION == 2 61 if (!strcmp(filename, "libGLESv1_CM.so.1")) 62 return NULL; 63#else 64 if (!strcmp(filename, "libGLESv2.so.2")) 65 return NULL; 66#endif 67 } 68 69 dlopen_unwrapped = dlsym(RTLD_NEXT, "dlopen"); 70 assert(dlopen_unwrapped); 71 72 return dlopen_unwrapped(filename, flag); 73} 74 75 76static EGLenum last_api; 77static EGLenum extra_error = EGL_SUCCESS; 78 79/** 80 * Override of the real libEGL's eglBindAPI to simulate the target 81 * system's eglBindAPI. 82 */ 83static EGLBoolean 84override_eglBindAPI(EGLenum api) 85{ 86 void *egl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); 87 EGLBoolean (*real_eglBindAPI)(EGLenum api) = dlsym(egl, "eglBindAPI"); 88 89 last_api = api; 90 91 if (api == EGL_OPENGL_API) { 92 extra_error = EGL_BAD_PARAMETER; 93 return EGL_FALSE; 94 } 95 96 assert(real_eglBindAPI); 97 return real_eglBindAPI(api); 98} 99 100/** 101 * Override of the real libEGL's eglGetError() to feed back the error 102 * that might have been generated by override_eglBindAPI(). 103 */ 104static EGLint 105override_eglGetError(void) 106{ 107 void *egl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); 108 EGLint (*real_eglGetError)(void) = dlsym(egl, "eglGetError"); 109 110 if (extra_error != EGL_SUCCESS) { 111 EGLenum error = extra_error; 112 extra_error = EGL_SUCCESS; 113 return error; 114 } 115 116 assert(real_eglGetError); 117 return real_eglGetError(); 118} 119 120int 121main(int argc, char **argv) 122{ 123 bool pass = true; 124 EGLDisplay *dpy = get_egl_display_or_skip(); 125 EGLint context_attribs[] = { 126 EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, 127 EGL_NONE 128 }; 129 EGLConfig cfg; 130 EGLint config_attribs[] = { 131 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 132 EGL_RED_SIZE, 1, 133 EGL_GREEN_SIZE, 1, 134 EGL_BLUE_SIZE, 1, 135 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, 136 EGL_NONE 137 }; 138 EGLint count; 139 EGLContext ctx; 140 const unsigned char *string; 141 142 epoxy_eglBindAPI = override_eglBindAPI; 143 epoxy_eglGetError = override_eglGetError; 144 145 if (!epoxy_has_egl_extension(dpy, "EGL_KHR_surfaceless_context")) 146 errx(77, "Test requires EGL_KHR_surfaceless_context"); 147 148 eglBindAPI(EGL_OPENGL_ES_API); 149 150 if (!eglChooseConfig(dpy, config_attribs, &cfg, 1, &count)) 151 errx(77, "Couldn't get an EGLConfig\n"); 152 153 ctx = eglCreateContext(dpy, cfg, NULL, context_attribs); 154 if (!ctx) 155 errx(77, "Couldn't create a GLES%d context\n", GLES_VERSION); 156 157 eglMakeCurrent(dpy, NULL, NULL, ctx); 158 159 string = glGetString(GL_VERSION); 160 printf("GL_VERSION: %s\n", string); 161 162 assert(eglGetError() == EGL_SUCCESS); 163 164 return pass != true; 165} 166