diff options
author | 2017-03-29 12:10:31 -0700 | |
---|---|---|
committer | 2017-03-30 11:52:15 -0700 | |
commit | cae605cd5668f8107e340ad8a672c7f034147401 (patch) | |
tree | 145744d0c7568e98e12bebfc6125797c7c1f1484 | |
parent | a615e47ef0ebdf6ab666dbc4c51df33ed11ff00a (diff) |
Fix seamless rotation with SurfaceView WM bypass.
First a brief review on seamless rotation. In seamless rotation
the WM will do the following atomically:
1. Update the display transform.
2. Set window transforms to make the surfaces at their old size appear
at the correct location in the new coordinate space.
3. Set a flag to undo the transforms when the surfaces resize.
However, windows with NATIVE_WINDOW_TRANSFORM_DISPLAY needed to be special cased.
The flag will perform step 2 in terms of buffer mapping, but not in terms of bounds
computation. So to compensate the WM would apply the transform to the bounds,
set these bounds, and then skip applying the transform matrix (as the buffer is
transformed by the flag).
Now that the WM can't see the Camera view, it can't implement this special logic
and the Camera view inherits the parent transform. We compensate for this in
SurfaceFlinger by omitting parent rotation transform components for
Surfaces with NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY. To some extent this
breaks arbitrary rotation for surfaces with NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY
but this is essentially ok:
1. We lived with that bug until N-MR1
2. We fixed it in N-MR1 because the camera was falling back to ROTATE
a lot which shouldn't be happening anymore, following introduction
of specifying rotation animation in manifest.
Test: Rotate camera, disable HWC, rotate camera some more. Switch to front camera, repeat.
Bug: 36230754
Bug: 36727915
Change-Id: Ied390c9cb3968fcce32a84ee7947f699746fdc81
-rw-r--r-- | include/gui/ISurfaceComposerClient.h | 4 | ||||
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 3 | ||||
-rw-r--r-- | include/gui/SurfaceControl.h | 2 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposerClient.cpp | 11 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 8 | ||||
-rw-r--r-- | libs/gui/SurfaceControl.cpp | 7 | ||||
-rw-r--r-- | services/surfaceflinger/Client.cpp | 10 | ||||
-rw-r--r-- | services/surfaceflinger/Client.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 65 |
9 files changed, 44 insertions, 68 deletions
diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h index 1c890005b6..a680bc67c4 100644 --- a/include/gui/ISurfaceComposerClient.h +++ b/include/gui/ISurfaceComposerClient.h @@ -34,7 +34,6 @@ public: DestroySurface, ClearLayerFrameStats, GetLayerFrameStats, - GetTransformToDisplayInverse, Last, }; @@ -76,9 +75,6 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0; - - virtual status_t getTransformToDisplayInverse(const sp<IBinder>& handle, - bool* outTransformToDisplayInverse) const = 0; }; class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> { diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 1e8cf76627..394425a328 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -169,9 +169,6 @@ public: status_t clearLayerFrameStats(const sp<IBinder>& token) const; status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const; - status_t getTransformToDisplayInverse(const sp<IBinder>& token, - bool* outTransformToDisplayInverse) const; - static status_t clearAnimationFrameStats(); static status_t getAnimationFrameStats(FrameStats* outStats); diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h index 8ee35bc495..3cff7df260 100644 --- a/include/gui/SurfaceControl.h +++ b/include/gui/SurfaceControl.h @@ -119,8 +119,6 @@ public: status_t clearLayerFrameStats() const; status_t getLayerFrameStats(FrameStats* outStats) const; - status_t getTransformToDisplayInverse(bool* outTransformToDisplayInverse) const; - private: // can't be copied SurfaceControl& operator = (SurfaceControl& rhs); diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 853e23a8cd..2d2146b356 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -68,14 +68,6 @@ public: &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GetLayerFrameStats, handle, outStats); } - - status_t getTransformToDisplayInverse(const sp<IBinder>& handle, - bool* outTransformToDisplayInverse) const override { - return callRemote<decltype( - &ISurfaceComposerClient:: - getTransformToDisplayInverse)>(Tag::GetTransformToDisplayInverse, handle, - outTransformToDisplayInverse); - } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -105,9 +97,6 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, case Tag::GetLayerFrameStats: { return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats); } - case Tag::GetTransformToDisplayInverse: { - return callLocal(data, reply, &ISurfaceComposerClient::getTransformToDisplayInverse); - } case Tag::Last: // Should not be possible because of the check at the beginning of the method return BBinder::onTransact(code, data, reply, flags); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 088933afb6..56c7586041 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -711,14 +711,6 @@ status_t SurfaceComposerClient::getLayerFrameStats(const sp<IBinder>& token, return mClient->getLayerFrameStats(token, outStats); } -status_t SurfaceComposerClient::getTransformToDisplayInverse(const sp<IBinder>& token, - bool* outTransformToDisplayInverse) const { - if (mStatus != NO_ERROR) { - return mStatus; - } - return mClient->getTransformToDisplayInverse(token, outTransformToDisplayInverse); -} - inline Composer& SurfaceComposerClient::getComposer() { return mComposer; } diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 1e693796eb..7a68f1174a 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -209,13 +209,6 @@ status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const { return client->getLayerFrameStats(mHandle, outStats); } -status_t SurfaceControl::getTransformToDisplayInverse(bool* outTransformToDisplayInverse) const { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->getTransformToDisplayInverse(mHandle, outTransformToDisplayInverse); -} - status_t SurfaceControl::validate() const { if (mHandle==0 || mClient==0) { diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 9ddae2b4dc..e9a251305f 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -210,15 +210,5 @@ status_t Client::getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outSt return NO_ERROR; } -status_t Client::getTransformToDisplayInverse(const sp<IBinder>& handle, - bool* outTransformToDisplayInverse) const { - sp<Layer> layer = getLayerUser(handle); - if (layer == NULL) { - return NAME_NOT_FOUND; - } - *outTransformToDisplayInverse = layer->getTransformToDisplayInverse(); - return NO_ERROR; -} - // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 141f6c767e..b5f98b8a6f 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -67,8 +67,6 @@ private: virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const; virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const; - virtual status_t getTransformToDisplayInverse( - const sp<IBinder>& handle, bool* outTransformToDisplayInverse) const; virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ac7e08393a..16d8160f79 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -505,7 +505,7 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { // which means using the inverse of the current transform set on the // SurfaceFlingerConsumer. uint32_t invTransform = mCurrentTransform; - if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { + if (getTransformToDisplayInverse()) { /* * the code below applies the primary display's inverse transform to the * buffer @@ -713,7 +713,7 @@ void Layer::setGeometry( const Transform bufferOrientation(mCurrentTransform); Transform transform(tr * t * bufferOrientation); - if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { + if (getTransformToDisplayInverse()) { /* * the code below applies the primary display's inverse transform to the * buffer @@ -725,8 +725,14 @@ void Layer::setGeometry( invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - // and apply to the current transform - transform = Transform(invTransform) * transform; + + /* + * Here we cancel out the orientation component of the WM transform. + * The scaling and translate components are already included in our bounds + * computation so it's enough to just omit it in the composition. + * See comment in onDraw with ref to b/36727915 for why. + */ + transform = Transform(invTransform) * tr * bufferOrientation; } // this gives us only the "orientation" component of the transform @@ -987,6 +993,24 @@ void Layer::draw(const sp<const DisplayDevice>& hw) const { onDraw(hw, Region(hw->bounds()), false); } +static constexpr mat4 inverseOrientation(uint32_t transform) { + const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1); + const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1); + const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1); + mat4 tr; + + if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + tr = tr * rot90; + } + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { + tr = tr * flipH; + } + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { + tr = tr * flipV; + } + return inverse(tr); +} + void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, bool useIdentityTransform) const { @@ -1041,30 +1065,29 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); - if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { + if (getTransformToDisplayInverse()) { /* * the code below applies the primary display's inverse transform to * the texture transform */ - - // create a 4x4 transform matrix from the display transform flags - const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1); - const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1); - const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1); - - mat4 tr; uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform(); - if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) - tr = tr * rot90; - if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) - tr = tr * flipH; - if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) - tr = tr * flipV; - - // calculate the inverse - tr = inverse(tr); + mat4 tr = inverseOrientation(transform); + + /** + * TODO(b/36727915): This is basically a hack. + * + * Ensure that regardless of the parent transformation, + * this buffer is always transformed from native display + * orientation to display orientation. For example, in the case + * of a camera where the buffer remains in native orientation, + * we want the pixels to always be upright. + */ + if (getParent() != nullptr) { + const auto parentTransform = getParent()->getTransform(); + tr = tr * inverseOrientation(parentTransform.getOrientation()); + } // and finally apply it to the original texture matrix const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr); |