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