make transform hint multi-display aware

if a layer is not mirrored, we now use its display
as the source for the transfrom hint calculation
instead of always using the default (main) display.

this change does two thing:
1) we make updateTransformHint take a DisplayDevice
   as a parameter instead of hard-coding the
   main display.

2) each time we do a transaction that could change
   the hint, we go through all layers and
   figure out which display should be used for their
   transform hint.

Bug: 7599344
Change-Id: I9b04a95e6c372dd770bacf81d8ef6f8e31b87b83
This commit is contained in:
Mathias Agopian 2012-11-21 16:02:13 -08:00
parent 764c197c6f
commit 8430095879
4 changed files with 64 additions and 23 deletions

View File

@ -110,7 +110,8 @@ void Layer::onFirstRef()
mSurfaceTexture->setDefaultMaxBufferCount(3);
#endif
updateTransformHint();
const sp<const DisplayDevice> 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<const DisplayDevice>& 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<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
const Transform& planeTransform(hw->getTransform());
orientation = planeTransform.getOrientation();
if (orientation & Transform::ROT_INVALID) {

View File

@ -91,8 +91,8 @@ public:
inline const sp<GraphicBuffer>& 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<const DisplayDevice>& hw) const;
protected:
virtual void onFirstRef();

View File

@ -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<const DisplayDevice>& hw) const { }
/** always call base class first */
virtual void dump(String8& result, char* scratch, size_t size) const;

View File

@ -1069,7 +1069,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (transactionFlags & eTraversalNeeded) {
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer = currentLayers[i];
const sp<LayerBase>& layer(currentLayers[i]);
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) continue;
@ -1142,18 +1142,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>& layerBase = currentLayers[i];
layerBase->updateTransformHint();
}
}
}
}
@ -1208,6 +1196,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<const DisplayDevice> disp;
uint32_t currentlayerStack = 0;
for (size_t i=0; i<count; i++) {
// NOTE: we rely on the fact that layers are sorted by
// layerStack first (so we don't have to traverse the list
// of displays for every layer).
const sp<LayerBase>& 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<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> 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
*/