Merge "Return information about whether overlays are disabled."
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
index 3378d97..691ba2f 100644
--- a/include/binder/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -41,6 +41,7 @@
int getCallingPid();
int getCallingUid();
+ int getOrigCallingUid();
void setStrictModePolicy(int32_t policy);
int32_t getStrictModePolicy() const;
@@ -116,6 +117,7 @@
status_t mLastError;
pid_t mCallingPid;
uid_t mCallingUid;
+ uid_t mOrigCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
};
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index a281377..7bca8d6 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -95,6 +95,8 @@
* should be destroyed and getEvents() shouldn't be called again.
*/
ssize_t getEvents(Event* events, size_t count);
+ static ssize_t getEvents(const sp<BitTube>& dataChannel,
+ Event* events, size_t count);
/*
* setVsyncRate() sets the Event::VSync delivery rate. A value of
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 629b899..b578a6c 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -371,6 +371,11 @@
return mCallingUid;
}
+int IPCThreadState::getOrigCallingUid()
+{
+ return mOrigCallingUid;
+}
+
int64_t IPCThreadState::clearCallingIdentity()
{
int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid;
@@ -641,6 +646,7 @@
{
pthread_setspecific(gTLS, this);
clearCaller();
+ mOrigCallingUid = mCallingUid;
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
@@ -987,6 +993,7 @@
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
+ mOrigCallingUid = tr.sender_euid;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
@@ -1045,6 +1052,7 @@
mCallingPid = origPid;
mCallingUid = origUid;
+ mOrigCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 785da39..55f4178 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -17,8 +17,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
#include <utils/Errors.h>
@@ -38,6 +39,8 @@
mSendFd = fds[1];
fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
fcntl(mSendFd, F_SETFL, O_NONBLOCK);
+ // ignore SIGPIPE, we handle write errors through EPIPE instead
+ signal(SIGPIPE, SIG_IGN);
} else {
mReceiveFd = -errno;
ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 3b3ccaa..6a4763d 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -80,7 +80,13 @@
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
size_t count) {
- ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
+ return DisplayEventReceiver::getEvents(mDataChannel, events, count);
+}
+
+ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
+ Event* events, size_t count)
+{
+ ssize_t size = dataChannel->read(events, sizeof(events[0])*count);
ALOGE_IF(size<0,
"DisplayEventReceiver::getEvents error (%s)",
strerror(-size));
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 5cf5236..6b2ae51 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -345,42 +345,73 @@
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);
+ egl_display_t* display = cur_c->getDisplay();
+ if (display) {
+ display->loseCurrentImpl(cur_c);
+ }
+ }
+}
- // 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);
+void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
+{
+ // 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_c ? get_surface(cur_c->read) : NULL);
+ SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
+ { // scope for the lock
+ Mutex::Autolock _l(lock);
cur_c->onLooseCurrent();
- _cur_c.release();
- _cur_r.release();
- _cur_d.release();
}
+
+ // This cannot be called with the lock held because it might end-up
+ // calling back into EGL (in particular when a surface is destroyed
+ // it calls ANativeWindow::disconnect
+ _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);
+
+ // 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_c ? get_surface(cur_c->read) : NULL);
+ SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
+
+ { // scope for the lock
+ Mutex::Autolock _l(lock);
if (c) {
- c->onMakeCurrent(draw, read);
+ result = c->cnx->egl.eglMakeCurrent(
+ disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ if (result == EGL_TRUE) {
+ c->onMakeCurrent(draw, read);
+ }
+ } else {
+ result = cur_c->cnx->egl.eglMakeCurrent(
+ disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ if (result == EGL_TRUE) {
+ cur_c->onLooseCurrent();
+ }
}
}
+
+ if (result == EGL_TRUE) {
+ // This cannot be called with the lock held because it might end-up
+ // calling back into EGL (in particular when a surface is destroyed
+ // it calls ANativeWindow::disconnect
+ _cur_c.release();
+ _cur_r.release();
+ _cur_d.release();
+ }
+
return result;
}
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 4479e00..f3c4ddf 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -64,6 +64,7 @@
class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
static egl_display_t sDisplay[NUM_DISPLAYS];
EGLDisplay getDisplay(EGLNativeDisplayType display);
+ void loseCurrentImpl(egl_context_t * cur_c);
public:
enum {
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index fc211e5..42e280f 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -32,7 +32,7 @@
endif
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
- LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1
+ LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING
endif
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index f4afeea..69f1aca 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -22,15 +21,6 @@
#include <unistd.h>
#include <fcntl.h>
-#include <signal.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-
-#include <linux/unistd.h>
#include <utils/Log.h>
@@ -45,39 +35,22 @@
// ----------------------------------------------------------------------------
-DisplayHardwareBase::DisplayEventThreadBase::DisplayEventThreadBase(
+DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
const sp<SurfaceFlinger>& flinger)
: Thread(false), mFlinger(flinger) {
}
-DisplayHardwareBase::DisplayEventThreadBase::~DisplayEventThreadBase() {
+DisplayHardwareBase::DisplayEventThread::~DisplayEventThread() {
}
-// ----------------------------------------------------------------------------
-
-DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
- const sp<SurfaceFlinger>& flinger)
- : DisplayEventThreadBase(flinger)
-{
+status_t DisplayHardwareBase::DisplayEventThread::initCheck() const {
+ return ((access(kSleepFileName, R_OK) == 0 &&
+ access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
}
-DisplayHardwareBase::DisplayEventThread::~DisplayEventThread()
-{
-}
+bool DisplayHardwareBase::DisplayEventThread::threadLoop() {
-bool DisplayHardwareBase::DisplayEventThread::threadLoop()
-{
- int err = 0;
- char buf;
- int fd;
-
- fd = open(kSleepFileName, O_RDONLY, 0);
- do {
- err = read(fd, &buf, 1);
- } while (err < 0 && errno == EINTR);
- close(fd);
- ALOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
- if (err >= 0) {
+ if (waitForFbSleep() == NO_ERROR) {
sp<SurfaceFlinger> flinger = mFlinger.promote();
ALOGD("About to give-up screen, flinger = %p", flinger.get());
if (flinger != 0) {
@@ -85,39 +58,51 @@
flinger->screenReleased(0);
mBarrier.wait();
}
+ if (waitForFbWake() == NO_ERROR) {
+ sp<SurfaceFlinger> flinger = mFlinger.promote();
+ ALOGD("Screen about to return, flinger = %p", flinger.get());
+ if (flinger != 0) {
+ flinger->screenAcquired(0);
+ }
+ return true;
+ }
}
- fd = open(kWakeFileName, O_RDONLY, 0);
+
+ // error, exit the thread
+ return false;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::waitForFbSleep() {
+ int err = 0;
+ char buf;
+ int fd = open(kSleepFileName, O_RDONLY, 0);
+ // if the file doesn't exist, the error will be caught in read() below
do {
- err = read(fd, &buf, 1);
+ err = read(fd, &buf, 1);
} while (err < 0 && errno == EINTR);
close(fd);
- ALOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
- if (err >= 0) {
- sp<SurfaceFlinger> flinger = mFlinger.promote();
- ALOGD("Screen about to return, flinger = %p", flinger.get());
- if (flinger != 0)
- flinger->screenAcquired(0);
- }
- return true;
+ ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
+ return err < 0 ? -errno : int(NO_ERROR);
}
-status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const
-{
+status_t DisplayHardwareBase::DisplayEventThread::waitForFbWake() {
+ int err = 0;
+ char buf;
+ int fd = open(kWakeFileName, O_RDONLY, 0);
+ // if the file doesn't exist, the error will be caught in read() below
+ do {
+ err = read(fd, &buf, 1);
+ } while (err < 0 && errno == EINTR);
+ close(fd);
+ ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
+ return err < 0 ? -errno : int(NO_ERROR);
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const {
mBarrier.open();
return NO_ERROR;
}
-status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
-{
- return NO_ERROR;
-}
-
-status_t DisplayHardwareBase::DisplayEventThread::initCheck() const
-{
- return ((access(kSleepFileName, R_OK) == 0 &&
- access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
-}
-
// ----------------------------------------------------------------------------
DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
@@ -127,35 +112,35 @@
mDisplayEventThread = new DisplayEventThread(flinger);
}
-DisplayHardwareBase::~DisplayHardwareBase()
-{
+void DisplayHardwareBase::startSleepManagement() const {
+ if (mDisplayEventThread->initCheck() == NO_ERROR) {
+ mDisplayEventThread->run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
+ } else {
+ ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist");
+ }
+}
+
+DisplayHardwareBase::~DisplayHardwareBase() {
// request exit
mDisplayEventThread->requestExitAndWait();
}
-bool DisplayHardwareBase::canDraw() const
-{
+bool DisplayHardwareBase::canDraw() const {
return mScreenAcquired;
}
-void DisplayHardwareBase::releaseScreen() const
-{
+void DisplayHardwareBase::releaseScreen() const {
status_t err = mDisplayEventThread->releaseScreen();
if (err >= 0) {
mScreenAcquired = false;
}
}
-void DisplayHardwareBase::acquireScreen() const
-{
- status_t err = mDisplayEventThread->acquireScreen();
- if (err >= 0) {
- mScreenAcquired = true;
- }
+void DisplayHardwareBase::acquireScreen() const {
+ mScreenAcquired = true;
}
-bool DisplayHardwareBase::isScreenAcquired() const
-{
+bool DisplayHardwareBase::isScreenAcquired() const {
return mScreenAcquired;
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index ef2df43..fba211b 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
#include <stdint.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
-#include <linux/kd.h>
-#include <linux/vt.h>
#include "Barrier.h"
namespace android {
@@ -31,11 +29,13 @@
class DisplayHardwareBase
{
public:
- DisplayHardwareBase(
- const sp<SurfaceFlinger>& flinger,
- uint32_t displayIndex);
+ DisplayHardwareBase(
+ const sp<SurfaceFlinger>& flinger,
+ uint32_t displayIndex);
- ~DisplayHardwareBase();
+ ~DisplayHardwareBase();
+
+ void startSleepManagement() const;
// console management
void releaseScreen() const;
@@ -46,34 +46,21 @@
private:
- class DisplayEventThreadBase : public Thread {
- protected:
+ class DisplayEventThread : public Thread {
wp<SurfaceFlinger> mFlinger;
- public:
- DisplayEventThreadBase(const sp<SurfaceFlinger>& flinger);
- virtual ~DisplayEventThreadBase();
- virtual void onFirstRef() {
- run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
- }
- virtual status_t acquireScreen() const { return NO_ERROR; };
- virtual status_t releaseScreen() const { return NO_ERROR; };
- virtual status_t initCheck() const = 0;
- };
-
- class DisplayEventThread : public DisplayEventThreadBase
- {
mutable Barrier mBarrier;
+ status_t waitForFbSleep();
+ status_t waitForFbWake();
public:
- DisplayEventThread(const sp<SurfaceFlinger>& flinger);
+ DisplayEventThread(const sp<SurfaceFlinger>& flinger);
virtual ~DisplayEventThread();
virtual bool threadLoop();
- virtual status_t readyToRun();
- virtual status_t releaseScreen() const;
- virtual status_t initCheck() const;
+ status_t releaseScreen() const;
+ status_t initCheck() const;
};
- sp<DisplayEventThreadBase> mDisplayEventThread;
- mutable int mScreenAcquired;
+ sp<DisplayEventThread> mDisplayEventThread;
+ mutable int mScreenAcquired;
};
}; // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9c04d59..3e6b872 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -55,6 +55,7 @@
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentOpacity(true),
+ mRefreshPending(0),
mFrameLatencyNeeded(false),
mFrameLatencyOffset(0),
mFormat(PIXEL_FORMAT_NONE),
@@ -113,7 +114,7 @@
void Layer::onFrameQueued() {
android_atomic_inc(&mQueuedFrames);
- mFlinger->signalEvent();
+ mFlinger->signalLayerUpdate();
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -407,16 +408,37 @@
// pageflip handling...
// ----------------------------------------------------------------------------
+bool Layer::onPreComposition()
+{
+ // if there was more than one pending update, request a refresh
+ if (mRefreshPending >= 2) {
+ mRefreshPending = 0;
+ return true;
+ }
+ mRefreshPending = 0;
+ return false;
+}
+
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
if (mQueuedFrames > 0) {
+
+ // if we've already called updateTexImage() without going through
+ // a composition step, we have to skip this layer at this point
+ // because we cannot call updateTeximage() without a corresponding
+ // compositionComplete() call.
+ // we'll trigger an update in onPreComposition().
+ if (mRefreshPending++) {
+ return;
+ }
+
// Capture the old state of the layer for comparisons later
const bool oldOpacity = isOpaque();
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
// signal another event if we have more frames pending
if (android_atomic_dec(&mQueuedFrames) > 1) {
- mFlinger->signalEvent();
+ mFlinger->signalLayerUpdate();
}
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
@@ -519,6 +541,10 @@
void Layer::unlockPageFlip(
const Transform& planeTransform, Region& outDirtyRegion)
{
+ if (mRefreshPending >= 2) {
+ return;
+ }
+
Region dirtyRegion(mPostedDirtyRegion);
if (!dirtyRegion.isEmpty()) {
mPostedDirtyRegion.clear();
@@ -552,9 +578,9 @@
snprintf(buffer, SIZE,
" "
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
- " transform-hint=0x%02x, queued-frames=%d\n",
+ " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
mFormat, w0, h0, s0,f0,
- getTransformHint(), mQueuedFrames);
+ getTransformHint(), mQueuedFrames, mRefreshPending);
result.append(buffer);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2dd4da1..bf30608 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -80,6 +80,7 @@
virtual wp<IBinder> getSurfaceTextureBinder() const;
virtual void onLayerDisplayed();
+ virtual bool onPreComposition();
// only for debugging
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
@@ -115,14 +116,17 @@
uint32_t mCurrentTransform;
uint32_t mCurrentScalingMode;
bool mCurrentOpacity;
+ size_t mRefreshPending;
bool mFrameLatencyNeeded;
int mFrameLatencyOffset;
+
struct Statistics {
Statistics() : timestamp(0), set(0), vsync(0) { }
nsecs_t timestamp; // buffer timestamp
nsecs_t set; // buffer displayed timestamp
nsecs_t vsync; // vsync immediately before set
};
+
// protected by mLock
Statistics mFrameStats[128];
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index d32fcdd..e764001 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -47,8 +47,7 @@
mOrientation(0),
mPlaneOrientation(0),
mTransactionFlags(0),
- mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
- mInvalidate(0)
+ mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
mFlags = hw.getFlags();
@@ -262,23 +261,11 @@
mTransformedBounds = tr.makeBounds(w, h);
}
-void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
-{
+void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
}
void LayerBase::unlockPageFlip(
- const Transform& planeTransform, Region& outDirtyRegion)
-{
- if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
- outDirtyRegion.orSelf(visibleRegionScreen);
- }
-}
-
-void LayerBase::invalidate()
-{
- if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
- mFlinger->signalEvent();
- }
+ const Transform& planeTransform, Region& outDirtyRegion) {
}
void LayerBase::drawRegion(const Region& reg) const
@@ -471,16 +458,21 @@
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
const Layer::State& s(drawingState());
+
+ snprintf(buffer, SIZE,
+ "+ %s %p (%s)\n",
+ getTypeId(), this, getName().string());
+ result.append(buffer);
+
s.transparentRegion.dump(result, "transparentRegion");
transparentRegionScreen.dump(result, "transparentRegionScreen");
visibleRegionScreen.dump(result, "visibleRegionScreen");
+
snprintf(buffer, SIZE,
- "+ %s %p (%s)\n"
" "
"z=%9d, pos=(%g,%g), size=(%4d,%4d), "
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- getTypeId(), this, getName().string(),
s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 6b62c9d..b8f7680 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -103,8 +103,6 @@
Rect visibleBounds() const;
void drawRegion(const Region& reg) const;
- void invalidate();
-
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
virtual sp<Layer> getLayer() const { return 0; }
@@ -204,9 +202,16 @@
/** called with the state lock when the surface is removed from the
* current list */
- virtual void onRemoved() { };
+ virtual void onRemoved() { }
- virtual void onLayerDisplayed() { };
+ /** called after page-flip
+ */
+ virtual void onLayerDisplayed() { }
+
+ /** called before composition.
+ * returns true if the layer has pending updates.
+ */
+ virtual bool onPreComposition() { return false; }
/** always call base class first */
virtual void dump(String8& result, char* scratch, size_t size) const;
@@ -275,10 +280,6 @@
mutable bool mDebug;
- // atomic
- volatile int32_t mInvalidate;
-
-
public:
// called from class SurfaceFlinger
virtual ~LayerBase();
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 70711e7..290fff4 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -29,6 +29,7 @@
#include "MessageQueue.h"
#include "EventThread.h"
+#include "SurfaceFlinger.h"
namespace android {
@@ -48,14 +49,47 @@
// ---------------------------------------------------------------------------
+void MessageQueue::Handler::signalRefresh() {
+ if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
+ mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
+ }
+}
+
+void MessageQueue::Handler::signalInvalidate() {
+ if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
+ mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
+ }
+}
+
+void MessageQueue::Handler::handleMessage(const Message& message) {
+ switch (message.what) {
+ case INVALIDATE:
+ android_atomic_and(~eventMaskInvalidate, &mEventMask);
+ mQueue.mFlinger->onMessageReceived(message.what);
+ break;
+ case REFRESH:
+ android_atomic_and(~eventMaskRefresh, &mEventMask);
+ mQueue.mFlinger->onMessageReceived(message.what);
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+
MessageQueue::MessageQueue()
- : mLooper(new Looper(true)), mWorkPending(0)
{
}
MessageQueue::~MessageQueue() {
}
+void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
+{
+ mFlinger = flinger;
+ mLooper = new Looper(true);
+ mHandler = new Handler(*this);
+}
+
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
mEventThread = eventThread;
@@ -68,25 +102,16 @@
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
-
int32_t ret = mLooper->pollOnce(-1);
switch (ret) {
case ALOOPER_POLL_WAKE:
case ALOOPER_POLL_CALLBACK:
- // callback and/or wake
- if (android_atomic_and(0, &mWorkPending)) {
- return;
- }
continue;
-
+ case ALOOPER_POLL_ERROR:
+ ALOGE("ALOOPER_POLL_ERROR");
case ALOOPER_POLL_TIMEOUT:
// timeout (should not happen)
continue;
-
- case ALOOPER_POLL_ERROR:
- ALOGE("ALOOPER_POLL_ERROR");
- continue;
-
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
@@ -107,15 +132,13 @@
return NO_ERROR;
}
-void MessageQueue::scheduleWorkASAP() {
- if (android_atomic_or(1, &mWorkPending) == 0) {
- mLooper->wake();
- }
+void MessageQueue::invalidate() {
+// mHandler->signalInvalidate();
+ mEvents->requestNextVsync();
}
-status_t MessageQueue::invalidate() {
+void MessageQueue::refresh() {
mEvents->requestNextVsync();
- return NO_ERROR;
}
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
@@ -126,10 +149,10 @@
int MessageQueue::eventReceiver(int fd, int events) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
- while ((n = getEvents(buffer, 8)) > 0) {
+ while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- scheduleWorkASAP();
+ mHandler->signalRefresh();
break;
}
}
@@ -137,24 +160,6 @@
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 5ea197d..ea29e7e 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -33,6 +33,7 @@
class IDisplayEventConnection;
class EventThread;
+class SurfaceFlinger;
// ---------------------------------------------------------------------------
@@ -59,25 +60,48 @@
// ---------------------------------------------------------------------------
class MessageQueue {
+ class Handler : public MessageHandler {
+ enum {
+ eventMaskInvalidate = 0x1,
+ eventMaskRefresh = 0x2
+ };
+ MessageQueue& mQueue;
+ int32_t mEventMask;
+ public:
+ Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
+ virtual void handleMessage(const Message& message);
+ void signalRefresh();
+ void signalInvalidate();
+ };
+
+ friend class Handler;
+
+ sp<SurfaceFlinger> mFlinger;
sp<Looper> mLooper;
sp<EventThread> mEventThread;
sp<IDisplayEventConnection> mEvents;
sp<BitTube> mEventTube;
- int32_t mWorkPending;
+ sp<Handler> mHandler;
+
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:
+ enum {
+ INVALIDATE = 0,
+ REFRESH = 1,
+ };
+
MessageQueue();
~MessageQueue();
+ void init(const sp<SurfaceFlinger>& flinger);
void setEventThread(const sp<EventThread>& events);
void waitMessage();
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
- status_t invalidate();
+ void invalidate();
+ void refresh();
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5535699..40717f4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -125,11 +125,34 @@
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
+void SurfaceFlinger::onFirstRef()
+{
+ mEventQueue.init(this);
+
+ run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
+
+ // Wait for the main thread to be done with its initialization
+ mReadyToRunBarrier.wait();
+}
+
+
SurfaceFlinger::~SurfaceFlinger()
{
glDeleteTextures(1, &mWormholeTexName);
}
+void SurfaceFlinger::binderDied(const wp<IBinder>& who)
+{
+ // the window manager died on us. prepare its eulogy.
+
+ // reset screen orientation
+ Vector<ComposerState> state;
+ setTransactionState(state, eOrientationDefault, 0);
+
+ // restart the boot-animation
+ property_set("ctl.start", "bootanim");
+}
+
sp<IMemoryHeap> SurfaceFlinger::getCblk() const
{
return mServerHeap;
@@ -183,26 +206,6 @@
property_set("ctl.stop", "bootanim");
}
-void SurfaceFlinger::binderDied(const wp<IBinder>& who)
-{
- // the window manager died on us. prepare its eulogy.
-
- // reset screen orientation
- Vector<ComposerState> state;
- setTransactionState(state, eOrientationDefault, 0);
-
- // restart the boot-animation
- property_set("ctl.start", "bootanim");
-}
-
-void SurfaceFlinger::onFirstRef()
-{
- run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
-
- // Wait for the main thread to be done with its initialization
- mReadyToRunBarrier.wait();
-}
-
static inline uint16_t pack565(int r, int g, int b) {
return (r<<11)|(g<<5)|b;
}
@@ -297,6 +300,7 @@
// start the EventThread
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
+ hw.startSleepManagement();
/*
* We're now ready to accept clients...
@@ -311,34 +315,6 @@
}
// ----------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#pragma mark Events Handler
-#endif
-
-void SurfaceFlinger::waitForEvent() {
- mEventQueue.waitMessage();
-}
-
-void SurfaceFlinger::signalEvent() {
- mEventQueue.invalidate();
-}
-
-status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t flags) {
- return mEventQueue.postMessage(msg, reltime);
-}
-
-status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t flags) {
- status_t res = mEventQueue.postMessage(msg, reltime);
- if (res == NO_ERROR) {
- msg->wait();
- }
- return res;
-}
-
-// ----------------------------------------------------------------------------
bool SurfaceFlinger::authenticateSurfaceTexture(
const sp<ISurfaceTexture>& surfaceTexture) const {
@@ -388,59 +364,104 @@
}
// ----------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#pragma mark Main loop
-#endif
+
+void SurfaceFlinger::waitForEvent() {
+ mEventQueue.waitMessage();
+}
+
+void SurfaceFlinger::signalTransaction() {
+ mEventQueue.invalidate();
+}
+
+void SurfaceFlinger::signalLayerUpdate() {
+ mEventQueue.invalidate();
+}
+
+void SurfaceFlinger::signalRefresh() {
+ mEventQueue.refresh();
+}
+
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags) {
+ return mEventQueue.postMessage(msg, reltime);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags) {
+ status_t res = mEventQueue.postMessage(msg, reltime);
+ if (res == NO_ERROR) {
+ msg->wait();
+ }
+ return res;
+}
bool SurfaceFlinger::threadLoop()
{
waitForEvent();
-
- // check for transactions
- if (CC_UNLIKELY(mConsoleSignals)) {
- handleConsoleEvents();
- }
-
- // if we're in a global transaction, don't do anything.
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- uint32_t transactionFlags = peekTransactionFlags(mask);
- if (CC_UNLIKELY(transactionFlags)) {
- handleTransaction(transactionFlags);
- }
-
- // post surfaces (if needed)
- handlePageFlip();
-
- if (mDirtyRegion.isEmpty()) {
- // nothing new to do.
- return true;
- }
-
- if (CC_UNLIKELY(mHwWorkListDirty)) {
- // build the h/w work list
- handleWorkList();
- }
-
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- if (CC_LIKELY(hw.canDraw())) {
- // repaint the framebuffer (if needed)
- handleRepaint();
- // inform the h/w that we're done compositing
- hw.compositionComplete();
- postFramebuffer();
- } else {
- // pretend we did the post
- hw.compositionComplete();
- }
return true;
}
+void SurfaceFlinger::onMessageReceived(int32_t what)
+{
+ switch (what) {
+ case MessageQueue::REFRESH: {
+// case MessageQueue::INVALIDATE: {
+ // check for transactions
+ if (CC_UNLIKELY(mConsoleSignals)) {
+ handleConsoleEvents();
+ }
+
+ // if we're in a global transaction, don't do anything.
+ const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+ uint32_t transactionFlags = peekTransactionFlags(mask);
+ if (CC_UNLIKELY(transactionFlags)) {
+ handleTransaction(transactionFlags);
+ }
+
+ // post surfaces (if needed)
+ handlePageFlip();
+
+// signalRefresh();
+//
+// } break;
+//
+// case MessageQueue::REFRESH: {
+
+ handleRefresh();
+
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+
+// if (mDirtyRegion.isEmpty()) {
+// return;
+// }
+
+ if (CC_UNLIKELY(mHwWorkListDirty)) {
+ // build the h/w work list
+ handleWorkList();
+ }
+
+ if (CC_LIKELY(hw.canDraw())) {
+ // repaint the framebuffer (if needed)
+ handleRepaint();
+ // inform the h/w that we're done compositing
+ hw.compositionComplete();
+ postFramebuffer();
+ } else {
+ // pretend we did the post
+ hw.compositionComplete();
+ }
+
+ } break;
+ }
+}
+
void SurfaceFlinger::postFramebuffer()
{
- // this should never happen. we do the flip anyways so we don't
- // risk to cause a deadlock with hwc
- ALOGW_IF(mSwapRegion.isEmpty(), "mSwapRegion is empty");
+ // mSwapRegion can be empty here is some cases, for instance if a hidden
+ // or fully transparent window is updating.
+ // in that case, we need to flip anyways to not risk a deadlock with
+ // h/w composer.
+
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
@@ -717,13 +738,13 @@
void SurfaceFlinger::handlePageFlip()
{
- bool visibleRegions = mVisibleRegionsDirty;
- const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
- visibleRegions |= lockPageFlip(currentLayers);
+ const DisplayHardware& hw = graphicPlane(0).displayHardware();
+ const Region screenRegion(hw.bounds());
- const DisplayHardware& hw = graphicPlane(0).displayHardware();
- const Region screenRegion(hw.bounds());
- if (visibleRegions) {
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ const bool visibleRegions = lockPageFlip(currentLayers);
+
+ if (visibleRegions || mVisibleRegionsDirty) {
Region opaqueRegion;
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
@@ -770,7 +791,7 @@
{
const GraphicPlane& plane(graphicPlane(0));
const Transform& planeTransform(plane.transform());
- size_t count = currentLayers.size();
+ const size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
@@ -778,6 +799,23 @@
}
}
+void SurfaceFlinger::handleRefresh()
+{
+ bool needInvalidate = false;
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(currentLayers[i]);
+ if (layer->onPreComposition()) {
+ needInvalidate = true;
+ }
+ }
+ if (needInvalidate) {
+ signalLayerUpdate();
+ }
+}
+
+
void SurfaceFlinger::handleWorkList()
{
mHwWorkListDirty = false;
@@ -1175,7 +1213,7 @@
{
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
if ((old & flags)==0) { // wake the server up
- signalEvent();
+ signalTransaction();
}
return old;
}
@@ -1426,14 +1464,14 @@
{
// this may be called by a signal handler, we can't do too much in here
android_atomic_or(eConsoleReleased, &mConsoleSignals);
- signalEvent();
+ signalTransaction();
}
void SurfaceFlinger::screenAcquired(int dpy)
{
// this may be called by a signal handler, we can't do too much in here
android_atomic_or(eConsoleAcquired, &mConsoleSignals);
- signalEvent();
+ signalTransaction();
}
status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
@@ -1620,11 +1658,13 @@
snprintf(buffer, SIZE,
" last eglSwapBuffers() time: %f us\n"
" last transaction time : %f us\n"
+ " transaction-flags : %08x\n"
" refresh-rate : %f fps\n"
" x-dpi : %f\n"
" y-dpi : %f\n",
mLastSwapBufferTime/1000.0,
mLastTransactionTime/1000.0,
+ mTransactionFlags,
hw.getRefreshRate(),
hw.getDpiX(),
hw.getDpiY());
@@ -1770,7 +1810,7 @@
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const Rect bounds(hw.getBounds());
setInvalidateRegion(Region(bounds));
- signalEvent();
+ signalTransaction();
}
void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
@@ -2246,7 +2286,7 @@
// make sure to redraw the whole screen when the animation is done
mDirtyRegion.set(hw.bounds());
- signalEvent();
+ signalTransaction();
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c24a9de..fcd9361 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -190,6 +190,8 @@
status_t renderScreenToTextureLocked(DisplayID dpy,
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
+ void onMessageReceived(int32_t what);
+
status_t postMessageAsync(const sp<MessageBase>& msg,
nsecs_t reltime=0, uint32_t flags = 0);
@@ -283,7 +285,10 @@
public: // hack to work around gcc 4.0.3 bug
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
- void signalEvent();
+
+ void signalTransaction();
+ void signalLayerUpdate();
+ void signalRefresh();
void repaintEverything();
private:
@@ -300,6 +305,7 @@
void handlePageFlip();
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
+ void handleRefresh();
void handleWorkList();
void handleRepaint();
void postFramebuffer();