summaryrefslogtreecommitdiffstats
path: root/opengl/libs/EGL
diff options
context:
space:
mode:
Diffstat (limited to 'opengl/libs/EGL')
-rw-r--r--opengl/libs/EGL/egl.cpp54
-rw-r--r--opengl/libs/EGL/eglApi.cpp101
-rw-r--r--opengl/libs/EGL/egl_cache.cpp6
-rw-r--r--opengl/libs/EGL/egl_display.cpp15
-rw-r--r--opengl/libs/EGL/egl_entries.in2
-rw-r--r--opengl/libs/EGL/getProcAddress.cpp46
-rw-r--r--opengl/libs/EGL/trace.cpp103
7 files changed, 306 insertions, 21 deletions
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index b658240..0d4bed5 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -62,12 +62,18 @@ EGLAPI pthread_key_t gGLTraceKey = -1;
// ----------------------------------------------------------------------------
/**
- * There are two different tracing methods:
- * 1. libs/EGL/trace.cpp: Traces all functions to logcat.
+ * There are three different tracing methods:
+ * 1. libs/EGL/trace.cpp: Traces all functions to systrace.
+ * To enable:
+ * - set system property "debug.egl.trace" to "systrace" to trace all apps.
+ * 2. libs/EGL/trace.cpp: Logs a stack trace for GL errors after each function call.
+ * To enable:
+ * - set system property "debug.egl.trace" to "error" to trace all apps.
+ * 3. libs/EGL/trace.cpp: Traces all functions to logcat.
* To enable:
* - set system property "debug.egl.trace" to 1 to trace all apps.
* - or call setGLTraceLevel(1) from an app to enable tracing for that app.
- * 2. libs/GLES_trace: Traces all functions via protobuf to host.
+ * 4. libs/GLES_trace: Traces all functions via protobuf to host.
* To enable:
* - set system property "debug.egl.debug_proc" to the application name.
* - or call setGLDebugLevel(1) from the app.
@@ -75,10 +81,15 @@ EGLAPI pthread_key_t gGLTraceKey = -1;
static int sEGLTraceLevel;
static int sEGLApplicationTraceLevel;
+static bool sEGLSystraceEnabled;
+static bool sEGLGetErrorEnabled;
+
int gEGLDebugLevel;
static int sEGLApplicationDebugLevel;
extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksSystrace;
+extern gl_hooks_t gHooksErrorTrace;
static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
pthread_setspecific(gGLTraceKey, value);
@@ -91,6 +102,20 @@ gl_hooks_t const* getGLTraceThreadSpecific() {
void initEglTraceLevel() {
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.trace", value, "0");
+
+ sEGLGetErrorEnabled = !strcasecmp(value, "error");
+ if (sEGLGetErrorEnabled) {
+ sEGLSystraceEnabled = false;
+ sEGLTraceLevel = 0;
+ return;
+ }
+
+ sEGLSystraceEnabled = !strcasecmp(value, "systrace");
+ if (sEGLSystraceEnabled) {
+ sEGLTraceLevel = 0;
+ return;
+ }
+
int propertyLevel = atoi(value);
int applicationLevel = sEGLApplicationTraceLevel;
sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
@@ -99,6 +124,12 @@ void initEglTraceLevel() {
void initEglDebugLevel() {
int propertyLevel = 0;
char value[PROPERTY_VALUE_MAX];
+
+ // check system property only on userdebug or eng builds
+ property_get("ro.debuggable", value, "0");
+ if (value[0] == '0')
+ return;
+
property_get("debug.egl.debug_proc", value, "");
if (strlen(value) > 0) {
long pid = getpid();
@@ -125,7 +156,13 @@ void initEglDebugLevel() {
}
void setGLHooksThreadSpecific(gl_hooks_t const *value) {
- if (sEGLTraceLevel > 0) {
+ if (sEGLGetErrorEnabled) {
+ setGlTraceThreadSpecific(value);
+ setGlThreadSpecific(&gHooksErrorTrace);
+ } else if (sEGLSystraceEnabled) {
+ setGlTraceThreadSpecific(value);
+ setGlThreadSpecific(&gHooksSystrace);
+ } else if (sEGLTraceLevel > 0) {
setGlTraceThreadSpecific(value);
setGlThreadSpecific(&gHooksTrace);
} else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
@@ -166,8 +203,13 @@ void setGLHooksThreadSpecific(gl_hooks_t const *value) {
static int gl_no_context() {
if (egl_tls_t::logNoContextCall()) {
- ALOGE("call to OpenGL ES API with no current context "
- "(logged once per thread)");
+ char const* const error = "call to OpenGL ES API with "
+ "no current context (logged once per thread)";
+ if (LOG_NDEBUG) {
+ ALOGE(error);
+ } else {
+ LOG_ALWAYS_FATAL(error);
+ }
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.callstack", value, "0");
if (atoi(value)) {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index c943ec1..c25612d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -204,6 +204,59 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso) {
+ if (attrib_list) {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.egl.force_msaa", value, "false");
+
+ if (!strcmp(value, "true")) {
+ size_t attribCount = 0;
+ EGLint attrib = attrib_list[0];
+
+ // Only enable MSAA if the context is OpenGL ES 2.0 and
+ // if no caveat is requested
+ const EGLint *attribRendererable = NULL;
+ const EGLint *attribCaveat = NULL;
+
+ // Count the number of attributes and look for
+ // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
+ while (attrib != EGL_NONE) {
+ attrib = attrib_list[attribCount];
+ switch (attrib) {
+ case EGL_RENDERABLE_TYPE:
+ attribRendererable = &attrib_list[attribCount];
+ break;
+ case EGL_CONFIG_CAVEAT:
+ attribCaveat = &attrib_list[attribCount];
+ break;
+ }
+ attribCount++;
+ }
+
+ if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
+ (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
+
+ // Insert 2 extra attributes to force-enable MSAA 4x
+ EGLint aaAttribs[attribCount + 4];
+ aaAttribs[0] = EGL_SAMPLE_BUFFERS;
+ aaAttribs[1] = 1;
+ aaAttribs[2] = EGL_SAMPLES;
+ aaAttribs[3] = 4;
+
+ memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
+
+ EGLint numConfigAA;
+ EGLBoolean resAA = cnx->egl.eglChooseConfig(
+ dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
+
+ if (resAA == EGL_TRUE && numConfigAA > 0) {
+ ALOGD("Enabling MSAA 4x");
+ *num_config = numConfigAA;
+ return resAA;
+ }
+ }
+ }
+ }
+
res = cnx->egl.eglChooseConfig(
dp->disp.dpy, attrib_list, configs, config_size, num_config);
}
@@ -419,6 +472,12 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
GLTrace_eglCreateContext(version, c);
#endif
return c;
+ } else {
+ EGLint error = eglGetError();
+ ALOGE_IF(error == EGL_SUCCESS,
+ "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT "
+ "but no EGL error!",
+ dpy, config, share_list, attrib_list);
}
}
return EGL_NO_CONTEXT;
@@ -657,6 +716,8 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
// These extensions should not be exposed to applications. They're used
// internally by the Android EGL layer.
if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID") ||
+ !strcmp(procname, "eglDupNativeFenceFDANDROID") ||
+ !strcmp(procname, "eglWaitSyncANDROID") ||
!strcmp(procname, "eglHibernateProcessIMG") ||
!strcmp(procname, "eglAwakenProcessIMG")) {
return NULL;
@@ -704,8 +765,8 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && cnx->egl.eglGetProcAddress) {
- found = true;
// Extensions are independent of the bound context
+ addr =
cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
#if EGL_TRACE
@@ -713,10 +774,13 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
gHooksTrace.ext.extensions[slot] =
#endif
cnx->egl.eglGetProcAddress(procname);
+ if (addr) found = true;
}
if (found) {
+#if USE_FAST_TLS_KEY
addr = gExtensionForwarders[slot];
+#endif
sGLExtentionMap.add(name, addr);
sGLExtentionSlot++;
}
@@ -1115,11 +1179,12 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
const egl_display_ptr dp = validate_display(dpy);
if (!dp) return EGL_FALSE;
+ EGLBoolean result = EGL_FALSE;
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
- cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
+ result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
}
- return EGL_TRUE;
+ return result;
}
// ----------------------------------------------------------------------------
@@ -1195,7 +1260,35 @@ EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
// ANDROID extensions
// ----------------------------------------------------------------------------
-/* ANDROID extensions entry-point go here */
+EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
+
+ EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
+ result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
+ }
+ return result;
+}
+
+EGLint eglWaitSyncANDROID(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
+
+ EGLint result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglWaitSyncANDROID) {
+ result = cnx->egl.eglWaitSyncANDROID(dp->disp.dpy, sync, flags);
+ }
+ return result;
+}
// ----------------------------------------------------------------------------
// NVIDIA extensions
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index ed2bef3..72655df 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -29,12 +29,16 @@
#define MAX_EGL_CACHE_ENTRY_SIZE (16 * 1024);
#endif
+#ifndef MAX_EGL_CACHE_KEY_SIZE
+#define MAX_EGL_CACHE_KEY_SIZE (1024);
+#endif
+
#ifndef MAX_EGL_CACHE_SIZE
#define MAX_EGL_CACHE_SIZE (64 * 1024);
#endif
// Cache size limits.
-static const size_t maxKeySize = 1024;
+static const size_t maxKeySize = MAX_EGL_CACHE_KEY_SIZE;
static const size_t maxValueSize = MAX_EGL_CACHE_ENTRY_SIZE;
static const size_t maxTotalSize = MAX_EGL_CACHE_SIZE;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index a46aa38..7ca9e40 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -52,13 +52,16 @@ static char const * const sExtensionString =
"EGL_KHR_gl_texture_cubemap_image "
"EGL_KHR_gl_renderbuffer_image "
"EGL_KHR_fence_sync "
+ "EGL_EXT_create_context_robustness "
"EGL_NV_system_time "
"EGL_ANDROID_image_native_buffer " // mandatory
;
// extensions not exposed to applications but used by the ANDROID system
// "EGL_ANDROID_recordable " // mandatory
+// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
// "EGL_ANDROID_blob_cache " // strongly recommended
+// "EGL_ANDROID_native_fence_sync " // strongly recommended
// "EGL_IMG_hibernate_process " // optional
extern void initEglTraceLevel();
@@ -263,7 +266,13 @@ EGLBoolean egl_display_t::terminate() {
Mutex::Autolock _l(lock);
if (refs == 0) {
- return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+ /*
+ * From the EGL spec (3.2):
+ * "Termination of a display that has already been terminated,
+ * (...), is allowed, but the only effect of such a call is
+ * to return EGL_TRUE (...)
+ */
+ return EGL_TRUE;
}
// this is specific to Android, display termination is ref-counted.
@@ -286,6 +295,10 @@ EGLBoolean egl_display_t::terminate() {
mHibernation.setDisplayValid(false);
+ // Reset the extension string since it will be regenerated if we get
+ // reinitialized.
+ mExtensionString.setTo("");
+
// Mark all objects remaining in the list as terminated, unless
// there are no reference to them, it which case, we're free to
// delete them.
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 9feb716..2ffd417 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -62,6 +62,8 @@ EGL_ENTRY(EGLBoolean, eglGetSyncAttribKHR, EGLDisplay, EGLSyncKHR, EGLint,
EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR)
+EGL_ENTRY(EGLint, eglWaitSyncANDROID, EGLDisplay, EGLSyncKHR, EGLint)
/* NVIDIA extensions */
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 8dcf38d..d23da7a 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -37,14 +37,9 @@ namespace android {
#if USE_FAST_TLS_KEY
- #ifdef HAVE_ARM_TLS_REGISTER
- #define GET_TLS(reg) \
- "mrc p15, 0, " #reg ", c13, c0, 3 \n"
- #else
- #define GET_TLS(reg) \
- "mov " #reg ", #0xFFFF0FFF \n" \
- "ldr " #reg ", [" #reg ", #-15] \n"
- #endif
+ #if defined(__arm__)
+
+ #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
@@ -64,6 +59,41 @@ namespace android {
: \
);
+ #elif defined(__mips__)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_EXTENSION_API(_api, ...) \
+ register unsigned int t0 asm("t0"); \
+ register unsigned int fn asm("t1"); \
+ register unsigned int tls asm("v1"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ ".set mips32r2\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "lw %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn], $ra\n\t" \
+ "lw %[fn], %[API](%[t0])\n\t" \
+ "movz %[fn], $ra, %[fn]\n\t" \
+ "1:\n\t" \
+ "j %[fn]\n\t" \
+ " nop\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(fn), \
+ [tls] "=&r"(tls), \
+ [t0] "=&r"(t0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4), \
+ [API] "I"(__builtin_offsetof(gl_hooks_t, \
+ ext.extensions[_api])) \
+ : \
+ );
+
+ #else
+ #error Unsupported architecture
+ #endif
+
#define GL_EXTENSION_NAME(_n) __glExtFwd##_n
#define GL_EXTENSION(_n) \
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
index 52907c1..a51b086 100644
--- a/opengl/libs/EGL/trace.cpp
+++ b/opengl/libs/EGL/trace.cpp
@@ -26,6 +26,11 @@
#include <cutils/log.h>
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <utils/Trace.h>
+
+#include <utils/CallStack.h>
+
#include "egl_tls.h"
#include "hooks.h"
@@ -314,6 +319,10 @@ static void TraceGL(const char* name, int numArgs, ...) {
va_end(argp);
}
+///////////////////////////////////////////////////////////////////////////
+// Log trace
+///////////////////////////////////////////////////////////////////////////
+
#undef TRACE_GL_VOID
#undef TRACE_GL
@@ -349,7 +358,6 @@ EGLAPI gl_hooks_t gHooksTrace = {
};
#undef GL_ENTRY
-
#undef TRACE_GL_VOID
#undef TRACE_GL
@@ -372,6 +380,99 @@ extern "C" {
#include "../debug.in"
}
+///////////////////////////////////////////////////////////////////////////
+// Systrace
+///////////////////////////////////////////////////////////////////////////
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...) \
+static void Systrace_ ## _api _args { \
+ ATRACE_NAME(#_api); \
+ gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
+ _c->_api _argList; \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...) \
+static _type Systrace_ ## _api _args { \
+ ATRACE_NAME(#_api); \
+ gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
+ return _c->_api _argList; \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
+EGLAPI gl_hooks_t gHooksSystrace = {
+ {
+ #include "entries.in"
+ },
+ {
+ {0}
+ }
+};
+#undef GL_ENTRY
+
+///////////////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////////////
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define CHECK_ERROR(_c, _api) \
+ GLenum status = GL_NO_ERROR; \
+ bool error = false; \
+ while ((status = _c->glGetError()) != GL_NO_ERROR) { \
+ ALOGD("[" #_api "] 0x%x", status); \
+ error = true; \
+ } \
+ if (error) { \
+ CallStack s; \
+ s.update(); \
+ s.dump("glGetError:" #_api); \
+ } \
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...) \
+static void ErrorTrace_ ## _api _args { \
+ gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
+ _c->_api _argList; \
+ CHECK_ERROR(_c, _api); \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...) \
+static _type ErrorTrace_ ## _api _args { \
+ gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
+ _type _r = _c->_api _argList; \
+ CHECK_ERROR(_c, _api); \
+ return _r; \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
+EGLAPI gl_hooks_t gHooksErrorTrace = {
+ {
+ #include "entries.in"
+ },
+ {
+ {0}
+ }
+};
+#undef GL_ENTRY
+#undef CHECK_ERROR
+
#undef TRACE_GL_VOID
#undef TRACE_GL