1 /*
   2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * an EGL library wrapper
  28  *
  29  * The why of this GL/EGL library wrapper:
  30  * Vendors provide very different versions of the libraries, and linking
  31  * directly with those libraries introduces a loader depenancy chain.
  32  * But using this wrapper allows us to avoid this at the code of loading
  33  * all the symbols needed at runtime and one level of indirection.
  34  *
  35  * to use, simply link this file, as well as the provided stub versions of -lEGL -lGLESv2
  36  * call openNativeFramebuffer() to get the NativeDisplayType and the NativeWindowType
  37  * that match the platform.
  38  *
  39  */
  40 
  41 #include <stdio.h>
  42 #include <stdlib.h>
  43 #include <linux/fb.h>
  44 #include <fcntl.h>
  45 #ifndef __USE_GNU // required for dladdr() & Dl_info
  46 #define __USE_GNU
  47 #endif
  48 #include <dlfcn.h>
  49 #include <sys/ioctl.h>
  50 
  51 #include <string.h>
  52 #include <strings.h>
  53 
  54 #define WRAPPEDAPI
  55 #include "eglWrapper.h"
  56 
  57 int load_wrapped_gles_symbols(void);
  58 void *libglesv2;
  59 void *libegl;
  60 int done_loading_symbols = 0;
  61 
  62 /***************************** UTILITY ********************************/
  63 
  64 #ifdef ANDROID_NDK
  65 
  66 static EGLDisplay(*_eglGetDisplay)(EGLNativeDisplayType display_id);
  67 static EGLNativeWindowType(*_ANDROID_getNativeWindow)();
  68 
  69 #else
  70 
  71 PrismNativePort prismPort;
  72 
  73 #endif
  74 
  75 int load_wrapped_gles_symbols() {
  76     if (done_loading_symbols)  {
  77         return 0;
  78     }
  79     done_loading_symbols = 1;
  80 
  81 #ifdef ANDROID_NDK
  82     libegl = dlopen("libEGL.so", RTLD_LAZY | RTLD_GLOBAL);
  83     if (!libegl) {
  84         fprintf(stderr, "Did not find libEGL.so %s\n", dlerror());
  85         return 0;
  86     }
  87 
  88     _eglGetDisplay = dlsym(libegl, "eglGetDisplay");
  89 
  90     libglesv2 = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_GLOBAL);
  91     if (!libglesv2) {
  92         fprintf(stderr, "Did not find libGLESv2.so %s\n", dlerror());
  93         return 0;
  94     }
  95 #else
  96 
  97     Dl_info dlinfo;
  98     if (dladdr(&load_wrapped_gles_symbols, &dlinfo)) {
  99 
 100         size_t rslash = (size_t)rindex(dlinfo.dli_fname,'/');
 101         if (rslash) {
 102             char *b = (char *) alloca(strlen(dlinfo.dli_fname)+20);
 103             rslash = rslash + 1 - (size_t)dlinfo.dli_fname;
 104             strncpy(b, dlinfo.dli_fname,rslash);
 105             strcpy(b + rslash, LENSPORT_LIBRARY_NAME);
 106 
 107             jboolean (*prism_platform_init)(PrismNativePort*) =  0;
 108 
 109             void *dlhand = dlopen(b,RTLD_NOW);
 110             if (dlhand) {
 111                 prism_platform_init =  dlsym(dlhand, "prism_platform_initialize");
 112                 if (!prism_platform_init) {
 113                     fprintf(stderr,"prism_platform_initialize missing in %s\n",LENSPORT_LIBRARY_NAME);
 114                     exit(-1);
 115                 }
 116             } else {
 117                 fprintf(stderr,"Prism FAILED TO OPEN %s\n",b);
 118                 fprintf(stderr,"dlopen reports %s\n",dlerror());
 119                 exit(-1);
 120             }
 121             prismPort.version = NATIVE_PRISM_PORT_VERSION;
 122 
 123             if (!(*prism_platform_init)(&prismPort)) {
 124                 fprintf(stderr,"prism_platform_initialize failed\n");
 125                 exit(-1);
 126             }
 127         }
 128     } else {
 129         printf("Did not get DLINFO\n");
 130         exit(-1);
 131     }
 132 
 133 #endif
 134     return 1;
 135 }
 136 
 137 EGLNativeDisplayType getNativeDisplayType() {
 138     if (!done_loading_symbols) {
 139         load_wrapped_gles_symbols();
 140     }
 141 #ifdef ANDROID_NDK
 142     return (EGLNativeDisplayType) NULL;
 143 #else
 144     return (EGLNativeDisplayType) (*prismPort.getNativeDisplayType)();
 145 #endif
 146 
 147 }
 148 
 149 EGLNativeWindowType getNativeWindowType() {
 150     if (!done_loading_symbols) {
 151         load_wrapped_gles_symbols();
 152     }
 153 
 154 #ifdef ANDROID_NDK
 155 #ifdef DALVIK_VM
 156 #define ANDROID_LIB "libactivity.so"
 157 #define GET_NATIVE_WINDOW "android_getNativeWindow"
 158 #else
 159 #define ANDROID_LIB "libglass_lens_android.so"
 160 #define GET_NATIVE_WINDOW "ANDROID_getNativeWindow"
 161 #endif
 162     //don't cache for Android!
 163     printf("Using %s\n", ANDROID_LIB);
 164     void *libglass_android = dlopen(ANDROID_LIB, RTLD_LAZY | RTLD_GLOBAL);
 165     if (!libglass_android) {
 166         fprintf(stderr, "Did not find %s %s\n", ANDROID_LIB, dlerror());
 167            return NULL;
 168     }
 169     _ANDROID_getNativeWindow = dlsym(libglass_android, GET_NATIVE_WINDOW);
 170     if (!_ANDROID_getNativeWindow) {
 171        fprintf(stderr, "Did not find symbol \"%s\" %s\n", GET_NATIVE_WINDOW, dlerror());
 172        return NULL;
 173     }
 174     return (*_ANDROID_getNativeWindow)();
 175 #else
 176     return (EGLNativeWindowType) (*prismPort.getNativeWindowType)();
 177 #endif
 178 }
 179 
 180 EGLDisplay wr_eglGetDisplay(EGLNativeDisplayType display_id) {
 181 #ifdef ANDROID_NDK
 182     return  (*_eglGetDisplay)(display_id);
 183 #else
 184     return (EGLDisplay) (*prismPort.wr_eglGetDisplay)((void*)display_id);
 185 #endif
 186 }
 187 
 188 void * getLibGLEShandle() {
 189 #ifdef ANDROID_NDK
 190     return libglesv2;
 191 #else
 192     return (*prismPort.getLibGLEShandle)();
 193 #endif
 194 }
 195