summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/Layer.cpp78
-rw-r--r--services/surfaceflinger/Layer.h9
-rw-r--r--services/surfaceflinger/LayerBase.cpp107
-rw-r--r--services/surfaceflinger/LayerBase.h60
-rw-r--r--services/surfaceflinger/LayerDim.cpp7
-rw-r--r--services/surfaceflinger/LayerScreenshot.cpp7
-rw-r--r--services/surfaceflinger/MessageQueue.cpp30
-rw-r--r--services/surfaceflinger/MessageQueue.h4
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp328
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h19
10 files changed, 335 insertions, 314 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0d1cb45..a09b5c7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -145,14 +145,6 @@ void Layer::setName(const String8& name) {
mSurfaceTexture->setName(name);
}
-void Layer::validateVisibility(const Transform& globalTransform, const DisplayHardware& hw) {
- LayerBase::validateVisibility(globalTransform, hw);
-
- // This optimization allows the SurfaceTexture to bake in
- // the rotation so hardware overlays can be used
- mSurfaceTexture->setTransformHint(getTransformHint());
-}
-
sp<ISurface> Layer::createSurface()
{
class BSurface : public BnSurface, public LayerCleaner {
@@ -225,7 +217,8 @@ Rect Layer::computeBufferCrop() const {
} else if (mActiveBuffer != NULL){
crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
} else {
- crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
+ crop.makeInvalid();
+ return crop;
}
// ... then reduce that in the same proportions as the window crop reduces
@@ -258,9 +251,11 @@ Rect Layer::computeBufferCrop() const {
return crop;
}
-void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
+void Layer::setGeometry(
+ const DisplayHardware& hw,
+ HWComposer::HWCLayerInterface& layer)
{
- LayerBaseClient::setGeometry(layer);
+ LayerBaseClient::setGeometry(hw, layer);
// enable this layer
layer.setSkip(false);
@@ -276,12 +271,11 @@ void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
* 1) buffer orientation/flip/mirror
* 2) state transformation (window manager)
* 3) layer orientation (screen orientation)
- * mTransform is already the composition of (2) and (3)
* (NOTE: the matrices are multiplied in reverse order)
*/
const Transform bufferOrientation(mCurrentTransform);
- const Transform tr(mTransform * bufferOrientation);
+ const Transform tr(hw.getTransform() * s.transform * bufferOrientation);
// this gives us only the "orientation" component of the transform
const uint32_t finalTransform = tr.getOrientation();
@@ -339,7 +333,7 @@ void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
const sp<LayerBase>& layer(drawingLayers[i]);
if (layer.get() == static_cast<LayerBase const*>(this))
break;
- under.orSelf(layer->visibleRegionScreen);
+ under.orSelf( hw.getTransform().transform(layer->visibleRegion) );
}
// if not everything below us is covered, we plug the holes!
Region holes(clip.subtract(under));
@@ -527,10 +521,11 @@ bool Layer::onPreComposition() {
return mQueuedFrames > 0;
}
-void Layer::lockPageFlip(bool& recomputeVisibleRegions)
+Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
ATRACE_CALL();
+ Region outDirtyRegion;
if (mQueuedFrames > 0) {
// if we've already called updateTexImage() without going through
@@ -539,8 +534,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// compositionComplete() call.
// we'll trigger an update in onPreComposition().
if (mRefreshPending) {
- mPostedDirtyRegion.clear();
- return;
+ return outDirtyRegion;
}
// Capture the old state of the layer for comparisons later
@@ -637,17 +631,21 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
+ // XXX: not sure if setTransformHint belongs here
+ // it should only be needed when the main screen orientation changes
+ mSurfaceTexture->setTransformHint(getTransformHint());
+
if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
// something happened!
recomputeVisibleRegions = true;
- return;
+ return outDirtyRegion;
}
// update the active buffer
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
if (mActiveBuffer == NULL) {
// this can only happen if the very first buffer was rejected.
- return;
+ return outDirtyRegion;
}
mRefreshPending = true;
@@ -686,38 +684,17 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
recomputeVisibleRegions = true;
}
- // FIXME: mPostedDirtyRegion = dirty & bounds
- const Layer::State& front(drawingState());
- mPostedDirtyRegion.set(front.active.w, front.active.h);
-
glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-}
-void Layer::unlockPageFlip(
- const Transform& planeTransform, Region& outDirtyRegion)
-{
- ATRACE_CALL();
+ // FIXME: postedRegion should be dirty & bounds
+ const Layer::State& front(drawingState());
+ Region dirtyRegion(Rect(front.active.w, front.active.h));
- Region postedRegion(mPostedDirtyRegion);
- if (!postedRegion.isEmpty()) {
- mPostedDirtyRegion.clear();
- if (!visibleRegionScreen.isEmpty()) {
- // The dirty region is given in the layer's coordinate space
- // transform the dirty region by the surface's transformation
- // and the global transformation.
- const Layer::State& s(drawingState());
- const Transform tr(planeTransform * s.transform);
- postedRegion = tr.transform(postedRegion);
-
- // At this point, the dirty region is in screen space.
- // Make sure it's constrained by the visible region (which
- // is in screen space as well).
- postedRegion.andSelf(visibleRegionScreen);
- outDirtyRegion.orSelf(postedRegion);
- }
+ // transform the dirty region to window-manager space
+ outDirtyRegion = (front.transform.transform(dirtyRegion));
}
+ return outDirtyRegion;
}
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
@@ -786,7 +763,14 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
uint32_t Layer::getTransformHint() const {
uint32_t orientation = 0;
if (!mFlinger->mDebugDisableTransformHint) {
- orientation = getPlaneOrientation();
+ // The transform hint is used to improve performance on the main
+ // display -- we can only have a single transform hint, it cannot
+ // apply to all displays.
+ // This is why we use the default display here. This is not an
+ // oversight.
+ const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
+ const Transform& planeTransform(hw.getTransform());
+ orientation = planeTransform.getOrientation();
if (orientation & Transform::ROT_INVALID) {
orientation = 0;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index b6ae0ae..239250d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -64,20 +64,20 @@ public:
bool isFixedSize() const;
// LayerBase interface
- virtual void setGeometry(HWComposer::HWCLayerInterface& layer);
+ virtual void setGeometry(const DisplayHardware& hw,
+ HWComposer::HWCLayerInterface& layer);
virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer);
virtual void setAcquireFence(HWComposer::HWCLayerInterface& layer);
+
virtual void onDraw(const DisplayHardware& hw, const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
- virtual void lockPageFlip(bool& recomputeVisibleRegions);
- virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
+ virtual Region latchBuffer(bool& recomputeVisibleRegions);
virtual bool isOpaque() const;
virtual bool isSecure() const { return mSecure; }
virtual bool isProtected() const;
virtual void onRemoved();
virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
virtual void setName(const String8& name);
- virtual void validateVisibility(const Transform& globalTransform, const DisplayHardware& hw);
// LayerBaseClient interface
virtual wp<IBinder> getSurfaceTextureBinder() const;
@@ -142,7 +142,6 @@ private:
// page-flip thread (currently main thread)
bool mSecure; // no screenshots
bool mProtectedByApp; // application requires protected path to external sink
- Region mPostedDirtyRegion;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 8350d27..2070cb9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -45,8 +45,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
sequence(uint32_t(android_atomic_inc(&sSequence))),
mFlinger(flinger), mFiltering(false),
mNeedsFiltering(false),
- mOrientation(0),
- mPlaneOrientation(0),
mTransactionFlags(0),
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
{
@@ -170,19 +168,14 @@ bool LayerBase::setCrop(const Rect& crop) {
return true;
}
-Rect LayerBase::visibleBounds() const
-{
- return mTransformedBounds;
-}
-
void LayerBase::setVisibleRegion(const Region& visibleRegion) {
// always called from main thread
- visibleRegionScreen = visibleRegion;
+ this->visibleRegion = visibleRegion;
}
void LayerBase::setCoveredRegion(const Region& coveredRegion) {
// always called from main thread
- coveredRegionScreen = coveredRegion;
+ this->coveredRegion = coveredRegion;
}
uint32_t LayerBase::doTransaction(uint32_t flags)
@@ -219,57 +212,45 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
return flags;
}
-void LayerBase::validateVisibility(const Transform& planeTransform, const DisplayHardware& hw)
+void LayerBase::computeGeometry(const DisplayHardware& hw, LayerMesh* mesh) const
{
const Layer::State& s(drawingState());
- const Transform tr(planeTransform * s.transform);
- const bool transformed = tr.transformed();
+ const Transform tr(hw.getTransform() * s.transform);
const uint32_t hw_h = hw.getHeight();
const Rect& crop(s.active.crop);
-
Rect win(s.active.w, s.active.h);
if (!crop.isEmpty()) {
win.intersect(crop, &win);
}
-
- mNumVertices = 4;
- tr.transform(mVertices[0], win.left, win.top);
- tr.transform(mVertices[1], win.left, win.bottom);
- tr.transform(mVertices[2], win.right, win.bottom);
- tr.transform(mVertices[3], win.right, win.top);
- for (size_t i=0 ; i<4 ; i++)
- mVertices[i][1] = hw_h - mVertices[i][1];
-
- if (CC_UNLIKELY(transformed)) {
- // NOTE: here we could also punt if we have too many rectangles
- // in the transparent region
- if (tr.preserveRects()) {
- // transform the transparent region
- transparentRegionScreen = tr.transform(s.transparentRegion);
- } else {
- // transformation too complex, can't do the transparent region
- // optimization.
- transparentRegionScreen.clear();
+ if (mesh) {
+ tr.transform(mesh->mVertices[0], win.left, win.top);
+ tr.transform(mesh->mVertices[1], win.left, win.bottom);
+ tr.transform(mesh->mVertices[2], win.right, win.bottom);
+ tr.transform(mesh->mVertices[3], win.right, win.top);
+ for (size_t i=0 ; i<4 ; i++) {
+ mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1];
}
- } else {
- transparentRegionScreen = s.transparentRegion;
}
-
- // cache a few things...
- mOrientation = tr.getOrientation();
- mPlaneOrientation = planeTransform.getOrientation();
- mTransform = tr;
- mTransformedBounds = tr.transform(win);
}
-void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
+Rect LayerBase::computeBounds() const {
+ const Layer::State& s(drawingState());
+ const Rect& crop(s.active.crop);
+ Rect win(s.active.w, s.active.h);
+ if (!crop.isEmpty()) {
+ win.intersect(crop, &win);
+ }
+ return s.transform.transform(win);
}
-void LayerBase::unlockPageFlip(
- const Transform& planeTransform, Region& outDirtyRegion) {
+Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
+ Region result;
+ return result;
}
-void LayerBase::setGeometry(HWComposer::HWCLayerInterface& layer)
+void LayerBase::setGeometry(
+ const DisplayHardware& hw,
+ HWComposer::HWCLayerInterface& layer)
{
layer.setDefaultState();
@@ -289,10 +270,14 @@ void LayerBase::setGeometry(HWComposer::HWCLayerInterface& layer)
HWC_BLENDING_COVERAGE);
}
- // scaling is already applied in mTransformedBounds
- layer.setFrame(mTransformedBounds);
- layer.setVisibleRegionScreen(visibleRegionScreen);
- layer.setCrop(mTransformedBounds.getBounds());
+ const Transform& tr = hw.getTransform();
+ Rect transformedBounds(computeBounds());
+ transformedBounds = tr.transform(transformedBounds);
+
+ // scaling is already applied in transformedBounds
+ layer.setFrame(transformedBounds);
+ layer.setCrop(transformedBounds.getBounds());
+ layer.setVisibleRegionScreen(tr.transform(visibleRegion));
}
void LayerBase::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
@@ -335,8 +320,11 @@ void LayerBase::clearWithOpenGL(const DisplayHardware& hw, const Region& clip,
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- glVertexPointer(2, GL_FLOAT, 0, mVertices);
- glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
+ LayerMesh mesh;
+ computeGeometry(hw, &mesh);
+
+ glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
}
void LayerBase::clearWithOpenGL(const DisplayHardware& hw, const Region& clip) const
@@ -371,6 +359,12 @@ void LayerBase::drawWithOpenGL(const DisplayHardware& hw, const Region& clip) co
}
}
+ LayerMesh mesh;
+ computeGeometry(hw, &mesh);
+
+ // TODO: we probably want to generate the texture coords with the mesh
+ // here we assume that we only have 4 vertices
+
struct TexCoords {
GLfloat u;
GLfloat v;
@@ -380,9 +374,9 @@ void LayerBase::drawWithOpenGL(const DisplayHardware& hw, const Region& clip) co
if (!s.active.crop.isEmpty()) {
crop = s.active.crop;
}
- GLfloat left = GLfloat(crop.left) / GLfloat(s.active.w);
- GLfloat top = GLfloat(crop.top) / GLfloat(s.active.h);
- GLfloat right = GLfloat(crop.right) / GLfloat(s.active.w);
+ GLfloat left = GLfloat(crop.left) / GLfloat(s.active.w);
+ GLfloat top = GLfloat(crop.top) / GLfloat(s.active.h);
+ GLfloat right = GLfloat(crop.right) / GLfloat(s.active.w);
GLfloat bottom = GLfloat(crop.bottom) / GLfloat(s.active.h);
TexCoords texCoords[4];
@@ -399,9 +393,9 @@ void LayerBase::drawWithOpenGL(const DisplayHardware& hw, const Region& clip) co
}
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, mVertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
- glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
+ glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_BLEND);
@@ -417,8 +411,7 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
result.append(buffer);
s.transparentRegion.dump(result, "transparentRegion");
- transparentRegionScreen.dump(result, "transparentRegionScreen");
- visibleRegionScreen.dump(result, "visibleRegionScreen");
+ visibleRegion.dump(result, "visibleRegion");
snprintf(buffer, SIZE,
" "
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 83e871c..d227b2d 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -57,9 +57,9 @@ public:
DisplayID dpy;
mutable bool contentDirty;
- Region visibleRegionScreen;
- Region transparentRegionScreen;
- Region coveredRegionScreen;
+ // regions below are in window-manager space
+ Region visibleRegion;
+ Region coveredRegion;
int32_t sequence;
struct Geometry {
@@ -86,6 +86,20 @@ public:
Region transparentRegion;
};
+ class LayerMesh {
+ friend class LayerBase;
+ GLfloat mVertices[4][2];
+ size_t mNumVertices;
+ public:
+ LayerMesh() : mNumVertices(4) { }
+ GLfloat const* getVertices() const {
+ return &mVertices[0][0];
+ }
+ size_t getVertexCount() const {
+ return mNumVertices;
+ }
+ };
+
virtual void setName(const String8& name);
String8 getName() const;
@@ -105,15 +119,18 @@ public:
uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags);
-
- Rect visibleBounds() const;
+
+ void computeGeometry(const DisplayHardware& hw, LayerMesh* mesh) const;
+ Rect computeBounds() const;
+
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
virtual sp<Layer> getLayer() const { return 0; }
virtual const char* getTypeId() const { return "LayerBase"; }
- virtual void setGeometry(HWComposer::HWCLayerInterface& layer);
+ virtual void setGeometry(const DisplayHardware& hw,
+ HWComposer::HWCLayerInterface& layer);
virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer);
virtual void setAcquireFence(HWComposer::HWCLayerInterface& layer);
@@ -156,26 +173,13 @@ public:
virtual void setCoveredRegion(const Region& coveredRegion);
/**
- * validateVisibility - cache a bunch of things
- */
- virtual void validateVisibility(const Transform& globalTransform, const DisplayHardware& hw);
-
- /**
- * lockPageFlip - called each time the screen is redrawn and returns whether
+ * latchBuffer - called each time the screen is redrawn and returns whether
* the visible regions need to be recomputed (this is a fairly heavy
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual void lockPageFlip(bool& recomputeVisibleRegions);
-
- /**
- * unlockPageFlip - called each time the screen is redrawn. updates the
- * final dirty region wrt the planeTransform.
- * At this point, all visible regions, surface position and size, etc... are
- * correct.
- */
- virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
-
+ virtual Region latchBuffer(bool& recomputeVisibleRegions);
+
/**
* isOpaque - true if this surface is opaque
*/
@@ -233,9 +237,6 @@ public:
inline const State& currentState() const { return mCurrentState; }
inline State& currentState() { return mCurrentState; }
- int32_t getOrientation() const { return mOrientation; }
- int32_t getPlaneOrientation() const { return mPlaneOrientation; }
-
void clearWithOpenGL(const DisplayHardware& hw, const Region& clip) const;
protected:
@@ -253,19 +254,10 @@ private:
// Whether filtering is forced on or not
bool mFiltering;
- // cached during validateVisibility()
// Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering;
protected:
- // cached during validateVisibility()
- int32_t mOrientation;
- int32_t mPlaneOrientation;
- Transform mTransform;
- GLfloat mVertices[4][2];
- size_t mNumVertices;
- Rect mTransformedBounds;
-
// these are protected by an external lock
State mCurrentState;
State mDrawingState;
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index ceead45..5c37d01 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -58,8 +58,11 @@ void LayerDim::onDraw(const DisplayHardware& hw, const Region& clip) const
glColor4f(0, 0, 0, alpha);
- glVertexPointer(2, GL_FLOAT, 0, mVertices);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ LayerMesh mesh;
+ computeGeometry(hw, &mesh);
+
+ glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
glDisable(GL_BLEND);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index d046879..f2bf19d 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -120,6 +120,9 @@ void LayerScreenshot::onDraw(const DisplayHardware& hw, const Region& clip) cons
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
+ LayerMesh mesh;
+ computeGeometry(hw, &mesh);
+
glColor4f(0, 0, 0, alpha);
glDisable(GL_TEXTURE_EXTERNAL_OES);
@@ -133,8 +136,8 @@ void LayerScreenshot::onDraw(const DisplayHardware& hw, const Region& clip) cons
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
- glVertexPointer(2, GL_FLOAT, 0, mVertices);
- glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
+ glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 290fff4..3f77f74 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -49,13 +49,13 @@ void MessageBase::handleMessage(const Message&) {
// ---------------------------------------------------------------------------
-void MessageQueue::Handler::signalRefresh() {
+void MessageQueue::Handler::dispatchRefresh() {
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
}
}
-void MessageQueue::Handler::signalInvalidate() {
+void MessageQueue::Handler::dispatchInvalidate() {
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}
@@ -132,13 +132,31 @@ status_t MessageQueue::postMessage(
return NO_ERROR;
}
+/* when INVALIDATE_ON_VSYNC is set SF only processes
+ * buffer updates on VSYNC and performs a refresh immediately
+ * after.
+ *
+ * when INVALIDATE_ON_VSYNC is set to false, SF will instead
+ * perform the buffer updates immediately, but the refresh only
+ * at the next VSYNC.
+ * THIS MODE IS BUGGY ON GALAXY NEXUS AND WILL CAUSE HANGS
+ */
+#define INVALIDATE_ON_VSYNC 1
+
void MessageQueue::invalidate() {
-// mHandler->signalInvalidate();
+#if INVALIDATE_ON_VSYNC
mEvents->requestNextVsync();
+#else
+ mHandler->dispatchInvalidate();
+#endif
}
void MessageQueue::refresh() {
+#if INVALIDATE_ON_VSYNC
+ mHandler->dispatchRefresh();
+#else
mEvents->requestNextVsync();
+#endif
}
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
@@ -152,7 +170,11 @@ int MessageQueue::eventReceiver(int fd, int events) {
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- mHandler->signalRefresh();
+#if INVALIDATE_ON_VSYNC
+ mHandler->dispatchInvalidate();
+#else
+ mHandler->dispatchRefresh();
+#endif
break;
}
}
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index ea29e7e..710b2c2 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -70,8 +70,8 @@ class MessageQueue {
public:
Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
virtual void handleMessage(const Message& message);
- void signalRefresh();
- void signalInvalidate();
+ void dispatchRefresh();
+ void dispatchInvalidate();
};
friend class Handler;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3b2bf00..6c900be 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -425,98 +425,115 @@ status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
return res;
}
-bool SurfaceFlinger::threadLoop()
-{
+bool SurfaceFlinger::threadLoop() {
waitForEvent();
return true;
}
-void SurfaceFlinger::onMessageReceived(int32_t what)
-{
+void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
- case MessageQueue::REFRESH: {
-// case MessageQueue::INVALIDATE: {
- // 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);
- }
+ case MessageQueue::INVALIDATE:
+ handleMessageTransaction();
+ handleMessageInvalidate();
+ signalRefresh();
+ break;
+ case MessageQueue::REFRESH:
+ handleMessageRefresh();
+ break;
+ }
+}
- // post surfaces (if needed)
- handlePageFlip();
+void SurfaceFlinger::handleMessageTransaction() {
+ const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+ uint32_t transactionFlags = peekTransactionFlags(mask);
+ if (transactionFlags) {
+ Region dirtyRegion;
+ dirtyRegion = handleTransaction(transactionFlags);
+ // XXX: dirtyRegion should be per screen
+ mDirtyRegion |= dirtyRegion;
+ }
+}
-// signalRefresh();
-//
-// } break;
-//
-// case MessageQueue::REFRESH: {
+void SurfaceFlinger::handleMessageInvalidate() {
+ Region dirtyRegion;
+ dirtyRegion = handlePageFlip();
+ // XXX: dirtyRegion should be per screen
+ mDirtyRegion |= dirtyRegion;
+}
- handleRefresh();
+void SurfaceFlinger::handleMessageRefresh() {
+ handleRefresh();
- // TODO: iterate through all displays
- const DisplayHardware& hw(getDisplayHardware(0));
+ // XXX: dirtyRegion should be per screen, we should check all of them
+ if (mDirtyRegion.isEmpty()) {
+ return;
+ }
-// if (mDirtyRegion.isEmpty()) {
-// return;
-// }
+ // TODO: iterate through all displays
+ const DisplayHardware& hw(getDisplayHardware(0));
- if (CC_UNLIKELY(mHwWorkListDirty)) {
- // build the h/w work list
- handleWorkList(hw);
- }
+ // XXX: dirtyRegion should be per screen
+ // transform the dirty region into this screen's coordinate space
+ const Transform& planeTransform(hw.getTransform());
+ mDirtyRegion = planeTransform.transform(mDirtyRegion);
+ mDirtyRegion.orSelf(getAndClearInvalidateRegion());
+ mDirtyRegion.andSelf(hw.bounds());
- if (CC_LIKELY(hw.canDraw())) {
- // repaint the framebuffer (if needed)
- handleRepaint(hw);
- // inform the h/w that we're done compositing
- hw.compositionComplete();
- postFramebuffer();
- } else {
- // pretend we did the post
- hw.compositionComplete();
- }
- // 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 Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; ++i) {
- const sp<LayerBase>& layer(layers[i]);
- layer->drawForSreenShot(hw);
- }
+ if (CC_UNLIKELY(mHwWorkListDirty)) {
+ // build the h/w work list
+ handleWorkList(hw);
+ }
- success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface);
- ALOGE_IF(!success, "external display eglSwapBuffers failed");
+ if (CC_LIKELY(hw.canDraw())) {
+ // repaint the framebuffer (if needed)
+ handleRepaint(hw);
+ // inform the h/w that we're done compositing
+ hw.compositionComplete();
+ postFramebuffer();
+ } else {
+ // pretend we did the post
+ hw.compositionComplete();
+ }
- hw.compositionComplete();
- }
+ // 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());
- success = eglMakeCurrent(eglGetCurrentDisplay(),
- cur, cur, eglGetCurrentContext());
+ ALOGE_IF(!success, "eglMakeCurrent -> external failed");
- ALOGE_IF(!success, "eglMakeCurrent -> internal 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 Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ const size_t count = layers.size();
+ for (size_t i=0 ; i<count ; ++i) {
+ const sp<LayerBase>& layer(layers[i]);
+ layer->drawForSreenShot(hw);
}
- } break;
+ 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");
}
+
}
void SurfaceFlinger::postFramebuffer()
@@ -564,10 +581,12 @@ void SurfaceFlinger::postFramebuffer()
mSwapRegion.clear();
}
-void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
+Region SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
ATRACE_CALL();
+ Region dirtyRegion;
+
Mutex::Autolock _l(mStateLock);
const nsecs_t now = systemTime();
mDebugInTransaction = now;
@@ -580,16 +599,19 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
transactionFlags = getTransactionFlags(mask);
- handleTransactionLocked(transactionFlags);
+ dirtyRegion = handleTransactionLocked(transactionFlags);
mLastTransactionTime = systemTime() - now;
mDebugInTransaction = 0;
invalidateHwcGeometry();
// here the transaction has been committed
+
+ return dirtyRegion;
}
-void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
+Region SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
+ Region dirtyRegion;
const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
const size_t count = currentLayers.size();
@@ -652,13 +674,34 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
const sp<LayerBase>& layer(previousLayers[i]);
if (currentLayers.indexOf( layer ) < 0) {
// this layer is not visible anymore
- mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
+ // TODO: we could traverse the tree from front to back and compute the actual visible region
+ // TODO: we could cache the transformed region
+ Layer::State front(layer->drawingState());
+ Region visibleReg = front.transform.transform(
+ Region(Rect(front.active.w, front.active.h)));
+ dirtyRegion.orSelf(visibleReg);
}
}
}
}
commitTransaction();
+ return dirtyRegion;
+}
+
+void SurfaceFlinger::commitTransaction()
+{
+ if (!mLayersPendingRemoval.isEmpty()) {
+ // Notify removed layers now that they can't be drawn from
+ for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
+ mLayersPendingRemoval[i]->onRemoved();
+ }
+ mLayersPendingRemoval.clear();
+ }
+
+ mDrawingState = mCurrentState;
+ mTransationPending = false;
+ mTransactionCV.broadcast();
}
void SurfaceFlinger::computeVisibleRegions(
@@ -666,10 +709,6 @@ void SurfaceFlinger::computeVisibleRegions(
{
ATRACE_CALL();
- const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: we shouldn't rely on DisplayHardware here
- const Transform& planeTransform(hw.getTransform());
- const Region screenRegion(hw.bounds());
-
Region aboveOpaqueLayers;
Region aboveCoveredLayers;
Region dirty;
@@ -679,7 +718,6 @@ void SurfaceFlinger::computeVisibleRegions(
size_t i = currentLayers.size();
while (i--) {
const sp<LayerBase>& layer = currentLayers[i];
- layer->validateVisibility(planeTransform, hw);
// start with the whole surface at its current location
const Layer::State& s(layer->drawingState());
@@ -707,17 +745,30 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
const bool translucent = !layer->isOpaque();
- const Rect bounds(layer->visibleBounds());
+ Rect bounds(layer->computeBounds());
visibleRegion.set(bounds);
- visibleRegion.andSelf(screenRegion);
if (!visibleRegion.isEmpty()) {
// Remove the transparent area from the visible region
if (translucent) {
- visibleRegion.subtractSelf(layer->transparentRegionScreen);
+ Region transparentRegionScreen;
+ const Transform tr(s.transform);
+ if (tr.transformed()) {
+ if (tr.preserveRects()) {
+ // transform the transparent region
+ transparentRegionScreen = tr.transform(s.transparentRegion);
+ } else {
+ // transformation too complex, can't do the
+ // transparent region optimization.
+ transparentRegionScreen.clear();
+ }
+ } else {
+ transparentRegionScreen = s.transparentRegion;
+ }
+ visibleRegion.subtractSelf(transparentRegionScreen);
}
// compute the opaque region
- const int32_t layerOrientation = layer->getOrientation();
+ const int32_t layerOrientation = s.transform.getOrientation();
if (s.alpha==255 && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
// the opaque region is the layer's footprint
@@ -740,7 +791,7 @@ void SurfaceFlinger::computeVisibleRegions(
// we need to invalidate the whole region
dirty = visibleRegion;
// as well, as the old visible region
- dirty.orSelf(layer->visibleRegionScreen);
+ dirty.orSelf(layer->visibleRegion);
layer->contentDirty = false;
} else {
/* compute the exposed region:
@@ -756,8 +807,8 @@ void SurfaceFlinger::computeVisibleRegions(
* exposed because of a resize.
*/
const Region newExposed = visibleRegion - coveredRegion;
- const Region oldVisibleRegion = layer->visibleRegionScreen;
- const Region oldCoveredRegion = layer->coveredRegionScreen;
+ const Region oldVisibleRegion = layer->visibleRegion;
+ const Region oldCoveredRegion = layer->coveredRegion;
const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
}
@@ -779,63 +830,51 @@ void SurfaceFlinger::computeVisibleRegions(
}
}
- // invalidate the areas where a layer was removed
- dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
- mDirtyRegionRemovedLayer.clear();
-
mSecureFrameBuffer = secureFrameBuffer;
opaqueRegion = aboveOpaqueLayers;
}
-
-void SurfaceFlinger::commitTransaction()
-{
- if (!mLayersPendingRemoval.isEmpty()) {
- // Notify removed layers now that they can't be drawn from
- for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
- mLayersPendingRemoval[i]->onRemoved();
- }
- mLayersPendingRemoval.clear();
- }
-
- mDrawingState = mCurrentState;
- mTransationPending = false;
- mTransactionCV.broadcast();
-}
-
-void SurfaceFlinger::handlePageFlip()
+Region SurfaceFlinger::handlePageFlip()
{
ATRACE_CALL();
- const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: it's a problem we need DisplayHardware here
- const Region screenRegion(hw.bounds());
+ Region dirtyRegion;
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
- const bool visibleRegions = lockPageFlip(currentLayers);
- if (visibleRegions || mVisibleRegionsDirty) {
- Region opaqueRegion;
- computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
+ bool visibleRegions = false;
+ 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]);
+ dirtyRegion.orSelf( layer->latchBuffer(visibleRegions) );
+ }
- /*
- * rebuild the visible layer list
- */
- const size_t count = currentLayers.size();
- mVisibleLayersSortedByZ.clear();
- mVisibleLayersSortedByZ.setCapacity(count);
- for (size_t i=0 ; i<count ; i++) {
- if (!currentLayers[i]->visibleRegionScreen.isEmpty())
- mVisibleLayersSortedByZ.add(currentLayers[i]);
- }
+ if (visibleRegions || mVisibleRegionsDirty) {
+ Region opaqueRegion;
+ computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
+
+ /*
+ * rebuild the visible layer list
+ */
- mWormholeRegion = screenRegion.subtract(opaqueRegion);
- mVisibleRegionsDirty = false;
- invalidateHwcGeometry();
+ // XXX: mVisibleLayersSortedByZ should be per-screen
+ const size_t count = currentLayers.size();
+ mVisibleLayersSortedByZ.clear();
+ mVisibleLayersSortedByZ.setCapacity(count);
+ for (size_t i=0 ; i<count ; i++) {
+ if (!currentLayers[i]->visibleRegion.isEmpty())
+ mVisibleLayersSortedByZ.add(currentLayers[i]);
}
- unlockPageFlip(currentLayers);
+ // FIXME: mWormholeRegion needs to be calculated per screen
+ const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
+ mWormholeRegion = Region(hw.getBounds()).subtract(
+ hw.getTransform().transform(opaqueRegion) );
+ mVisibleRegionsDirty = false;
+ invalidateHwcGeometry();
+ }
- mDirtyRegion.orSelf(getAndClearInvalidateRegion());
- mDirtyRegion.andSelf(screenRegion);
+ return dirtyRegion;
}
void SurfaceFlinger::invalidateHwcGeometry()
@@ -843,30 +882,6 @@ void SurfaceFlinger::invalidateHwcGeometry()
mHwWorkListDirty = true;
}
-bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
-{
- bool recomputeVisibleRegions = false;
- 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]);
- layer->lockPageFlip(recomputeVisibleRegions);
- }
- return recomputeVisibleRegions;
-}
-
-void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
-{
- const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: it's a problem we need DisplayHardware here
- const Transform& planeTransform(hw.getTransform());
- 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]);
- layer->unlockPageFlip(planeTransform, mDirtyRegion);
- }
-}
-
void SurfaceFlinger::handleRefresh()
{
bool needInvalidate = false;
@@ -896,7 +911,7 @@ void SurfaceFlinger::handleWorkList(const DisplayHardware& hw)
HWComposer::LayerListIterator cur = hwc.begin();
const HWComposer::LayerListIterator end = hwc.end();
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- currentLayers[i]->setGeometry(*cur);
+ currentLayers[i]->setGeometry(hw, *cur);
if (mDebugDisableHWC || mDebugRegion) {
cur->setSkip(true);
}
@@ -1012,9 +1027,10 @@ void SurfaceFlinger::composeSurfaces(const DisplayHardware& hw, const Region& di
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
const size_t count = layers.size();
+ const Transform& tr = hw.getTransform();
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
const sp<LayerBase>& layer(layers[i]);
- const Region clip(dirty.intersect(layer->visibleRegionScreen));
+ const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
if (cur->getCompositionType() == HWC_OVERLAY) {
if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3e27564..91cc6a5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -129,6 +129,9 @@ public:
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
void onMessageReceived(int32_t what);
+ void handleMessageTransaction();
+ void handleMessageInvalidate();
+ void handleMessageRefresh();
status_t postMessageAsync(const sp<MessageBase>& msg,
nsecs_t reltime=0, uint32_t flags = 0);
@@ -237,17 +240,23 @@ public: // hack to work around gcc 4.0.3 bug
private:
void waitForEvent();
- void handleTransaction(uint32_t transactionFlags);
- void handleTransactionLocked(uint32_t transactionFlags);
+ Region handleTransaction(uint32_t transactionFlags);
+ Region handleTransactionLocked(uint32_t transactionFlags);
void computeVisibleRegions(
const LayerVector& currentLayers,
Region& dirtyRegion,
Region& wormholeRegion);
- void handlePageFlip();
- bool lockPageFlip(const LayerVector& currentLayers);
- void unlockPageFlip(const LayerVector& currentLayers);
+ /* handlePageFilp: this is were we latch a new buffer
+ * if available and compute the dirty region.
+ * The return value is the dirty region expressed in the
+ * window manager's coordinate space (or the layer's state
+ * space, which is the same thing), in particular the dirty
+ * region is independent from a specific display's orientation.
+ */
+ Region handlePageFlip();
+
void handleRefresh();
void handleWorkList(const DisplayHardware& hw);
void handleRepaint(const DisplayHardware& hw);