egl.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. ** Copyright 2007, 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. #include <ctype.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <hardware/gralloc.h>
  20. #include <system/window.h>
  21. #include <EGL/egl.h>
  22. #include <EGL/eglext.h>
  23. #include <cutils/log.h>
  24. #include <cutils/atomic.h>
  25. #include <cutils/properties.h>
  26. #include <utils/CallStack.h>
  27. #include <utils/String8.h>
  28. #include "../egl_impl.h"
  29. #include "../glestrace.h"
  30. #include "egl_tls.h"
  31. #include "egldefs.h"
  32. #include "Loader.h"
  33. #include "egl_display.h"
  34. #include "egl_object.h"
  35. typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
  36. // ----------------------------------------------------------------------------
  37. namespace android {
  38. // ----------------------------------------------------------------------------
  39. egl_connection_t gEGLImpl;
  40. gl_hooks_t gHooks[2];
  41. gl_hooks_t gHooksNoContext;
  42. pthread_key_t gGLWrapperKey = -1;
  43. // ----------------------------------------------------------------------------
  44. #if EGL_TRACE
  45. EGLAPI pthread_key_t gGLTraceKey = -1;
  46. // ----------------------------------------------------------------------------
  47. /**
  48. * There are three different tracing methods:
  49. * 1. libs/EGL/trace.cpp: Traces all functions to systrace.
  50. * To enable:
  51. * - set system property "debug.egl.trace" to "systrace" to trace all apps.
  52. * 2. libs/EGL/trace.cpp: Logs a stack trace for GL errors after each function call.
  53. * To enable:
  54. * - set system property "debug.egl.trace" to "error" to trace all apps.
  55. * 3. libs/EGL/trace.cpp: Traces all functions to logcat.
  56. * To enable:
  57. * - set system property "debug.egl.trace" to 1 to trace all apps.
  58. * - or call setGLTraceLevel(1) from an app to enable tracing for that app.
  59. * 4. libs/GLES_trace: Traces all functions via protobuf to host.
  60. * To enable:
  61. * - set system property "debug.egl.debug_proc" to the application name.
  62. * - or call setGLDebugLevel(1) from the app.
  63. */
  64. static int sEGLTraceLevel;
  65. static int sEGLApplicationTraceLevel;
  66. static bool sEGLSystraceEnabled;
  67. static bool sEGLGetErrorEnabled;
  68. static volatile int sEGLDebugLevel;
  69. extern gl_hooks_t gHooksTrace;
  70. extern gl_hooks_t gHooksSystrace;
  71. extern gl_hooks_t gHooksErrorTrace;
  72. int getEGLDebugLevel() {
  73. return sEGLDebugLevel;
  74. }
  75. void setEGLDebugLevel(int level) {
  76. sEGLDebugLevel = level;
  77. }
  78. static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
  79. pthread_setspecific(gGLTraceKey, value);
  80. }
  81. gl_hooks_t const* getGLTraceThreadSpecific() {
  82. return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
  83. }
  84. void initEglTraceLevel() {
  85. char value[PROPERTY_VALUE_MAX];
  86. property_get("debug.egl.trace", value, "0");
  87. sEGLGetErrorEnabled = !strcasecmp(value, "error");
  88. if (sEGLGetErrorEnabled) {
  89. sEGLSystraceEnabled = false;
  90. sEGLTraceLevel = 0;
  91. return;
  92. }
  93. sEGLSystraceEnabled = !strcasecmp(value, "systrace");
  94. if (sEGLSystraceEnabled) {
  95. sEGLTraceLevel = 0;
  96. return;
  97. }
  98. int propertyLevel = atoi(value);
  99. int applicationLevel = sEGLApplicationTraceLevel;
  100. sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
  101. }
  102. void initEglDebugLevel() {
  103. if (getEGLDebugLevel() == 0) {
  104. char value[PROPERTY_VALUE_MAX];
  105. // check system property only on userdebug or eng builds
  106. property_get("ro.debuggable", value, "0");
  107. if (value[0] == '0')
  108. return;
  109. property_get("debug.egl.debug_proc", value, "");
  110. if (strlen(value) > 0) {
  111. FILE * file = fopen("/proc/self/cmdline", "r");
  112. if (file) {
  113. char cmdline[256];
  114. if (fgets(cmdline, sizeof(cmdline), file)) {
  115. if (!strncmp(value, cmdline, strlen(value))) {
  116. // set EGL debug if the "debug.egl.debug_proc" property
  117. // matches the prefix of this application's command line
  118. setEGLDebugLevel(1);
  119. }
  120. }
  121. fclose(file);
  122. }
  123. }
  124. }
  125. if (getEGLDebugLevel() > 0) {
  126. if (GLTrace_start() < 0) {
  127. ALOGE("Error starting Tracer for OpenGL ES. Disabling..");
  128. setEGLDebugLevel(0);
  129. }
  130. }
  131. }
  132. void setGLHooksThreadSpecific(gl_hooks_t const *value) {
  133. if (sEGLGetErrorEnabled) {
  134. setGlTraceThreadSpecific(value);
  135. setGlThreadSpecific(&gHooksErrorTrace);
  136. } else if (sEGLSystraceEnabled) {
  137. setGlTraceThreadSpecific(value);
  138. setGlThreadSpecific(&gHooksSystrace);
  139. } else if (sEGLTraceLevel > 0) {
  140. setGlTraceThreadSpecific(value);
  141. setGlThreadSpecific(&gHooksTrace);
  142. } else if (getEGLDebugLevel() > 0 && value != &gHooksNoContext) {
  143. setGlTraceThreadSpecific(value);
  144. setGlThreadSpecific(GLTrace_getGLHooks());
  145. } else {
  146. setGlTraceThreadSpecific(NULL);
  147. setGlThreadSpecific(value);
  148. }
  149. }
  150. /*
  151. * Global entry point to allow applications to modify their own trace level.
  152. * The effective trace level is the max of this level and the value of debug.egl.trace.
  153. */
  154. extern "C"
  155. void setGLTraceLevel(int level) {
  156. sEGLApplicationTraceLevel = level;
  157. }
  158. /*
  159. * Global entry point to allow applications to modify their own debug level.
  160. * Debugging is enabled if either the application requested it, or if the system property
  161. * matches the application's name.
  162. * Note that this only sets the debug level. The value is read and used either in
  163. * initEglDebugLevel() if the application hasn't initialized its display yet, or when
  164. * eglSwapBuffers() is called next.
  165. */
  166. void EGLAPI setGLDebugLevel(int level) {
  167. setEGLDebugLevel(level);
  168. }
  169. #else
  170. void setGLHooksThreadSpecific(gl_hooks_t const *value) {
  171. setGlThreadSpecific(value);
  172. }
  173. #endif
  174. /*****************************************************************************/
  175. static int gl_no_context() {
  176. if (egl_tls_t::logNoContextCall()) {
  177. char const* const error = "call to OpenGL ES API with "
  178. "no current context (logged once per thread)";
  179. if (LOG_NDEBUG) {
  180. ALOGE(error);
  181. } else {
  182. LOG_ALWAYS_FATAL(error);
  183. }
  184. char value[PROPERTY_VALUE_MAX];
  185. property_get("debug.egl.callstack", value, "0");
  186. if (atoi(value)) {
  187. CallStack stack(LOG_TAG);
  188. }
  189. }
  190. return 0;
  191. }
  192. static void early_egl_init(void)
  193. {
  194. #if EGL_TRACE
  195. pthread_key_create(&gGLTraceKey, NULL);
  196. initEglTraceLevel();
  197. #endif
  198. int numHooks = sizeof(gHooksNoContext) / sizeof(EGLFuncPointer);
  199. EGLFuncPointer *iter = reinterpret_cast<EGLFuncPointer*>(&gHooksNoContext);
  200. for (int hook = 0; hook < numHooks; ++hook) {
  201. *(iter++) = reinterpret_cast<EGLFuncPointer>(gl_no_context);
  202. }
  203. setGLHooksThreadSpecific(&gHooksNoContext);
  204. }
  205. static pthread_once_t once_control = PTHREAD_ONCE_INIT;
  206. static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
  207. // ----------------------------------------------------------------------------
  208. egl_display_ptr validate_display(EGLDisplay dpy) {
  209. egl_display_ptr dp = get_display(dpy);
  210. if (!dp)
  211. return setError(EGL_BAD_DISPLAY, egl_display_ptr(NULL));
  212. if (!dp->isReady())
  213. return setError(EGL_NOT_INITIALIZED, egl_display_ptr(NULL));
  214. return dp;
  215. }
  216. egl_display_ptr validate_display_connection(EGLDisplay dpy,
  217. egl_connection_t*& cnx) {
  218. cnx = NULL;
  219. egl_display_ptr dp = validate_display(dpy);
  220. if (!dp)
  221. return dp;
  222. cnx = &gEGLImpl;
  223. if (cnx->dso == 0) {
  224. return setError(EGL_BAD_CONFIG, egl_display_ptr(NULL));
  225. }
  226. return dp;
  227. }
  228. // ----------------------------------------------------------------------------
  229. const GLubyte * egl_get_string_for_current_context(GLenum name) {
  230. // NOTE: returning NULL here will fall-back to the default
  231. // implementation.
  232. EGLContext context = egl_tls_t::getContext();
  233. if (context == EGL_NO_CONTEXT)
  234. return NULL;
  235. egl_context_t const * const c = get_context(context);
  236. if (c == NULL) // this should never happen, by construction
  237. return NULL;
  238. if (name != GL_EXTENSIONS)
  239. return NULL;
  240. return (const GLubyte *)c->gl_extensions.string();
  241. }
  242. const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) {
  243. // NOTE: returning NULL here will fall-back to the default
  244. // implementation.
  245. EGLContext context = egl_tls_t::getContext();
  246. if (context == EGL_NO_CONTEXT)
  247. return NULL;
  248. egl_context_t const * const c = get_context(context);
  249. if (c == NULL) // this should never happen, by construction
  250. return NULL;
  251. if (name != GL_EXTENSIONS)
  252. return NULL;
  253. // if index is out of bounds, assume it will be in the default
  254. // implementation too, so we don't have to generate a GL error here
  255. if (index >= c->tokenized_gl_extensions.size())
  256. return NULL;
  257. return (const GLubyte *)c->tokenized_gl_extensions.itemAt(index).string();
  258. }
  259. GLint egl_get_num_extensions_for_current_context() {
  260. // NOTE: returning -1 here will fall-back to the default
  261. // implementation.
  262. EGLContext context = egl_tls_t::getContext();
  263. if (context == EGL_NO_CONTEXT)
  264. return -1;
  265. egl_context_t const * const c = get_context(context);
  266. if (c == NULL) // this should never happen, by construction
  267. return -1;
  268. return (GLint)c->tokenized_gl_extensions.size();
  269. }
  270. // ----------------------------------------------------------------------------
  271. // this mutex protects:
  272. // d->disp[]
  273. // egl_init_drivers_locked()
  274. //
  275. static EGLBoolean egl_init_drivers_locked() {
  276. if (sEarlyInitState) {
  277. // initialized by static ctor. should be set here.
  278. return EGL_FALSE;
  279. }
  280. // get our driver loader
  281. Loader& loader(Loader::getInstance());
  282. // dynamically load our EGL implementation
  283. egl_connection_t* cnx = &gEGLImpl;
  284. if (cnx->dso == 0) {
  285. cnx->hooks[egl_connection_t::GLESv1_INDEX] =
  286. &gHooks[egl_connection_t::GLESv1_INDEX];
  287. cnx->hooks[egl_connection_t::GLESv2_INDEX] =
  288. &gHooks[egl_connection_t::GLESv2_INDEX];
  289. cnx->dso = loader.open(cnx);
  290. }
  291. return cnx->dso ? EGL_TRUE : EGL_FALSE;
  292. }
  293. static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
  294. EGLBoolean egl_init_drivers() {
  295. EGLBoolean res;
  296. pthread_mutex_lock(&sInitDriverMutex);
  297. res = egl_init_drivers_locked();
  298. pthread_mutex_unlock(&sInitDriverMutex);
  299. return res;
  300. }
  301. static pthread_mutex_t sLogPrintMutex = PTHREAD_MUTEX_INITIALIZER;
  302. static nsecs_t sLogPrintTime = 0;
  303. #define NSECS_DURATION 1000000000
  304. void gl_unimplemented() {
  305. bool printLog = false;
  306. nsecs_t now = systemTime();
  307. pthread_mutex_lock(&sLogPrintMutex);
  308. if ((now - sLogPrintTime) > NSECS_DURATION) {
  309. sLogPrintTime = now;
  310. printLog = true;
  311. }
  312. pthread_mutex_unlock(&sLogPrintMutex);
  313. if (printLog) {
  314. ALOGE("called unimplemented OpenGL ES API");
  315. char value[PROPERTY_VALUE_MAX];
  316. property_get("debug.egl.callstack", value, "0");
  317. if (atoi(value)) {
  318. CallStack stack(LOG_TAG);
  319. }
  320. }
  321. }
  322. void gl_noop() {
  323. }
  324. // ----------------------------------------------------------------------------
  325. void setGlThreadSpecific(gl_hooks_t const *value) {
  326. gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
  327. tls_hooks[TLS_SLOT_OPENGL_API] = value;
  328. }
  329. // ----------------------------------------------------------------------------
  330. // GL / EGL hooks
  331. // ----------------------------------------------------------------------------
  332. #undef GL_ENTRY
  333. #undef EGL_ENTRY
  334. #define GL_ENTRY(_r, _api, ...) #_api,
  335. #define EGL_ENTRY(_r, _api, ...) #_api,
  336. char const * const gl_names[] = {
  337. #include "../entries.in"
  338. NULL
  339. };
  340. char const * const egl_names[] = {
  341. #include "egl_entries.in"
  342. NULL
  343. };
  344. #undef GL_ENTRY
  345. #undef EGL_ENTRY
  346. // ----------------------------------------------------------------------------
  347. }; // namespace android
  348. // ----------------------------------------------------------------------------