Merge "Add BufferItemConsumer, a simple BufferQueue consumer." into jb-mr1-dev
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 9765e28..65d9eb3 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -107,9 +107,11 @@
};
enum {
- eSurfaceChanged = 0x1,
- eLayerStackChanged = 0x2,
- eTransformChanged = 0x4
+ eSurfaceChanged = 0x01,
+ eLayerStackChanged = 0x02,
+ eOrientationChanged = 0x04,
+ eViewportChanged = 0x08,
+ eFrameChanged = 0x10
};
uint32_t what;
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index fd1cb82..2d3e82a 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -98,8 +98,6 @@
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
- //! same as operator [], but allows to access the vector backward (from the end) with a negative index
- const TYPE& mirrorItemAt(ssize_t index) const;
/*!
* modifying the array
@@ -200,15 +198,6 @@
}
template<class TYPE> inline
-const TYPE& SortedVector<TYPE>::mirrorItemAt(ssize_t index) const {
- const size_t i = index>0 ? index : -index;
- LOG_FATAL_IF(index>=size(),
- "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
- int(index), int(size()));
- return *(array() + i);
-}
-
-template<class TYPE> inline
const TYPE& SortedVector<TYPE>::top() const {
return *(array() + size() - 1);
}
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index 506acae..7927328 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -99,8 +99,6 @@
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
- //! same as operator [], but allows to access the vector backward (from the end) with a negative index
- const TYPE& mirrorItemAt(ssize_t index) const;
/*!
* modifying the array
@@ -284,15 +282,6 @@
}
template<class TYPE> inline
-const TYPE& Vector<TYPE>::mirrorItemAt(ssize_t index) const {
- const size_t i = index>0 ? index : -index;
- LOG_FATAL_IF(index>=size(),
- "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
- int(index), int(size()));
- return *(array() + i);
-}
-
-template<class TYPE> inline
const TYPE& Vector<TYPE>::top() const {
return *(array() + size() - 1);
}
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index b1224c6..c4ec2ff 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -104,6 +104,16 @@
virtual void do_splat(void* dest, const void* item, size_t num) const = 0;
virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0;
virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0;
+
+ // take care of FBC...
+ virtual void reservedVectorImpl1();
+ virtual void reservedVectorImpl2();
+ virtual void reservedVectorImpl3();
+ virtual void reservedVectorImpl4();
+ virtual void reservedVectorImpl5();
+ virtual void reservedVectorImpl6();
+ virtual void reservedVectorImpl7();
+ virtual void reservedVectorImpl8();
private:
void* _grow(size_t where, size_t amount);
@@ -155,6 +165,16 @@
protected:
virtual int do_compare(const void* lhs, const void* rhs) const = 0;
+ // take care of FBC...
+ virtual void reservedSortedVectorImpl1();
+ virtual void reservedSortedVectorImpl2();
+ virtual void reservedSortedVectorImpl3();
+ virtual void reservedSortedVectorImpl4();
+ virtual void reservedSortedVectorImpl5();
+ virtual void reservedSortedVectorImpl6();
+ virtual void reservedSortedVectorImpl7();
+ virtual void reservedSortedVectorImpl8();
+
private:
ssize_t _indexOrderOf(const void* item, size_t* order = 0) const;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index db86d4a..1e6e1bd 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -326,7 +326,7 @@
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.orientation = orientation;
- s.what |= DisplayState::eTransformChanged;
+ s.what |= DisplayState::eOrientationChanged;
mForceSynchronous = true; // TODO: do we actually still need this?
}
@@ -343,7 +343,7 @@
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.viewport = viewport;
- s.what |= DisplayState::eTransformChanged;
+ s.what |= DisplayState::eViewportChanged;
}
void Composer::setDisplayFrame(const sp<IBinder>& token,
@@ -351,7 +351,7 @@
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.frame = frame;
- s.what |= DisplayState::eTransformChanged;
+ s.what |= DisplayState::eFrameChanged;
}
// ---------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 718fe84..18a0c10 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -815,12 +815,16 @@
ALOGW_IF(res, "failed locking buffer (handle = %p)",
backBuffer->handle);
- mLockedBuffer = backBuffer;
- outBuffer->width = backBuffer->width;
- outBuffer->height = backBuffer->height;
- outBuffer->stride = backBuffer->stride;
- outBuffer->format = backBuffer->format;
- outBuffer->bits = vaddr;
+ if (res != 0) {
+ err = INVALID_OPERATION;
+ } else {
+ mLockedBuffer = backBuffer;
+ outBuffer->width = backBuffer->width;
+ outBuffer->height = backBuffer->height;
+ outBuffer->stride = backBuffer->stride;
+ outBuffer->format = backBuffer->format;
+ outBuffer->bits = vaddr;
+ }
}
return err;
}
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 020ec15..3855305 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -494,6 +494,15 @@
do_move_backward(dest, from, num);
}
+void VectorImpl::reservedVectorImpl1() { }
+void VectorImpl::reservedVectorImpl2() { }
+void VectorImpl::reservedVectorImpl3() { }
+void VectorImpl::reservedVectorImpl4() { }
+void VectorImpl::reservedVectorImpl5() { }
+void VectorImpl::reservedVectorImpl6() { }
+void VectorImpl::reservedVectorImpl7() { }
+void VectorImpl::reservedVectorImpl8() { }
+
/*****************************************************************************/
SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
@@ -609,6 +618,16 @@
return i;
}
+void SortedVectorImpl::reservedSortedVectorImpl1() { };
+void SortedVectorImpl::reservedSortedVectorImpl2() { };
+void SortedVectorImpl::reservedSortedVectorImpl3() { };
+void SortedVectorImpl::reservedSortedVectorImpl4() { };
+void SortedVectorImpl::reservedSortedVectorImpl5() { };
+void SortedVectorImpl::reservedSortedVectorImpl6() { };
+void SortedVectorImpl::reservedSortedVectorImpl7() { };
+void SortedVectorImpl::reservedSortedVectorImpl8() { };
+
+
/*****************************************************************************/
}; // namespace android
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index c79fb5f..ed2bef3 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -241,19 +241,11 @@
}
size_t fileSize = headerSize + cacheSize;
- if (ftruncate(fd, fileSize) == -1) {
- ALOGE("error setting cache file size: %s (%d)", strerror(errno),
- errno);
- close(fd);
- unlink(fname);
- return;
- }
- uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
- PROT_WRITE, MAP_SHARED, fd, 0));
- if (buf == MAP_FAILED) {
- ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
- errno);
+ uint8_t* buf = new uint8_t [fileSize];
+ if (!buf) {
+ ALOGE("error allocating buffer for cache contents: %s (%d)",
+ strerror(errno), errno);
close(fd);
unlink(fname);
return;
@@ -264,7 +256,7 @@
if (err != OK) {
ALOGE("error writing cache contents: %s (%d)", strerror(-err),
-err);
- munmap(buf, fileSize);
+ delete [] buf;
close(fd);
unlink(fname);
return;
@@ -275,7 +267,16 @@
uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
*crc = crc32c(buf + headerSize, cacheSize);
- munmap(buf, fileSize);
+ if (write(fd, buf, fileSize) == -1) {
+ ALOGE("error writing cache file: %s (%d)", strerror(errno),
+ errno);
+ delete [] buf;
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ delete [] buf;
fchmod(fd, S_IRUSR);
close(fd);
}
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
index 91b291e..3a8decc 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp
@@ -209,6 +209,8 @@
GLMessage_Function func = msg->function();
if (func == GLMessage::eglSwapBuffers
+ || func == GLMessage::eglCreateContext
+ || func == GLMessage::eglMakeCurrent
|| func == GLMessage::glDrawArrays
|| func == GLMessage::glDrawElements) {
mBufferedOutputStream->flush();
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4cae692..2289444 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -140,6 +140,9 @@
mFormat = format;
mPageFlipCount = 0;
+ // external displays are always considered enabled
+ mScreenAcquired = mId >= DisplayDevice::DISPLAY_ID_COUNT;
+
// initialize the display orientation transform.
DisplayDevice::setOrientation(DisplayState::eOrientationDefault);
}
@@ -215,6 +218,18 @@
return mSecureLayerVisible;
}
+Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
+ Region dirty;
+ const Transform& planeTransform(mGlobalTransform);
+ if (repaintEverything) {
+ dirty.set(getBounds());
+ } else {
+ dirty = planeTransform.transform(this->dirtyRegion);
+ dirty.andSelf(getBounds());
+ }
+ return dirty;
+}
+
// ----------------------------------------------------------------------------
bool DisplayDevice::canDraw() const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e9ba5ff..9790699 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -87,6 +87,7 @@
void setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers);
Vector< sp<LayerBase> > getVisibleLayersSortedByZ() const;
bool getSecureLayerVisible() const;
+ Region getDirtyRegion(bool repaintEverything) const;
status_t setOrientation(int orientation);
void setLayerStack(uint32_t stack);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c9df7a4..a3ec352 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -334,7 +334,8 @@
}
}
-status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { // FIXME: handle multiple displays
+status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
+ // FIXME: handle multiple displays
if (uint32_t(id) >= MAX_DISPLAYS)
return BAD_INDEX;
@@ -360,6 +361,15 @@
int err = hwcPrepare(mHwc, 1,
const_cast<hwc_display_contents_1_t**>(mLists));
if (err == NO_ERROR) {
+
+ // here we're just making sure that "skip" layers are set
+ // to HWC_FRAMEBUFFER and we're also counting how many layers
+ // we have of each type.
+ // It would be nice if we could get rid of this entirely, which I
+ // think is almost possible.
+
+ // TODO: must handle multiple displays here
+
size_t numOVLayers = 0;
size_t numFBLayers = 0;
size_t count = getNumLayers(0);
@@ -397,7 +407,15 @@
return (status_t)err;
}
-size_t HWComposer::getLayerCount(int32_t id, int type) const { // FIXME: handle multiple displays
+size_t HWComposer::getLayerCount(int32_t id, int type) const {
+ // FIXME: handle multiple displays
+ if (uint32_t(id) >= MAX_DISPLAYS) {
+ // FIXME: in practice this is only use to know
+ // if we have at least one layer of type.
+ return (type == HWC_FRAMEBUFFER) ? 1 : 0;
+ }
+
+
switch (type) {
case HWC_OVERLAY:
return mNumOVLayers;
@@ -623,7 +641,11 @@
/*
* returns an iterator initialized at a given index in the layer list
*/
-HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) { // FIXME: handle multiple displays
+HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
+ // FIXME: handle multiple displays
+ if (uint32_t(id) >= MAX_DISPLAYS)
+ return LayerListIterator();
+
if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
return LayerListIterator();
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
@@ -638,14 +660,14 @@
/*
* returns an iterator on the beginning of the layer list
*/
-HWComposer::LayerListIterator HWComposer::begin(int32_t id) { // FIXME: handle multiple displays
+HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
return getLayerIterator(id, 0);
}
/*
* returns an iterator on the end of the layer list
*/
-HWComposer::LayerListIterator HWComposer::end(int32_t id) { // FIXME: handle multiple displays
+HWComposer::LayerListIterator HWComposer::end(int32_t id) {
return getLayerIterator(id, getNumLayers(id));
}
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 9b61fa9..59390c0 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -19,6 +19,8 @@
#include <stdint.h>
#include <sys/types.h>
+#include <cutils/compiler.h>
+
#include <gui/BitTube.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/DisplayEventReceiver.h>
@@ -36,10 +38,9 @@
EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger),
- mLastVSyncTimestamp(0),
mVSyncTimestamp(0),
mUseSoftwareVSync(false),
- mDeliveredEvents(0),
+ mVSyncCount(0),
mDebugVsyncEnabled(false) {
}
@@ -116,133 +117,121 @@
void EventThread::onVSyncReceived(int, nsecs_t timestamp) {
Mutex::Autolock _l(mLock);
mVSyncTimestamp = timestamp;
+ mVSyncCount++;
mCondition.broadcast();
}
bool EventThread::threadLoop() {
nsecs_t timestamp;
+ size_t vsyncCount;
DisplayEventReceiver::Event vsync;
- Vector< wp<EventThread::Connection> > displayEventConnections;
+ Vector< sp<EventThread::Connection> > activeConnections;
+ Vector< sp<EventThread::Connection> > signalConnections;
do {
+ // release our references
+ signalConnections.clear();
+ activeConnections.clear();
+
Mutex::Autolock _l(mLock);
- do {
- // latch VSYNC event if any
- timestamp = mVSyncTimestamp;
- mVSyncTimestamp = 0;
- // check if we should be waiting for VSYNC events
- bool waitForNextVsync = false;
- size_t count = mDisplayEventConnections.size();
- for (size_t i=0 ; i<count ; i++) {
- sp<Connection> connection =
- mDisplayEventConnections.itemAt(i).promote();
- if (connection!=0 && connection->count >= 0) {
- // at least one continuous mode or active one-shot event
- waitForNextVsync = true;
- break;
- }
- }
+ // latch VSYNC event if any
+ bool waitForVSync = false;
+ vsyncCount = mVSyncCount;
+ timestamp = mVSyncTimestamp;
+ mVSyncTimestamp = 0;
- if (timestamp) {
- if (!waitForNextVsync) {
- // we received a VSYNC but we have no clients
- // don't report it, and disable VSYNC events
- disableVSyncLocked();
- } else {
- // report VSYNC event
- break;
- }
- } else {
- // never disable VSYNC events immediately, instead
- // we'll wait to receive the event and we'll
- // reevaluate whether we need to dispatch it and/or
- // disable VSYNC events then.
- if (waitForNextVsync) {
- // enable
- enableVSyncLocked();
- }
- }
-
- // wait for something to happen
- if (mUseSoftwareVSync && waitForNextVsync) {
- // h/w vsync cannot be used (screen is off), so we use
- // a timeout instead. it doesn't matter how imprecise this
- // is, we just need to make sure to serve the clients
- if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
- mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
- }
- } else {
- mCondition.wait(mLock);
- }
- } while(true);
-
- // process vsync event
- mDeliveredEvents++;
- mLastVSyncTimestamp = timestamp;
-
- // now see if we still need to report this VSYNC event
- const size_t count = mDisplayEventConnections.size();
+ // find out connections waiting for VSYNC events
+ size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
- bool reportVsync = false;
- sp<Connection> connection =
- mDisplayEventConnections.itemAt(i).promote();
- if (connection == 0)
- continue;
-
- const int32_t count = connection->count;
- if (count >= 1) {
- if (count==1 || (mDeliveredEvents % count) == 0) {
- // continuous event, and time to report it
- reportVsync = true;
+ sp<Connection> connection(mDisplayEventConnections[i].promote());
+ if (connection != NULL) {
+ activeConnections.add(connection);
+ if (connection->count >= 0) {
+ // we need vsync events because at least
+ // one connection is waiting for it
+ waitForVSync = true;
+ if (connection->count == 0) {
+ // fired this time around
+ if (timestamp) {
+ // only "consume" this event if we're going to
+ // report it
+ connection->count = -1;
+ }
+ signalConnections.add(connection);
+ } else if (connection->count == 1 ||
+ (vsyncCount % connection->count) == 0) {
+ // continuous event, and time to report it
+ signalConnections.add(connection);
+ }
}
- } else if (count >= -1) {
- if (count == 0) {
- // fired this time around
- reportVsync = true;
- }
- connection->count--;
- }
- if (reportVsync) {
- displayEventConnections.add(connection);
}
}
- } while (!displayEventConnections.size());
+
+ if (timestamp) {
+ // we have a vsync event we can dispatch
+ if (!waitForVSync) {
+ // we received a VSYNC but we have no clients
+ // don't report it, and disable VSYNC events
+ disableVSyncLocked();
+ } else {
+ // report VSYNC event
+ break;
+ }
+ } else {
+ // never disable VSYNC events immediately, instead
+ // we'll wait to receive the event and we'll
+ // reevaluate whether we need to dispatch it and/or
+ // disable VSYNC events then.
+ if (waitForVSync) {
+ // enable
+ enableVSyncLocked();
+ }
+ }
+
+ // wait for something to happen
+ if (CC_UNLIKELY(mUseSoftwareVSync && waitForVSync)) {
+ // h/w vsync cannot be used (screen is off), so we use
+ // a timeout instead. it doesn't matter how imprecise this
+ // is, we just need to make sure to serve the clients
+ if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
+ mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ mVSyncCount++;
+ }
+ } else {
+ if (!timestamp || signalConnections.isEmpty()) {
+ // This is where we spend most of our time, waiting
+ // for a vsync events and registered clients
+ mCondition.wait(mLock);
+ }
+ }
+ } while (!timestamp || signalConnections.isEmpty());
// dispatch vsync events to listeners...
vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
vsync.header.timestamp = timestamp;
- vsync.vsync.count = mDeliveredEvents;
+ vsync.vsync.count = vsyncCount;
- const size_t count = displayEventConnections.size();
+ const size_t count = signalConnections.size();
for (size_t i=0 ; i<count ; i++) {
- sp<Connection> conn(displayEventConnections[i].promote());
- // make sure the connection didn't die
- if (conn != NULL) {
- status_t err = conn->postEvent(vsync);
- if (err == -EAGAIN || err == -EWOULDBLOCK) {
- // The destination doesn't accept events anymore, it's probably
- // full. For now, we just drop the events on the floor.
- // Note that some events cannot be dropped and would have to be
- // re-sent later. Right-now we don't have the ability to do
- // this, but it doesn't matter for VSYNC.
- } else if (err < 0) {
- // handle any other error on the pipe as fatal. the only
- // reasonable thing to do is to clean-up this connection.
- // The most common error we'll get here is -EPIPE.
- removeDisplayEventConnection(displayEventConnections[i]);
- }
- } else {
- // somehow the connection is dead, but we still have it in our list
- // just clean the list.
- removeDisplayEventConnection(displayEventConnections[i]);
+ const sp<Connection>& conn(signalConnections[i]);
+ // now see if we still need to report this VSYNC event
+ status_t err = conn->postEvent(vsync);
+ if (err == -EAGAIN || err == -EWOULDBLOCK) {
+ // The destination doesn't accept events anymore, it's probably
+ // full. For now, we just drop the events on the floor.
+ // Note that some events cannot be dropped and would have to be
+ // re-sent later. Right-now we don't have the ability to do
+ // this, but it doesn't matter for VSYNC.
+ } else if (err < 0) {
+ // handle any other error on the pipe as fatal. the only
+ // reasonable thing to do is to clean-up this connection.
+ // The most common error we'll get here is -EPIPE.
+ removeDisplayEventConnection(signalConnections[i]);
}
}
- // clear all our references without holding mLock
- displayEventConnections.clear();
-
return true;
}
@@ -273,7 +262,7 @@
result.appendFormat(" soft-vsync: %s\n",
mUseSoftwareVSync?"enabled":"disabled");
result.appendFormat(" numListeners=%u,\n events-delivered: %u\n",
- mDisplayEventConnections.size(), mDeliveredEvents);
+ mDisplayEventConnections.size(), mVSyncCount);
for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {
sp<Connection> connection =
mDisplayEventConnections.itemAt(i).promote();
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index a71d985..aa0ea7f 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -47,7 +47,6 @@
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
// count ==-1 : one-shot event that fired this round / disabled
- // count ==-2 : one-shot event that fired the round before
int32_t count;
private:
@@ -100,12 +99,9 @@
// protected by mLock
SortedVector< wp<Connection> > mDisplayEventConnections;
- nsecs_t mLastVSyncTimestamp;
nsecs_t mVSyncTimestamp;
bool mUseSoftwareVSync;
-
- // main thread only
- size_t mDeliveredEvents;
+ size_t mVSyncCount;
// for debugging
bool mDebugVsyncEnabled;
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index e6189f7..2311e6d 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -426,10 +426,10 @@
snprintf(buffer, SIZE,
" "
- "z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
+ "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
+ s.z, s.layerStack, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
s.active.crop.left, s.active.crop.top,
s.active.crop.right, s.active.crop.bottom,
isOpaque(), needsDithering(), contentDirty,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9178dfc..aba701c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -95,8 +95,7 @@
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
- mBootFinished(false),
- mExternalDisplaySurface(EGL_NO_SURFACE)
+ mBootFinished(false)
{
ALOGI("SurfaceFlinger is starting");
@@ -138,15 +137,8 @@
{
// the window manager died on us. prepare its eulogy.
- // reset screen orientation
- Vector<ComposerState> state;
- Vector<DisplayState> displays;
- DisplayState d;
- d.what = DisplayState::eTransformChanged;
- d.token = mDefaultDisplays[DisplayDevice::DISPLAY_ID_MAIN];
- d.orientation = DisplayState::eOrientationDefault;
- displays.add(d);
- setTransactionState(state, displays, 0);
+ // restore initial conditions (default device unblank, etc)
+ initializeDisplays();
// restart the boot-animation
startBootAnim();
@@ -432,6 +424,9 @@
// We're now ready to accept clients...
mReadyToRunBarrier.open();
+ // set initial conditions (e.g. unblank default device)
+ initializeDisplays();
+
// start boot animation
startBootAnim();
@@ -555,40 +550,34 @@
return mEventThread->createEventConnection();
}
-void SurfaceFlinger::connectDisplay(const sp<ISurfaceTexture> display) {
- EGLSurface result = EGL_NO_SURFACE;
- EGLSurface old_surface = EGL_NO_SURFACE;
- sp<SurfaceTextureClient> stc;
+void SurfaceFlinger::connectDisplay(const sp<ISurfaceTexture> surface) {
- if (display != NULL) {
- stc = new SurfaceTextureClient(display);
- result = eglCreateWindowSurface(mEGLDisplay,
- mEGLConfig, (EGLNativeWindowType)stc.get(), NULL);
- ALOGE_IF(result == EGL_NO_SURFACE,
- "eglCreateWindowSurface failed (ISurfaceTexture=%p)",
- display.get());
+ sp<IBinder> token;
+ { // scope for the lock
+ Mutex::Autolock _l(mStateLock);
+ token = mExtDisplayToken;
+ }
+
+ if (token == 0) {
+ token = createDisplay();
}
{ // scope for the lock
Mutex::Autolock _l(mStateLock);
- old_surface = mExternalDisplaySurface;
- mExternalDisplayNativeWindow = stc;
- mExternalDisplaySurface = result;
- ALOGD("mExternalDisplaySurface = %p", result);
- }
+ if (surface == 0) {
+ // release our current display. we're guarantee to have
+ // a reference to it (token), while we hold the lock
+ mExtDisplayToken = 0;
+ } else {
+ mExtDisplayToken = token;
+ }
- if (old_surface != EGL_NO_SURFACE) {
- // Note: EGL allows to destroy an object while its current
- // it will fail to become current next time though.
- eglDestroySurface(mEGLDisplay, old_surface);
+ DisplayDeviceState& info(mCurrentState.displays.editValueFor(token));
+ info.surface = surface;
+ setTransactionFlags(eDisplayTransactionNeeded);
}
}
-EGLSurface SurfaceFlinger::getExternalDisplaySurface() const {
- Mutex::Autolock _l(mStateLock);
- return mExternalDisplaySurface;
-}
-
// ----------------------------------------------------------------------------
void SurfaceFlinger::waitForEvent() {
@@ -656,20 +645,101 @@
}
void SurfaceFlinger::handleMessageInvalidate() {
+ ATRACE_CALL();
handlePageFlip();
}
void SurfaceFlinger::handleMessageRefresh() {
- handleRefresh();
+ ATRACE_CALL();
+ preComposition();
+ rebuildLayerStacks();
+ setUpHWComposer();
+ doDebugFlashRegions();
+ doComposition();
+ postComposition();
+}
+void SurfaceFlinger::doDebugFlashRegions()
+{
+ // is debugging enabled
+ if (CC_LIKELY(!mDebugRegion))
+ return;
+
+ const bool repaintEverything = mRepaintEverything;
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ const sp<DisplayDevice>& hw(mDisplays[dpy]);
+ if (hw->canDraw()) {
+ // transform the dirty region into this screen's coordinate space
+ const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+ if (!dirtyRegion.isEmpty()) {
+ // redraw the whole screen
+ doComposeSurfaces(hw, Region(hw->bounds()));
+
+ // and draw the dirty region
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glColor4f(1, 0, 1, 1);
+ const int32_t height = hw->getHeight();
+ Region::const_iterator it = dirtyRegion.begin();
+ Region::const_iterator const end = dirtyRegion.end();
+ while (it != end) {
+ const Rect& r = *it++;
+ GLfloat vertices[][2] = {
+ { r.left, height - r.top },
+ { r.left, height - r.bottom },
+ { r.right, height - r.bottom },
+ { r.right, height - r.top }
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ hw->compositionComplete();
+ // FIXME
+ if (hw->getDisplayId() >= DisplayDevice::DISPLAY_ID_COUNT) {
+ eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
+ }
+ }
+ }
+ }
+
+ postFramebuffer();
+
+ if (mDebugRegion > 1) {
+ usleep(mDebugRegion * 1000);
+ }
+}
+
+void SurfaceFlinger::preComposition()
+{
+ bool needExtraInvalidate = false;
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ if (currentLayers[i]->onPreComposition()) {
+ needExtraInvalidate = true;
+ }
+ }
+ if (needExtraInvalidate) {
+ signalLayerUpdate();
+ }
+}
+
+void SurfaceFlinger::postComposition()
+{
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ currentLayers[i]->onPostComposition();
+ }
+}
+
+void SurfaceFlinger::rebuildLayerStacks() {
+ // rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
+ ATRACE_CALL();
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
-
- /*
- * rebuild the visible layer list per screen
- */
-
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
@@ -691,10 +761,13 @@
}
hw->setVisibleLayersSortedByZ(layersSortedByZ);
hw->undefinedRegion.set(hw->getBounds());
- hw->undefinedRegion.subtractSelf(hw->getTransform().transform(opaqueRegion));
+ hw->undefinedRegion.subtractSelf(
+ hw->getTransform().transform(opaqueRegion));
}
}
+}
+void SurfaceFlinger::setUpHWComposer() {
HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
// build the h/w work list
@@ -702,7 +775,8 @@
mHwWorkListDirty = false;
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
- const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
+ const Vector< sp<LayerBase> >& currentLayers(
+ hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
const int32_t id = hw->getDisplayId();
@@ -730,76 +804,28 @@
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
}
+}
+void SurfaceFlinger::doComposition() {
+ ATRACE_CALL();
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
-
- // transform the dirty region into this screen's coordinate space
- const Transform& planeTransform(hw->getTransform());
- Region dirtyRegion;
- if (repaintEverything) {
- dirtyRegion.set(hw->bounds());
- } else {
- dirtyRegion = planeTransform.transform(hw->dirtyRegion);
- dirtyRegion.andSelf(hw->bounds());
- }
- hw->dirtyRegion.clear();
-
- if (!dirtyRegion.isEmpty()) {
- if (hw->canDraw()) {
+ if (hw->canDraw()) {
+ // transform the dirty region into this screen's coordinate space
+ const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+ if (!dirtyRegion.isEmpty()) {
// repaint the framebuffer (if needed)
- handleRepaint(hw, dirtyRegion);
+ doDisplayComposition(hw, dirtyRegion);
}
+ hw->dirtyRegion.clear();
+ hw->flip(hw->swapRegion);
+ hw->swapRegion.clear();
}
// inform the h/w that we're done compositing
hw->compositionComplete();
}
-
postFramebuffer();
-
-
-#if 1
- // render to the external display if we have one
- EGLSurface externalDisplaySurface = getExternalDisplaySurface();
- if (externalDisplaySurface != EGL_NO_SURFACE) {
- EGLSurface cur = eglGetCurrentSurface(EGL_DRAW);
- EGLBoolean success = eglMakeCurrent(eglGetCurrentDisplay(),
- externalDisplaySurface, externalDisplaySurface,
- eglGetCurrentContext());
-
- ALOGE_IF(!success, "eglMakeCurrent -> external failed");
-
- if (success) {
- // redraw the screen entirely...
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- glDisable(GL_TEXTURE_2D);
- glClearColor(0,0,0,1);
- glClear(GL_COLOR_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- const sp<DisplayDevice>& hw(getDisplayDevice(0));
- const Vector< sp<LayerBase> >& layers( hw->getVisibleLayersSortedByZ() );
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; ++i) {
- const sp<LayerBase>& layer(layers[i]);
- layer->draw(hw);
- }
-
- success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface);
- ALOGE_IF(!success, "external display eglSwapBuffers failed");
-
- hw->compositionComplete();
- }
-
- success = eglMakeCurrent(eglGetCurrentDisplay(),
- cur, cur, eglGetCurrentContext());
-
- ALOGE_IF(!success, "eglMakeCurrent -> internal failed");
- }
-#endif
-
}
void SurfaceFlinger::postFramebuffer()
@@ -810,26 +836,13 @@
mDebugInSwapBuffers = now;
HWComposer& hwc(getHwComposer());
-
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hwc.initCheck() == NO_ERROR) {
- const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- const int32_t id = hw->getDisplayId();
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- const sp<LayerBase>& layer(currentLayers[i]);
- layer->setAcquireFence(hw, *cur);
- }
- }
- hw->flip(hw->swapRegion);
- hw->swapRegion.clear();
- }
-
if (hwc.initCheck() == NO_ERROR) {
// FIXME: eventually commit() won't take arguments
+ // FIXME: EGL spec says:
+ // "surface must be bound to the calling thread's current context,
+ // for the current rendering API."
+ DisplayDevice::makeCurrent(
+ getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext);
hwc.commit(mEGLDisplay, getDefaultDisplayDevice()->getEGLSurface());
}
@@ -845,13 +858,10 @@
currentLayers[i]->onLayerDisplayed(hw, &*cur);
}
} else {
- eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
for (size_t i = 0; i < count; i++) {
currentLayers[i]->onLayerDisplayed(hw, NULL);
}
}
-
- // FIXME: we need to call eglSwapBuffers() on displays that have GL composition
}
mLastSwapBufferTime = systemTime() - now;
@@ -934,7 +944,7 @@
} else {
// this display is in both lists. see if something changed.
const DisplayDeviceState& state(curr[j]);
- if (state.surface != draw[i].surface) {
+ if (state.surface->asBinder() != draw[i].surface->asBinder()) {
// changing the surface is like destroying and
// recreating the DisplayDevice
@@ -967,7 +977,6 @@
// (ie: in current state but not in drawing state)
for (size_t i=0 ; i<cc ; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
- // FIXME: we need to pass the surface here
const DisplayDeviceState& state(curr[i]);
sp<SurfaceTextureClient> stc(
new SurfaceTextureClient(state.surface));
@@ -983,7 +992,8 @@
* Perform our own transaction if needed
*/
- if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
+ const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
+ if (currentLayers.size() > previousLayers.size()) {
// layers have been added
mVisibleRegionsDirty = true;
}
@@ -993,7 +1003,6 @@
if (mLayersRemoved) {
mLayersRemoved = false;
mVisibleRegionsDirty = true;
- const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
const size_t count = previousLayers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(previousLayers[i]);
@@ -1169,16 +1178,13 @@
void SurfaceFlinger::handlePageFlip()
{
- ATRACE_CALL();
Region dirtyRegion;
- const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
-
bool visibleRegions = false;
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
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]);
+ const sp<LayerBase>& layer(currentLayers[i]);
const Region dirty(layer->latchBuffer(visibleRegions));
Layer::State s(layer->drawingState());
invalidateLayerStack(s.layerStack, dirty);
@@ -1192,36 +1198,15 @@
mHwWorkListDirty = true;
}
-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::handleRepaint(const sp<const DisplayDevice>& hw,
+void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
const Region& inDirtyRegion)
{
- ATRACE_CALL();
-
Region dirtyRegion(inDirtyRegion);
// compute the invalid region
hw->swapRegion.orSelf(dirtyRegion);
- if (CC_UNLIKELY(mDebugRegion)) {
- debugFlashRegions(hw, dirtyRegion);
- }
-
uint32_t flags = hw->getFlags();
if (flags & DisplayDevice::SWAP_RECTANGLE) {
// we can redraw only what's dirty, but since SWAP_RECTANGLE only
@@ -1242,19 +1227,24 @@
}
}
- composeSurfaces(hw, dirtyRegion);
+ doComposeSurfaces(hw, dirtyRegion);
- const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
- const size_t count = currentLayers.size();
- for (size_t i=0 ; i<count ; i++) {
- currentLayers[i]->onPostComposition();
+ // FIXME: we need to call eglSwapBuffers() on displays that have
+ // GL composition and only on those.
+ // however, currently hwc.commit() already does that for the main
+ // display and never for the other ones
+ if (hw->getDisplayId() >= DisplayDevice::DISPLAY_ID_COUNT) {
+ // FIXME: EGL spec says:
+ // "surface must be bound to the calling thread's current context,
+ // for the current rendering API."
+ eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
}
// update the swap region and clear the dirty region
hw->swapRegion.orSelf(dirtyRegion);
}
-void SurfaceFlinger::composeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
+void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
HWComposer& hwc(getHwComposer());
int32_t id = hw->getDisplayId();
@@ -1298,74 +1288,32 @@
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
- if (!clip.isEmpty()) {
- if (cur != end && cur->getCompositionType() == HWC_OVERLAY) {
- if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
- && layer->isOpaque()) {
- // never clear the very first layer since we're
- // guaranteed the FB is already cleared
- layer->clearWithOpenGL(hw, clip);
- }
- ++cur;
- continue;
- }
- // render the layer
- layer->draw(hw, clip);
- }
if (cur != end) {
+ // we're using h/w composer
+ if (!clip.isEmpty()) {
+ if (cur->getCompositionType() == HWC_OVERLAY) {
+ if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
+ && layer->isOpaque()) {
+ // never clear the very first layer since we're
+ // guaranteed the FB is already cleared
+ layer->clearWithOpenGL(hw, clip);
+ }
+ } else {
+ layer->draw(hw, clip);
+ }
+ layer->setAcquireFence(hw, *cur);
+ }
++cur;
+ } else {
+ // we're not using h/w composer
+ if (!clip.isEmpty()) {
+ layer->draw(hw, clip);
+ }
}
}
}
}
-void SurfaceFlinger::debugFlashRegions(const sp<const DisplayDevice>& hw,
- const Region& dirtyRegion)
-{
- const uint32_t flags = hw->getFlags();
- const int32_t height = hw->getHeight();
- if (hw->swapRegion.isEmpty()) {
- return;
- }
-
- if (!(flags & DisplayDevice::SWAP_RECTANGLE)) {
- const Region repaint((flags & DisplayDevice::PARTIAL_UPDATES) ?
- dirtyRegion.bounds() : hw->bounds());
- composeSurfaces(hw, repaint);
- }
-
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
-
- static int toggle = 0;
- toggle = 1 - toggle;
- if (toggle) {
- glColor4f(1, 0, 1, 1);
- } else {
- glColor4f(1, 1, 0, 1);
- }
-
- Region::const_iterator it = dirtyRegion.begin();
- Region::const_iterator const end = dirtyRegion.end();
- while (it != end) {
- const Rect& r = *it++;
- GLfloat vertices[][2] = {
- { r.left, height - r.top },
- { r.left, height - r.bottom },
- { r.right, height - r.bottom },
- { r.right, height - r.top }
- };
- glVertexPointer(2, GL_FLOAT, 0, vertices);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
-
- hw->flip(hw->swapRegion);
-
- if (mDebugRegion > 1)
- usleep(mDebugRegion * 1000);
-}
-
void SurfaceFlinger::drawWormhole(const Region& region) const
{
glDisable(GL_TEXTURE_EXTERNAL_OES);
@@ -1521,15 +1469,19 @@
flags |= eDisplayTransactionNeeded;
}
}
- if (what & DisplayState::eTransformChanged) {
+ if (what & DisplayState::eOrientationChanged) {
if (disp.orientation != s.orientation) {
disp.orientation = s.orientation;
flags |= eDisplayTransactionNeeded;
}
+ }
+ if (what & DisplayState::eFrameChanged) {
if (disp.frame != s.frame) {
disp.frame = s.frame;
flags |= eDisplayTransactionNeeded;
}
+ }
+ if (what & DisplayState::eViewportChanged) {
if (disp.viewport != s.viewport) {
disp.viewport = s.viewport;
flags |= eDisplayTransactionNeeded;
@@ -1745,6 +1697,36 @@
// ---------------------------------------------------------------------------
+void SurfaceFlinger::onInitializeDisplays() {
+ // reset screen orientation
+ Vector<ComposerState> state;
+ Vector<DisplayState> displays;
+ DisplayState d;
+ d.what = DisplayState::eOrientationChanged;
+ d.token = mDefaultDisplays[DisplayDevice::DISPLAY_ID_MAIN];
+ d.orientation = DisplayState::eOrientationDefault;
+ displays.add(d);
+ setTransactionState(state, displays, 0);
+
+ // XXX: this should init default device to "unblank" and all other devices to "blank"
+ onScreenAcquired();
+}
+
+void SurfaceFlinger::initializeDisplays() {
+ class MessageScreenInitialized : public MessageBase {
+ SurfaceFlinger* flinger;
+ public:
+ MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
+ virtual bool handler() {
+ flinger->onInitializeDisplays();
+ return true;
+ }
+ };
+ sp<MessageBase> msg = new MessageScreenInitialized(this);
+ postMessageAsync(msg); // we may be called from main thread, use async message
+}
+
+
void SurfaceFlinger::onScreenAcquired() {
ALOGD("Screen about to return, flinger = %p", this);
sp<const DisplayDevice> hw(getDefaultDisplayDevice()); // XXX: this should be per DisplayDevice
@@ -1951,6 +1933,26 @@
}
/*
+ * Dump Display state
+ */
+
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ const sp<const DisplayDevice>& hw(mDisplays[dpy]);
+ snprintf(buffer, SIZE,
+ "+ DisplayDevice[%u]\n"
+ " id=%x, layerStack=%u, (%4dx%4d), orient=%2d, tr=%08x, "
+ "flips=%u, secure=%d, numLayers=%u\n",
+ dpy,
+ hw->getDisplayId(), hw->getLayerStack(),
+ hw->getWidth(), hw->getHeight(),
+ hw->getOrientation(), hw->getTransform().getType(),
+ hw->getPageFlipCount(),
+ hw->getSecureLayerVisible(),
+ hw->getVisibleLayersSortedByZ().size());
+ result.append(buffer);
+ }
+
+ /*
* Dump SurfaceFlinger global state
*/
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6438bee..b1fe738 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -231,9 +231,11 @@
void signalLayerUpdate();
void signalRefresh();
- // called on the main thread in response to screenReleased()
+ // called on the main thread in response to initializeDisplays()
+ void onInitializeDisplays();
+ // called on the main thread in response to blank()
void onScreenReleased();
- // called on the main thread in response to screenAcquired()
+ // called on the main thread in response to unblank()
void onScreenAcquired();
void handleMessageTransaction();
@@ -248,9 +250,6 @@
*/
void handlePageFlip();
- void handleRefresh();
- void handleRepaint(const sp<const DisplayDevice>& hw, const Region& dirtyRegion);
-
/* ------------------------------------------------------------------------
* Transactions
*/
@@ -324,6 +323,9 @@
/* ------------------------------------------------------------------------
* Display and layer stack management
*/
+ // called when starting, or restarting after system_server death
+ void initializeDisplays();
+
sp<const DisplayDevice> getDisplayDevice(DisplayID dpy) const {
return mDisplays.valueFor(dpy);
}
@@ -348,8 +350,19 @@
void computeVisibleRegions(const LayerVector& currentLayers,
uint32_t layerStack,
Region& dirtyRegion, Region& opaqueRegion);
+
+ void preComposition();
+ void postComposition();
+ void rebuildLayerStacks();
+ void setUpHWComposer();
+ void doComposition();
+ void doDebugFlashRegions();
+ void doDisplayComposition(const sp<const DisplayDevice>& hw,
+ const Region& dirtyRegion);
+ void doComposeSurfaces(const sp<const DisplayDevice>& hw,
+ const Region& dirty);
+
void postFramebuffer();
- void composeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty);
void drawWormhole(const Region& region) const;
GLuint getProtectedTexName() const {
return mProtectedTexName;
@@ -358,7 +371,6 @@
/* ------------------------------------------------------------------------
* Debugging & dumpsys
*/
- void debugFlashRegions(const sp<const DisplayDevice>& hw, const Region& dirtyReg);
void listLayersLocked(const Vector<String16>& args, size_t& index,
String8& result, char* buffer, size_t SIZE) const;
void dumpStatsLocked(const Vector<String16>& args, size_t& index,
@@ -428,9 +440,7 @@
* Feature prototyping
*/
- EGLSurface getExternalDisplaySurface() const;
- sp<SurfaceTextureClient> mExternalDisplayNativeWindow;
- EGLSurface mExternalDisplaySurface;
+ sp<IBinder> mExtDisplayToken;
};
// ---------------------------------------------------------------------------