Merge "Dump xt_qtaguid stats to using GID instead of su."
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 2fc6125..06be2ef 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -253,6 +253,19 @@
if (f == NULL) {
//ALOGD("%s", name);
f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
+
+ /*
+ * GL_EXT_debug_label is special, we always report it as
+ * supported, it's handled by GLES_trace. If GLES_trace is not
+ * enabled, then these are no-ops.
+ */
+ if (!strcmp(name, "glInsertEventMarkerEXT")) {
+ f = (__eglMustCastToProperFunctionPointerType)gl_noop;
+ } else if (!strcmp(name, "glPushGroupMarkerEXT")) {
+ f = (__eglMustCastToProperFunctionPointerType)gl_noop;
+ } else if (!strcmp(name, "glPopGroupMarkerEXT")) {
+ f = (__eglMustCastToProperFunctionPointerType)gl_noop;
+ }
}
*curr++ = f;
api++;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index e053589..83933e5 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -233,6 +233,26 @@
// ----------------------------------------------------------------------------
+const GLubyte * egl_get_string_for_current_context(GLenum name) {
+ // NOTE: returning NULL here will fall-back to the default
+ // implementation.
+
+ EGLContext context = egl_tls_t::getContext();
+ if (context == EGL_NO_CONTEXT)
+ return NULL;
+
+ egl_context_t const * const c = get_context(context);
+ if (c == NULL) // this should never happen, by construction
+ return NULL;
+
+ if (name != GL_EXTENSIONS)
+ return NULL;
+
+ return (const GLubyte *)c->gl_extensions.string();
+}
+
+// ----------------------------------------------------------------------------
+
// this mutex protects:
// d->disp[]
// egl_init_drivers_locked()
@@ -290,6 +310,9 @@
ALOGE("called unimplemented OpenGL ES API");
}
+void gl_noop() {
+}
+
// ----------------------------------------------------------------------------
#if USE_FAST_TLS_KEY
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 8b37da5..73aab26 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -566,27 +566,6 @@
return result;
}
-static void loseCurrent(egl_context_t * cur_c)
-{
- if (cur_c) {
- egl_surface_t * cur_r = get_surface(cur_c->read);
- egl_surface_t * cur_d = get_surface(cur_c->draw);
-
- // by construction, these are either 0 or valid (possibly terminated)
- // it should be impossible for these to be invalid
- ContextRef _cur_c(cur_c);
- SurfaceRef _cur_r(cur_r);
- SurfaceRef _cur_d(cur_d);
-
- cur_c->read = NULL;
- cur_c->draw = NULL;
-
- _cur_c.release();
- _cur_r.release();
- _cur_d.release();
- }
-}
-
EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
EGLSurface read, EGLContext ctx)
{
@@ -663,21 +642,13 @@
impl_read = r->surface;
}
- EGLBoolean result;
- if (c) {
- result = c->cnx->egl.eglMakeCurrent(
- dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
- } else {
- result = cur_c->cnx->egl.eglMakeCurrent(
- dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
- }
+ EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c,
+ draw, read, ctx,
+ impl_draw, impl_read, impl_ctx);
if (result == EGL_TRUE) {
-
- loseCurrent(cur_c);
-
- if (ctx != EGL_NO_CONTEXT) {
+ if (c) {
setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
egl_tls_t::setContext(ctx);
#if EGL_TRACE
@@ -687,8 +658,6 @@
_c.acquire();
_r.acquire();
_d.acquire();
- c->read = read;
- c->draw = draw;
} else {
setGLHooksThreadSpecific(&gHooksNoContext);
egl_tls_t::setContext(EGL_NO_CONTEXT);
@@ -924,7 +893,8 @@
cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
#if EGL_TRACE
- debugHooks->ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
+ debugHooks->ext.extensions[slot] =
+ gHooksTrace.ext.extensions[slot] =
#endif
cnx->egl.eglGetProcAddress(procname);
}
@@ -1180,7 +1150,7 @@
clearError();
// If there is context bound to the thread, release it
- loseCurrent(get_context(getContext()));
+ egl_display_t::loseCurrent(get_context(getContext()));
for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 53eaf9a..5cf5236 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -342,6 +342,47 @@
return res;
}
+void egl_display_t::loseCurrent(egl_context_t * cur_c)
+{
+ if (cur_c) {
+ egl_surface_t * cur_r = get_surface(cur_c->read);
+ egl_surface_t * cur_d = get_surface(cur_c->draw);
+
+ // by construction, these are either 0 or valid (possibly terminated)
+ // it should be impossible for these to be invalid
+ ContextRef _cur_c(cur_c);
+ SurfaceRef _cur_r(cur_r);
+ SurfaceRef _cur_d(cur_d);
+
+ cur_c->onLooseCurrent();
+
+ _cur_c.release();
+ _cur_r.release();
+ _cur_d.release();
+ }
+}
+
+EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
+ EGLSurface draw, EGLSurface read, EGLContext ctx,
+ EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
+{
+ Mutex::Autolock _l(lock);
+ EGLBoolean result;
+ if (c) {
+ result = c->cnx->egl.eglMakeCurrent(
+ disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ } else {
+ result = cur_c->cnx->egl.eglMakeCurrent(
+ disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ }
+ if (result == EGL_TRUE) {
+ loseCurrent(cur_c);
+ if (c) {
+ c->onMakeCurrent(draw, read);
+ }
+ }
+ return result;
+}
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 042ae07..4479e00 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -39,6 +39,7 @@
// ----------------------------------------------------------------------------
class egl_object_t;
+class egl_context_t;
class egl_connection_t;
// ----------------------------------------------------------------------------
@@ -84,10 +85,14 @@
// add reference to this object. returns true if this is a valid object.
bool getObject(egl_object_t* object) const;
-
static egl_display_t* get(EGLDisplay dpy);
static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp);
+ EGLBoolean makeCurrent(egl_context_t* c, egl_context_t* cur_c,
+ EGLSurface draw, EGLSurface read, EGLContext ctx,
+ EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx);
+ static void loseCurrent(egl_context_t * cur_c);
+
inline bool isReady() const { return (refs > 0); }
inline bool isValid() const { return magic == '_dpy'; }
inline bool isAlive() const { return isValid(); }
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 26e8c3e..b660c53 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -62,5 +62,41 @@
}
// ----------------------------------------------------------------------------
+
+egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
+ int impl, egl_connection_t const* cnx, int version) :
+ egl_object_t(get_display(dpy)), dpy(dpy), context(context),
+ config(config), read(0), draw(0), impl(impl), cnx(cnx),
+ version(version)
+{
+}
+
+void egl_context_t::onLooseCurrent() {
+ read = NULL;
+ draw = NULL;
+}
+
+void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) {
+ this->read = read;
+ this->draw = draw;
+
+ /*
+ * Here we cache the GL_EXTENSIONS string for this context and we
+ * add the extensions always handled by the wrapper
+ */
+
+ if (gl_extensions.isEmpty()) {
+ // call the implementation's glGetString(GL_EXTENSIONS)
+ const char* exts = (const char *)gEGLImpl[impl].hooks[version]->gl.glGetString(GL_EXTENSIONS);
+ gl_extensions.setTo(exts);
+ if (gl_extensions.find("GL_EXT_debug_marker") < 0) {
+ String8 temp("GL_EXT_debug_marker ");
+ temp.append(gl_extensions);
+ gl_extensions.setTo(temp);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 7106fa5..abd4cbb 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -28,6 +28,7 @@
#include <GLES/glext.h>
#include <utils/threads.h>
+#include <utils/String8.h>
#include <system/window.h>
@@ -158,11 +159,11 @@
typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
- int impl, egl_connection_t const* cnx, int version) :
- egl_object_t(get_display(dpy)), dpy(dpy), context(context),
- config(config), read(0), draw(0), impl(impl), cnx(cnx),
- version(version) {
- }
+ int impl, egl_connection_t const* cnx, int version);
+
+ void onLooseCurrent();
+ void onMakeCurrent(EGLSurface draw, EGLSurface read);
+
EGLDisplay dpy;
EGLContext context;
EGLConfig config;
@@ -171,6 +172,7 @@
int impl;
egl_connection_t const* cnx;
int version;
+ String8 gl_extensions;
};
class egl_image_t: public egl_object_t {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 107acd9..ff20957 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -58,6 +58,7 @@
extern gl_hooks_t gHooksNoContext;
extern pthread_key_t gGLWrapperKey;
extern "C" void gl_unimplemented();
+extern "C" void gl_noop();
extern char const * const gl_names[];
extern char const * const egl_names[];
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index f89c865..8dcf38d 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -82,23 +82,41 @@
#endif
+
#define GL_EXTENSION_LIST(name) \
- name(0) name(1) name(2) name(3) \
- name(4) name(5) name(6) name(7) \
- name(8) name(9) name(10) name(11) \
- name(12) name(13) name(14) name(15) \
- name(16) name(17) name(18) name(19) \
- name(20) name(21) name(22) name(23) \
- name(24) name(25) name(26) name(27) \
- name(28) name(29) name(30) name(31) \
- name(32) name(33) name(34) name(35) \
- name(36) name(37) name(38) name(39) \
- name(40) name(41) name(42) name(43) \
- name(44) name(45) name(46) name(47) \
- name(48) name(49) name(50) name(51) \
- name(52) name(53) name(54) name(55) \
- name(56) name(57) name(58) name(59) \
- name(60) name(61) name(62) name(63)
+ name(0) name(1) name(2) name(3) name(4) name(5) name(6) name(7) \
+ name(8) name(9) name(10) name(11) name(12) name(13) name(14) name(15) \
+ name(16) name(17) name(18) name(19) name(20) name(21) name(22) name(23) \
+ name(24) name(25) name(26) name(27) name(28) name(29) name(30) name(31) \
+ name(32) name(33) name(34) name(35) name(36) name(37) name(38) name(39) \
+ name(40) name(41) name(42) name(43) name(44) name(45) name(46) name(47) \
+ name(48) name(49) name(50) name(51) name(52) name(53) name(54) name(55) \
+ name(56) name(57) name(58) name(59) name(60) name(61) name(62) name(63) \
+ name(64) name(65) name(66) name(67) name(68) name(69) name(70) name(71) \
+ name(72) name(73) name(74) name(75) name(76) name(77) name(78) name(79) \
+ name(80) name(81) name(82) name(83) name(84) name(85) name(86) name(87) \
+ name(88) name(89) name(90) name(91) name(92) name(93) name(94) name(95) \
+ name(96) name(97) name(98) name(99) \
+ name(100) name(101) name(102) name(103) name(104) name(105) name(106) name(107) \
+ name(108) name(109) name(110) name(111) name(112) name(113) name(114) name(115) \
+ name(116) name(117) name(118) name(119) name(120) name(121) name(122) name(123) \
+ name(124) name(125) name(126) name(127) name(128) name(129) name(130) name(131) \
+ name(132) name(133) name(134) name(135) name(136) name(137) name(138) name(139) \
+ name(140) name(141) name(142) name(143) name(144) name(145) name(146) name(147) \
+ name(148) name(149) name(150) name(151) name(152) name(153) name(154) name(155) \
+ name(156) name(157) name(158) name(159) name(160) name(161) name(162) name(163) \
+ name(164) name(165) name(166) name(167) name(168) name(169) name(170) name(171) \
+ name(172) name(173) name(174) name(175) name(176) name(177) name(178) name(179) \
+ name(180) name(181) name(182) name(183) name(184) name(185) name(186) name(187) \
+ name(188) name(189) name(190) name(191) name(192) name(193) name(194) name(195) \
+ name(196) name(197) name(198) name(199) \
+ name(200) name(201) name(202) name(203) name(204) name(205) name(206) name(207) \
+ name(208) name(209) name(210) name(211) name(212) name(213) name(214) name(215) \
+ name(216) name(217) name(218) name(219) name(220) name(221) name(222) name(223) \
+ name(224) name(225) name(226) name(227) name(228) name(229) name(230) name(231) \
+ name(232) name(233) name(234) name(235) name(236) name(237) name(238) name(239) \
+ name(240) name(241) name(242) name(243) name(244) name(245) name(246) name(247) \
+ name(248) name(249) name(250) name(251) name(252) name(253) name(254) name(255)
GL_EXTENSION_LIST( GL_EXTENSION )
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index df22b96..79aa3cd 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -110,6 +110,20 @@
#undef CALL_GL_API
#undef CALL_GL_API_RETURN
+/*
+ * glGetString() is special because we expose some extensions in the wrapper
+ */
+
+extern "C" const GLubyte * __glGetString(GLenum name);
+
+const GLubyte * glGetString(GLenum name)
+{
+ const GLubyte * ret = egl_get_string_for_current_context(name);
+ if (ret == NULL) {
+ ret = __glGetString(name);
+ }
+ return ret;
+}
/*
* These GL calls are special because they need to EGL to retrieve some
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
index 5164450..9a89a52 100644
--- a/opengl/libs/GLES2/gl2_api.in
+++ b/opengl/libs/GLES2/gl2_api.in
@@ -211,7 +211,7 @@
void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) {
CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
}
-const GLubyte* API_ENTRY(glGetString)(GLenum name) {
+const GLubyte* API_ENTRY(__glGetString)(GLenum name) {
CALL_GL_API_RETURN(glGetString, name);
}
void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) {
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 2d31a35..adeaa5b 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -165,6 +165,20 @@
#undef CALL_GL_API
#undef CALL_GL_API_RETURN
+/*
+ * glGetString() is special because we expose some extensions in the wrapper
+ */
+
+extern "C" const GLubyte * __glGetString(GLenum name);
+
+const GLubyte * glGetString(GLenum name)
+{
+ const GLubyte * ret = egl_get_string_for_current_context(name);
+ if (ret == NULL) {
+ ret = __glGetString(name);
+ }
+ return ret;
+}
/*
* These GL calls are special because they need to EGL to retrieve some
diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in
index 7f20c4f..c8f6b0c 100644
--- a/opengl/libs/GLES_CM/gl_api.in
+++ b/opengl/libs/GLES_CM/gl_api.in
@@ -262,7 +262,7 @@
void API_ENTRY(glGetPointerv)(GLenum pname, GLvoid **params) {
CALL_GL_API(glGetPointerv, pname, params);
}
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
+const GLubyte * API_ENTRY(__glGetString)(GLenum name) {
CALL_GL_API_RETURN(glGetString, name);
}
void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) {
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index a809316..8ff51ec 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -29,6 +29,7 @@
namespace android {
// ----------------------------------------------------------------------------
+EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name);
EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
index bd8dda3..9be40cf 100755
--- a/opengl/libs/tools/glapigen
+++ b/opengl/libs/tools/glapigen
@@ -43,6 +43,9 @@
if ($name eq "glEGLImageTargetRenderbufferStorageOES") {
$prefix = "__";
}
+ if ($name eq "glGetString") {
+ $prefix = "__";
+ }
printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 95d651a..732af53 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -23,18 +23,22 @@
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+ifeq ($(TARGET_HAS_WAITFORVSYNC), true)
+ LOCAL_CFLAGS += -DHAS_WAITFORVSYNC
+endif
+
ifeq ($(TARGET_BOARD_PLATFORM), omap3)
LOCAL_CFLAGS += -DNO_RGBX_8888
endif
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+ LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1
endif
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
LOCAL_CFLAGS += -DREFRESH_RATE=56
endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware \
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 6796d7d..92d4266 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -36,6 +36,7 @@
EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger),
mHw(flinger->graphicPlane(0).displayHardware()),
+ mLastVSyncTimestamp(0),
mDeliveredEvents(0)
{
}
@@ -44,6 +45,20 @@
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
+sp<DisplayEventConnection> EventThread::createEventConnection() const {
+ return new DisplayEventConnection(const_cast<EventThread*>(this));
+}
+
+nsecs_t EventThread::getLastVSyncTimestamp() const {
+ Mutex::Autolock _l(mLock);
+ return mLastVSyncTimestamp;
+}
+
+nsecs_t EventThread::getVSyncPeriod() const {
+ return mHw.getRefreshPeriod();
+
+}
+
status_t EventThread::registerDisplayEventConnection(
const sp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
@@ -80,8 +95,11 @@
Mutex::Autolock _l(mLock);
ConnectionInfo* info = getConnectionInfoLocked(connection);
if (info) {
- info->count = (count == 0) ? -1 : count;
- mCondition.signal();
+ const int32_t new_count = (count == 0) ? -1 : count;
+ if (info->count != new_count) {
+ info->count = new_count;
+ mCondition.signal();
+ }
}
}
}
@@ -90,10 +108,8 @@
const wp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
ConnectionInfo* info = getConnectionInfoLocked(connection);
- if (info) {
- if (info->count < 0) {
- info->count = 0;
- }
+ if (info && info->count < 0) {
+ info->count = 0;
mCondition.signal();
}
}
@@ -132,6 +148,7 @@
timestamp = mHw.waitForRefresh();
mLock.lock();
mDeliveredEvents++;
+ mLastVSyncTimestamp = timestamp;
// now see if we still need to report this VSYNC event
bool reportVsync = false;
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 35bd299..3a3071e 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -36,6 +36,7 @@
class SurfaceFlinger;
class DisplayHardware;
+class DisplayEventConnection;
// ---------------------------------------------------------------------------
@@ -45,6 +46,8 @@
public:
EventThread(const sp<SurfaceFlinger>& flinger);
+ sp<DisplayEventConnection> createEventConnection() const;
+
status_t registerDisplayEventConnection(
const sp<DisplayEventConnection>& connection);
@@ -56,6 +59,10 @@
void requestNextVsync(const wp<DisplayEventConnection>& connection);
+ nsecs_t getLastVSyncTimestamp() const;
+
+ nsecs_t getVSyncPeriod() const;
+
void dump(String8& result, char* buffer, size_t SIZE) const;
private:
@@ -88,6 +95,7 @@
// protected by mLock
KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections;
+ nsecs_t mLastVSyncTimestamp;
// main thread only
size_t mDeliveredEvents;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8e87b88..9c04d59 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -97,7 +97,12 @@
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
mSurfaceTexture->setSynchronousMode(true);
+#ifdef USE_TRIPLE_BUFFERING
+#warning "using triple buffering"
+ mSurfaceTexture->setBufferCountServer(3);
+#else
mSurfaceTexture->setBufferCountServer(2);
+#endif
}
Layer::~Layer()
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index cbd530c..70711e7 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -18,12 +18,17 @@
#include <errno.h>
#include <sys/types.h>
+#include <binder/IPCThreadState.h>
+
#include <utils/threads.h>
#include <utils/Timers.h>
#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
+
+#include <gui/IDisplayEventConnection.h>
+#include <gui/BitTube.h>
#include "MessageQueue.h"
+#include "EventThread.h"
namespace android {
@@ -51,6 +56,15 @@
MessageQueue::~MessageQueue() {
}
+void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
+{
+ mEventThread = eventThread;
+ mEvents = eventThread->createEventConnection();
+ mEventTube = mEvents->getDataChannel();
+ mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
+ MessageQueue::cb_eventReceiver, this);
+}
+
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
@@ -93,13 +107,54 @@
return NO_ERROR;
}
-status_t MessageQueue::invalidate() {
+void MessageQueue::scheduleWorkASAP() {
if (android_atomic_or(1, &mWorkPending) == 0) {
mLooper->wake();
- }
+ }
+}
+
+status_t MessageQueue::invalidate() {
+ mEvents->requestNextVsync();
return NO_ERROR;
}
+int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
+ MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
+ return queue->eventReceiver(fd, events);
+}
+
+int MessageQueue::eventReceiver(int fd, int events) {
+ ssize_t n;
+ DisplayEventReceiver::Event buffer[8];
+ while ((n = getEvents(buffer, 8)) > 0) {
+ for (int i=0 ; i<n ; i++) {
+ if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ scheduleWorkASAP();
+ break;
+ }
+ }
+ }
+ return 1;
+}
+
+ssize_t MessageQueue::getEvents(
+ DisplayEventReceiver::Event* events, size_t count)
+{
+ ssize_t size = mEventTube->read(events, sizeof(events[0])*count);
+ ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size));
+ if (size >= 0) {
+ // Note: if (size % sizeof(events[0])) != 0, we've got a
+ // partial read. This can happen if the queue filed up (ie: if we
+ // didn't pull from it fast enough).
+ // We discard the partial event and rely on the sender to
+ // re-send the event if appropriate (some events, like VSYNC
+ // can be lost forever).
+ // returns number of events read
+ size /= sizeof(events[0]);
+ }
+ return size;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 2317d81..5ea197d 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -25,10 +25,15 @@
#include <utils/Timers.h>
#include <utils/Looper.h>
+#include <gui/DisplayEventReceiver.h>
+
#include "Barrier.h"
namespace android {
+class IDisplayEventConnection;
+class EventThread;
+
// ---------------------------------------------------------------------------
class MessageBase : public MessageHandler
@@ -55,11 +60,20 @@
class MessageQueue {
sp<Looper> mLooper;
- volatile int32_t mWorkPending;
+ sp<EventThread> mEventThread;
+ sp<IDisplayEventConnection> mEvents;
+ sp<BitTube> mEventTube;
+ int32_t mWorkPending;
+
+ static int cb_eventReceiver(int fd, int events, void* data);
+ int eventReceiver(int fd, int events);
+ ssize_t getEvents(DisplayEventReceiver::Event* events, size_t count);
+ void scheduleWorkASAP();
public:
MessageQueue();
~MessageQueue();
+ void setEventThread(const sp<EventThread>& events);
void waitMessage();
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 887aee7..ff70ec3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -296,6 +296,7 @@
// start the EventThread
mEventThread = new EventThread(this);
+ mEventQueue.setEventThread(mEventThread);
/*
* We're now ready to accept clients...
@@ -383,8 +384,7 @@
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
- sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread));
- return result;
+ return mEventThread->createEventConnection();
}
// ----------------------------------------------------------------------------
@@ -432,7 +432,6 @@
} else {
// pretend we did the post
hw.compositionComplete();
- hw.waitForRefresh();
}
return true;
}
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 259b937..49e8e63 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -94,6 +94,10 @@
*outTransform = orientation;
}
switch(api) {
+ case NATIVE_WINDOW_API_CPU:
+ // SurfaceTextureClient supports only 2 buffers for CPU connections
+ this->setBufferCountServer(2);
+ break;
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
// Camera preview and videos are rate-limited on the producer