1+ #include " mobileglues_info_getter.h"
2+
3+ static void * mg_handle = nullptr ;
4+
5+ static void * try_load_symbol (void * handle, const char * name) {
6+ void * s = dlsym (handle, name);
7+ if (!s) {
8+ LOGE (" Error: dlsym %s failed: %s" , name, dlerror ());
9+ }
10+ return s;
11+ }
12+
13+ static bool load_mobile_symbols () {
14+ if (mg_handle) return true ;
15+ mg_handle = dlopen (" libmobileglues.so" , RTLD_NOW | RTLD_LOCAL);
16+ if (!mg_handle) {
17+ LOGE (" Error: dlopen libmobileglues.so failed: %s" , dlerror ());
18+ return false ;
19+ }
20+
21+ p_eglGetDisplay = (PFN_eglGetDisplay) try_load_symbol (mg_handle, " eglGetDisplay" );
22+ p_eglInitialize = (PFN_eglInitialize) try_load_symbol (mg_handle, " eglInitialize" );
23+ p_eglChooseConfig = (PFN_eglChooseConfig) try_load_symbol (mg_handle, " eglChooseConfig" );
24+ p_eglCreatePbufferSurface = (PFN_eglCreatePbufferSurface) try_load_symbol (mg_handle, " eglCreatePbufferSurface" );
25+ p_eglCreateContext = (PFN_eglCreateContext) try_load_symbol (mg_handle, " eglCreateContext" );
26+ p_eglMakeCurrent = (PFN_eglMakeCurrent) try_load_symbol (mg_handle, " eglMakeCurrent" );
27+ p_eglDestroySurface = (PFN_eglDestroySurface) try_load_symbol (mg_handle, " eglDestroySurface" );
28+ p_eglDestroyContext = (PFN_eglDestroyContext) try_load_symbol (mg_handle, " eglDestroyContext" );
29+ p_eglTerminate = (PFN_eglTerminate) try_load_symbol (mg_handle, " eglTerminate" );
30+
31+ p_glGetIntegerv = (PFN_glGetIntegerv) try_load_symbol (mg_handle, " glGetIntegerv" );
32+ p_glGetString = (PFN_glGetString) try_load_symbol (mg_handle, " glGetString" );
33+ p_glGetStringi = (PFN_glGetStringi) try_load_symbol (mg_handle, " glGetStringi" );
34+
35+ if (!p_glGetStringi) {
36+ typedef void * (*PFN_eglGetProcAddress)(const char *);
37+ auto p_eglGetProcAddress = (PFN_eglGetProcAddress) try_load_symbol (mg_handle, " eglGetProcAddress" );
38+ if (p_eglGetProcAddress) {
39+ p_glGetStringi = (PFN_glGetStringi) p_eglGetProcAddress (" glGetStringi" );
40+ }
41+ }
42+
43+ if (!p_eglGetDisplay || !p_eglInitialize || !p_eglChooseConfig || !p_eglCreatePbufferSurface || !p_eglCreateContext || !p_eglMakeCurrent || !p_glGetString || !p_glGetIntegerv) {
44+ LOGE (" Error: some required symbols are missing" );
45+ return false ;
46+ }
47+
48+ return true ;
49+ }
50+
51+ static std::string create_context_and_query () {
52+ if (!load_mobile_symbols ()) return " Error: failed to load libmobileglues symbols" ;
53+
54+ EGLDisplay display = p_eglGetDisplay (EGL_DEFAULT_DISPLAY);
55+ if (display == EGL_NO_DISPLAY) return " Error: eglGetDisplay returned EGL_NO_DISPLAY" ;
56+
57+ EGLint major = 0 , minor = 0 ;
58+ if (!p_eglInitialize (display, &major, &minor)) {
59+ return " Error: eglInitialize failed" ;
60+ }
61+
62+ EGLint configAttribs[] = {
63+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
64+ EGL_RED_SIZE, 8 ,
65+ EGL_GREEN_SIZE, 8 ,
66+ EGL_BLUE_SIZE, 8 ,
67+ EGL_ALPHA_SIZE, 8 ,
68+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
69+ EGL_NONE
70+ };
71+ EGLConfig config;
72+ EGLint numConfigs = 0 ;
73+ if (!p_eglChooseConfig (display, configAttribs, &config, 1 , &numConfigs) || numConfigs <= 0 ) {
74+ p_eglTerminate (display);
75+ return " Error: eglChooseConfig failed" ;
76+ }
77+
78+ EGLint pbufAttribs[] = { EGL_WIDTH, 1 , EGL_HEIGHT, 1 , EGL_NONE };
79+ EGLSurface surface = p_eglCreatePbufferSurface (display, config, pbufAttribs);
80+ if (surface == EGL_NO_SURFACE) {
81+ p_eglTerminate (display);
82+ return " Error: eglCreatePbufferSurface failed" ;
83+ }
84+
85+ EGLContext context = EGL_NO_CONTEXT;
86+ EGLint ctxAttribs3[] = { EGL_CONTEXT_CLIENT_VERSION, 3 , EGL_NONE };
87+ EGLint ctxAttribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2 , EGL_NONE };
88+
89+ context = p_eglCreateContext (display, config, EGL_NO_CONTEXT, ctxAttribs3);
90+ if (context == EGL_NO_CONTEXT) {
91+ LOGI (" Error: ES3 context failed, try ES2" );
92+ context = p_eglCreateContext (display, config, EGL_NO_CONTEXT, ctxAttribs2);
93+ }
94+
95+ if (context == EGL_NO_CONTEXT) {
96+ p_eglDestroySurface (display, surface);
97+ p_eglTerminate (display);
98+ return " Error: eglCreateContext failed" ;
99+ }
100+
101+ if (!p_eglMakeCurrent (display, surface, surface, context)) {
102+ p_eglDestroyContext (display, context);
103+ p_eglDestroySurface (display, surface);
104+ p_eglTerminate (display);
105+ return " Error: eglMakeCurrent failed" ;
106+ }
107+
108+ std::ostringstream out;
109+
110+ std::ostringstream out_exts;
111+
112+ GLint numExt = 0 ;
113+ p_glGetIntegerv (GL_NUM_EXTENSIONS, &numExt);
114+ if (numExt > 0 && p_glGetStringi) {
115+ out_exts << " Extensions (" << numExt << " ):\n " ;
116+ for (GLint i = 0 ; i < numExt; ++i) {
117+ const GLubyte* ext = p_glGetStringi (GL_EXTENSIONS, (GLuint)i);
118+ if (ext) {
119+ const char * extStr = reinterpret_cast <const char *>(ext);
120+ if (strcmp (extStr, " GL_MG_mobileglues" ) == 0 ) g_MGQueryCapability.HasMobileGluesExt = true ;
121+ if (strcmp (extStr, " GL_MG_backend_string_getter_access" ) == 0 ) g_MGQueryCapability.BackendStringGetterAccess = true ;
122+ if (strcmp (extStr, " GL_MG_settings_string_dump" ) == 0 ) g_MGQueryCapability.SettingsStringDump = true ;
123+ out_exts << " " << reinterpret_cast <const char *>(ext) << " \n " ;
124+ }
125+ }
126+ } else {
127+ const GLubyte* exts = p_glGetString (GL_EXTENSIONS);
128+ out_exts << " Extensions: " << (exts ? reinterpret_cast <const char *>(exts) : " NULL" ) << " \n " ;
129+ if (exts) {
130+ const char * extStr = reinterpret_cast <const char *>(exts);
131+ if (strstr (extStr, " GL_MG_mobileglues " )) g_MGQueryCapability.HasMobileGluesExt = true ;
132+ if (strstr (extStr, " GL_MG_backend_string_getter_access " )) g_MGQueryCapability.BackendStringGetterAccess = true ;
133+ if (strstr (extStr, " GL_MG_settings_string_dump " )) g_MGQueryCapability.SettingsStringDump = true ;
134+ }
135+ }
136+
137+ out << " Is MobileGlues (>=1.3.3): " << (g_MGQueryCapability.HasMobileGluesExt ? " Yes\n " : " No\n " );
138+
139+ const GLubyte* renderer = p_glGetString (GL_RENDERER);
140+ const GLubyte* version = p_glGetString (GL_VERSION);
141+ const GLubyte* vendor = p_glGetString (GL_VENDOR);
142+ const GLubyte* shading = p_glGetString (GL_SHADING_LANGUAGE_VERSION);
143+
144+ out << " \n OpenGL Frontend\n ====\n " ;
145+ out << " Renderer: " << (renderer ? reinterpret_cast <const char *>(renderer) : " NULL" ) << " \n " ;
146+ out << " Version: " << (version ? reinterpret_cast <const char *>(version) : " NULL" ) << " \n " ;
147+ out << " Vendor: " << (vendor ? reinterpret_cast <const char *>(vendor) : " NULL" ) << " \n " ;
148+ out << " Shading language version: " << (shading ? reinterpret_cast <const char *>(shading) : " NULL" ) << " \n " ;
149+ out << out_exts.str ();
150+
151+ out << " \n OpenGL ES Backend\n ====\n " ;
152+ if (g_MGQueryCapability.BackendStringGetterAccess ) {
153+ const GLubyte* backendRenderer = p_glGetString (GL_RENDERER + GL_BACKEND_GETTER_MG);
154+ const GLubyte* backendVersion = p_glGetString (GL_VERSION + GL_BACKEND_GETTER_MG);
155+ const GLubyte* backendVendor = p_glGetString (GL_VENDOR + GL_BACKEND_GETTER_MG);
156+ const GLubyte* backendShading = p_glGetString (GL_SHADING_LANGUAGE_VERSION + GL_BACKEND_GETTER_MG);
157+ out << " Renderer: " << (backendRenderer ? reinterpret_cast <const char *>(backendRenderer) : " NULL" ) << " \n " ;
158+ out << " Version: " << (backendVersion ? reinterpret_cast <const char *>(backendVersion) : " NULL" ) << " \n " ;
159+ out << " Vendor: " << (backendVendor ? reinterpret_cast <const char *>(backendVendor) : " NULL" ) << " \n " ;
160+ out << " Shading language version: " << (backendShading ? reinterpret_cast <const char *>(backendShading) : " NULL" ) << " \n " ;
161+
162+ GLint backendNumExt = 0 ;
163+ p_glGetIntegerv (GL_NUM_EXTENSIONS + GL_BACKEND_GETTER_MG, &backendNumExt);
164+ if (backendNumExt > 0 && p_glGetStringi) {
165+ out << " Extensions (" << backendNumExt << " ):\n " ;
166+ for (GLint i = 0 ; i < backendNumExt; ++i) {
167+ const GLubyte* ext = p_glGetStringi (GL_EXTENSIONS + GL_BACKEND_GETTER_MG, (GLuint)i);
168+ out << " " << reinterpret_cast <const char *>(ext) << " \n " ;
169+ }
170+ } else {
171+ const GLubyte* exts = p_glGetString (GL_EXTENSIONS + GL_BACKEND_GETTER_MG);
172+ out << " Extensions: " << (exts ? reinterpret_cast <const char *>(exts) : " NULL" ) << " \n " ;
173+ }
174+ } else {
175+ out << " Not Compatible. GL_MG_backend_string_getter_access is not supported in current context.\n " ;
176+ }
177+
178+ out << " \n Settings\n ====\n " ;
179+ if (g_MGQueryCapability.SettingsStringDump ) {
180+ const GLubyte* settingsStr = p_glGetString (GL_SETTINGS_MG);
181+ out << reinterpret_cast <const char *>(settingsStr) << " \n " ;
182+ } else {
183+ out << " Not Compatible. GL_MG_settings_string_dump is not supported in current context.\n " ;
184+ }
185+
186+ p_eglMakeCurrent (display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
187+ p_eglDestroySurface (display, surface);
188+ p_eglDestroyContext (display, context);
189+ p_eglTerminate (display);
190+
191+ dlclose (mg_handle);
192+ mg_handle = nullptr ;
193+
194+ return out.str ();
195+ }
196+
197+ extern " C"
198+ JNIEXPORT jstring JNICALL
199+ Java_com_fcl_plugin_mobileglues_MGGLInfoDialogBuilder_getMobileGluesGLInfo (JNIEnv *env,
200+ jobject thiz) {
201+ std::string res = create_context_and_query ();
202+ LOGI (" MobileGlues GL Info: \n %s" , res.c_str ());
203+ return env->NewStringUTF (res.c_str ());
204+ }
205+
206+ JNIEXPORT jint JNI_OnLoad (JavaVM* vm, void * reserved) {
207+ (void )vm;
208+ (void )reserved;
209+ LOGI (" JNI_OnLoad called" );
210+ return JNI_VERSION_1_6;
211+ }
212+
213+ extern " C"
214+ JNIEXPORT jint JNICALL
215+ Java_com_fcl_plugin_mobileglues_MGGLInfoDialogBuilder_setenv (JNIEnv *env, jobject thiz, jstring key,
216+ jstring value, jint overwrite) {
217+ const char * k = env->GetStringUTFChars (key, nullptr );
218+ const char * v = env->GetStringUTFChars (value, nullptr );
219+ int ret = setenv (k, v, overwrite);
220+ env->ReleaseStringUTFChars (key, k);
221+ env->ReleaseStringUTFChars (value, v);
222+ return ret;
223+ }
0 commit comments