diff options
author | Mathias Agopian <mathias@google.com> | 2012-06-29 14:12:52 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2012-07-10 14:29:27 -0700 |
commit | 4fec873a98f7b4380720cd1ad006f74c8cdc73da (patch) | |
tree | 5d21495a3f4e9f87bf20c6a3d3ea0db83cbe33c0 /services/surfaceflinger/SurfaceFlinger.cpp | |
parent | e7db724bed5d1e5086801df7705d9b1f2a071785 (diff) | |
download | frameworks_native-4fec873a98f7b4380720cd1ad006f74c8cdc73da.zip frameworks_native-4fec873a98f7b4380720cd1ad006f74c8cdc73da.tar.gz frameworks_native-4fec873a98f7b4380720cd1ad006f74c8cdc73da.tar.bz2 |
one more step towards multiple display support
- remove dependency on cached state in validateVisibility
- get rid of mVertices and mTransformedBounds
- get rid of validateVisibility
- get rid of unlockPageFlip
- handleTransaction now returns a dirty region
- computevisibileregion now uses window-manager space
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 328 |
1 files changed, 172 insertions, 156 deletions
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) |