Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <android/log.h>
     18 #include <cstring>
     19 #include <EGL/egl.h>
     20 #include <GLES3/gl3.h>
     21 #include <string>
     22 #include <string.h>
     23 #include <unordered_map>
     24 
     25 #define xstr(a) str(a)
     26 #define str(a) #a
     27 
     28 #define LOG_TAG "glesLayer" xstr(LAYERNAME)
     29 
     30 #define ALOGI(msg, ...) \
     31     __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
     32 
     33 
     34 // Announce if anything loads this layer.  LAYERNAME is defined in Android.mk
     35 class StaticLogMessage {
     36     public:
     37         StaticLogMessage(const char* msg) {
     38             ALOGI("%s", msg);
     39     }
     40 };
     41 StaticLogMessage g_initMessage("glesLayer" xstr(LAYERNAME) " loaded");
     42 
     43 typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
     44 typedef void* (*PFNEGLGETNEXTLAYERPROCADDRESSPROC)(void*, const char*);
     45 
     46 namespace {
     47 
     48 std::unordered_map<std::string, EGLFuncPointer> funcMap;
     49 
     50 EGLAPI void EGLAPIENTRY glesLayer_glCompileShaderA (GLuint shader) {
     51     ALOGI("%s%u", "glesLayer_glCompileShaderA called with parameter ", shader);
     52 
     53     if (funcMap.find("glCompileShader") == funcMap.end())
     54         ALOGI("%s", "Unable to find funcMap entry for glCompileShader");
     55 
     56     EGLFuncPointer entry = funcMap["glCompileShader"];
     57 
     58     PFNGLCOMPILESHADERPROC next = reinterpret_cast<PFNGLCOMPILESHADERPROC>(entry);
     59 
     60     next(shader);
     61 }
     62 
     63 EGLAPI void EGLAPIENTRY glesLayer_glCompileShaderB (GLuint shader) {
     64     ALOGI("%s%u", "glesLayer_CompileShaderB called with parameter ", shader);
     65 
     66     if (funcMap.find("glCompileShader") == funcMap.end())
     67         ALOGI("%s", "Unable to find funcMap entry for glCompileShader");
     68 
     69     EGLFuncPointer entry = funcMap["glCompileShader"];
     70 
     71     PFNGLCOMPILESHADERPROC next = reinterpret_cast<PFNGLCOMPILESHADERPROC>(entry);
     72 
     73     next(shader);
     74 }
     75 
     76 EGLAPI void EGLAPI glesLayer_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
     77     ALOGI("%s %i, %i, %i", "glesLayer_glDrawArraysInstanced called with parameters (minus GLenum):", first, count, instancecount);
     78 
     79     if (funcMap.find("glDrawArraysInstanced") == funcMap.end())
     80         ALOGI("%s", "Unable to find funcMap entry for glDrawArraysInstanced");
     81 
     82     EGLFuncPointer entry = funcMap["glDrawArraysInstanced"];
     83 
     84     PFNGLDRAWARRAYSINSTANCEDPROC next = reinterpret_cast<PFNGLDRAWARRAYSINSTANCEDPROC>(entry);
     85 
     86     next(mode, first, count, instancecount);
     87 }
     88 
     89 EGLAPI void EGLAPIENTRY glesLayer_glBindBuffer(GLenum target, GLuint buffer) {
     90     ALOGI("%s %i", "glesLayer_glBindBuffer called with parameters (minus GLenum):", buffer);
     91 
     92     if (funcMap.find("glBindBuffer") == funcMap.end())
     93         ALOGI("%s", "Unable to find funcMap entry for glBindBuffer");
     94 
     95     EGLFuncPointer entry = funcMap["glBindBuffer"];
     96 
     97     PFNGLBINDBUFFERPROC next = reinterpret_cast<PFNGLBINDBUFFERPROC>(entry);
     98 
     99     next(target, buffer);
    100 }
    101 
    102 EGLAPI const GLubyte* EGLAPIENTRY glesLayer_glGetString(GLenum name) {
    103     ALOGI("%s %lu", "glesLayer_glGetString called with parameters:", (unsigned long)name);
    104 
    105     if (funcMap.find("glGetString") == funcMap.end())
    106         ALOGI("%s", "Unable to find funcMap entry for glGetString");
    107 
    108     EGLFuncPointer entry = funcMap["glGetString"];
    109 
    110     PFNGLGETSTRINGPROC next = reinterpret_cast<PFNGLGETSTRINGPROC>(entry);
    111 
    112     return next(name);
    113 }
    114 
    115 EGLAPI EGLDisplay EGLAPIENTRY glesLayer_eglGetDisplay(EGLNativeDisplayType display_type) {
    116     ALOGI("%s %lu", "glesLayer_eglGetDisplay called with parameters:", (unsigned long)display_type);
    117 
    118     if (funcMap.find("eglGetDisplay") == funcMap.end())
    119         ALOGI("%s", "Unable to find funcMap entry for eglGetDisplay");
    120 
    121     EGLFuncPointer entry = funcMap["eglGetDisplay"];
    122 
    123     typedef EGLDisplay (*PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
    124     PFNEGLGETDISPLAYPROC next = reinterpret_cast<PFNEGLGETDISPLAYPROC>(entry);
    125 
    126     return next(display_type);
    127 }
    128 
    129 EGLAPI EGLBoolean EGLAPIENTRY glesLayer_eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) {
    130     ALOGI("%s %lu %li %li", "glesLayer_eglInitialize called with parameters:", (unsigned long)dpy, major ? (long)*major : 0, minor ? (long)*minor : 0);
    131 
    132     if (funcMap.find("eglInitialize") == funcMap.end())
    133         ALOGI("%s", "Unable to find funcMap entry for eglInitialize");
    134 
    135     EGLFuncPointer entry = funcMap["eglInitialize"];
    136 
    137     typedef EGLBoolean (*PFNEGLINITIALIZEPROC)(EGLDisplay, EGLint*, EGLint*);
    138     PFNEGLINITIALIZEPROC next = reinterpret_cast<PFNEGLINITIALIZEPROC>(entry);
    139 
    140     return next(dpy, major, minor);
    141 }
    142 
    143 EGLAPI EGLBoolean EGLAPIENTRY glesLayer_eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) {
    144 
    145     const char* msg = "glesLayer_eglChooseConfig called in glesLayer" xstr(LAYERNAME);
    146     ALOGI("%s", msg);
    147 
    148     if (funcMap.find("eglChooseConfig") == funcMap.end())
    149         ALOGI("%s", "Unable to find funcMap entry for eglChooseConfig");
    150 
    151     EGLFuncPointer entry = funcMap["eglChooseConfig"];
    152 
    153     typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*);
    154     PFNEGLCHOOSECONFIGPROC next = reinterpret_cast<PFNEGLCHOOSECONFIGPROC>(entry);
    155 
    156     return next(dpy, attrib_list, configs, config_size, num_config);
    157 }
    158 
    159 EGLAPI EGLBoolean EGLAPIENTRY glesLayer_eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects) {
    160 
    161     const char* msg = "glesLayer_eglSwapBuffersWithDamageKHR called in glesLayer" xstr(LAYERNAME);
    162     ALOGI("%s", msg);
    163 
    164     if (funcMap.find("eglSwapBuffersWithDamageKHR") == funcMap.end())
    165         ALOGI("%s", "Unable to find funcMap entry for eglSwapBuffersWithDamageKHR");
    166 
    167     EGLFuncPointer entry = funcMap["eglSwapBuffersWithDamageKHR"];
    168 
    169     typedef EGLBoolean (*PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC)(EGLDisplay, EGLSurface, EGLint*, EGLint);
    170     PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC next = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC>(entry);
    171 
    172     return next(dpy, surface, rects, n_rects);
    173 }
    174 
    175 EGLAPI void* EGLAPIENTRY glesLayer_eglGetProcAddress (const char* procname) {
    176 
    177     const char* msg = "glesLayer_eglGetProcAddress called in glesLayer" xstr(LAYERNAME) " for:";
    178     ALOGI("%s%s", msg, procname);
    179 
    180     if (funcMap.find("eglGetProcAddress") == funcMap.end())
    181         ALOGI("%s", "Unable to find funcMap entry for eglGetProcAddress");
    182 
    183     EGLFuncPointer entry = funcMap["eglGetProcAddress"];
    184 
    185     typedef void* (*PFNEGLGETPROCADDRESSPROC)(const char*);
    186     PFNEGLGETPROCADDRESSPROC next = reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(entry);
    187 
    188     return next(procname);
    189 }
    190 
    191 EGLAPI EGLFuncPointer EGLAPIENTRY eglGPA(const char* funcName) {
    192 
    193 #define GETPROCADDR(func) if(!strcmp(funcName, #func)) { \
    194 ALOGI("%s%s%s", "Returning glesLayer_" #func " for ", funcName, " in eglGPA"); \
    195 return (EGLFuncPointer)glesLayer_##func; \
    196 }
    197 
    198     if (strcmp("A", xstr(LAYERNAME)) == 0) {
    199 
    200         const char* targetFunc = "glCompileShader";
    201         if (strcmp(targetFunc, funcName) == 0) {
    202             ALOGI("%s%s%s", "Returning glesLayer_glCompileShaderA for ", funcName, " in eglGPA");
    203             return (EGLFuncPointer)glesLayer_glCompileShaderA;
    204         }
    205 
    206         GETPROCADDR(glDrawArraysInstanced);
    207 
    208     } else if (strcmp("B", xstr(LAYERNAME)) == 0) {
    209 
    210         const char* targetFunc = "glCompileShader";
    211         if (strcmp(targetFunc, funcName) == 0) {
    212             ALOGI("%s%s%s", "Returning glesLayer_glCompileShaderB for ", funcName, " in eglGPA");
    213             return (EGLFuncPointer)glesLayer_glCompileShaderB;
    214         }
    215 
    216         GETPROCADDR(glBindBuffer);
    217     }
    218 
    219     GETPROCADDR(glGetString);
    220     GETPROCADDR(eglGetDisplay);
    221     GETPROCADDR(eglInitialize);
    222     GETPROCADDR(eglChooseConfig);
    223     GETPROCADDR(eglSwapBuffersWithDamageKHR);
    224     GETPROCADDR(eglGetProcAddress);
    225 
    226     // Don't return anything for unrecognized functions
    227     return nullptr;
    228 }
    229 
    230 EGLAPI void EGLAPIENTRY glesLayer_InitializeLayer(void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address) {
    231     ALOGI("%s%llu%s%llu", "glesLayer_InitializeLayer called with layer_id (", (unsigned long long) layer_id,
    232                               ") get_next_layer_proc_address (", (unsigned long long) get_next_layer_proc_address);
    233 
    234     // Pick a real function to look up and test the pointer we've been handed
    235     const char* func = "eglGetProcAddress";
    236 
    237     ALOGI("%s%s%s%llu%s%llu%s", "Looking up address of ", func,
    238                                 " using get_next_layer_proc_address (", (unsigned long long) get_next_layer_proc_address,
    239                                 ") with layer_id (", (unsigned long long) layer_id,
    240                                 ")");
    241 
    242     void* gpa = get_next_layer_proc_address(layer_id, func);
    243 
    244     // Pick a fake function to look up and test the pointer we've been handed
    245     func = "eglFoo";
    246 
    247     ALOGI("%s%s%s%llu%s%llu%s", "Looking up address of ", func,
    248                                 " using get_next_layer_proc_address (", (unsigned long long) get_next_layer_proc_address,
    249                                 ") with layer_id (", (unsigned long long) layer_id,
    250                                 ")");
    251 
    252     gpa = get_next_layer_proc_address(layer_id, func);
    253 
    254     ALOGI("%s%llu%s%s", "Got back (", (unsigned long long) gpa, ") for ", func);
    255 }
    256 
    257 EGLAPI EGLFuncPointer EGLAPIENTRY glesLayer_GetLayerProcAddress(const char* funcName, EGLFuncPointer next) {
    258 
    259     EGLFuncPointer entry = eglGPA(funcName);
    260 
    261     if (entry != nullptr) {
    262         ALOGI("%s%s%s%llu%s", "Setting up glesLayer version of ", funcName, " calling down with: next (", (unsigned long long) next, ")");
    263         funcMap[std::string(funcName)] = next;
    264         return entry;
    265     }
    266 
    267     // If the layer does not intercept the function, just return original func pointer
    268     return next;
    269 }
    270 
    271 }  // namespace
    272 
    273 extern "C" {
    274 
    275     __attribute((visibility("default"))) EGLAPI void AndroidGLESLayer_Initialize(void* layer_id,
    276             PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address) {
    277         return (void)glesLayer_InitializeLayer(layer_id, get_next_layer_proc_address);
    278     }
    279 
    280     __attribute((visibility("default"))) EGLAPI void* AndroidGLESLayer_GetProcAddress(const char *funcName, EGLFuncPointer next) {
    281         return (void*)glesLayer_GetLayerProcAddress(funcName, next);
    282     }
    283 }
    284