diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 064f68963..7edbdc50d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -110,7 +110,8 @@ void Layer::onFirstRef() mSurfaceTexture->setDefaultMaxBufferCount(3); #endif - updateTransformHint(); + const sp hw(mFlinger->getDefaultDisplayDevice()); + updateTransformHint(hw); } Layer::~Layer() @@ -767,15 +768,12 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const return usage; } -void Layer::updateTransformHint() const { +void Layer::updateTransformHint(const sp& hw) const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { - // The transform hint is used to improve performance on the main - // display -- we can only have a single transform hint, it cannot + // The transform hint is used to improve performance, but 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. - sp hw(mFlinger->getDefaultDisplayDevice()); const Transform& planeTransform(hw->getTransform()); orientation = planeTransform.getOrientation(); if (orientation & Transform::ROT_INVALID) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6f75d8c1c..c5eb26b12 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -91,8 +91,8 @@ public: inline const sp& getActiveBuffer() const { return mActiveBuffer; } // Updates the transform hint in our SurfaceTexture to match - // the current orientation of the default display device. - virtual void updateTransformHint() const; + // the current orientation of the display device. + virtual void updateTransformHint(const sp& hw) const; protected: virtual void onFirstRef(); diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 00c4ffecd..4d5a5b02b 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -246,7 +246,7 @@ public: * Updates the SurfaceTexture's transform hint, for layers that have * a SurfaceTexture. */ - virtual void updateTransformHint() const { } + virtual void updateTransformHint(const sp& hw) const { } /** always call base class first */ virtual void dump(String8& result, char* scratch, size_t size) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3097965ce..9afa4c12c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1076,7 +1076,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (transactionFlags & eTraversalNeeded) { for (size_t i=0 ; i& layer = currentLayers[i]; + const sp& layer(currentLayers[i]); uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -1149,18 +1149,6 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) disp->setProjection(state.orientation, state.viewport, state.frame); } - - // Walk through all the layers in currentLayers, - // and update their transform hint. - // - // TODO: we could be much more clever about which - // layers we touch and how often we do these updates - // (e.g. only touch the layers associated with this - // display, and only on a rotation). - for (size_t i = 0; i < count; i++) { - const sp& layerBase = currentLayers[i]; - layerBase->updateTransformHint(); - } } } } @@ -1209,6 +1197,61 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } } + if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) { + // The transform hint might have changed for some layers + // (either because a display has changed, or because a layer + // as changed). + // + // Walk through all the layers in currentLayers, + // and update their transform hint. + // + // If a layer is visible only on a single display, then that + // display is used to calculate the hint, otherwise we use the + // default display. + // + // NOTE: we do this here, rather than in rebuildLayerStacks() so that + // the hint is set before we acquire a buffer from the surface texture. + // + // NOTE: layer transactions have taken place already, so we use their + // drawing state. However, SurfaceFlinger's own transaction has not + // happened yet, so we must use the current state layer list + // (soon to become the drawing state list). + // + sp disp; + uint32_t currentlayerStack = 0; + for (size_t i=0; i& layerBase(currentLayers[i]); + uint32_t layerStack = layerBase->drawingState().layerStack; + if (i==0 || currentlayerStack != layerStack) { + currentlayerStack = layerStack; + // figure out if this layerstack is mirrored + // (more than one display) if so, pick the default display, + // if not, pick the only display it's on. + disp.clear(); + for (size_t dpy=0 ; dpy hw(mDisplays[dpy]); + if (hw->getLayerStack() == currentlayerStack) { + if (disp == NULL) { + disp = hw; + } else { + disp = getDefaultDisplayDevice(); + break; + } + } + } + } + if (disp != NULL) { + // presumably this means this layer is using a layerStack + // that is not visible on any display + layerBase->updateTransformHint(disp); + } + } + } + + /* * Perform our own transaction if needed */