From 0617894190ea0c3ee50889bee1d4df0f369b0761 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 27 Jul 2017 10:25:59 -0700 Subject: Add a re-parent function to re-parent a specific child. This is similar to reparentChildren, but the reparentChild will only re-parent a specific child to the new parent and not all children. Test: Added test in Transaction_test for reparentChild. Change-Id: I4275e0d5f1d5601b489956753c78a56d1a5d4c1c --- libs/gui/SurfaceComposerClient.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7ae2672249..b0ae7e0bdf 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -176,6 +176,9 @@ public: status_t reparentChildren(const sp& client, const sp& id, const sp& newParentHandle); + status_t reparentChild(const sp& client, + const sp& id, const sp& newParentHandle, + const sp& childHandle); status_t detachChildren(const sp& client, const sp& id); status_t setOverrideScalingMode(const sp& client, @@ -493,6 +496,21 @@ status_t Composer::reparentChildren( return NO_ERROR; } +status_t Composer::reparentChild(const sp& client, + const sp& id, + const sp& newParentHandle, + const sp& childHandle) { + Mutex::Autolock lock(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) { + return BAD_INDEX; + } + s->what |= layer_state_t::eReparentChild; + s->parentHandleForChild = newParentHandle; + s->childHandle = childHandle; + return NO_ERROR; +} + status_t Composer::detachChildren( const sp& client, const sp& id) { @@ -831,6 +849,11 @@ status_t SurfaceComposerClient::reparentChildren(const sp& id, return getComposer().reparentChildren(this, id, newParentHandle); } +status_t SurfaceComposerClient::reparentChild(const sp& id, + const sp& newParentHandle, const sp& childHandle) { + return getComposer().reparentChild(this, id, newParentHandle, childHandle); +} + status_t SurfaceComposerClient::detachChildren(const sp& id) { return getComposer().detachChildren(this, id); } -- cgit v1.2.3-59-g8ed1b From f1961f713de2b3f54c8ce7653964b969e1a02bc8 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 18 Sep 2017 16:41:07 -0700 Subject: Re-parent invoked on child instead of on parent. The function to re-parent an individual child is now invoked on the child instead of the parent. This ensures the child ends up with the last parent set if multiple reparent requests are made in the same transaction. This also allows adding a parent to a layer that didn't have one previously. Test: Transaction_test -> Reparent, ReparentToNoParent, ReparentFromNoParent Change-Id: Idab429eb2dca5a4ae1b020a5a7629d719dd4d995 --- libs/gui/LayerState.cpp | 2 - libs/gui/SurfaceComposerClient.cpp | 19 +++--- libs/gui/SurfaceControl.cpp | 5 +- libs/gui/include/gui/SurfaceComposerClient.h | 3 +- libs/gui/include/gui/SurfaceControl.h | 7 +-- libs/gui/include/private/gui/LayerState.h | 3 +- services/surfaceflinger/Layer.cpp | 28 +++------ services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 6 +- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 6 +- services/surfaceflinger/tests/Transaction_test.cpp | 67 +++++++++++++++++++++- 11 files changed, 94 insertions(+), 54 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 573f6856d6..3418a4983e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -46,7 +46,6 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(IInterface::asBinder(barrierGbp)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); - output.writeStrongBinder(childHandle); output.write(transparentRegion); return NO_ERROR; } @@ -80,7 +79,6 @@ status_t layer_state_t::read(const Parcel& input) interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); - childHandle = input.readStrongBinder(); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b0ae7e0bdf..be7b1d2f6a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -176,9 +176,8 @@ public: status_t reparentChildren(const sp& client, const sp& id, const sp& newParentHandle); - status_t reparentChild(const sp& client, - const sp& id, const sp& newParentHandle, - const sp& childHandle); + status_t reparent(const sp& client, + const sp& id, const sp& newParentHandle); status_t detachChildren(const sp& client, const sp& id); status_t setOverrideScalingMode(const sp& client, @@ -496,18 +495,16 @@ status_t Composer::reparentChildren( return NO_ERROR; } -status_t Composer::reparentChild(const sp& client, +status_t Composer::reparent(const sp& client, const sp& id, - const sp& newParentHandle, - const sp& childHandle) { + const sp& newParentHandle) { Mutex::Autolock lock(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) { return BAD_INDEX; } - s->what |= layer_state_t::eReparentChild; + s->what |= layer_state_t::eReparent; s->parentHandleForChild = newParentHandle; - s->childHandle = childHandle; return NO_ERROR; } @@ -849,9 +846,9 @@ status_t SurfaceComposerClient::reparentChildren(const sp& id, return getComposer().reparentChildren(this, id, newParentHandle); } -status_t SurfaceComposerClient::reparentChild(const sp& id, - const sp& newParentHandle, const sp& childHandle) { - return getComposer().reparentChild(this, id, newParentHandle, childHandle); +status_t SurfaceComposerClient::reparent(const sp& id, + const sp& newParentHandle) { + return getComposer().reparent(this, id, newParentHandle); } status_t SurfaceComposerClient::detachChildren(const sp& id) { diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index b9c5ef9580..d801d12738 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -191,11 +191,10 @@ status_t SurfaceControl::reparentChildren(const sp& newParentHandle) { return mClient->reparentChildren(mHandle, newParentHandle); } -status_t SurfaceControl::reparentChild(const sp& newParentHandle, - const sp& childHandle) { +status_t SurfaceControl::reparent(const sp& newParentHandle) { status_t err = validate(); if (err < 0) return err; - return mClient->reparentChild(mHandle, newParentHandle, childHandle); + return mClient->reparent(mHandle, newParentHandle); } status_t SurfaceControl::detachChildren() { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6e2cb83544..cf2ff5b96e 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -161,8 +161,7 @@ public: const sp& handle, uint64_t frameNumber); status_t reparentChildren(const sp& id, const sp& newParentHandle); - status_t reparentChild(const sp& id, const sp& newParentHandle, - const sp& childHandle); + status_t reparent(const sp& id, const sp& newParentHandle); status_t detachChildren(const sp& id); status_t setOverrideScalingMode(const sp& id, int32_t overrideScalingMode); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index d8b67ef96a..b506e00672 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -124,11 +124,10 @@ public: // Reparents all children of this layer to the new parent handle. status_t reparentChildren(const sp& newParentHandle); - // Reparents a specified child from this layer to the new parent handle. - // The child, parent, and new parent must all have the same client. + // Reparents the current layer to the new parent handle. The new parent must not be null. // This can be used instead of reparentChildren if the caller wants to - // only re-parent specific children. - status_t reparentChild(const sp& newParentHandle, const sp& childHandle); + // only re-parent a specific child. + status_t reparent(const sp& newParentHandle); // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h index 4f73e04e22..4ff2e5e0d6 100644 --- a/libs/gui/include/private/gui/LayerState.h +++ b/libs/gui/include/private/gui/LayerState.h @@ -60,7 +60,7 @@ struct layer_state_t { eReparentChildren = 0x00002000, eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, - eReparentChild = 0x00010000 + eReparent = 0x00010000 }; layer_state_t() @@ -109,7 +109,6 @@ struct layer_state_t { sp relativeLayerHandle; sp parentHandleForChild; - sp childHandle; // non POD must be last. see write/read Region transparentRegion; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9435a187d9..fd30e1614b 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2625,8 +2625,8 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return true; } -bool Layer::reparentChild(const sp& newParentHandle, const sp& childHandle) { - if (newParentHandle == nullptr || childHandle == nullptr) { +bool Layer::reparent(const sp& newParentHandle) { + if (newParentHandle == nullptr) { return false; } @@ -2637,29 +2637,19 @@ bool Layer::reparentChild(const sp& newParentHandle, const sp& return false; } - handle = static_cast(childHandle.get()); - sp child = handle->owner.promote(); - if (child == nullptr) { - ALOGE("Unable to promote child Layer handle"); - return false; - } - - if (mCurrentChildren.indexOf(child) < 0) { - ALOGE("Child layer is not child of current layer"); - return false; + sp parent = getParent(); + if (parent != nullptr) { + parent->removeChild(this); } + newParent->addChild(this); - sp parentClient(mClientRef.promote()); - sp childClient(child->mClientRef.promote()); + sp client(mClientRef.promote()); sp newParentClient(newParent->mClientRef.promote()); - if (parentClient != childClient || childClient != newParentClient) { - ALOGE("Current layer, child layer, and new parent layer must have the same client"); - return false; + if (client != newParentClient) { + client->setParentLayer(newParent); } - newParent->addChild(child); - mCurrentChildren.remove(child); return true; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f94833b32f..e7ece4579e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -241,7 +241,7 @@ public: bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp& layer); - bool reparentChild(const sp& newParentHandle, const sp& childHandle); + bool reparent(const sp& newParentHandle); bool detachChildren(); // If we have received a new buffer this frame, we will pass its surface diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cae4deacb0..6ee14fe72a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3121,10 +3121,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } - // Always re-parent the children that explicitly requested to get - // re-parented before the general re-parent of all children. - if (what & layer_state_t::eReparentChild) { - if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) { + if (what & layer_state_t::eReparent) { + if (layer->reparent(s.parentHandleForChild)) { flags |= eTransactionNeeded|eTraversalNeeded; } } diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 71aa52dee6..1cf6ce33b7 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -2679,10 +2679,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } - // Always re-parent the children that explicitly requested to get - // re-parented before the general re-parent of all children. - if (what & layer_state_t::eReparentChild) { - if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) { + if (what & layer_state_t::eReparent) { + if (layer->reparent(s.parentHandleForChild)) { flags |= eTransactionNeeded|eTraversalNeeded; } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index dea6503e4e..21194926da 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1169,7 +1169,7 @@ TEST_F(ChildLayerTest, Bug36858924) { fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); } -TEST_F(ChildLayerTest, ReparentChild) { +TEST_F(ChildLayerTest, Reparent) { SurfaceComposerClient::openGlobalTransaction(); mChild->show(); mChild->setPosition(10, 10); @@ -1185,7 +1185,7 @@ TEST_F(ChildLayerTest, ReparentChild) { // And 10 more pixels we should be back to the foreground surface mCapture->expectFGColor(84, 84); } - mFGSurfaceControl->reparentChild(mBGSurfaceControl->getHandle(), mChild->getHandle()); + mChild->reparent(mBGSurfaceControl->getHandle()); { ScreenCapture::captureScreen(&mCapture); mCapture->expectFGColor(64, 64); @@ -1198,6 +1198,69 @@ TEST_F(ChildLayerTest, ReparentChild) { } } +TEST_F(ChildLayerTest, ReparentToNoParent) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mChild->setPosition(10, 10); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + mChild->reparent(nullptr); + { + ScreenCapture::captureScreen(&mCapture); + // Nothing should have changed. + mCapture->expectFGColor(64, 64); + mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(84, 84); + } +} + +TEST_F(ChildLayerTest, ReparentFromNoParent) { + sp newSurface = mComposerClient->createSurface( + String8("New Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0); + ASSERT_TRUE(newSurface != NULL); + ASSERT_TRUE(newSurface->isValid()); + + fillSurfaceRGBA8(newSurface, 63, 195, 63); + SurfaceComposerClient::openGlobalTransaction(); + mChild->hide(); + newSurface->show(); + newSurface->setPosition(10, 10); + newSurface->setLayer(INT32_MAX-2); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // At 10, 10 we should see the new surface + mCapture->checkPixel(10, 10, 63, 195, 63); + } + + SurfaceComposerClient::openGlobalTransaction(); + newSurface->reparent(mFGSurfaceControl->getHandle()); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from + // mFGSurface, putting it at 74, 74. + mCapture->expectFGColor(64, 64); + mCapture->checkPixel(74, 74, 63, 195, 63); + mCapture->expectFGColor(84, 84); + } +} + TEST_F(ChildLayerTest, NestedChildren) { sp grandchild = mComposerClient->createSurface( String8("Grandchild surface"), -- cgit v1.2.3-59-g8ed1b From 13fdc49516d17f41e64e62e73c313b0928bf13cc Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 27 Jun 2017 12:40:18 -0700 Subject: Added native functionality to create a color layer. Added a new layer that can draw a specified color and specified alpha. This will replace creating a dim layer and allow any colors, not just black, to be set for this layer. Test: Added tests to Transaction_test.cpp to test with a color and a color layer with alpha. Change-Id: I00a38d1bbc01093026f088c3347454281bdc2b8c --- libs/gui/LayerDebugInfo.cpp | 20 ++++- libs/gui/LayerState.cpp | 6 ++ libs/gui/SurfaceComposerClient.cpp | 17 ++++ libs/gui/SurfaceControl.cpp | 5 ++ libs/gui/include/gui/ISurfaceComposerClient.h | 2 +- libs/gui/include/gui/LayerDebugInfo.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 + libs/gui/include/gui/SurfaceControl.h | 2 + libs/gui/include/private/gui/LayerState.h | 6 +- services/surfaceflinger/Android.mk | 2 +- services/surfaceflinger/ColorLayer.cpp | 66 +++++++++++++++ services/surfaceflinger/ColorLayer.h | 49 +++++++++++ services/surfaceflinger/Layer.cpp | 75 ++++++++--------- services/surfaceflinger/Layer.h | 24 ++---- services/surfaceflinger/LayerDim.cpp | 68 ---------------- services/surfaceflinger/LayerDim.h | 49 ----------- .../surfaceflinger/RenderEngine/Description.cpp | 14 +--- services/surfaceflinger/RenderEngine/Description.h | 9 +-- .../RenderEngine/GLES20RenderEngine.cpp | 50 ++---------- .../RenderEngine/GLES20RenderEngine.h | 9 +-- services/surfaceflinger/RenderEngine/Program.cpp | 8 +- services/surfaceflinger/RenderEngine/Program.h | 3 - .../surfaceflinger/RenderEngine/ProgramCache.cpp | 25 +++--- .../surfaceflinger/RenderEngine/ProgramCache.h | 10 +-- .../surfaceflinger/RenderEngine/RenderEngine.h | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 18 +++-- services/surfaceflinger/SurfaceFlinger.h | 4 +- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 25 +++--- services/surfaceflinger/SurfaceInterceptor.cpp | 2 +- .../tests/SurfaceFlinger_test.filter | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 94 ++++++++++++++++++++++ 31 files changed, 381 insertions(+), 296 deletions(-) create mode 100644 services/surfaceflinger/ColorLayer.cpp create mode 100644 services/surfaceflinger/ColorLayer.h delete mode 100644 services/surfaceflinger/LayerDim.cpp delete mode 100644 services/surfaceflinger/LayerDim.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp index 57ddde075a..d3dc16d30e 100644 --- a/libs/gui/LayerDebugInfo.cpp +++ b/libs/gui/LayerDebugInfo.cpp @@ -43,7 +43,10 @@ status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const { RETURN_ON_ERROR(parcel->writeInt32(mHeight)); RETURN_ON_ERROR(parcel->write(mCrop)); RETURN_ON_ERROR(parcel->write(mFinalCrop)); - RETURN_ON_ERROR(parcel->writeFloat(mAlpha)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.r)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.g)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.b)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.a)); RETURN_ON_ERROR(parcel->writeUint32(mFlags)); RETURN_ON_ERROR(parcel->writeInt32(mPixelFormat)); RETURN_ON_ERROR(parcel->writeUint32(static_cast(mDataSpace))); @@ -79,7 +82,14 @@ status_t LayerDebugInfo::readFromParcel(const Parcel* parcel) { RETURN_ON_ERROR(parcel->readInt32(&mHeight)); RETURN_ON_ERROR(parcel->read(mCrop)); RETURN_ON_ERROR(parcel->read(mFinalCrop)); - RETURN_ON_ERROR(parcel->readFloat(&mAlpha)); + mColor.r = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); + mColor.g = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); + mColor.b = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); + mColor.a = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); RETURN_ON_ERROR(parcel->readUint32(&mFlags)); RETURN_ON_ERROR(parcel->readInt32(&mPixelFormat)); // \todo [2017-07-25 kraita]: Static casting mDataSpace pointer to an uint32 does work. Better ways? @@ -116,8 +126,10 @@ std::string to_string(const LayerDebugInfo& info) { result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty); result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str()); result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str()); - result.appendFormat("alpha=%.3f, flags=0x%08x, ", - static_cast(info.mAlpha), info.mFlags); + result.appendFormat("color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", + static_cast(info.mColor.r), static_cast(info.mColor.g), + static_cast(info.mColor.b), static_cast(info.mColor.a), + info.mFlags); result.appendFormat("tr=[%.2f, %.2f][%.2f, %.2f]", static_cast(info.mMatrix[0][0]), static_cast(info.mMatrix[0][1]), static_cast(info.mMatrix[1][0]), static_cast(info.mMatrix[1][1])); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 3418a4983e..fcee73f445 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -46,6 +46,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(IInterface::asBinder(barrierGbp)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); + output.writeFloat(color.r); + output.writeFloat(color.g); + output.writeFloat(color.b); output.write(transparentRegion); return NO_ERROR; } @@ -79,6 +82,9 @@ status_t layer_state_t::read(const Parcel& input) interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); + color.r = input.readFloat(); + color.g = input.readFloat(); + color.b = input.readFloat(); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index be7b1d2f6a..c5a4389ae8 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -158,6 +158,8 @@ public: const Region& transparentRegion); status_t setAlpha(const sp& client, const sp& id, float alpha); + status_t setColor(const sp& client, const sp& id, + const half3& color); status_t setMatrix(const sp& client, const sp& id, float dsdx, float dtdx, float dtdy, float dsdy); status_t setOrientation(int orientation); @@ -402,6 +404,17 @@ status_t Composer::setAlpha(const sp& client, return NO_ERROR; } +status_t Composer::setColor(const sp& client, + const sp& id, const half3& color) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eColorChanged; + s->color = color; + return NO_ERROR; +} + status_t Composer::setLayerStack(const sp& client, const sp& id, uint32_t layerStack) { Mutex::Autolock _l(mLock); @@ -822,6 +835,10 @@ status_t SurfaceComposerClient::setAlpha(const sp& id, float alpha) { return getComposer().setAlpha(this, id, alpha); } +status_t SurfaceComposerClient::setColor(const sp& id, const half3& color) { + return getComposer().setColor(this, id, color); +} + status_t SurfaceComposerClient::setLayerStack(const sp& id, uint32_t layerStack) { return getComposer().setLayerStack(this, id, layerStack); } diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index d801d12738..9e1d7b6647 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -155,6 +155,11 @@ status_t SurfaceControl::setAlpha(float alpha) { if (err < 0) return err; return mClient->setAlpha(mHandle, alpha); } +status_t SurfaceControl::setColor(const half3& color) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setColor(mHandle, color); +} status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) { status_t err = validate(); if (err < 0) return err; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 2c613ea8c5..d5bbef25f8 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -41,7 +41,7 @@ public: eCursorWindow = 0x00002000, eFXSurfaceNormal = 0x00000000, - eFXSurfaceDim = 0x00020000, + eFXSurfaceColor = 0x00020000, eFXSurfaceMask = 0x000F0000, }; diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h index 8453e043ef..92bd8c5b28 100644 --- a/libs/gui/include/gui/LayerDebugInfo.h +++ b/libs/gui/include/gui/LayerDebugInfo.h @@ -22,6 +22,7 @@ #include #include +#include namespace android { @@ -52,7 +53,7 @@ public: int32_t mHeight = -1; Rect mCrop = Rect::INVALID_RECT; Rect mFinalCrop = Rect::INVALID_RECT; - float mAlpha = 0.f; + half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf); uint32_t mFlags = 0; PixelFormat mPixelFormat = PIXEL_FORMAT_NONE; android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index cf2ff5b96e..17181430c7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -32,6 +32,7 @@ #include #include +#include namespace android { @@ -149,6 +150,7 @@ public: status_t setRelativeLayer(const sp& id, const sp& relativeTo, int32_t layer); status_t setAlpha(const sp& id, float alpha=1.0f); + status_t setColor(const sp& id, const half3& color); status_t setMatrix(const sp& id, float dsdx, float dtdx, float dtdy, float dsdy); status_t setPosition(const sp& id, float x, float y); status_t setSize(const sp& id, uint32_t w, uint32_t h); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index b506e00672..e98e26a391 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -29,6 +29,7 @@ #include #include +#include namespace android { @@ -90,6 +91,7 @@ public: status_t setFlags(uint32_t flags, uint32_t mask); status_t setTransparentRegionHint(const Region& transparent); status_t setAlpha(float alpha=1.0f); + status_t setColor(const half3& color); // Experimentarily it appears that the matrix transforms the // on-screen rectangle and it's contents before the position is diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h index 4ff2e5e0d6..bd42634730 100644 --- a/libs/gui/include/private/gui/LayerState.h +++ b/libs/gui/include/private/gui/LayerState.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace android { @@ -60,7 +61,8 @@ struct layer_state_t { eReparentChildren = 0x00002000, eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, - eReparent = 0x00010000 + eReparent = 0x00010000, + eColorChanged = 0x00020000 }; layer_state_t() @@ -110,6 +112,8 @@ struct layer_state_t { sp parentHandleForChild; + half3 color; + // non POD must be last. see write/read Region transparentRegion; }; diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 38529b6d0a..1f4427a11a 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -14,7 +14,7 @@ LOCAL_SRC_FILES := \ FrameTracker.cpp \ GpuService.cpp \ Layer.cpp \ - LayerDim.cpp \ + ColorLayer.cpp \ LayerRejecter.cpp \ LayerVector.cpp \ MessageQueue.cpp \ diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp new file mode 100644 index 0000000000..6923782b27 --- /dev/null +++ b/services/surfaceflinger/ColorLayer.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "ColorLayer" + +#include +#include +#include + +#include +#include + +#include + +#include "ColorLayer.h" +#include "SurfaceFlinger.h" +#include "DisplayDevice.h" +#include "RenderEngine/RenderEngine.h" + +namespace android { +// --------------------------------------------------------------------------- + +ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags) { +} + +void ColorLayer::onDraw(const sp& hw, + const Region& /* clip */, bool useIdentityTransform) const +{ + const State& s(getDrawingState()); + if (s.color.a>0) { + Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); + computeGeometry(hw, mesh, useIdentityTransform); + RenderEngine& engine(mFlinger->getRenderEngine()); + engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, + true /* disableTexture */, s.color); + engine.drawMesh(mesh); + engine.disableBlending(); + } +} + +bool ColorLayer::isVisible() const { + const Layer::State& s(getDrawingState()); + return !isHiddenByPolicy() && s.color.a; +} + + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h new file mode 100644 index 0000000000..ac3e2a95dc --- /dev/null +++ b/services/surfaceflinger/ColorLayer.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_COLOR_LAYER_H +#define ANDROID_COLOR_LAYER_H + +#include +#include + +#include "Layer.h" + +// --------------------------------------------------------------------------- + +namespace android { + +class ColorLayer : public Layer +{ +public: + ColorLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags); + virtual ~ColorLayer() = default; + + virtual const char* getTypeId() const { return "ColorLayer"; } + virtual void onDraw(const sp& hw, const Region& clip, + bool useIdentityTransform) const; + virtual bool isOpaque(const Layer::State&) const { return false; } + virtual bool isSecure() const { return false; } + virtual bool isFixedSize() const { return true; } + virtual bool isVisible() const; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_COLOR_LAYER_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fd30e1614b..8734ee19fd 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -137,11 +137,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mCurrentState.requestedFinalCrop = mCurrentState.finalCrop; mCurrentState.requestedCrop = mCurrentState.crop; mCurrentState.z = 0; -#ifdef USE_HWC2 - mCurrentState.alpha = 1.0f; -#else - mCurrentState.alpha = 0xFF; -#endif + mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; mCurrentState.flags = layerFlags; mCurrentState.sequence = 0; @@ -334,6 +330,10 @@ const String8& Layer::getName() const { return mName; } +bool Layer::getPremultipledAlpha() const { + return mPremultipliedAlpha; +} + status_t Layer::setBuffers( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { @@ -683,7 +683,7 @@ void Layer::setGeometry( " %s (%d)", mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(), static_cast(error)); #else - if (!isOpaque(s) || getAlpha() != 0xFF) { + if (!isOpaque(s) || getAlpha() != 1.0f) { layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); @@ -757,7 +757,7 @@ void Layer::setGeometry( hwcInfo.sourceCrop = sourceCrop; } - float alpha = getAlpha(); + float alpha = static_cast(getAlpha()); error = hwcLayer->setPlaneAlpha(alpha); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: " "%s (%d)", mName.string(), alpha, to_string(error).c_str(), @@ -787,7 +787,7 @@ void Layer::setGeometry( const Transform& tr(hw->getTransform()); layer.setFrame(tr.transform(frame)); layer.setCrop(computeCrop(hw)); - layer.setPlaneAlpha(getAlpha()); + layer.setPlaneAlpha(static_cast(std::round(255.0f*getAlpha()))); #endif /* @@ -904,8 +904,11 @@ void Layer::setPerFrameData(const sp& displayDevice) { if (mActiveBuffer == nullptr) { setCompositionType(hwcId, HWC2::Composition::SolidColor); - // For now, we only support black for DimLayer - error = hwcLayer->setColor({0, 0, 0, 255}); + half4 color = getColor(); + error = hwcLayer->setColor({static_cast(std::round(255.0f*color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), + 255}); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); @@ -1254,7 +1257,8 @@ void Layer::drawWithOpenGL(const sp& hw, texCoords[3] = vec2(right, 1.0f - top); RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha()); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), + false /* disableTexture */, getColor()); #ifdef USE_HWC2 engine.setSourceDataSpace(mCurrentState.dataSpace); #endif @@ -1877,19 +1881,30 @@ bool Layer::setSize(uint32_t w, uint32_t h) { setTransactionFlags(eTransactionNeeded); return true; } -#ifdef USE_HWC2 bool Layer::setAlpha(float alpha) { -#else -bool Layer::setAlpha(uint8_t alpha) { -#endif - if (mCurrentState.alpha == alpha) + if (mCurrentState.color.a == alpha) return false; mCurrentState.sequence++; - mCurrentState.alpha = alpha; + mCurrentState.color.a = alpha; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } + +bool Layer::setColor(const half3& color) { + if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g + && color.b == mCurrentState.color.b) + return false; + + mCurrentState.sequence++; + mCurrentState.color.r = color.r; + mCurrentState.color.g = color.g; + mCurrentState.color.b = color.b; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { mCurrentState.sequence++; mCurrentState.requested.transform.set( @@ -2141,13 +2156,8 @@ bool Layer::isHiddenByPolicy() const { } bool Layer::isVisible() const { -#ifdef USE_HWC2 return !(isHiddenByPolicy()) && getAlpha() > 0.0f && (mActiveBuffer != NULL || mSidebandStream != NULL); -#else - return !(isHiddenByPolicy()) && getAlpha() - && (mActiveBuffer != NULL || mSidebandStream != NULL); -#endif } bool Layer::allTransactionsSignaled() { @@ -2439,7 +2449,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mHeight = ds.active.h; info.mCrop = ds.crop; info.mFinalCrop = ds.finalCrop; - info.mAlpha = ds.alpha; + info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); info.mDataSpace = getDataSpace(); @@ -2467,7 +2477,6 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mContentDirty = contentDirty; return info; } - #ifdef USE_HWC2 void Layer::miniDumpHeader(String8& result) { result.append("----------------------------------------"); @@ -2791,23 +2800,17 @@ Transform Layer::getTransform() const { return t * getDrawingState().active.transform; } -#ifdef USE_HWC2 -float Layer::getAlpha() const { +half Layer::getAlpha() const { const auto& p = mDrawingParent.promote(); - float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0; - return parentAlpha * getDrawingState().alpha; + half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf; + return parentAlpha * getDrawingState().color.a; } -#else -uint8_t Layer::getAlpha() const { - const auto& p = mDrawingParent.promote(); - float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0; - float drawingAlpha = getDrawingState().alpha / 255.0f; - drawingAlpha = drawingAlpha * parentAlpha; - return static_cast(std::round(drawingAlpha * 255)); +half4 Layer::getColor() const { + const half4 color(getDrawingState().color); + return half4(color.r, color.g, color.b, getAlpha()); } -#endif void Layer::commitChildList() { for (size_t i = 0; i < mCurrentChildren.size(); i++) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e7ece4579e..921492b210 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -51,6 +51,8 @@ #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" +#include + namespace android { // --------------------------------------------------------------------------- @@ -119,11 +121,6 @@ public: // to achieve mirroring. uint32_t layerStack; -#ifdef USE_HWC2 - float alpha; -#else - uint8_t alpha; -#endif uint8_t flags; uint8_t mask; uint8_t reserved[2]; @@ -158,6 +155,8 @@ public: // A list of surfaces whose Z-order is interpreted relative to ours. SortedVector> zOrderRelatives; + + half4 color; }; // ----------------------------------------------------------------------- @@ -225,11 +224,8 @@ public: bool setLayer(int32_t z); bool setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ); -#ifdef USE_HWC2 bool setAlpha(float alpha); -#else - bool setAlpha(uint8_t alpha); -#endif + bool setColor(const half3& color); bool setTransparentRegionHint(const Region& transparent); bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); @@ -509,11 +505,8 @@ public: // Returns the Alpha of the Surface, accounting for the Alpha // of parent Surfaces in the hierarchy (alpha's will be multiplied // down the hierarchy). -#ifdef USE_HWC2 - float getAlpha() const; -#else - uint8_t getAlpha() const; -#endif + half getAlpha() const; + half4 getColor() const; void traverseInReverseZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); @@ -683,9 +676,8 @@ public: sp getProducer() const; const String8& getName() const; void notifyAvailableFrames(); - PixelFormat getPixelFormat() const { return mFormat; } - + bool getPremultipledAlpha() const; private: // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp deleted file mode 100644 index daebf8abcd..0000000000 --- a/services/surfaceflinger/LayerDim.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// #define LOG_NDEBUG 0 -#undef LOG_TAG -#define LOG_TAG "LayerDim" - -#include -#include -#include - -#include -#include - -#include - -#include "LayerDim.h" -#include "SurfaceFlinger.h" -#include "DisplayDevice.h" -#include "RenderEngine/RenderEngine.h" - -namespace android { -// --------------------------------------------------------------------------- - -LayerDim::LayerDim(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags) { -} - -LayerDim::~LayerDim() { -} - -void LayerDim::onDraw(const sp& hw, - const Region& /* clip */, bool useIdentityTransform) const -{ - const State& s(getDrawingState()); - if (s.alpha>0) { - Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); - computeGeometry(hw, mesh, useIdentityTransform); - RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupDimLayerBlending(s.alpha); - engine.drawMesh(mesh); - engine.disableBlending(); - } -} - -bool LayerDim::isVisible() const { - const Layer::State& s(getDrawingState()); - return !isHiddenByPolicy() && s.alpha; -} - - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h deleted file mode 100644 index a0cfca98cf..0000000000 --- a/services/surfaceflinger/LayerDim.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_DIM_H -#define ANDROID_LAYER_DIM_H - -#include -#include - -#include "Layer.h" - -// --------------------------------------------------------------------------- - -namespace android { - -class LayerDim : public Layer -{ -public: - LayerDim(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags); - virtual ~LayerDim(); - - virtual const char* getTypeId() const { return "LayerDim"; } - virtual void onDraw(const sp& hw, const Region& clip, - bool useIdentityTransform) const; - virtual bool isOpaque(const Layer::State&) const { return false; } - virtual bool isSecure() const { return false; } - virtual bool isFixedSize() const { return true; } - virtual bool isVisible() const; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_DIM_H diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index effd3191c8..706960cafe 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -27,22 +27,15 @@ namespace android { Description::Description() { - mPlaneAlpha = 1.0f; mPremultipliedAlpha = false; mOpaque = true; mTextureEnabled = false; mColorMatrixEnabled = false; - - memset(mColor, 0, sizeof(mColor)); } Description::~Description() { } -void Description::setPlaneAlpha(GLclampf planeAlpha) { - mPlaneAlpha = planeAlpha; -} - void Description::setPremultipliedAlpha(bool premultipliedAlpha) { mPremultipliedAlpha = premultipliedAlpha; } @@ -60,11 +53,8 @@ void Description::disableTexture() { mTextureEnabled = false; } -void Description::setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - mColor[0] = red; - mColor[1] = green; - mColor[2] = blue; - mColor[3] = alpha; +void Description::setColor(const half4& color) { + mColor = color; } void Description::setProjectionMatrix(const mat4& mtx) { diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 3beffdf9e1..cbac855ff3 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -35,8 +35,6 @@ class Description { friend class Program; friend class ProgramCache; - // value of the plane-alpha, between 0 and 1 - GLclampf mPlaneAlpha; // whether textures are premultiplied bool mPremultipliedAlpha; // whether this layer is marked as opaque @@ -46,8 +44,8 @@ class Description { Texture mTexture; bool mTextureEnabled; - // color used when texturing is disabled - GLclampf mColor[4]; + // color used when texturing is disabled or when setting alpha. + half4 mColor; // projection matrix mat4 mProjectionMatrix; @@ -60,12 +58,11 @@ public: Description(); ~Description(); - void setPlaneAlpha(GLclampf planeAlpha); void setPremultipliedAlpha(bool premultipliedAlpha); void setOpaque(bool opaque); void setTexture(const Texture& texture); void disableTexture(); - void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void setColor(const half4& color); void setProjectionMatrix(const mat4& mtx); void setColorMatrix(const mat4& mtx); const mat4& getColorMatrix() const; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 37a530b33a..daaa11e1d3 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -204,25 +204,17 @@ void GLES20RenderEngine::setViewportAndProjection( mVpHeight = vph; } -#ifdef USE_HWC2 void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, - bool opaque, float alpha) { -#else -void GLES20RenderEngine::setupLayerBlending( - bool premultipliedAlpha, bool opaque, int alpha) { -#endif - + bool opaque, bool disableTexture, const half4& color) { mState.setPremultipliedAlpha(premultipliedAlpha); mState.setOpaque(opaque); -#ifdef USE_HWC2 - mState.setPlaneAlpha(alpha); + mState.setColor(color); - if (alpha < 1.0f || !opaque) { -#else - mState.setPlaneAlpha(alpha / 255.0f); + if (disableTexture) { + mState.disableTexture(); + } - if (alpha < 0xFF || !opaque) { -#endif + if (color.a < 1.0f || !opaque) { glEnable(GL_BLEND); glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -230,33 +222,6 @@ void GLES20RenderEngine::setupLayerBlending( } } -#ifdef USE_HWC2 -void GLES20RenderEngine::setupDimLayerBlending(float alpha) { -#else -void GLES20RenderEngine::setupDimLayerBlending(int alpha) { -#endif - mState.setPlaneAlpha(1.0f); - mState.setPremultipliedAlpha(true); - mState.setOpaque(false); -#ifdef USE_HWC2 - mState.setColor(0, 0, 0, alpha); -#else - mState.setColor(0, 0, 0, alpha/255.0f); -#endif - mState.disableTexture(); - -#ifdef USE_HWC2 - if (alpha == 1.0f) { -#else - if (alpha == 0xFF) { -#endif - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } -} - #ifdef USE_HWC2 void GLES20RenderEngine::setColorMode(android_color_mode mode) { ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode); @@ -355,10 +320,9 @@ void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { } void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { - mState.setPlaneAlpha(1.0f); mState.setPremultipliedAlpha(true); mState.setOpaque(false); - mState.setColor(r, g, b, a); + mState.setColor(half4(r, g, b, a)); mState.disableTexture(); glDisable(GL_BLEND); } diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index eaf94af54c..5ac12fc3d6 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -68,10 +68,9 @@ protected: virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation); -#ifdef USE_HWC2 virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, - float alpha) override; - virtual void setupDimLayerBlending(float alpha) override; + bool disableTexture, const half4& color) override; +#ifdef USE_HWC2 // Color management related functions and state void setColorMode(android_color_mode mode); @@ -92,10 +91,6 @@ protected: // Currently only supporting sRGB and DisplayP3 color spaces mat4 mSrgbToDisplayP3; -#else - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, - int alpha); - virtual void setupDimLayerBlending(int alpha); #endif bool mPlatformHasWideColor = false; diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index 48a8da5e8e..e95a6c573b 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -22,6 +22,7 @@ #include "Program.h" #include "ProgramCache.h" #include "Description.h" +#include namespace android { @@ -63,7 +64,6 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); mSamplerLoc = glGetUniformLocation(programId, "sampler"); mColorLoc = glGetUniformLocation(programId, "color"); - mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane"); // set-up the default values for our uniforms glUseProgram(programId); @@ -132,11 +132,9 @@ void Program::setUniforms(const Description& desc) { glUniform1i(mSamplerLoc, 0); glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray()); } - if (mAlphaPlaneLoc >= 0) { - glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha); - } if (mColorLoc >= 0) { - glUniform4fv(mColorLoc, 1, desc.mColor); + const float* color = &static_cast const &>(desc.mColor)[0]; + glUniform4fv(mColorLoc, 1, color); } if (mColorMatrixLoc >= 0) { glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray()); diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h index 36bd120e39..a2ae2ee007 100644 --- a/services/surfaceflinger/RenderEngine/Program.h +++ b/services/surfaceflinger/RenderEngine/Program.h @@ -79,9 +79,6 @@ private: /* location of the sampler uniform */ GLint mSamplerLoc; - /* location of the alpha plane uniform */ - GLint mAlphaPlaneLoc; - /* location of the color uniform */ GLint mColorLoc; }; diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index 06b225299c..b4375454cc 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -89,7 +89,7 @@ ProgramCache::~ProgramCache() { void ProgramCache::primeCache() { uint32_t shaderCount = 0; uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | - Key::PLANE_ALPHA_MASK | Key::TEXTURE_MASK; + Key::ALPHA_MASK | Key::TEXTURE_MASK; // Prime the cache for all combinations of the above masks, // leaving off the experimental color matrix mask options. @@ -122,8 +122,8 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) { description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_EXT : description.mTexture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_2D : Key::TEXTURE_OFF) - .set(Key::PLANE_ALPHA_MASK, - (description.mPlaneAlpha < 1) ? Key::PLANE_ALPHA_LT_ONE : Key::PLANE_ALPHA_EQ_ONE) + .set(Key::ALPHA_MASK, + (description.mColor.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE) .set(Key::BLEND_MASK, description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL) .set(Key::OPACITY_MASK, @@ -168,12 +168,12 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } else if (needs.getTextureTarget() == Key::TEXTURE_2D) { fs << "uniform sampler2D sampler;" << "varying vec2 outTexCoords;"; - } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) { - fs << "uniform vec4 color;"; } - if (needs.hasPlaneAlpha()) { - fs << "uniform float alphaPlane;"; + + if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) { + fs << "uniform vec4 color;"; } + if (needs.hasColorMatrix()) { fs << "uniform mat4 colorMatrix;"; } @@ -225,18 +225,19 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { if (needs.isTexturing()) { fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; } else { - fs << "gl_FragColor = color;"; + fs << "gl_FragColor.rgb = color.rgb;"; + fs << "gl_FragColor.a = 1.0;"; } if (needs.isOpaque()) { fs << "gl_FragColor.a = 1.0;"; } - if (needs.hasPlaneAlpha()) { - // modulate the alpha value with planeAlpha + if (needs.hasAlpha()) { + // modulate the current alpha value with alpha set if (needs.isPremultiplied()) { // ... and the color too if we're premultiplied - fs << "gl_FragColor *= alphaPlane;"; + fs << "gl_FragColor *= color.a;"; } else { - fs << "gl_FragColor.a *= alphaPlane;"; + fs << "gl_FragColor.a *= color.a;"; } } diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h index 5b0fbcd153..ff5cf0f21a 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.h +++ b/services/surfaceflinger/RenderEngine/ProgramCache.h @@ -57,9 +57,9 @@ public: OPACITY_TRANSLUCENT = 0x00000000, OPACITY_MASK = 0x00000002, - PLANE_ALPHA_LT_ONE = 0x00000004, - PLANE_ALPHA_EQ_ONE = 0x00000000, - PLANE_ALPHA_MASK = 0x00000004, + ALPHA_LT_ONE = 0x00000004, + ALPHA_EQ_ONE = 0x00000000, + ALPHA_MASK = 0x00000004, TEXTURE_OFF = 0x00000000, TEXTURE_EXT = 0x00000008, @@ -95,8 +95,8 @@ public: inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } - inline bool hasPlaneAlpha() const { - return (mKey & PLANE_ALPHA_MASK) == PLANE_ALPHA_LT_ONE; + inline bool hasAlpha() const { + return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 954457946e..fa65979edd 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -25,6 +25,7 @@ #include #include #include +#include #define EGL_NO_CONFIG ((EGLConfig)0) @@ -98,16 +99,13 @@ public: virtual void checkErrors() const; virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0; + virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, + bool disableTexture, const half4& color) = 0; #ifdef USE_HWC2 - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0; - virtual void setupDimLayerBlending(float alpha) = 0; virtual void setColorMode(android_color_mode mode) = 0; virtual void setSourceDataSpace(android_dataspace source) = 0; virtual void setWideColor(bool hasWideColor) = 0; virtual bool usesWideColor() = 0; -#else - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0; - virtual void setupDimLayerBlending(int alpha) = 0; #endif virtual void setupLayerTexturing(const Texture& texture) = 0; virtual void setupLayerBlackedOut() = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e21379cd70..a7e7008b20 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -73,7 +73,7 @@ #include "EventThread.h" #include "Layer.h" #include "LayerVector.h" -#include "LayerDim.h" +#include "ColorLayer.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" @@ -2725,7 +2725,7 @@ bool SurfaceFlinger::doComposeSurfaces( case HWC2::Composition::SolidColor: { const Layer::State& state(layer->getDrawingState()); if (layer->getClearClientTarget(hwcId) && !firstLayer && - layer->isOpaque(state) && (state.alpha == 1.0f) + layer->isOpaque(state) && (state.color.a == 1.0f) && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared @@ -3065,6 +3065,10 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (layer->setAlpha(s.alpha)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorChanged) { + if (layer->setColor(s.color)) + flags |= eTraversalNeeded; + } if (what & layer_state_t::eMatrixChanged) { if (layer->setMatrix(s.matrix)) flags |= eTraversalNeeded; @@ -3168,8 +3172,8 @@ status_t SurfaceFlinger::createLayer( uniqueName, w, h, flags, format, handle, gbp, &layer); break; - case ISurfaceComposerClient::eFXSurfaceDim: - result = createDimLayer(client, + case ISurfaceComposerClient::eFXSurfaceColor: + result = createColorLayer(client, uniqueName, w, h, flags, handle, gbp, &layer); break; @@ -3251,11 +3255,11 @@ status_t SurfaceFlinger::createNormalLayer(const sp& client, return err; } -status_t SurfaceFlinger::createDimLayer(const sp& client, +status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* gbp, sp* outLayer) { - *outLayer = new LayerDim(this, client, name, w, h, flags); + *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); return NO_ERROR; @@ -4594,7 +4598,7 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", layer->isVisible() ? '+' : '-', i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, state.alpha); + layer->isVisible(), state.flags, static_cast(state.color.a)); i++; }); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1b77aafc58..e87d35f912 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -84,7 +84,7 @@ class Client; class DisplayEventConnection; class EventThread; class Layer; -class LayerDim; +class ColorLayer; class Surface; class RenderEngine; class EventControlThread; @@ -410,7 +410,7 @@ private: sp* outHandle, sp* outGbp, sp* outLayer); - status_t createDimLayer(const sp& client, const String8& name, + status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* outHandle, sp* outGbp, sp* outLayer); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index b1c8c0ab69..b0021383ff 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -71,7 +71,7 @@ #include "EventThread.h" #include "Layer.h" #include "LayerVector.h" -#include "LayerDim.h" +#include "ColorLayer.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" @@ -2024,7 +2024,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa // compute the opaque region const int32_t layerOrientation = tr.getOrientation(); - if (s.alpha==255 && !translucent && + if (layer->getAlpha()==1.0f && !translucent && ((layerOrientation & Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; @@ -2297,7 +2297,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const const Layer::State& state(layer->getDrawingState()); if ((cur->getHints() & HWC_HINT_CLEAR_FB) && i - && layer->isOpaque(state) && (state.alpha == 0xFF) + && layer->isOpaque(state) && (state.color.a == 1.0f) && hasGlesComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared @@ -2622,9 +2622,14 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eAlphaChanged) { - if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) + if (layer->setAlpha(s.alpha)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorChanged) { + if (layer->setColor(s.color)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eMatrixChanged) { if (layer->setMatrix(s.matrix)) flags |= eTraversalNeeded; @@ -2728,8 +2733,8 @@ status_t SurfaceFlinger::createLayer( uniqueName, w, h, flags, format, handle, gbp, &layer); break; - case ISurfaceComposerClient::eFXSurfaceDim: - result = createDimLayer(client, + case ISurfaceComposerClient::eFXSurfaceColor: + result = createColorLayer(client, uniqueName, w, h, flags, handle, gbp, &layer); break; @@ -2804,11 +2809,11 @@ status_t SurfaceFlinger::createNormalLayer(const sp& client, return err; } -status_t SurfaceFlinger::createDimLayer(const sp& client, +status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* gbp, sp* outLayer) { - *outLayer = new LayerDim(this, client, name, w, h, flags); + *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); return NO_ERROR; @@ -4089,10 +4094,10 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ && state.z <= maxLayerZ) { layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x", + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", layer->isVisible() ? '+' : '-', i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, state.alpha); + layer->isVisible(), state.flags, static_cast(state.color.a)); i++; }); } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index db489b2456..eeb492978c 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -98,7 +98,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), layer->mCurrentState.active.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); - addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha); + addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a); addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); addCropLocked(transaction, layerId, layer->mCurrentState.crop); diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 6be708ad1c..5c188dc8a5 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*" + "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:LayerColorTest.*" } } \ No newline at end of file diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 21194926da..8900a4d258 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -28,6 +28,7 @@ #include #include +#include namespace android { @@ -1276,4 +1277,97 @@ TEST_F(ChildLayerTest, NestedChildren) { } } +class LayerColorTest : public LayerUpdateTest { + protected: + void SetUp() override { + LayerUpdateTest::SetUp(); + + mLayerColorControl = mComposerClient->createSurface( + String8("Layer color surface"), + 128, 128, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor); + + ASSERT_TRUE(mLayerColorControl != NULL); + ASSERT_TRUE(mLayerColorControl->isValid()); + + SurfaceComposerClient::openGlobalTransaction(); + ASSERT_EQ(NO_ERROR, mLayerColorControl->setLayer(INT32_MAX-1)); + ASSERT_EQ(NO_ERROR, mLayerColorControl->setPosition(140, 140)); + ASSERT_EQ(NO_ERROR, mLayerColorControl->hide()); + ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide()); + SurfaceComposerClient::closeGlobalTransaction(true); + } + + void TearDown() override { + LayerUpdateTest::TearDown(); + mLayerColorControl = 0; + } + + sp mLayerColorControl; +}; + +TEST_F(LayerColorTest, ColorLayerNoAlpha) { + sp sc; + + { + SCOPED_TRACE("before setColor"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(145, 145); + } + + + SurfaceComposerClient::openGlobalTransaction(); + half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); + mLayerColorControl->setColor(color); + mLayerColorControl->show(); + SurfaceComposerClient::closeGlobalTransaction(true); + { + // There should now be a color + SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel(145, 145, 43, 207, 131); + } +} + +TEST_F(LayerColorTest, ColorLayerWithAlpha) { + sp sc; + { + SCOPED_TRACE("before setColor"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(145, 145); + } + + SurfaceComposerClient::openGlobalTransaction(); + half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); + mLayerColorControl->setColor(color); + mLayerColorControl->setAlpha(.75f); + mLayerColorControl->show(); + SurfaceComposerClient::closeGlobalTransaction(true); + { + // There should now be a color with .75 alpha + SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel(145, 145, 48, 171, 147); + } +} + +TEST_F(LayerColorTest, ColorLayerWithNoColor) { + sp sc; + { + SCOPED_TRACE("before setColor"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(145, 145); + } + + SurfaceComposerClient::openGlobalTransaction(); + mLayerColorControl->show(); + SurfaceComposerClient::closeGlobalTransaction(true); + { + // There should now be set to 0,0,0 (black) as default. + SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel(145, 145, 0, 0, 0); + } +} + } -- cgit v1.2.3-59-g8ed1b From 4cdc58f6840d15b4952149d2b345ec1f97d505bc Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 23 Aug 2017 14:22:20 -0700 Subject: SurfaceFlinger Transactions as distinct objects. Essentially a process global singleton for transactions is not so useful once we make surface control public API as process isn't something an app developer is really thinking about. It's also nice that we get to delete two of the plumbing layers. Test: Boots Change-Id: I8864bd7e2f5865e3c0a425cf82f9928211911774 --- cmds/flatland/GLHelper.cpp | 22 +- cmds/surfacereplayer/replayer/Replayer.cpp | 154 +++-- cmds/surfacereplayer/replayer/Replayer.h | 64 +- libs/gui/ISurfaceComposer.cpp | 3 +- libs/gui/LayerState.cpp | 2 +- libs/gui/SurfaceComposerClient.cpp | 694 ++++++--------------- libs/gui/SurfaceControl.cpp | 122 +--- libs/gui/include/gui/LayerState.h | 177 ++++++ libs/gui/include/gui/SurfaceComposerClient.h | 189 ++++-- libs/gui/include/gui/SurfaceControl.h | 89 +-- libs/gui/include/private/gui/LayerState.h | 163 ----- libs/gui/tests/GLTest.cpp | 10 +- libs/gui/tests/Surface_test.cpp | 10 +- opengl/tests/lib/WindowSurface.cpp | 17 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/SurfaceFlinger.h | 4 +- .../tests/SurfaceInterceptor_test.cpp | 144 +++-- services/surfaceflinger/tests/Transaction_test.cpp | 566 +++++++++-------- .../tests/fakehwc/FakeComposerUtils.h | 17 +- .../tests/fakehwc/SFFakeHwc_test.cpp | 352 ++++++----- 20 files changed, 1229 insertions(+), 1573 deletions(-) create mode 100644 libs/gui/include/gui/LayerState.h delete mode 100644 libs/gui/include/private/gui/LayerState.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp index dfc3e581fd..d5b3372f96 100644 --- a/cmds/flatland/GLHelper.cpp +++ b/cmds/flatland/GLHelper.cpp @@ -269,24 +269,10 @@ bool GLHelper::createWindowSurface(uint32_t w, uint32_t h, return false; } - SurfaceComposerClient::openGlobalTransaction(); - err = sc->setLayer(0x7FFFFFFF); - if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err); - return false; - } - err = sc->setMatrix(scale, 0.0f, 0.0f, scale); - if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::setMatrix error: %#x\n", err); - return false; - } - - err = sc->show(); - if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::show error: %#x\n", err); - return false; - } - SurfaceComposerClient::closeGlobalTransaction(); + SurfaceComposerClient::Transaction{}.setLayer(sc, 0x7FFFFFFF) + .setMatrix(sc, scale, 0.0f, 0.0f, scale) + .show(sc) + .apply(); sp anw = sc->getSurface(); EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), NULL); diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 2b5389b8dc..4140f40888 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -24,9 +24,9 @@ #include #include +#include #include #include -#include #include #include @@ -338,27 +338,29 @@ status_t Replayer::dispatchEvent(int index) { status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr& event) { ALOGV("Started Transaction"); - SurfaceComposerClient::openGlobalTransaction(); + SurfaceComposerClient::Transaction liveTransaction; status_t status = NO_ERROR; - status = doSurfaceTransaction(t.surface_change()); - doDisplayTransaction(t.display_change()); + status = doSurfaceTransaction(liveTransaction, t.surface_change()); + doDisplayTransaction(liveTransaction, t.display_change()); if (t.animation()) { - SurfaceComposerClient::setAnimationTransaction(); + liveTransaction.setAnimationTransaction(); } event->readyToExecute(); - SurfaceComposerClient::closeGlobalTransaction(t.synchronous()); + liveTransaction.apply(t.synchronous()); ALOGV("Ended Transaction"); return status; } -status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) { +status_t Replayer::doSurfaceTransaction( + SurfaceComposerClient::Transaction& transaction, + const SurfaceChanges& surfaceChanges) { status_t status = NO_ERROR; for (const SurfaceChange& change : surfaceChanges) { @@ -369,62 +371,66 @@ status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) { switch (change.SurfaceChange_case()) { case SurfaceChange::SurfaceChangeCase::kPosition: - status = setPosition(change.id(), change.position()); + setPosition(transaction, change.id(), change.position()); break; case SurfaceChange::SurfaceChangeCase::kSize: - status = setSize(change.id(), change.size()); + setSize(transaction, change.id(), change.size()); break; case SurfaceChange::SurfaceChangeCase::kAlpha: - status = setAlpha(change.id(), change.alpha()); + setAlpha(transaction, change.id(), change.alpha()); break; case SurfaceChange::SurfaceChangeCase::kLayer: - status = setLayer(change.id(), change.layer()); + setLayer(transaction, change.id(), change.layer()); break; case SurfaceChange::SurfaceChangeCase::kCrop: - status = setCrop(change.id(), change.crop()); + setCrop(transaction, change.id(), change.crop()); break; case SurfaceChange::SurfaceChangeCase::kMatrix: - status = setMatrix(change.id(), change.matrix()); + setMatrix(transaction, change.id(), change.matrix()); break; case SurfaceChange::SurfaceChangeCase::kFinalCrop: - status = setFinalCrop(change.id(), change.final_crop()); + setFinalCrop(transaction, change.id(), change.final_crop()); break; case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode: - status = setOverrideScalingMode(change.id(), change.override_scaling_mode()); + setOverrideScalingMode(transaction, change.id(), + change.override_scaling_mode()); break; case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint: - status = setTransparentRegionHint(change.id(), change.transparent_region_hint()); + setTransparentRegionHint(transaction, change.id(), + change.transparent_region_hint()); break; case SurfaceChange::SurfaceChangeCase::kLayerStack: - status = setLayerStack(change.id(), change.layer_stack()); + setLayerStack(transaction, change.id(), change.layer_stack()); break; case SurfaceChange::SurfaceChangeCase::kHiddenFlag: - status = setHiddenFlag(change.id(), change.hidden_flag()); + setHiddenFlag(transaction, change.id(), change.hidden_flag()); break; case SurfaceChange::SurfaceChangeCase::kOpaqueFlag: - status = setOpaqueFlag(change.id(), change.opaque_flag()); + setOpaqueFlag(transaction, change.id(), change.opaque_flag()); break; case SurfaceChange::SurfaceChangeCase::kSecureFlag: - status = setSecureFlag(change.id(), change.secure_flag()); + setSecureFlag(transaction, change.id(), change.secure_flag()); break; case SurfaceChange::SurfaceChangeCase::kDeferredTransaction: waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock); - status = setDeferredTransaction(change.id(), change.deferred_transaction()); + setDeferredTransaction(transaction, change.id(), + change.deferred_transaction()); break; default: - status = NO_ERROR; + status = 1; break; } if (status != NO_ERROR) { - ALOGE("SET TRANSACTION FAILED"); + ALOGE("Unknown Transaction Code"); return status; } } return status; } -void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) { +void Replayer::doDisplayTransaction(SurfaceComposerClient::Transaction& t, + const DisplayChanges& displayChanges) { for (const DisplayChange& change : displayChanges) { ALOGV("Doing display transaction"); std::unique_lock lock(mDisplayLock); @@ -434,16 +440,16 @@ void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) { switch (change.DisplayChange_case()) { case DisplayChange::DisplayChangeCase::kSurface: - setDisplaySurface(change.id(), change.surface()); + setDisplaySurface(t, change.id(), change.surface()); break; case DisplayChange::DisplayChangeCase::kLayerStack: - setDisplayLayerStack(change.id(), change.layer_stack()); + setDisplayLayerStack(t, change.id(), change.layer_stack()); break; case DisplayChange::DisplayChangeCase::kSize: - setDisplaySize(change.id(), change.size()); + setDisplaySize(t, change.id(), change.size()); break; case DisplayChange::DisplayChangeCase::kProjection: - setDisplayProjection(change.id(), change.projection()); + setDisplayProjection(t, change.id(), change.projection()); break; default: break; @@ -451,57 +457,66 @@ void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) { } } -status_t Replayer::setPosition(layer_id id, const PositionChange& pc) { +void Replayer::setPosition(SurfaceComposerClient::Transaction& t, + layer_id id, const PositionChange& pc) { ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y()); - return mLayers[id]->setPosition(pc.x(), pc.y()); + t.setPosition(mLayers[id], pc.x(), pc.y()); } -status_t Replayer::setSize(layer_id id, const SizeChange& sc) { +void Replayer::setSize(SurfaceComposerClient::Transaction& t, + layer_id id, const SizeChange& sc) { ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h()); - return mLayers[id]->setSize(sc.w(), sc.h()); + t.setSize(mLayers[id], sc.w(), sc.h()); } -status_t Replayer::setLayer(layer_id id, const LayerChange& lc) { +void Replayer::setLayer(SurfaceComposerClient::Transaction& t, + layer_id id, const LayerChange& lc) { ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer()); - return mLayers[id]->setLayer(lc.layer()); + t.setLayer(mLayers[id], lc.layer()); } -status_t Replayer::setAlpha(layer_id id, const AlphaChange& ac) { +void Replayer::setAlpha(SurfaceComposerClient::Transaction& t, + layer_id id, const AlphaChange& ac) { ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha()); - return mLayers[id]->setAlpha(ac.alpha()); + t.setAlpha(mLayers[id], ac.alpha()); } -status_t Replayer::setCrop(layer_id id, const CropChange& cc) { +void Replayer::setCrop(SurfaceComposerClient::Transaction& t, + layer_id id, const CropChange& cc) { ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id, cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(), cc.rectangle().bottom()); Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(), cc.rectangle().bottom()); - return mLayers[id]->setCrop(r); + t.setCrop(mLayers[id], r); } -status_t Replayer::setFinalCrop(layer_id id, const FinalCropChange& fcc) { +void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, + layer_id id, const FinalCropChange& fcc) { ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id, fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), fcc.rectangle().bottom()); Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), fcc.rectangle().bottom()); - return mLayers[id]->setFinalCrop(r); + t.setFinalCrop(mLayers[id], r); } -status_t Replayer::setMatrix(layer_id id, const MatrixChange& mc) { +void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, + layer_id id, const MatrixChange& mc) { ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy()); - return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy()); + t.setMatrix(mLayers[id], mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy()); } -status_t Replayer::setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc) { +void Replayer::setOverrideScalingMode(SurfaceComposerClient::Transaction& t, + layer_id id, const OverrideScalingModeChange& osmc) { ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode()); - return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode()); + t.setOverrideScalingMode(mLayers[id], osmc.override_scaling_mode()); } -status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trhc) { +void Replayer::setTransparentRegionHint(SurfaceComposerClient::Transaction& t, + layer_id id, const TransparentRegionHintChange& trhc) { ALOGV("Setting Transparent Region Hint"); Region re = Region(); @@ -510,71 +525,80 @@ status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegion re.merge(rect); } - return mLayers[id]->setTransparentRegionHint(re); + t.setTransparentRegionHint(mLayers[id], re); } -status_t Replayer::setLayerStack(layer_id id, const LayerStackChange& lsc) { +void Replayer::setLayerStack(SurfaceComposerClient::Transaction& t, + layer_id id, const LayerStackChange& lsc) { ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack()); - return mLayers[id]->setLayerStack(lsc.layer_stack()); + t.setLayerStack(mLayers[id], lsc.layer_stack()); } -status_t Replayer::setHiddenFlag(layer_id id, const HiddenFlagChange& hfc) { +void Replayer::setHiddenFlag(SurfaceComposerClient::Transaction& t, + layer_id id, const HiddenFlagChange& hfc) { ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag()); layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0; - return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden); + t.setFlags(mLayers[id], flag, layer_state_t::eLayerHidden); } -status_t Replayer::setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc) { +void Replayer::setOpaqueFlag(SurfaceComposerClient::Transaction& t, + layer_id id, const OpaqueFlagChange& ofc) { ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag()); layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0; - return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque); + t.setFlags(mLayers[id], flag, layer_state_t::eLayerOpaque); } -status_t Replayer::setSecureFlag(layer_id id, const SecureFlagChange& sfc) { +void Replayer::setSecureFlag(SurfaceComposerClient::Transaction& t, + layer_id id, const SecureFlagChange& sfc) { ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag()); layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0; - return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure); + t.setFlags(mLayers[id], flag, layer_state_t::eLayerSecure); } -status_t Replayer::setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc) { +void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, + layer_id id, const DeferredTransactionChange& dtc) { ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, " "frame_number=%llu", id, dtc.layer_id(), dtc.frame_number()); if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) { ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id()); - return BAD_VALUE; + return; } auto handle = mLayers[dtc.layer_id()]->getHandle(); - return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number()); + t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number()); } -void Replayer::setDisplaySurface(display_id id, const DispSurfaceChange& /*dsc*/) { +void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, + display_id id, const DispSurfaceChange& /*dsc*/) { sp outProducer; sp outConsumer; BufferQueue::createBufferQueue(&outProducer, &outConsumer); - SurfaceComposerClient::setDisplaySurface(mDisplays[id], outProducer); + t.setDisplaySurface(mDisplays[id], outProducer); } -void Replayer::setDisplayLayerStack(display_id id, const LayerStackChange& lsc) { - SurfaceComposerClient::setDisplayLayerStack(mDisplays[id], lsc.layer_stack()); +void Replayer::setDisplayLayerStack(SurfaceComposerClient::Transaction& t, + display_id id, const LayerStackChange& lsc) { + t.setDisplayLayerStack(mDisplays[id], lsc.layer_stack()); } -void Replayer::setDisplaySize(display_id id, const SizeChange& sc) { - SurfaceComposerClient::setDisplaySize(mDisplays[id], sc.w(), sc.h()); +void Replayer::setDisplaySize(SurfaceComposerClient::Transaction& t, + display_id id, const SizeChange& sc) { + t.setDisplaySize(mDisplays[id], sc.w(), sc.h()); } -void Replayer::setDisplayProjection(display_id id, const ProjectionChange& pc) { +void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t, + display_id id, const ProjectionChange& pc) { Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(), pc.viewport().bottom()); Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom()); - SurfaceComposerClient::setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame); + t.setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame); } status_t Replayer::createSurfaceControl( diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index f36c9fd4a4..295403eace 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -77,28 +77,48 @@ class Replayer { void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr& event); void updatePowerMode(const PowerModeUpdate& update, const std::shared_ptr& event); - status_t doSurfaceTransaction(const SurfaceChanges& surfaceChange); - void doDisplayTransaction(const DisplayChanges& displayChange); - - status_t setPosition(layer_id id, const PositionChange& pc); - status_t setSize(layer_id id, const SizeChange& sc); - status_t setAlpha(layer_id id, const AlphaChange& ac); - status_t setLayer(layer_id id, const LayerChange& lc); - status_t setCrop(layer_id id, const CropChange& cc); - status_t setFinalCrop(layer_id id, const FinalCropChange& fcc); - status_t setMatrix(layer_id id, const MatrixChange& mc); - status_t setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc); - status_t setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trgc); - status_t setLayerStack(layer_id id, const LayerStackChange& lsc); - status_t setHiddenFlag(layer_id id, const HiddenFlagChange& hfc); - status_t setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc); - status_t setSecureFlag(layer_id id, const SecureFlagChange& sfc); - status_t setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc); - - void setDisplaySurface(display_id id, const DispSurfaceChange& dsc); - void setDisplayLayerStack(display_id id, const LayerStackChange& lsc); - void setDisplaySize(display_id id, const SizeChange& sc); - void setDisplayProjection(display_id id, const ProjectionChange& pc); + status_t doSurfaceTransaction(SurfaceComposerClient::Transaction& transaction, + const SurfaceChanges& surfaceChange); + void doDisplayTransaction(SurfaceComposerClient::Transaction& transaction, + const DisplayChanges& displayChange); + + void setPosition(SurfaceComposerClient::Transaction& t, + layer_id id, const PositionChange& pc); + void setSize(SurfaceComposerClient::Transaction& t, + layer_id id, const SizeChange& sc); + void setAlpha(SurfaceComposerClient::Transaction& t, + layer_id id, const AlphaChange& ac); + void setLayer(SurfaceComposerClient::Transaction& t, + layer_id id, const LayerChange& lc); + void setCrop(SurfaceComposerClient::Transaction& t, + layer_id id, const CropChange& cc); + void setFinalCrop(SurfaceComposerClient::Transaction& t, + layer_id id, const FinalCropChange& fcc); + void setMatrix(SurfaceComposerClient::Transaction& t, + layer_id id, const MatrixChange& mc); + void setOverrideScalingMode(SurfaceComposerClient::Transaction& t, + layer_id id, const OverrideScalingModeChange& osmc); + void setTransparentRegionHint(SurfaceComposerClient::Transaction& t, + layer_id id, const TransparentRegionHintChange& trgc); + void setLayerStack(SurfaceComposerClient::Transaction& t, + layer_id id, const LayerStackChange& lsc); + void setHiddenFlag(SurfaceComposerClient::Transaction& t, + layer_id id, const HiddenFlagChange& hfc); + void setOpaqueFlag(SurfaceComposerClient::Transaction& t, + layer_id id, const OpaqueFlagChange& ofc); + void setSecureFlag(SurfaceComposerClient::Transaction& t, + layer_id id, const SecureFlagChange& sfc); + void setDeferredTransaction(SurfaceComposerClient::Transaction& t, + layer_id id, const DeferredTransactionChange& dtc); + + void setDisplaySurface(SurfaceComposerClient::Transaction& t, + display_id id, const DispSurfaceChange& dsc); + void setDisplayLayerStack(SurfaceComposerClient::Transaction& t, + display_id id, const LayerStackChange& lsc); + void setDisplaySize(SurfaceComposerClient::Transaction& t, + display_id id, const SizeChange& sc); + void setDisplayProjection(SurfaceComposerClient::Transaction& t, + display_id id, const ProjectionChange& pc); void doDeleteSurfaceControls(); void waitUntilTimestamp(int64_t timestamp); diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 8e7f814313..96771257c1 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -29,8 +29,7 @@ #include #include #include - -#include +#include #include diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index fcee73f445..bfc6f28704 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include namespace android { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c5a4389ae8..40e319e28a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -37,11 +36,11 @@ #include #include #include +#include #include #include #include -#include namespace android { // --------------------------------------------------------------------------- @@ -97,208 +96,71 @@ void ComposerService::composerServiceDied() // --------------------------------------------------------------------------- -static inline -int compare_type(const ComposerState& lhs, const ComposerState& rhs) { - if (lhs.client < rhs.client) return -1; - if (lhs.client > rhs.client) return 1; - if (lhs.state.surface < rhs.state.surface) return -1; - if (lhs.state.surface > rhs.state.surface) return 1; - return 0; +SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : + mForceSynchronous(other.mForceSynchronous), + mTransactionNestCount(other.mTransactionNestCount), + mAnimation(other.mAnimation) { + mDisplayStates = other.mDisplayStates; + mComposerStates = other.mComposerStates; } -static inline -int compare_type(const DisplayState& lhs, const DisplayState& rhs) { - return compare_type(lhs.token, rhs.token); -} - -class Composer : public Singleton -{ - friend class Singleton; - - mutable Mutex mLock; - SortedVector mComposerStates; - SortedVector mDisplayStates; - uint32_t mForceSynchronous; - uint32_t mTransactionNestCount; - bool mAnimation; - - Composer() : Singleton(), - mForceSynchronous(0), mTransactionNestCount(0), - mAnimation(false) - { } - - void openGlobalTransactionImpl(); - void closeGlobalTransactionImpl(bool synchronous); - void setAnimationTransactionImpl(); - status_t enableVSyncInjectionsImpl(bool enable); - status_t injectVSyncImpl(nsecs_t when); - - layer_state_t* getLayerStateLocked( - const sp& client, const sp& id); - - DisplayState& getDisplayStateLocked(const sp& token); - -public: - sp createDisplay(const String8& displayName, bool secure); - void destroyDisplay(const sp& display); - sp getBuiltInDisplay(int32_t id); - - status_t setPosition(const sp& client, const sp& id, - float x, float y); - status_t setSize(const sp& client, const sp& id, - uint32_t w, uint32_t h); - status_t setLayer(const sp& client, const sp& id, - int32_t z); - status_t setRelativeLayer(const sp& client, const sp& id, - const sp& relativeTo, int32_t z); - status_t setFlags(const sp& client, const sp& id, - uint32_t flags, uint32_t mask); - status_t setTransparentRegionHint( - const sp& client, const sp& id, - const Region& transparentRegion); - status_t setAlpha(const sp& client, const sp& id, - float alpha); - status_t setColor(const sp& client, const sp& id, - const half3& color); - status_t setMatrix(const sp& client, const sp& id, - float dsdx, float dtdx, float dtdy, float dsdy); - status_t setOrientation(int orientation); - status_t setCrop(const sp& client, const sp& id, - const Rect& crop); - status_t setFinalCrop(const sp& client, - const sp& id, const Rect& crop); - status_t setLayerStack(const sp& client, - const sp& id, uint32_t layerStack); - status_t deferTransactionUntil(const sp& client, - const sp& id, const sp& handle, - uint64_t frameNumber); - status_t deferTransactionUntil(const sp& client, - const sp& id, const sp& barrierSurface, - uint64_t frameNumber); - status_t reparentChildren(const sp& client, - const sp& id, - const sp& newParentHandle); - status_t reparent(const sp& client, - const sp& id, const sp& newParentHandle); - status_t detachChildren(const sp& client, - const sp& id); - status_t setOverrideScalingMode(const sp& client, - const sp& id, int32_t overrideScalingMode); - status_t setGeometryAppliesWithResize(const sp& client, - const sp& id); - - status_t setDisplaySurface(const sp& token, - sp bufferProducer); - void setDisplayLayerStack(const sp& token, uint32_t layerStack); - void setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect); - void setDisplaySize(const sp& token, uint32_t width, uint32_t height); - - static void setAnimationTransaction() { - Composer::getInstance().setAnimationTransactionImpl(); +status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { + if (mStatus != NO_ERROR) { + return mStatus; } - static void openGlobalTransaction() { - Composer::getInstance().openGlobalTransactionImpl(); - } + sp sf(ComposerService::getComposerService()); - static void closeGlobalTransaction(bool synchronous) { - Composer::getInstance().closeGlobalTransactionImpl(synchronous); - } + Vector composerStates; + Vector displayStates; + uint32_t flags = 0; - static status_t enableVSyncInjections(bool enable) { - return Composer::getInstance().enableVSyncInjectionsImpl(enable); - } + mForceSynchronous |= synchronous; - static status_t injectVSync(nsecs_t when) { - return Composer::getInstance().injectVSyncImpl(when); + composerStates = mComposerStates; + mComposerStates.clear(); + + displayStates = mDisplayStates; + mDisplayStates.clear(); + + if (mForceSynchronous) { + flags |= ISurfaceComposer::eSynchronous; + } + if (mAnimation) { + flags |= ISurfaceComposer::eAnimation; } -}; -ANDROID_SINGLETON_STATIC_INSTANCE(Composer); + mForceSynchronous = false; + mAnimation = false; + + sf->setTransactionState(composerStates, displayStates, flags); + mStatus = NO_ERROR; + return NO_ERROR; +} // --------------------------------------------------------------------------- -sp Composer::createDisplay(const String8& displayName, bool secure) { +sp SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) { return ComposerService::getComposerService()->createDisplay(displayName, secure); } -void Composer::destroyDisplay(const sp& display) { +void SurfaceComposerClient::destroyDisplay(const sp& display) { return ComposerService::getComposerService()->destroyDisplay(display); } -sp Composer::getBuiltInDisplay(int32_t id) { +sp SurfaceComposerClient::getBuiltInDisplay(int32_t id) { return ComposerService::getComposerService()->getBuiltInDisplay(id); } -void Composer::openGlobalTransactionImpl() { - { // scope for the lock - Mutex::Autolock _l(mLock); - mTransactionNestCount += 1; - } -} - -void Composer::closeGlobalTransactionImpl(bool synchronous) { - sp sm(ComposerService::getComposerService()); - - Vector transaction; - Vector displayTransaction; - uint32_t flags = 0; - - { // scope for the lock - Mutex::Autolock _l(mLock); - mForceSynchronous |= synchronous; - if (!mTransactionNestCount) { - ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior " - "call to openGlobalTransaction()."); - } else if (--mTransactionNestCount) { - return; - } - - transaction = mComposerStates; - mComposerStates.clear(); - - displayTransaction = mDisplayStates; - mDisplayStates.clear(); - - if (mForceSynchronous) { - flags |= ISurfaceComposer::eSynchronous; - } - if (mAnimation) { - flags |= ISurfaceComposer::eAnimation; - } - - mForceSynchronous = false; - mAnimation = false; - } - - sm->setTransactionState(transaction, displayTransaction, flags); -} - -status_t Composer::enableVSyncInjectionsImpl(bool enable) { - sp sm(ComposerService::getComposerService()); - return sm->enableVSyncInjections(enable); -} - -status_t Composer::injectVSyncImpl(nsecs_t when) { - sp sm(ComposerService::getComposerService()); - return sm->injectVSync(when); -} - -void Composer::setAnimationTransactionImpl() { - Mutex::Autolock _l(mLock); +void SurfaceComposerClient::Transaction::setAnimationTransaction() { mAnimation = true; } -layer_state_t* Composer::getLayerStateLocked( - const sp& client, const sp& id) { - +layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp& sc) { ComposerState s; - s.client = client->mClient; - s.state.surface = id; + s.client = sc->getClient()->mClient; + s.state.surface = sc->getHandle(); ssize_t index = mComposerStates.indexOf(s); if (index < 0) { @@ -310,24 +172,36 @@ layer_state_t* Composer::getLayerStateLocked( return &(out[index].state); } -status_t Composer::setPosition(const sp& client, - const sp& id, float x, float y) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( + const sp& sc, float x, float y) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::ePositionChanged; s->x = x; s->y = y; - return NO_ERROR; + return *this; } -status_t Composer::setSize(const sp& client, - const sp& id, uint32_t w, uint32_t h) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::show( + const sp& sc) { + return setFlags(sc, 0, layer_state_t::eLayerHidden); +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::hide( + const sp& sc) { + return setFlags(sc, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden); +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( + const sp& sc, uint32_t w, uint32_t h) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eSizeChanged; s->w = w; s->h = h; @@ -335,41 +209,41 @@ status_t Composer::setSize(const sp& client, // Resizing a surface makes the transaction synchronous. mForceSynchronous = true; - return NO_ERROR; + return *this; } -status_t Composer::setLayer(const sp& client, - const sp& id, int32_t z) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer( + const sp& sc, int32_t z) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eLayerChanged; s->z = z; - return NO_ERROR; + return *this; } -status_t Composer::setRelativeLayer(const sp& client, - const sp& id, const sp& relativeTo, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer(const sp& sc, const sp& relativeTo, int32_t z) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; } s->what |= layer_state_t::eRelativeLayerChanged; s->relativeLayerHandle = relativeTo; s->z = z; - return NO_ERROR; + return *this; } -status_t Composer::setFlags(const sp& client, - const sp& id, uint32_t flags, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags( + const sp& sc, uint32_t flags, uint32_t mask) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) || (mask & layer_state_t::eLayerSecure)) { @@ -378,61 +252,54 @@ status_t Composer::setFlags(const sp& client, s->flags &= ~mask; s->flags |= (flags & mask); s->mask |= mask; - return NO_ERROR; + return *this; } -status_t Composer::setTransparentRegionHint( - const sp& client, const sp& id, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransparentRegionHint( + const sp& sc, const Region& transparentRegion) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eTransparentRegionChanged; s->transparentRegion = transparentRegion; - return NO_ERROR; + return *this; } -status_t Composer::setAlpha(const sp& client, - const sp& id, float alpha) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha( + const sp& sc, float alpha) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eAlphaChanged; s->alpha = alpha; - return NO_ERROR; + return *this; } -status_t Composer::setColor(const sp& client, - const sp& id, const half3& color) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= layer_state_t::eColorChanged; - s->color = color; - return NO_ERROR; -} - -status_t Composer::setLayerStack(const sp& client, - const sp& id, uint32_t layerStack) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayerStack( + const sp& sc, uint32_t layerStack) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eLayerStackChanged; s->layerStack = layerStack; - return NO_ERROR; + return *this; } -status_t Composer::setMatrix(const sp& client, - const sp& id, float dsdx, float dtdx, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix( + const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eMatrixChanged; layer_state_t::matrix22_t matrix; matrix.dsdx = dsdx; @@ -440,106 +307,115 @@ status_t Composer::setMatrix(const sp& client, matrix.dsdy = dsdy; matrix.dtdy = dtdy; s->matrix = matrix; - return NO_ERROR; + return *this; } -status_t Composer::setCrop(const sp& client, - const sp& id, const Rect& crop) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( + const sp& sc, const Rect& crop) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } s->what |= layer_state_t::eCropChanged; s->crop = crop; - return NO_ERROR; + return *this; } -status_t Composer::setFinalCrop(const sp& client, - const sp& id, const Rect& crop) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp& sc, const Rect& crop) { + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eFinalCropChanged; s->finalCrop = crop; - return NO_ERROR; + return *this; } -status_t Composer::deferTransactionUntil( - const sp& client, const sp& id, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( + const sp& sc, const sp& handle, uint64_t frameNumber) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eDeferTransaction; s->barrierHandle = handle; s->frameNumber = frameNumber; - return NO_ERROR; + return *this; } -status_t Composer::deferTransactionUntil( - const sp& client, const sp& id, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( + const sp& sc, const sp& barrierSurface, uint64_t frameNumber) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eDeferTransaction; s->barrierGbp = barrierSurface->getIGraphicBufferProducer(); s->frameNumber = frameNumber; - return NO_ERROR; + return *this; } -status_t Composer::reparentChildren( - const sp& client, - const sp& id, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren( + const sp& sc, const sp& newParentHandle) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eReparentChildren; s->reparentHandle = newParentHandle; - return NO_ERROR; + return *this; } -status_t Composer::reparent(const sp& client, - const sp& id, +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent( + const sp& sc, const sp& newParentHandle) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eReparent; s->parentHandleForChild = newParentHandle; - return NO_ERROR; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor( + const sp& sc, + const half3& color) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eColorChanged; + s->color = color; + return *this; } -status_t Composer::detachChildren( - const sp& client, - const sp& id) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( + const sp& sc) { + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; } s->what |= layer_state_t::eDetachChildren; - return NO_ERROR; + return *this; } -status_t Composer::setOverrideScalingMode( - const sp& client, - const sp& id, int32_t overrideScalingMode) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverrideScalingMode( + const sp& sc, int32_t overrideScalingMode) { + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } switch (overrideScalingMode) { @@ -552,29 +428,29 @@ status_t Composer::setOverrideScalingMode( default: ALOGE("unknown scaling mode: %d", overrideScalingMode); - return BAD_VALUE; + mStatus = BAD_VALUE; + return *this; } s->what |= layer_state_t::eOverrideScalingModeChanged; s->overrideScalingMode = overrideScalingMode; - return NO_ERROR; + return *this; } -status_t Composer::setGeometryAppliesWithResize( - const sp& client, - const sp& id) { - Mutex::Autolock lock(mLock); - layer_state_t* s = getLayerStateLocked(client, id); +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize( + const sp& sc) { + layer_state_t* s = getLayerStateLocked(sc); if (!s) { - return BAD_INDEX; + mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eGeometryAppliesWithResize; - return NO_ERROR; + return *this; } // --------------------------------------------------------------------------- -DisplayState& Composer::getDisplayStateLocked(const sp& token) { +DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp& token) { DisplayState s; s.token = token; ssize_t index = mDisplayStates.indexOf(s); @@ -586,8 +462,8 @@ DisplayState& Composer::getDisplayStateLocked(const sp& token) { return mDisplayStates.editItemAt(static_cast(index)); } -status_t Composer::setDisplaySurface(const sp& token, - sp bufferProducer) { +status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp& token, + const sp& bufferProducer) { if (bufferProducer.get() != nullptr) { // Make sure that composition can never be stalled by a virtual display // consumer that isn't processing buffers fast enough. @@ -599,26 +475,23 @@ status_t Composer::setDisplaySurface(const sp& token, return err; } } - Mutex::Autolock _l(mLock); DisplayState& s(getDisplayStateLocked(token)); s.surface = bufferProducer; s.what |= DisplayState::eSurfaceChanged; return NO_ERROR; } -void Composer::setDisplayLayerStack(const sp& token, +void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp& token, uint32_t layerStack) { - Mutex::Autolock _l(mLock); DisplayState& s(getDisplayStateLocked(token)); s.layerStack = layerStack; s.what |= DisplayState::eLayerStackChanged; } -void Composer::setDisplayProjection(const sp& token, +void SurfaceComposerClient::Transaction::setDisplayProjection(const sp& token, uint32_t orientation, const Rect& layerStackRect, const Rect& displayRect) { - Mutex::Autolock _l(mLock); DisplayState& s(getDisplayStateLocked(token)); s.orientation = orientation; s.viewport = layerStackRect; @@ -627,8 +500,7 @@ void Composer::setDisplayProjection(const sp& token, mForceSynchronous = true; // TODO: do we actually still need this? } -void Composer::setDisplaySize(const sp& token, uint32_t width, uint32_t height) { - Mutex::Autolock _l(mLock); +void SurfaceComposerClient::Transaction::setDisplaySize(const sp& token, uint32_t width, uint32_t height) { DisplayState& s(getDisplayStateLocked(token)); s.width = width; s.height = height; @@ -638,22 +510,22 @@ void Composer::setDisplaySize(const sp& token, uint32_t width, uint32_t // --------------------------------------------------------------------------- SurfaceComposerClient::SurfaceComposerClient() - : mStatus(NO_INIT), mComposer(Composer::getInstance()) + : mStatus(NO_INIT) { } SurfaceComposerClient::SurfaceComposerClient(const sp& root) - : mStatus(NO_INIT), mComposer(Composer::getInstance()), mParent(root) + : mStatus(NO_INIT), mParent(root) { } void SurfaceComposerClient::onFirstRef() { - sp sm(ComposerService::getComposerService()); - if (sm != 0) { + sp sf(ComposerService::getComposerService()); + if (sf != 0) { auto rootProducer = mParent.promote(); sp conn; - conn = (rootProducer != nullptr) ? sm->createScopedConnection(rootProducer) : - sm->createConnection(); + conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) : + sf->createConnection(); if (conn != 0) { mClient = conn; mStatus = NO_ERROR; @@ -676,8 +548,8 @@ sp SurfaceComposerClient::connection() const { status_t SurfaceComposerClient::linkToComposerDeath( const sp& recipient, void* cookie, uint32_t flags) { - sp sm(ComposerService::getComposerService()); - return IInterface::asBinder(sm)->linkToDeath(recipient, cookie, flags); + sp sf(ComposerService::getComposerService()); + return IInterface::asBinder(sf)->linkToDeath(recipient, cookie, flags); } void SurfaceComposerClient::dispose() { @@ -720,19 +592,6 @@ sp SurfaceComposerClient::createSurface( return sur; } -sp SurfaceComposerClient::createDisplay(const String8& displayName, - bool secure) { - return Composer::getInstance().createDisplay(displayName, secure); -} - -void SurfaceComposerClient::destroyDisplay(const sp& display) { - Composer::getInstance().destroyDisplay(display); -} - -sp SurfaceComposerClient::getBuiltInDisplay(int32_t id) { - return Composer::getInstance().getBuiltInDisplay(id); -} - status_t SurfaceComposerClient::destroySurface(const sp& sid) { if (mStatus != NO_ERROR) return mStatus; @@ -755,161 +614,18 @@ status_t SurfaceComposerClient::getLayerFrameStats(const sp& token, return mClient->getLayerFrameStats(token, outStats); } -inline Composer& SurfaceComposerClient::getComposer() { - return mComposer; -} - // ---------------------------------------------------------------------------- -void SurfaceComposerClient::openGlobalTransaction() { - Composer::openGlobalTransaction(); -} - -void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) { - Composer::closeGlobalTransaction(synchronous); -} - -void SurfaceComposerClient::setAnimationTransaction() { - Composer::setAnimationTransaction(); -} - status_t SurfaceComposerClient::enableVSyncInjections(bool enable) { - return Composer::enableVSyncInjections(enable); + sp sf(ComposerService::getComposerService()); + return sf->enableVSyncInjections(enable); } status_t SurfaceComposerClient::injectVSync(nsecs_t when) { - return Composer::injectVSync(when); -} - -// ---------------------------------------------------------------------------- - -status_t SurfaceComposerClient::setCrop(const sp& id, const Rect& crop) { - return getComposer().setCrop(this, id, crop); -} - -status_t SurfaceComposerClient::setFinalCrop(const sp& id, - const Rect& crop) { - return getComposer().setFinalCrop(this, id, crop); -} - -status_t SurfaceComposerClient::setPosition(const sp& id, float x, float y) { - return getComposer().setPosition(this, id, x, y); + sp sf(ComposerService::getComposerService()); + return sf->injectVSync(when); } -status_t SurfaceComposerClient::setSize(const sp& id, uint32_t w, uint32_t h) { - return getComposer().setSize(this, id, w, h); -} - -status_t SurfaceComposerClient::setLayer(const sp& id, int32_t z) { - return getComposer().setLayer(this, id, z); -} - -status_t SurfaceComposerClient::setRelativeLayer(const sp& id, - const sp& relativeTo, int32_t z) { - return getComposer().setRelativeLayer(this, id, relativeTo, z); -} - -status_t SurfaceComposerClient::hide(const sp& id) { - return getComposer().setFlags(this, id, - layer_state_t::eLayerHidden, - layer_state_t::eLayerHidden); -} - -status_t SurfaceComposerClient::show(const sp& id) { - return getComposer().setFlags(this, id, - 0, - layer_state_t::eLayerHidden); -} - -status_t SurfaceComposerClient::setFlags(const sp& id, uint32_t flags, - uint32_t mask) { - return getComposer().setFlags(this, id, flags, mask); -} - -status_t SurfaceComposerClient::setTransparentRegionHint(const sp& id, - const Region& transparentRegion) { - return getComposer().setTransparentRegionHint(this, id, transparentRegion); -} - -status_t SurfaceComposerClient::setAlpha(const sp& id, float alpha) { - return getComposer().setAlpha(this, id, alpha); -} - -status_t SurfaceComposerClient::setColor(const sp& id, const half3& color) { - return getComposer().setColor(this, id, color); -} - -status_t SurfaceComposerClient::setLayerStack(const sp& id, uint32_t layerStack) { - return getComposer().setLayerStack(this, id, layerStack); -} - -status_t SurfaceComposerClient::setMatrix(const sp& id, float dsdx, float dtdx, - float dtdy, float dsdy) { - return getComposer().setMatrix(this, id, dsdx, dtdx, dtdy, dsdy); -} - -status_t SurfaceComposerClient::deferTransactionUntil(const sp& id, - const sp& handle, uint64_t frameNumber) { - return getComposer().deferTransactionUntil(this, id, handle, frameNumber); -} - -status_t SurfaceComposerClient::deferTransactionUntil(const sp& id, - const sp& barrierSurface, uint64_t frameNumber) { - return getComposer().deferTransactionUntil(this, id, barrierSurface, frameNumber); -} - -status_t SurfaceComposerClient::reparentChildren(const sp& id, - const sp& newParentHandle) { - return getComposer().reparentChildren(this, id, newParentHandle); -} - -status_t SurfaceComposerClient::reparent(const sp& id, - const sp& newParentHandle) { - return getComposer().reparent(this, id, newParentHandle); -} - -status_t SurfaceComposerClient::detachChildren(const sp& id) { - return getComposer().detachChildren(this, id); -} - -status_t SurfaceComposerClient::setOverrideScalingMode( - const sp& id, int32_t overrideScalingMode) { - return getComposer().setOverrideScalingMode( - this, id, overrideScalingMode); -} - -status_t SurfaceComposerClient::setGeometryAppliesWithResize( - const sp& id) { - return getComposer().setGeometryAppliesWithResize(this, id); -} - -// ---------------------------------------------------------------------------- - -status_t SurfaceComposerClient::setDisplaySurface(const sp& token, - sp bufferProducer) { - return Composer::getInstance().setDisplaySurface(token, bufferProducer); -} - -void SurfaceComposerClient::setDisplayLayerStack(const sp& token, - uint32_t layerStack) { - Composer::getInstance().setDisplayLayerStack(token, layerStack); -} - -void SurfaceComposerClient::setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect) { - Composer::getInstance().setDisplayProjection(token, orientation, - layerStackRect, displayRect); -} - -void SurfaceComposerClient::setDisplaySize(const sp& token, - uint32_t width, uint32_t height) { - Composer::getInstance().setDisplaySize(token, width, height); -} - -// ---------------------------------------------------------------------------- - status_t SurfaceComposerClient::getDisplayConfigs( const sp& display, Vector* configs) { diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 9e1d7b6647..f6a2b8fed6 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -97,123 +97,6 @@ bool SurfaceControl::isSameSurface( return lhs->mHandle == rhs->mHandle; } -status_t SurfaceControl::setLayerStack(uint32_t layerStack) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setLayerStack(mHandle, layerStack); -} - -status_t SurfaceControl::setLayer(int32_t layer) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setLayer(mHandle, layer); -} - -status_t SurfaceControl::setRelativeLayer(const sp& relativeTo, int32_t layer) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setRelativeLayer(mHandle, relativeTo, layer); -} - -status_t SurfaceControl::setPosition(float x, float y) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setPosition(mHandle, x, y); -} -status_t SurfaceControl::setGeometryAppliesWithResize() { - status_t err = validate(); - if (err < 0) return err; - return mClient->setGeometryAppliesWithResize(mHandle); -} -status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setSize(mHandle, w, h); -} -status_t SurfaceControl::hide() { - status_t err = validate(); - if (err < 0) return err; - return mClient->hide(mHandle); -} -status_t SurfaceControl::show() { - status_t err = validate(); - if (err < 0) return err; - return mClient->show(mHandle); -} -status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setFlags(mHandle, flags, mask); -} -status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setTransparentRegionHint(mHandle, transparent); -} -status_t SurfaceControl::setAlpha(float alpha) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setAlpha(mHandle, alpha); -} -status_t SurfaceControl::setColor(const half3& color) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setColor(mHandle, color); -} -status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setMatrix(mHandle, dsdx, dtdx, dtdy, dsdy); -} -status_t SurfaceControl::setCrop(const Rect& crop) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setCrop(mHandle, crop); -} -status_t SurfaceControl::setFinalCrop(const Rect& crop) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setFinalCrop(mHandle, crop); -} - -status_t SurfaceControl::deferTransactionUntil(const sp& handle, - uint64_t frameNumber) { - status_t err = validate(); - if (err < 0) return err; - return mClient->deferTransactionUntil(mHandle, handle, frameNumber); -} - -status_t SurfaceControl::deferTransactionUntil(const sp& handle, - uint64_t frameNumber) { - status_t err = validate(); - if (err < 0) return err; - return mClient->deferTransactionUntil(mHandle, handle, frameNumber); -} - -status_t SurfaceControl::reparentChildren(const sp& newParentHandle) { - status_t err = validate(); - if (err < 0) return err; - return mClient->reparentChildren(mHandle, newParentHandle); -} - -status_t SurfaceControl::reparent(const sp& newParentHandle) { - status_t err = validate(); - if (err < 0) return err; - return mClient->reparent(mHandle, newParentHandle); -} - -status_t SurfaceControl::detachChildren() { - status_t err = validate(); - if (err < 0) return err; - return mClient->detachChildren(mHandle); -} - -status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) { - status_t err = validate(); - if (err < 0) return err; - return mClient->setOverrideScalingMode(mHandle, overrideScalingMode); -} - status_t SurfaceControl::clearLayerFrameStats() const { status_t err = validate(); if (err < 0) return err; @@ -278,5 +161,10 @@ sp SurfaceControl::getHandle() const return mHandle; } +sp SurfaceControl::getClient() const +{ + return mClient; +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h new file mode 100644 index 0000000000..ae6965a0fc --- /dev/null +++ b/libs/gui/include/gui/LayerState.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SF_LAYER_STATE_H +#define ANDROID_SF_LAYER_STATE_H + +#include +#include + +#include + +#include +#include +#include +#include + +namespace android { + +class Parcel; +class ISurfaceComposerClient; + +/* + * Used to communicate layer information between SurfaceFlinger and its clients. + */ +struct layer_state_t { + + + enum { + eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java + eLayerOpaque = 0x02, // SURFACE_OPAQUE + eLayerSecure = 0x80, // SECURE + }; + + enum { + ePositionChanged = 0x00000001, + eLayerChanged = 0x00000002, + eSizeChanged = 0x00000004, + eAlphaChanged = 0x00000008, + eMatrixChanged = 0x00000010, + eTransparentRegionChanged = 0x00000020, + eFlagsChanged = 0x00000040, + eLayerStackChanged = 0x00000080, + eCropChanged = 0x00000100, + eDeferTransaction = 0x00000200, + eFinalCropChanged = 0x00000400, + eOverrideScalingModeChanged = 0x00000800, + eGeometryAppliesWithResize = 0x00001000, + eReparentChildren = 0x00002000, + eDetachChildren = 0x00004000, + eRelativeLayerChanged = 0x00008000, + eReparent = 0x00010000, + eColorChanged = 0x00020000 + }; + + layer_state_t() + : what(0), + x(0), y(0), z(0), w(0), h(0), layerStack(0), + alpha(0), flags(0), mask(0), + reserved(0), crop(Rect::INVALID_RECT), + finalCrop(Rect::INVALID_RECT), frameNumber(0), + overrideScalingMode(-1) + { + matrix.dsdx = matrix.dtdy = 1.0f; + matrix.dsdy = matrix.dtdx = 0.0f; + } + + status_t write(Parcel& output) const; + status_t read(const Parcel& input); + + struct matrix22_t { + float dsdx{0}; + float dtdx{0}; + float dtdy{0}; + float dsdy{0}; + }; + sp surface; + uint32_t what; + float x; + float y; + int32_t z; + uint32_t w; + uint32_t h; + uint32_t layerStack; + float alpha; + uint8_t flags; + uint8_t mask; + uint8_t reserved; + matrix22_t matrix; + Rect crop; + Rect finalCrop; + sp barrierHandle; + sp reparentHandle; + uint64_t frameNumber; + int32_t overrideScalingMode; + + sp barrierGbp; + + sp relativeLayerHandle; + + sp parentHandleForChild; + + half3 color; + + // non POD must be last. see write/read + Region transparentRegion; +}; + +struct ComposerState { + sp client; + layer_state_t state; + status_t write(Parcel& output) const; + status_t read(const Parcel& input); +}; + +struct DisplayState { + + enum { + eOrientationDefault = 0, + eOrientation90 = 1, + eOrientation180 = 2, + eOrientation270 = 3, + eOrientationUnchanged = 4, + eOrientationSwapMask = 0x01 + }; + + enum { + eSurfaceChanged = 0x01, + eLayerStackChanged = 0x02, + eDisplayProjectionChanged = 0x04, + eDisplaySizeChanged = 0x08 + }; + + DisplayState(); + + uint32_t what; + sp token; + sp surface; + uint32_t layerStack; + uint32_t orientation; + Rect viewport; + Rect frame; + uint32_t width, height; + status_t write(Parcel& output) const; + status_t read(const Parcel& input); +}; + +static inline +int compare_type(const ComposerState& lhs, const ComposerState& rhs) { + if (lhs.client < rhs.client) return -1; + if (lhs.client > rhs.client) return 1; + if (lhs.state.surface < rhs.state.surface) return -1; + if (lhs.state.surface > rhs.state.surface) return 1; + return 0; +} + +static inline +int compare_type(const DisplayState& lhs, const DisplayState& rhs) { + return compare_type(lhs.token, rhs.token); +} + +}; // namespace android + +#endif // ANDROID_SF_LAYER_STATE_H + diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 17181430c7..00d593638d 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -33,13 +33,13 @@ #include #include #include +#include namespace android { // --------------------------------------------------------------------------- struct DisplayInfo; -class Composer; class HdrCapabilities; class ISurfaceComposerClient; class IGraphicBufferProducer; @@ -122,93 +122,158 @@ public: //! Possible values for id are eDisplayIdMain and eDisplayIdHdmi. static sp getBuiltInDisplay(int32_t id); - // ------------------------------------------------------------------------ - // Composer parameters - // All composer parameters must be changed within a transaction - // several surfaces can be updated in one transaction, all changes are - // committed at once when the transaction is closed. - // closeGlobalTransaction() requires an IPC with the server. - - //! Open a composer transaction on all active SurfaceComposerClients. - static void openGlobalTransaction(); - - //! Close a composer transaction on all active SurfaceComposerClients. - static void closeGlobalTransaction(bool synchronous = false); - static status_t enableVSyncInjections(bool enable); static status_t injectVSync(nsecs_t when); - //! Flag the currently open transaction as an animation transaction. - static void setAnimationTransaction(); - - status_t hide(const sp& id); - status_t show(const sp& id); - status_t setFlags(const sp& id, uint32_t flags, uint32_t mask); - status_t setTransparentRegionHint(const sp& id, const Region& transparent); - status_t setLayer(const sp& id, int32_t layer); - status_t setRelativeLayer(const sp& id, - const sp& relativeTo, int32_t layer); - status_t setAlpha(const sp& id, float alpha=1.0f); - status_t setColor(const sp& id, const half3& color); - status_t setMatrix(const sp& id, float dsdx, float dtdx, float dtdy, float dsdy); - status_t setPosition(const sp& id, float x, float y); - status_t setSize(const sp& id, uint32_t w, uint32_t h); - status_t setCrop(const sp& id, const Rect& crop); - status_t setFinalCrop(const sp& id, const Rect& crop); - status_t setLayerStack(const sp& id, uint32_t layerStack); - status_t deferTransactionUntil(const sp& id, - const sp& handle, uint64_t frameNumber); - status_t deferTransactionUntil(const sp& id, - const sp& handle, uint64_t frameNumber); - status_t reparentChildren(const sp& id, - const sp& newParentHandle); - status_t reparent(const sp& id, const sp& newParentHandle); - status_t detachChildren(const sp& id); - status_t setOverrideScalingMode(const sp& id, - int32_t overrideScalingMode); - status_t setGeometryAppliesWithResize(const sp& id); + class Transaction { + SortedVector mComposerStates; + SortedVector mDisplayStates; + uint32_t mForceSynchronous = 0; + uint32_t mTransactionNestCount = 0; + bool mAnimation = false; + + int mStatus = NO_ERROR; + + layer_state_t* getLayerStateLocked(const sp& sc); + DisplayState& getDisplayStateLocked(const sp& token); + + public: + Transaction() = default; + virtual ~Transaction() = default; + Transaction(Transaction const& other); + + status_t apply(bool synchronous = false); + + Transaction& show(const sp& sc); + Transaction& hide(const sp& sc); + Transaction& setPosition(const sp& sc, + float x, float y); + Transaction& setSize(const sp& sc, + uint32_t w, uint32_t h); + Transaction& setLayer(const sp& sc, + int32_t z); + + // Sets a Z order relative to the Surface specified by "relativeTo" but + // without becoming a full child of the relative. Z-ordering works exactly + // as if it were a child however. + // + // As a nod to sanity, only non-child surfaces may have a relative Z-order. + // + // This overrides any previous call and is overriden by any future calls + // to setLayer. + // + // If the relative is removed, the Surface will have no layer and be + // invisible, until the next time set(Relative)Layer is called. + Transaction& setRelativeLayer(const sp& sc, + const sp& relativeTo, int32_t z); + Transaction& setFlags(const sp& sc, + uint32_t flags, uint32_t mask); + Transaction& setTransparentRegionHint(const sp& sc, + const Region& transparentRegion); + Transaction& setAlpha(const sp& sc, + float alpha); + Transaction& setMatrix(const sp& sc, + float dsdx, float dtdx, float dtdy, float dsdy); + Transaction& setOrientation(const sp& sc, + const Rect& crop); + Transaction& setCrop(const sp& sc, const Rect& crop); + Transaction& setFinalCrop(const sp& sc, const Rect& crop); + Transaction& setLayerStack(const sp& sc, uint32_t layerStack); + // Defers applying any changes made in this transaction until the Layer + // identified by handle reaches the given frameNumber. If the Layer identified + // by handle is removed, then we will apply this transaction regardless of + // what frame number has been reached. + Transaction& deferTransactionUntil(const sp& sc, + const sp& handle, + uint64_t frameNumber); + // A variant of deferTransactionUntil which identifies the Layer we wait for by + // Surface instead of Handle. Useful for clients which may not have the + // SurfaceControl for some of their Surfaces. Otherwise behaves identically. + Transaction& deferTransactionUntil(const sp& sc, + const sp& barrierSurface, + uint64_t frameNumber); + // Reparents all children of this layer to the new parent handle. + Transaction& reparentChildren(const sp& sc, + const sp& newParentHandle); + + /// Reparents the current layer to the new parent handle. The new parent must not be null. + // This can be used instead of reparentChildren if the caller wants to + // only re-parent a specific child. + Transaction& reparent(const sp& sc, + const sp& newParentHandle); + + Transaction& setColor(const sp& sc, const half3& color); + + // Detaches all child surfaces (and their children recursively) + // from their SurfaceControl. + // The child SurfaceControls will not throw exceptions or return errors, + // but transactions will have no effect. + // The child surfaces will continue to follow their parent surfaces, + // and remain eligible for rendering, but their relative state will be + // frozen. We use this in the WindowManager, in app shutdown/relaunch + // scenarios, where the app would otherwise clean up its child Surfaces. + // Sometimes the WindowManager needs to extend their lifetime slightly + // in order to perform an exit animation or prevent flicker. + Transaction& detachChildren(const sp& sc); + // Set an override scaling mode as documented in + // the override scaling mode will take precedence over any client + // specified scaling mode. -1 will clear the override scaling mode. + Transaction& setOverrideScalingMode(const sp& sc, + int32_t overrideScalingMode); + + // If the size changes in this transaction, all geometry updates specified + // in this transaction will not complete until a buffer of the new size + // arrives. As some elements normally apply immediately, this enables + // freezing the total geometry of a surface until a resize is completed. + Transaction& setGeometryAppliesWithResize(const sp& sc); + + status_t setDisplaySurface(const sp& token, + const sp& bufferProducer); + + void setDisplayLayerStack(const sp& token, uint32_t layerStack); + + /* setDisplayProjection() defines the projection of layer stacks + * to a given display. + * + * - orientation defines the display's orientation. + * - layerStackRect defines which area of the window manager coordinate + * space will be used. + * - displayRect defines where on the display will layerStackRect be + * mapped to. displayRect is specified post-orientation, that is + * it uses the orientation seen by the end-user. + */ + void setDisplayProjection(const sp& token, + uint32_t orientation, + const Rect& layerStackRect, + const Rect& displayRect); + void setDisplaySize(const sp& token, uint32_t width, uint32_t height); + void setAnimationTransaction(); + }; status_t destroySurface(const sp& id); status_t clearLayerFrameStats(const sp& token) const; status_t getLayerFrameStats(const sp& token, FrameStats* outStats) const; - static status_t clearAnimationFrameStats(); static status_t getAnimationFrameStats(FrameStats* outStats); static status_t getHdrCapabilities(const sp& display, HdrCapabilities* outCapabilities); - static status_t setDisplaySurface(const sp& token, - sp bufferProducer); - static void setDisplayLayerStack(const sp& token, - uint32_t layerStack); - static void setDisplaySize(const sp& token, uint32_t width, uint32_t height); - - /* setDisplayProjection() defines the projection of layer stacks - * to a given display. - * - * - orientation defines the display's orientation. - * - layerStackRect defines which area of the window manager coordinate - * space will be used. - * - displayRect defines where on the display will layerStackRect be - * mapped to. displayRect is specified post-orientation, that is - * it uses the orientation seen by the end-user. - */ static void setDisplayProjection(const sp& token, uint32_t orientation, const Rect& layerStackRect, const Rect& displayRect); + inline sp getClient() { return mClient; } + private: virtual void onFirstRef(); - Composer& getComposer(); mutable Mutex mLock; status_t mStatus; sp mClient; - Composer& mComposer; wp mParent; }; diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index e98e26a391..384815dad8 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -61,93 +61,6 @@ public: // disconnect any api that's connected void disconnect(); - status_t setLayerStack(uint32_t layerStack); - status_t setLayer(int32_t layer); - - // Sets a Z order relative to the Surface specified by "relativeTo" but - // without becoming a full child of the relative. Z-ordering works exactly - // as if it were a child however. - // - // As a nod to sanity, only non-child surfaces may have a relative Z-order. - // - // This overrides any previous and is overriden by any future calls - // to setLayer. - // - // If the relative dissapears, the Surface will have no layer and be - // invisible, until the next time set(Relative)Layer is called. - // - // TODO: This is probably a hack. Currently it exists only to work around - // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type - // which allows inserting a window between a SurfaceView and it's main application - // window. However, since we are using child windows for the SurfaceView, but not using - // child windows elsewhere in O, the WindowManager can't set the layer appropriately. - // This is only used by the "TvInputService" and following the port of ViewRootImpl - // to child surfaces, we can then port this and remove this method. - status_t setRelativeLayer(const sp& relativeTo, int32_t layer); - status_t setPosition(float x, float y); - status_t setSize(uint32_t w, uint32_t h); - status_t hide(); - status_t show(); - status_t setFlags(uint32_t flags, uint32_t mask); - status_t setTransparentRegionHint(const Region& transparent); - status_t setAlpha(float alpha=1.0f); - status_t setColor(const half3& color); - - // Experimentarily it appears that the matrix transforms the - // on-screen rectangle and it's contents before the position is - // applied. - // - // TODO: Test with other combinations to find approximate transformation rules. - // - // For example: - // Layer sized (W,H) set to position (x,y) with matrix M=[-1, 0, 0, 1] (Horizontal flip) gives - // [((0, 0), (W, H)) x M] + (x,y) = ((-W, 0), (0, H)) + (x,y) = ((-W + x, y), (x, H+y)) - status_t setMatrix(float dsdx, float dtdx, float dtdy, float dsdy); - status_t setCrop(const Rect& crop); - status_t setFinalCrop(const Rect& crop); - - // If the size changes in this transaction, all geometry updates specified - // in this transaction will not complete until a buffer of the new size - // arrives. As some elements normally apply immediately, this enables - // freezing the total geometry of a surface until a resize is completed. - status_t setGeometryAppliesWithResize(); - - // Defers applying any changes made in this transaction until the Layer - // identified by handle reaches the given frameNumber. If the Layer identified - // by handle is removed, then we will apply this transaction regardless of - // what frame number has been reached. - status_t deferTransactionUntil(const sp& handle, uint64_t frameNumber); - - // A variant of deferTransactionUntil which identifies the Layer we wait for by - // Surface instead of Handle. Useful for clients which may not have the - // SurfaceControl for some of their Surfaces. Otherwise behaves identically. - status_t deferTransactionUntil(const sp& barrier, uint64_t frameNumber); - - // Reparents all children of this layer to the new parent handle. - status_t reparentChildren(const sp& newParentHandle); - - // Reparents the current layer to the new parent handle. The new parent must not be null. - // This can be used instead of reparentChildren if the caller wants to - // only re-parent a specific child. - status_t reparent(const sp& newParentHandle); - - // Detaches all child surfaces (and their children recursively) - // from their SurfaceControl. - // The child SurfaceControl's will not throw exceptions or return errors, - // but transactions will have no effect. - // The child surfaces will continue to follow their parent surfaces, - // and remain eligible for rendering, but their relative state will be - // frozen. We use this in the WindowManager, in app shutdown/relaunch - // scenarios, where the app would otherwise clean up its child Surfaces. - // Sometimes the WindowManager needs to extend their lifetime slightly - // in order to perform an exit animation or prevent flicker. - status_t detachChildren(); - - // Set an override scaling mode as documented in - // the override scaling mode will take precedence over any client - // specified scaling mode. -1 will clear the override scaling mode. - status_t setOverrideScalingMode(int32_t overrideScalingMode); - static status_t writeSurfaceToParcel( const sp& control, Parcel* parcel); @@ -158,6 +71,8 @@ public: status_t clearLayerFrameStats() const; status_t getLayerFrameStats(FrameStats* outStats) const; + sp getClient() const; + private: // can't be copied SurfaceControl& operator = (SurfaceControl& rhs); diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h deleted file mode 100644 index bd42634730..0000000000 --- a/libs/gui/include/private/gui/LayerState.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SF_LAYER_STATE_H -#define ANDROID_SF_LAYER_STATE_H - -#include -#include - -#include - -#include -#include -#include -#include - -namespace android { - -class Parcel; -class ISurfaceComposerClient; - -/* - * Used to communicate layer information between SurfaceFlinger and its clients. - */ -struct layer_state_t { - - - enum { - eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java - eLayerOpaque = 0x02, // SURFACE_OPAQUE - eLayerSecure = 0x80, // SECURE - }; - - enum { - ePositionChanged = 0x00000001, - eLayerChanged = 0x00000002, - eSizeChanged = 0x00000004, - eAlphaChanged = 0x00000008, - eMatrixChanged = 0x00000010, - eTransparentRegionChanged = 0x00000020, - eFlagsChanged = 0x00000040, - eLayerStackChanged = 0x00000080, - eCropChanged = 0x00000100, - eDeferTransaction = 0x00000200, - eFinalCropChanged = 0x00000400, - eOverrideScalingModeChanged = 0x00000800, - eGeometryAppliesWithResize = 0x00001000, - eReparentChildren = 0x00002000, - eDetachChildren = 0x00004000, - eRelativeLayerChanged = 0x00008000, - eReparent = 0x00010000, - eColorChanged = 0x00020000 - }; - - layer_state_t() - : what(0), - x(0), y(0), z(0), w(0), h(0), layerStack(0), - alpha(0), flags(0), mask(0), - reserved(0), crop(Rect::INVALID_RECT), - finalCrop(Rect::INVALID_RECT), frameNumber(0), - overrideScalingMode(-1) - { - matrix.dsdx = matrix.dtdy = 1.0f; - matrix.dsdy = matrix.dtdx = 0.0f; - } - - status_t write(Parcel& output) const; - status_t read(const Parcel& input); - - struct matrix22_t { - float dsdx{0}; - float dtdx{0}; - float dtdy{0}; - float dsdy{0}; - }; - sp surface; - uint32_t what; - float x; - float y; - int32_t z; - uint32_t w; - uint32_t h; - uint32_t layerStack; - float alpha; - uint8_t flags; - uint8_t mask; - uint8_t reserved; - matrix22_t matrix; - Rect crop; - Rect finalCrop; - sp barrierHandle; - sp reparentHandle; - uint64_t frameNumber; - int32_t overrideScalingMode; - - sp barrierGbp; - - sp relativeLayerHandle; - - sp parentHandleForChild; - - half3 color; - - // non POD must be last. see write/read - Region transparentRegion; -}; - -struct ComposerState { - sp client; - layer_state_t state; - status_t write(Parcel& output) const; - status_t read(const Parcel& input); -}; - -struct DisplayState { - - enum { - eOrientationDefault = 0, - eOrientation90 = 1, - eOrientation180 = 2, - eOrientation270 = 3, - eOrientationUnchanged = 4, - eOrientationSwapMask = 0x01 - }; - - enum { - eSurfaceChanged = 0x01, - eLayerStackChanged = 0x02, - eDisplayProjectionChanged = 0x04, - eDisplaySizeChanged = 0x08 - }; - - DisplayState(); - - uint32_t what; - sp token; - sp surface; - uint32_t layerStack; - uint32_t orientation; - Rect viewport; - Rect frame; - uint32_t width, height; - status_t write(Parcel& output) const; - status_t read(const Parcel& input); -}; - -}; // namespace android - -#endif // ANDROID_SF_LAYER_STATE_H - diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp index 1739d9c7ca..a91552f7fe 100644 --- a/libs/gui/tests/GLTest.cpp +++ b/libs/gui/tests/GLTest.cpp @@ -22,6 +22,8 @@ namespace android { +using Transaction = SurfaceComposerClient::Transaction; + static int abs(int value) { return value > 0 ? value : -value; } @@ -68,10 +70,10 @@ void GLTest::SetUp() { ASSERT_TRUE(mSurfaceControl != NULL); ASSERT_TRUE(mSurfaceControl->isValid()); - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); - ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); - SurfaceComposerClient::closeGlobalTransaction(); + Transaction t; + ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7FFFFFFF) + .show(mSurfaceControl) + .apply()); sp window = mSurfaceControl->getSurface(); mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 45e95a593b..bfcd75f26c 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -42,6 +42,8 @@ using namespace std::chrono_literals; using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using Transaction = SurfaceComposerClient::Transaction; + static bool hasWideColorDisplay = getBool(false); @@ -69,10 +71,10 @@ protected: ASSERT_TRUE(mSurfaceControl != NULL); ASSERT_TRUE(mSurfaceControl->isValid()); - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff)); - ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); - SurfaceComposerClient::closeGlobalTransaction(); + Transaction t; + ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7fffffff) + .show(mSurfaceControl) + .apply()); mSurface = mSurfaceControl->getSurface(); ASSERT_TRUE(mSurface != NULL); diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp index 142894524d..2b76279801 100644 --- a/opengl/tests/lib/WindowSurface.cpp +++ b/opengl/tests/lib/WindowSurface.cpp @@ -62,19 +62,10 @@ WindowSurface::WindowSurface() { return; } - SurfaceComposerClient::openGlobalTransaction(); - err = sc->setLayer(0x7FFFFFFF); // always on top - if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err); - return; - } - - err = sc->show(); - if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::show error: %#x\n", err); - return; - } - SurfaceComposerClient::closeGlobalTransaction(); + SurfaceComposerClient::Transaction{} + .setLayer(sc, 0x7FFFFFFF) + .show(sc) + .apply(); mSurfaceControl = sc; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 921492b210..47924ae877 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -33,8 +33,7 @@ #include #include - -#include +#include #include diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e87d35f912..32e4067ece 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -43,14 +43,14 @@ #include #include #include +#include + #include #include #include -#include - #include "Barrier.h" #include "DisplayDevice.h" #include "DispSync.h" diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 0cc763c740..ed806b87f5 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -22,10 +22,11 @@ #include #include +#include #include #include + #include -#include #include #include @@ -34,6 +35,8 @@ namespace android { +using Transaction = SurfaceComposerClient::Transaction; + constexpr int32_t SCALING_UPDATE = 1; constexpr uint32_t BUFFER_UPDATES = 18; constexpr uint32_t LAYER_UPDATE = INT_MAX - 2; @@ -149,11 +152,11 @@ protected: ASSERT_TRUE(mBGSurfaceControl->isValid()); mBGLayerId = getSurfaceId("BG Interceptor Test Surface"); - SurfaceComposerClient::openGlobalTransaction(); - mComposerClient->setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-3)); - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show()); - SurfaceComposerClient::closeGlobalTransaction(true); + Transaction t; + t.setDisplayLayerStack(display, 0); + ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3) + .show(mBGSurfaceControl) + .apply()); } virtual void TearDown() { @@ -169,13 +172,14 @@ protected: int32_t mTargetId; public: - void captureTest(void (SurfaceInterceptorTest::* action)(void), + void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), bool (SurfaceInterceptorTest::* verification)(Trace *)); - void captureTest(void (SurfaceInterceptorTest::* action)(void), + void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), SurfaceChange::SurfaceChangeCase changeCase); - void captureTest(void (SurfaceInterceptorTest::* action)(void), + void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), Increment::IncrementCase incrementCase); - void runInTransaction(void (SurfaceInterceptorTest::* action)(void), bool intercepted = false); + void runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&), + bool intercepted = false); // Verification of changes to a surface bool positionUpdateFound(const SurfaceChange& change, bool foundPosition); @@ -206,28 +210,29 @@ public: bool bufferUpdatesFound(Trace* trace); // Perform each of the possible changes to a surface - void positionUpdate(); - void sizeUpdate(); - void alphaUpdate(); - void layerUpdate(); - void cropUpdate(); - void finalCropUpdate(); - void matrixUpdate(); - void overrideScalingModeUpdate(); - void transparentRegionHintUpdate(); - void layerStackUpdate(); - void hiddenFlagUpdate(); - void opaqueFlagUpdate(); - void secureFlagUpdate(); - void deferredTransactionUpdate(); - void runAllUpdates(); - void surfaceCreation(); + void positionUpdate(Transaction&); + void sizeUpdate(Transaction&); + void alphaUpdate(Transaction&); + void layerUpdate(Transaction&); + void cropUpdate(Transaction&); + void finalCropUpdate(Transaction&); + void matrixUpdate(Transaction&); + void overrideScalingModeUpdate(Transaction&); + void transparentRegionHintUpdate(Transaction&); + void layerStackUpdate(Transaction&); + void hiddenFlagUpdate(Transaction&); + void opaqueFlagUpdate(Transaction&); + void secureFlagUpdate(Transaction&); + void deferredTransactionUpdate(Transaction&); + void surfaceCreation(Transaction&); + void displayCreation(Transaction&); + void displayDeletion(Transaction&); + void nBufferUpdates(); - void displayCreation(); - void displayDeletion(); + void runAllUpdates(); }; -void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void), +void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), bool (SurfaceInterceptorTest::* verification)(Trace *)) { runInTransaction(action, true); @@ -236,7 +241,7 @@ void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action) ASSERT_TRUE((this->*verification)(&capturedTrace)); } -void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void), +void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), Increment::IncrementCase incrementCase) { runInTransaction(action, true); @@ -245,7 +250,7 @@ void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action) ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase)); } -void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void), +void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), SurfaceChange::SurfaceChangeCase changeCase) { runInTransaction(action, true); @@ -254,83 +259,84 @@ void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action) ASSERT_TRUE(surfaceUpdateFound(&capturedTrace, changeCase)); } -void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(void), +void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&), bool intercepted) { if (intercepted) { enableInterceptor(); } - SurfaceComposerClient::openGlobalTransaction(); - (this->*action)(); - SurfaceComposerClient::closeGlobalTransaction(true); + Transaction t; + (this->*action)(t); + t.apply(true); + if (intercepted) { disableInterceptor(); } } -void SurfaceInterceptorTest::positionUpdate() { - mBGSurfaceControl->setPosition(POSITION_UPDATE, POSITION_UPDATE); +void SurfaceInterceptorTest::positionUpdate(Transaction& t) { + t.setPosition(mBGSurfaceControl, POSITION_UPDATE, POSITION_UPDATE); } -void SurfaceInterceptorTest::sizeUpdate() { - mBGSurfaceControl->setSize(SIZE_UPDATE, SIZE_UPDATE); +void SurfaceInterceptorTest::sizeUpdate(Transaction& t) { + t.setSize(mBGSurfaceControl, SIZE_UPDATE, SIZE_UPDATE); } -void SurfaceInterceptorTest::alphaUpdate() { - mBGSurfaceControl->setAlpha(ALPHA_UPDATE); +void SurfaceInterceptorTest::alphaUpdate(Transaction& t) { + t.setAlpha(mBGSurfaceControl, ALPHA_UPDATE); } -void SurfaceInterceptorTest::layerUpdate() { - mBGSurfaceControl->setLayer(LAYER_UPDATE); +void SurfaceInterceptorTest::layerUpdate(Transaction& t) { + t.setLayer(mBGSurfaceControl, LAYER_UPDATE); } -void SurfaceInterceptorTest::cropUpdate() { - mBGSurfaceControl->setCrop(CROP_UPDATE); +void SurfaceInterceptorTest::cropUpdate(Transaction& t) { + t.setCrop(mBGSurfaceControl, CROP_UPDATE); } -void SurfaceInterceptorTest::finalCropUpdate() { - mBGSurfaceControl->setFinalCrop(CROP_UPDATE); +void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) { + t.setFinalCrop(mBGSurfaceControl, CROP_UPDATE); } -void SurfaceInterceptorTest::matrixUpdate() { - mBGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2); +void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { + t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2); } -void SurfaceInterceptorTest::overrideScalingModeUpdate() { - mBGSurfaceControl->setOverrideScalingMode(SCALING_UPDATE); +void SurfaceInterceptorTest::overrideScalingModeUpdate(Transaction& t) { + t.setOverrideScalingMode(mBGSurfaceControl, SCALING_UPDATE); } -void SurfaceInterceptorTest::transparentRegionHintUpdate() { +void SurfaceInterceptorTest::transparentRegionHintUpdate(Transaction& t) { Region region(CROP_UPDATE); - mBGSurfaceControl->setTransparentRegionHint(region); + t.setTransparentRegionHint(mBGSurfaceControl, region); } -void SurfaceInterceptorTest::layerStackUpdate() { - mBGSurfaceControl->setLayerStack(STACK_UPDATE); +void SurfaceInterceptorTest::layerStackUpdate(Transaction& t) { + t.setLayerStack(mBGSurfaceControl, STACK_UPDATE); } -void SurfaceInterceptorTest::hiddenFlagUpdate() { - mBGSurfaceControl->setFlags(layer_state_t::eLayerHidden, layer_state_t::eLayerHidden); +void SurfaceInterceptorTest::hiddenFlagUpdate(Transaction& t) { + t.setFlags(mBGSurfaceControl, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden); } -void SurfaceInterceptorTest::opaqueFlagUpdate() { - mBGSurfaceControl->setFlags(layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); +void SurfaceInterceptorTest::opaqueFlagUpdate(Transaction& t) { + t.setFlags(mBGSurfaceControl, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); } -void SurfaceInterceptorTest::secureFlagUpdate() { - mBGSurfaceControl->setFlags(layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); +void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) { + t.setFlags(mBGSurfaceControl, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); } -void SurfaceInterceptorTest::deferredTransactionUpdate() { - mBGSurfaceControl->deferTransactionUntil(mBGSurfaceControl->getHandle(), DEFERRED_UPDATE); +void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { + t.deferTransactionUntil(mBGSurfaceControl, mBGSurfaceControl->getHandle(), DEFERRED_UPDATE); } -void SurfaceInterceptorTest::displayCreation() { +void SurfaceInterceptorTest::displayCreation(Transaction&) { sp testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true); SurfaceComposerClient::destroyDisplay(testDisplay); } -void SurfaceInterceptorTest::displayDeletion() { +void SurfaceInterceptorTest::displayDeletion(Transaction&) { sp testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false); mTargetId = getDisplayId(DISPLAY_NAME.string()); SurfaceComposerClient::destroyDisplay(testDisplay); @@ -353,7 +359,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate); } -void SurfaceInterceptorTest::surfaceCreation() { +void SurfaceInterceptorTest::surfaceCreation(Transaction&) { mComposerClient->createSurface(String8(LAYER_NAME), SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0); } @@ -825,8 +831,10 @@ TEST_F(SurfaceInterceptorTest, InterceptDisplayDeletionWorks) { } TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) { - captureTest(&SurfaceInterceptorTest::nBufferUpdates, - &SurfaceInterceptorTest::bufferUpdatesFound); + nBufferUpdates(); + Trace capturedTrace; + ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); + ASSERT_TRUE(bufferUpdatesFound(&capturedTrace)); } // If the interceptor is enabled while buffer updates are being pushed, the interceptor should diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index d285785c83..f61a978487 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -19,10 +19,11 @@ #include #include +#include + #include #include #include -#include #include #include @@ -30,8 +31,12 @@ #include #include +#include + namespace android { +using Transaction = SurfaceComposerClient::Transaction; + // Fill an RGBA_8888 formatted surface with a single color. static void fillSurfaceRGBA8(const sp& sc, uint8_t r, uint8_t g, uint8_t b, bool unlock=true) { @@ -66,8 +71,8 @@ public: sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - SurfaceComposerClient::openGlobalTransaction(); - SurfaceComposerClient::closeGlobalTransaction(true); + SurfaceComposerClient::Transaction().apply(true); + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 0, 0, 0, INT_MAX, false)); *sc = new ScreenCapture(cpuConsumer); @@ -149,23 +154,21 @@ protected: fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - SurfaceComposerClient::openGlobalTransaction(); - - mComposerClient->setDisplayLayerStack(display, 0); - - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX-2)); - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show()); + asTransaction([&](Transaction& t) { + t.setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX-1)); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64)); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show()); + t.setLayer(mBGSurfaceControl, INT32_MAX-2) + .show(mBGSurfaceControl); - ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT32_MAX-1)); - ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setPosition(displayWidth-2, - displayHeight-2)); - ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->show()); + t.setLayer(mFGSurfaceControl, INT32_MAX-1) + .setPosition(mFGSurfaceControl, 64, 64) + .show(mFGSurfaceControl); - SurfaceComposerClient::closeGlobalTransaction(true); + t.setLayer(mSyncSurfaceControl, INT32_MAX-1) + .setPosition(mSyncSurfaceControl, displayWidth-2, + displayHeight-2) + .show(mSyncSurfaceControl); + }); } virtual void TearDown() { @@ -186,6 +189,12 @@ protected: fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); } + void asTransaction(const std::function& exec) { + Transaction t; + exec(t); + t.apply(true); + } + sp mComposerClient; sp mBGSurfaceControl; sp mFGSurfaceControl; @@ -205,9 +214,10 @@ TEST_F(LayerUpdateTest, LayerMoveWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setPosition(mFGSurfaceControl, 128, 128); + }); + { // This should reflect the new position, but not the new color. SCOPED_TRACE("after move, before redraw"); @@ -240,9 +250,9 @@ TEST_F(LayerUpdateTest, LayerResizeWorks) { } ALOGD("resizing"); - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + }); ALOGD("resized"); { // This should not reflect the new size or color because SurfaceFlinger @@ -278,10 +288,10 @@ TEST_F(LayerUpdateTest, LayerCropWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - Rect cropRect(16, 16, 32, 32); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + Rect cropRect(16, 16, 32, 32); + t.setCrop(mFGSurfaceControl, cropRect); + }); { // This should crop the foreground surface. SCOPED_TRACE("after crop"); @@ -303,10 +313,10 @@ TEST_F(LayerUpdateTest, LayerFinalCropWorks) { sc->expectFGColor(75, 75); sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - Rect cropRect(16, 16, 32, 32); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + Rect cropRect(16, 16, 32, 32); + t.setFinalCrop(mFGSurfaceControl, cropRect); + }); { // This should crop the foreground surface. SCOPED_TRACE("after crop"); @@ -329,9 +339,10 @@ TEST_F(LayerUpdateTest, LayerSetLayerWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setLayer(mFGSurfaceControl, INT_MAX - 3); + }); + { // This should hide the foreground surface beneath the background. SCOPED_TRACE("after setLayer"); @@ -352,9 +363,10 @@ TEST_F(LayerUpdateTest, LayerShowHideWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide()); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.hide(mFGSurfaceControl); + }); + { // This should hide the foreground surface. SCOPED_TRACE("after hide, before show"); @@ -364,9 +376,10 @@ TEST_F(LayerUpdateTest, LayerShowHideWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show()); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mFGSurfaceControl); + }); + { // This should show the foreground surface. SCOPED_TRACE("after show"); @@ -387,9 +400,10 @@ TEST_F(LayerUpdateTest, LayerSetAlphaWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setAlpha(mFGSurfaceControl, 0.75f); + }); + { // This should set foreground to be 75% opaque. SCOPED_TRACE("after setAlpha"); @@ -410,9 +424,9 @@ TEST_F(LayerUpdateTest, LayerSetLayerStackWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setLayerStack(mFGSurfaceControl, 1); + }); { // This should hide the foreground surface since it goes to a different // layer stack. @@ -434,10 +448,10 @@ TEST_F(LayerUpdateTest, LayerSetFlagsWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags( - layer_state_t::eLayerHidden, layer_state_t::eLayerHidden)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setFlags(mFGSurfaceControl, + layer_state_t::eLayerHidden, layer_state_t::eLayerHidden); + }); { // This should hide the foreground surface SCOPED_TRACE("after setFlags"); @@ -459,10 +473,11 @@ TEST_F(LayerUpdateTest, LayerSetMatrixWorks) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2, - -M_SQRT1_2, M_SQRT1_2)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setMatrix(mFGSurfaceControl, + M_SQRT1_2, M_SQRT1_2, + -M_SQRT1_2, M_SQRT1_2); + }); { SCOPED_TRACE("after setMatrix"); ScreenCapture::captureScreen(&sc); @@ -498,12 +513,12 @@ protected: waitForPostedBuffers(); } void restoreInitialState() { - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(64, 64); - mFGSurfaceControl->setPosition(64, 64); - mFGSurfaceControl->setCrop(Rect(0, 0, 64, 64)); - mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 64, 64); + t.setPosition(mFGSurfaceControl, 64, 64); + t.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64)); + t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + }); EXPECT_INITIAL_STATE("After restoring initial state"); } @@ -515,10 +530,10 @@ TEST_F(GeometryLatchingTest, SurfacePositionLatching) { // By default position can be updated even while // a resize is pending. - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(32, 32); - mFGSurfaceControl->setPosition(100, 100); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 32, 32); + t.setPosition(mFGSurfaceControl, 100, 100); + }); { SCOPED_TRACE("After moving surface"); @@ -532,11 +547,11 @@ TEST_F(GeometryLatchingTest, SurfacePositionLatching) { // Now we repeat with setGeometryAppliesWithResize // and verify the position DOESN'T latch. - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setSize(32, 32); - mFGSurfaceControl->setPosition(100, 100); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setGeometryAppliesWithResize(mFGSurfaceControl); + t.setSize(mFGSurfaceControl, 32, 32); + t.setPosition(mFGSurfaceControl, 100, 100); + }); { SCOPED_TRACE("While resize is pending"); @@ -581,20 +596,20 @@ protected: TEST_F(CropLatchingTest, CropLatching) { EXPECT_INITIAL_STATE("before anything"); // Normally the crop applies immediately even while a resize is pending. - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + }); EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); restoreInitialState(); - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setGeometryAppliesWithResize(mFGSurfaceControl); + t.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + }); EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); @@ -606,20 +621,20 @@ TEST_F(CropLatchingTest, CropLatching) { TEST_F(CropLatchingTest, FinalCropLatching) { EXPECT_INITIAL_STATE("before anything"); // Normally the crop applies immediately even while a resize is pending. - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + }); EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); restoreInitialState(); - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setGeometryAppliesWithResize(mFGSurfaceControl); + t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + }); EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); @@ -633,10 +648,10 @@ TEST_F(CropLatchingTest, FinalCropLatching) { TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { EXPECT_INITIAL_STATE("before anything"); // Normally the crop applies immediately even while a resize is pending. - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + }); EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); @@ -646,11 +661,11 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { // initiating the resize. lockAndFillFGBuffer(); - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setGeometryAppliesWithResize(mFGSurfaceControl); + t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + }); EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); @@ -670,17 +685,17 @@ TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) { // In this scenario, we attempt to set the final crop a second time while the resize // is still pending, and ensure we are successful. Success meaning the second crop // is the one which eventually latches and not the first. - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 128); + t.setGeometryAppliesWithResize(mFGSurfaceControl); + t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + }); EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize"); - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + }); EXPECT_INITIAL_STATE("after setting another crop"); @@ -700,17 +715,17 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { } // set up two deferred transactions on different frames - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75)); - mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber()); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setAlpha(mFGSurfaceControl, 0.75); + t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber()); + }); - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128)); - mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setPosition(mFGSurfaceControl, 128,128); + t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + }); { SCOPED_TRACE("before any trigger"); @@ -731,9 +746,9 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { } // should show up immediately since it's not deferred - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setAlpha(mFGSurfaceControl, 1.0); + }); // trigger the second deferred transaction fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); @@ -762,12 +777,11 @@ TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) { waitForPostedBuffers(); // Now we stack the surface above the foreground surface and make sure it is visible. - SurfaceComposerClient::openGlobalTransaction(); - relativeSurfaceControl->setPosition(64, 64); - relativeSurfaceControl->show(); - relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1); - SurfaceComposerClient::closeGlobalTransaction(true); - + asTransaction([&](Transaction& t) { + t.setPosition(relativeSurfaceControl, 64, 64); + t.show(relativeSurfaceControl); + t.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1); + }); { SCOPED_TRACE("after adding relative surface"); @@ -777,9 +791,9 @@ TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) { } // A call to setLayer will override a call to setRelativeLayer - SurfaceComposerClient::openGlobalTransaction(); - relativeSurfaceControl->setLayer(0); - SurfaceComposerClient::closeGlobalTransaction(); + asTransaction([&](Transaction& t) { + t.setLayer(relativeSurfaceControl, 0); + }); { SCOPED_TRACE("after set layer"); @@ -801,11 +815,10 @@ TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); fillSurfaceRGBA8(childBuffer, 200, 200, 200); - SurfaceComposerClient::openGlobalTransaction(); - childNoBuffer->show(); - childBuffer->show(); - SurfaceComposerClient::closeGlobalTransaction(); - + SurfaceComposerClient::Transaction{} + .show(childNoBuffer) + .show(childBuffer) + .apply(true); { ScreenCapture::captureScreen(&sc); @@ -813,9 +826,9 @@ TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { sc->expectFGColor(74, 74); } - SurfaceComposerClient::openGlobalTransaction(); - childNoBuffer->setSize(20, 20); - SurfaceComposerClient::closeGlobalTransaction(true); + SurfaceComposerClient::Transaction{} + .setSize(childNoBuffer, 20, 20) + .apply(true); { ScreenCapture::captureScreen(&sc); @@ -850,11 +863,11 @@ protected: }; TEST_F(ChildLayerTest, ChildLayerPositioning) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -866,9 +879,9 @@ TEST_F(ChildLayerTest, ChildLayerPositioning) { mCapture->expectFGColor(84, 84); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setPosition(mFGSurfaceControl, 0, 0); + }); { ScreenCapture::captureScreen(&mCapture); @@ -882,12 +895,12 @@ TEST_F(ChildLayerTest, ChildLayerPositioning) { } TEST_F(ChildLayerTest, ChildLayerCropping) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + }); { ScreenCapture::captureScreen(&mCapture); @@ -898,12 +911,12 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { } TEST_F(ChildLayerTest, ChildLayerFinalCropping) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + }); { ScreenCapture::captureScreen(&mCapture); @@ -914,11 +927,11 @@ TEST_F(ChildLayerTest, ChildLayerFinalCropping) { } TEST_F(ChildLayerTest, ChildLayerConstraints) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mFGSurfaceControl->setPosition(0, 0); - mChild->setPosition(63, 63); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setPosition(mChild, 63, 63); + }); { ScreenCapture::captureScreen(&mCapture); @@ -932,9 +945,9 @@ TEST_F(ChildLayerTest, ChildLayerConstraints) { } TEST_F(ChildLayerTest, ChildLayerScaling) { - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setPosition(0, 0); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setPosition(mFGSurfaceControl, 0, 0); + }); // Find the boundary between the parent and child { @@ -943,9 +956,9 @@ TEST_F(ChildLayerTest, ChildLayerScaling) { mCapture->expectFGColor(10, 10); } - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); + }); // The boundary should be twice as far from the origin now. // The pixels from the last test should all be child now @@ -964,11 +977,11 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { fillSurfaceRGBA8(mChild, 0, 254, 0); waitForPostedBuffers(); - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); { ScreenCapture::captureScreen(&mCapture); @@ -976,9 +989,9 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { mCapture->checkPixel(0, 0, 0, 254, 0); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setAlpha(mChild, 0.5); + }); { ScreenCapture::captureScreen(&mCapture); @@ -986,9 +999,9 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { mCapture->checkPixel(0, 0, 127, 127, 0); } - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5)); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setAlpha(mFGSurfaceControl, 0.5); + }); { ScreenCapture::captureScreen(&mCapture); @@ -998,11 +1011,11 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { } TEST_F(ChildLayerTest, ReparentChildren) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1013,7 +1026,11 @@ TEST_F(ChildLayerTest, ReparentChildren) { // And 10 more pixels we should be back to the foreground surface mCapture->expectFGColor(84, 84); } - mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle()); + + asTransaction([&](Transaction& t) { + t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle()); + }); + { ScreenCapture::captureScreen(&mCapture); mCapture->expectFGColor(64, 64); @@ -1027,11 +1044,11 @@ TEST_F(ChildLayerTest, ReparentChildren) { } TEST_F(ChildLayerTest, DetachChildrenSameClient) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1043,13 +1060,13 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { mCapture->expectFGColor(84, 84); } - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->detachChildren(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.detachChildren(mFGSurfaceControl); + }); - SurfaceComposerClient::openGlobalTransaction(); - mChild->hide(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.hide(mChild); + }); // Since the child has the same client as the parent, it will not get // detached and will be hidden. @@ -1072,12 +1089,12 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { fillSurfaceRGBA8(mChildNewClient, 200, 200, 200); - SurfaceComposerClient::openGlobalTransaction(); - mChild->hide(); - mChildNewClient->show(); - mChildNewClient->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.hide(mChild); + t.show(mChildNewClient); + t.setPosition(mChildNewClient, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1089,13 +1106,13 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { mCapture->expectFGColor(84, 84); } - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->detachChildren(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.detachChildren(mFGSurfaceControl); + }); - SurfaceComposerClient::openGlobalTransaction(); - mChildNewClient->hide(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.hide(mChildNewClient); + }); // Nothing should have changed. { @@ -1107,11 +1124,11 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { } TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1121,11 +1138,11 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { mCapture->expectFGColor(10, 10); } - SurfaceComposerClient::openGlobalTransaction(); - mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - // We cause scaling by 2. - mFGSurfaceControl->setSize(128, 128); - SurfaceComposerClient::closeGlobalTransaction(); + asTransaction([&](Transaction& t) { + t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // We cause scaling by 2. + t.setSize(mFGSurfaceControl, 128, 128); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1140,11 +1157,11 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { // Regression test for b/37673612 TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1153,11 +1170,11 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { // But it's only 10x10. mCapture->expectFGColor(10, 10); } - - // We set things up as in b/37673612 so that there is a mismatch between the buffer size and // the WM specified state size. - mFGSurfaceControl->setSize(128, 64); + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 128, 64); + }); sp s = mFGSurfaceControl->getSurface(); auto anw = static_cast(s.get()); native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); @@ -1184,11 +1201,11 @@ TEST_F(ChildLayerTest, Bug36858924) { mFGSurfaceControl.get()); // Show the child layer in a deferred transaction - SurfaceComposerClient::openGlobalTransaction(); - mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); - mChild->show(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); + t.show(mChild); + }); // Render the foreground surface a few times // @@ -1206,11 +1223,11 @@ TEST_F(ChildLayerTest, Bug36858924) { } TEST_F(ChildLayerTest, Reparent) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1221,7 +1238,11 @@ TEST_F(ChildLayerTest, Reparent) { // And 10 more pixels we should be back to the foreground surface mCapture->expectFGColor(84, 84); } - mChild->reparent(mBGSurfaceControl->getHandle()); + + asTransaction([&](Transaction& t) { + t.reparent(mChild, mBGSurfaceControl->getHandle()); + }); + { ScreenCapture::captureScreen(&mCapture); mCapture->expectFGColor(64, 64); @@ -1235,11 +1256,11 @@ TEST_F(ChildLayerTest, Reparent) { } TEST_F(ChildLayerTest, ReparentToNoParent) { - SurfaceComposerClient::openGlobalTransaction(); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1250,7 +1271,9 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { // And 10 more pixels we should be back to the foreground surface mCapture->expectFGColor(84, 84); } - mChild->reparent(nullptr); + asTransaction([&](Transaction& t) { + t.reparent(mChild, nullptr); + }); { ScreenCapture::captureScreen(&mCapture); // Nothing should have changed. @@ -1267,13 +1290,13 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { ASSERT_TRUE(newSurface->isValid()); fillSurfaceRGBA8(newSurface, 63, 195, 63); - SurfaceComposerClient::openGlobalTransaction(); - mChild->hide(); - newSurface->show(); - newSurface->setPosition(10, 10); - newSurface->setLayer(INT32_MAX-2); - mFGSurfaceControl->setPosition(64, 64); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.hide(mChild); + t.show(newSurface); + t.setPosition(newSurface, 10, 10); + t.setLayer(newSurface, INT32_MAX-2); + t.setPosition(mFGSurfaceControl, 64, 64); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1283,9 +1306,9 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { mCapture->checkPixel(10, 10, 63, 195, 63); } - SurfaceComposerClient::openGlobalTransaction(); - newSurface->reparent(mFGSurfaceControl->getHandle()); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.reparent(newSurface, mFGSurfaceControl->getHandle()); + }); { ScreenCapture::captureScreen(&mCapture); @@ -1325,12 +1348,12 @@ class LayerColorTest : public LayerUpdateTest { ASSERT_TRUE(mLayerColorControl != NULL); ASSERT_TRUE(mLayerColorControl->isValid()); - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mLayerColorControl->setLayer(INT32_MAX-1)); - ASSERT_EQ(NO_ERROR, mLayerColorControl->setPosition(140, 140)); - ASSERT_EQ(NO_ERROR, mLayerColorControl->hide()); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide()); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.setLayer(mLayerColorControl, INT32_MAX-1); + t.setPosition(mLayerColorControl, 140, 140); + t.hide(mLayerColorControl); + t.hide(mFGSurfaceControl); + }); } void TearDown() override { @@ -1350,15 +1373,16 @@ TEST_F(LayerColorTest, ColorLayerNoAlpha) { sc->expectBGColor(145, 145); } + asTransaction([&](Transaction& t) { + half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); + t.setColor(mLayerColorControl, color); + t.show(mLayerColorControl); + }); - SurfaceComposerClient::openGlobalTransaction(); - half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); - mLayerColorControl->setColor(color); - mLayerColorControl->show(); - SurfaceComposerClient::closeGlobalTransaction(true); { // There should now be a color SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); sc->checkPixel(145, 145, 43, 207, 131); } @@ -1372,12 +1396,13 @@ TEST_F(LayerColorTest, ColorLayerWithAlpha) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); - mLayerColorControl->setColor(color); - mLayerColorControl->setAlpha(.75f); - mLayerColorControl->show(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); + t.setColor(mLayerColorControl, color); + t.setAlpha(mLayerColorControl, .75f); + t.show(mLayerColorControl); + }); + { // There should now be a color with .75 alpha SCOPED_TRACE("after setColor"); @@ -1394,9 +1419,10 @@ TEST_F(LayerColorTest, ColorLayerWithNoColor) { sc->expectBGColor(145, 145); } - SurfaceComposerClient::openGlobalTransaction(); - mLayerColorControl->show(); - SurfaceComposerClient::closeGlobalTransaction(true); + asTransaction([&](Transaction& t) { + t.show(mLayerColorControl); + }); + { // There should now be set to 0,0,0 (black) as default. SCOPED_TRACE("after setColor"); diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h index 74dc0e51bb..1258a970c7 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h @@ -87,7 +87,7 @@ public: /* * All surface state changes are supposed to happen inside a global - * transaction. GlobalTransactionScope object at the beginning of + * transaction. TransactionScope object at the beginning of * scope automates the process. The resulting scope gives a visual cue * on the span of the transaction as well. * @@ -96,23 +96,26 @@ public: * is built to explicitly request vsyncs one at the time. A delayed * request must be made before closing the transaction or the test * thread stalls until SurfaceFlinger does an emergency vsync by - * itself. GlobalTransactionScope encapsulates this vsync magic. + * itself. TransactionScope encapsulates this vsync magic. */ -class GlobalTransactionScope { +class TransactionScope : public android::SurfaceComposerClient::Transaction { public: - GlobalTransactionScope(FakeComposerClient& composer) : mComposer(composer) { - android::SurfaceComposerClient::openGlobalTransaction(); + TransactionScope(FakeComposerClient& composer) : + Transaction(), + mComposer(composer) { } - ~GlobalTransactionScope() { + + ~TransactionScope() { int frameCount = mComposer.getFrameCount(); mComposer.runVSyncAfter(1ms); - android::SurfaceComposerClient::closeGlobalTransaction(true); + LOG_ALWAYS_FATAL_IF(android::NO_ERROR != apply()); // Make sure that exactly one frame has been rendered. mComposer.waitUntilFrame(frameCount + 1); LOG_ALWAYS_FATAL_IF(frameCount + 1 != mComposer.getFrameCount(), "Unexpected frame advance. Delta: %d", mComposer.getFrameCount() - frameCount); } + FakeComposerClient& mComposer; }; diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 9ac3331892..7f4c58a9ba 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -24,11 +24,11 @@ #include #include +#include #include #include #include -#include #include @@ -62,6 +62,8 @@ using ::testing::Return; using ::testing::SetArgPointee; using ::testing::_; +using Transaction = SurfaceComposerClient::Transaction; + /////////////////////////////////////////////// struct TestColor { @@ -248,11 +250,11 @@ TEST_F(DisplayTest, Hotplug) { fillSurfaceRGBA8(surfaceControl, BLUE); { - GlobalTransactionScope gts(*mMockComposer); - mComposerClient->setDisplayLayerStack(display, 0); + TransactionScope ts(*mMockComposer); + ts.setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, surfaceControl->setLayer(INT32_MAX - 2)); - ASSERT_EQ(NO_ERROR, surfaceControl->show()); + ts.setLayer(surfaceControl, INT32_MAX - 2) + .show(surfaceControl); } } @@ -278,11 +280,11 @@ TEST_F(DisplayTest, Hotplug) { fillSurfaceRGBA8(surfaceControl, BLUE); { - GlobalTransactionScope gts(*mMockComposer); - mComposerClient->setDisplayLayerStack(display, 0); + TransactionScope ts(*mMockComposer); + ts.setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, surfaceControl->setLayer(INT32_MAX - 2)); - ASSERT_EQ(NO_ERROR, surfaceControl->show()); + ts.setLayer(surfaceControl, INT32_MAX - 2) + .show(surfaceControl); } } mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED); @@ -370,25 +372,24 @@ void TransactionTest::SetUp() { fillSurfaceRGBA8(mFGSurfaceControl, RED); - SurfaceComposerClient::openGlobalTransaction(); - - mComposerClient->setDisplayLayerStack(display, 0); + Transaction t; + t.setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX - 2)); - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show()); + t.setLayer(mBGSurfaceControl, INT32_MAX - 2); + t.show(mBGSurfaceControl); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX - 1)); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64)); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show()); + t.setLayer(mFGSurfaceControl, INT32_MAX - 1); + t.setPosition(mFGSurfaceControl, 64, 64); + t.show(mFGSurfaceControl); // Synchronous transaction will stop this thread, so we set up a // delayed, off-thread vsync request before closing the // transaction. In the test code this is usually done with - // GlobalTransactionScope. Leaving here in the 'vanilla' form for + // TransactionScope. Leaving here in the 'vanilla' form for // reference. ASSERT_EQ(0, sFakeComposer->getFrameCount()); sFakeComposer->runVSyncAfter(1ms); - SurfaceComposerClient::closeGlobalTransaction(true); + t.apply(); sFakeComposer->waitUntilFrame(1); // Reference data. This is what the HWC should see. @@ -445,8 +446,8 @@ TEST_F(TransactionTest, LayerMove) { // should be available in the latest frame stored by the fake // composer. { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128)); + TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 128, 128); // NOTE: No changes yet, so vsync will do nothing, HWC does not get any calls. // (How to verify that? Throw in vsync and wait a 2x frame time? Separate test?) // @@ -473,8 +474,8 @@ TEST_F(TransactionTest, LayerMove) { TEST_F(TransactionTest, LayerResize) { ALOGD("TransactionTest::LayerResize"); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); } fillSurfaceRGBA8(mFGSurfaceControl, GREEN); @@ -497,9 +498,9 @@ TEST_F(TransactionTest, LayerResize) { TEST_F(TransactionTest, LayerCrop) { // TODO: Add scaling to confirm that crop happens in buffer space? { - GlobalTransactionScope gts(*sFakeComposer); + TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect)); + ts.setCrop(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -512,9 +513,9 @@ TEST_F(TransactionTest, LayerCrop) { TEST_F(TransactionTest, LayerFinalCrop) { // TODO: Add scaling to confirm that crop happens in display space? { - GlobalTransactionScope gts(*sFakeComposer); + TransactionScope ts(*sFakeComposer); Rect cropRect(32, 32, 32 + 64, 32 + 64); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect)); + ts.setFinalCrop(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -530,9 +531,9 @@ TEST_F(TransactionTest, LayerFinalCrop) { TEST_F(TransactionTest, LayerFinalCropEmpty) { // TODO: Add scaling to confirm that crop happens in display space? { - GlobalTransactionScope gts(*sFakeComposer); + TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect)); + ts.setFinalCrop(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -545,8 +546,8 @@ TEST_F(TransactionTest, LayerFinalCropEmpty) { TEST_F(TransactionTest, LayerSetLayer) { { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3)); + TransactionScope ts(*sFakeComposer); + ts.setLayer(mFGSurfaceControl, INT_MAX - 3); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -560,11 +561,10 @@ TEST_F(TransactionTest, LayerSetLayer) { TEST_F(TransactionTest, LayerSetLayerOpaque) { { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3)); - ASSERT_EQ(NO_ERROR, - mBGSurfaceControl->setFlags(layer_state_t::eLayerOpaque, - layer_state_t::eLayerOpaque)); + TransactionScope ts(*sFakeComposer); + ts.setLayer(mFGSurfaceControl, INT_MAX - 3); + ts.setFlags(mBGSurfaceControl, layer_state_t::eLayerOpaque, + layer_state_t::eLayerOpaque); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -577,8 +577,8 @@ TEST_F(TransactionTest, LayerSetLayerOpaque) { TEST_F(TransactionTest, SetLayerStack) { ALOGD("TransactionTest::SetLayerStack"); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1)); + TransactionScope ts(*sFakeComposer); + ts.setLayerStack(mFGSurfaceControl, 1); } // Foreground layer should have disappeared. @@ -591,8 +591,8 @@ TEST_F(TransactionTest, SetLayerStack) { TEST_F(TransactionTest, LayerShowHide) { ALOGD("TransactionTest::LayerShowHide"); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide()); + TransactionScope ts(*sFakeComposer); + ts.hide(mFGSurfaceControl); } // Foreground layer should have disappeared. @@ -602,8 +602,8 @@ TEST_F(TransactionTest, LayerShowHide) { EXPECT_TRUE(framesAreSame(refFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show()); + TransactionScope ts(*sFakeComposer); + ts.show(mFGSurfaceControl); } // Foreground layer should be back @@ -613,8 +613,8 @@ TEST_F(TransactionTest, LayerShowHide) { TEST_F(TransactionTest, LayerSetAlpha) { { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f)); + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 0.75f); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -625,10 +625,9 @@ TEST_F(TransactionTest, LayerSetAlpha) { TEST_F(TransactionTest, LayerSetFlags) { { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, - mFGSurfaceControl->setFlags(layer_state_t::eLayerHidden, - layer_state_t::eLayerHidden)); + TransactionScope ts(*sFakeComposer); + ts.setFlags(mFGSurfaceControl, layer_state_t::eLayerHidden, + layer_state_t::eLayerHidden); } // Foreground layer should have disappeared. @@ -667,10 +666,9 @@ TEST_F(TransactionTest, LayerSetMatrix) { const matrixTestData& xform = MATRIX_TESTS[i]; SCOPED_TRACE(i); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, - mFGSurfaceControl->setMatrix(xform.matrix[0], xform.matrix[1], - xform.matrix[2], xform.matrix[3])); + TransactionScope ts(*sFakeComposer); + ts.setMatrix(mFGSurfaceControl, xform.matrix[0], xform.matrix[1], + xform.matrix[2], xform.matrix[3]); } auto referenceFrame = mBaseFrame; @@ -684,10 +682,10 @@ TEST_F(TransactionTest, LayerSetMatrix) { #if 0 TEST_F(TransactionTest, LayerSetMatrix2) { { - GlobalTransactionScope gts(*sFakeComposer); + TransactionScope ts(*sFakeComposer); // TODO: PLEASE SPEC THE FUNCTION! - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(0.11f, 0.123f, - -2.33f, 0.22f)); + ts.setMatrix(mFGSurfaceControl, 0.11f, 0.123f, + -2.33f, 0.22f); } auto referenceFrame = mBaseFrame; // TODO: Is this correct for sure? @@ -708,10 +706,10 @@ TEST_F(TransactionTest, DeferredTransaction) { fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, syncSurfaceControl->setLayer(INT32_MAX - 1)); - ASSERT_EQ(NO_ERROR, syncSurfaceControl->setPosition(mDisplayWidth - 2, mDisplayHeight - 2)); - ASSERT_EQ(NO_ERROR, syncSurfaceControl->show()); + TransactionScope ts(*sFakeComposer); + ts.setLayer(syncSurfaceControl, INT32_MAX - 1); + ts.setPosition(syncSurfaceControl, mDisplayWidth - 2, mDisplayHeight - 2); + ts.show(syncSurfaceControl); } auto referenceFrame = mBaseFrame; referenceFrame.push_back(makeSimpleRect(mDisplayWidth - 2, mDisplayHeight - 2, @@ -723,20 +721,20 @@ TEST_F(TransactionTest, DeferredTransaction) { // set up two deferred transactions on different frames - these should not yield composited // frames { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75)); - mFGSurfaceControl - ->deferTransactionUntil(syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber()); + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 0.75); + ts.deferTransactionUntil(mFGSurfaceControl, + syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber()); } EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128)); - mFGSurfaceControl - ->deferTransactionUntil(syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 128, 128); + ts.deferTransactionUntil(mFGSurfaceControl, + syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); } EXPECT_EQ(4, sFakeComposer->getFrameCount()); EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); @@ -752,8 +750,8 @@ TEST_F(TransactionTest, DeferredTransaction) { // should show up immediately since it's not deferred { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0)); + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 1.0); } referenceFrame[FG_LAYER].mPlaneAlpha = 1.f; EXPECT_EQ(6, sFakeComposer->getFrameCount()); @@ -777,10 +775,10 @@ TEST_F(TransactionTest, SetRelativeLayer) { // Now we stack the surface above the foreground surface and make sure it is visible. { - GlobalTransactionScope gts(*sFakeComposer); - relativeSurfaceControl->setPosition(64, 64); - relativeSurfaceControl->show(); - relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1); + TransactionScope ts(*sFakeComposer); + ts.setPosition(relativeSurfaceControl, 64, 64); + ts.show(relativeSurfaceControl); + ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1); } auto referenceFrame = mBaseFrame; // NOTE: All three layers will be visible as the surfaces are @@ -791,8 +789,8 @@ TEST_F(TransactionTest, SetRelativeLayer) { // A call to setLayer will override a call to setRelativeLayer { - GlobalTransactionScope gts(*sFakeComposer); - relativeSurfaceControl->setLayer(0); + TransactionScope ts(*sFakeComposer); + ts.setLayer(relativeSurfaceControl, 0); } // Previous top layer will now appear at the bottom. @@ -828,11 +826,11 @@ protected: TEST_F(ChildLayerTest, Positioning) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(10, 10); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 10, 10); // Move to the same position as in the original setup. - mFGSurfaceControl->setPosition(64, 64); + ts.setPosition(mFGSurfaceControl, 64, 64); } auto referenceFrame = mBaseFrame; @@ -842,8 +840,8 @@ TEST_F(ChildLayerTest, Positioning) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0)); + TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 0, 0); } auto referenceFrame2 = mBaseFrame; @@ -855,11 +853,11 @@ TEST_F(ChildLayerTest, Positioning) { TEST_F(ChildLayerTest, Cropping) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5)); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); + ts.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); } // NOTE: The foreground surface would be occluded by the child // now, but is included in the stack because the child is @@ -874,11 +872,11 @@ TEST_F(ChildLayerTest, Cropping) { TEST_F(ChildLayerTest, FinalCropping) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5)); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); + ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; @@ -890,10 +888,10 @@ TEST_F(ChildLayerTest, FinalCropping) { TEST_F(ChildLayerTest, Constraints) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mFGSurfaceControl->setPosition(0, 0); - mChild->setPosition(63, 63); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mFGSurfaceControl, 0, 0); + ts.setPosition(mChild, 63, 63); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64}; @@ -904,8 +902,8 @@ TEST_F(ChildLayerTest, Constraints) { TEST_F(ChildLayerTest, Scaling) { { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setPosition(0, 0); + TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 0, 0); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64}; @@ -913,8 +911,8 @@ TEST_F(ChildLayerTest, Scaling) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0); + TransactionScope ts(*sFakeComposer); + ts.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); } auto referenceFrame2 = mBaseFrame; @@ -925,11 +923,11 @@ TEST_F(ChildLayerTest, Scaling) { TEST_F(ChildLayerTest, LayerAlpha) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); - ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5)); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); + ts.setAlpha(mChild, 0.5); } auto referenceFrame = mBaseFrame; @@ -939,8 +937,8 @@ TEST_F(ChildLayerTest, LayerAlpha) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5)); + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 0.5); } auto referenceFrame2 = referenceFrame; @@ -951,10 +949,10 @@ TEST_F(ChildLayerTest, LayerAlpha) { TEST_F(ChildLayerTest, ReparentChildren) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 10, 10); + ts.setPosition(mFGSurfaceControl, 64, 64); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; @@ -963,8 +961,8 @@ TEST_F(ChildLayerTest, ReparentChildren) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle()); + TransactionScope ts(*sFakeComposer); + ts.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle()); } auto referenceFrame2 = referenceFrame; @@ -975,10 +973,10 @@ TEST_F(ChildLayerTest, ReparentChildren) { TEST_F(ChildLayerTest, DetachChildren) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(10, 10); - mFGSurfaceControl->setPosition(64, 64); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 10, 10); + ts.setPosition(mFGSurfaceControl, 64, 64); } auto referenceFrame = mBaseFrame; @@ -988,13 +986,13 @@ TEST_F(ChildLayerTest, DetachChildren) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->detachChildren(); + TransactionScope ts(*sFakeComposer); + ts.detachChildren(mFGSurfaceControl); } { - GlobalTransactionScope gts(*sFakeComposer); - mChild->hide(); + TransactionScope ts(*sFakeComposer); + ts.hide(mChild); } // Nothing should have changed. The child control becomes a no-op @@ -1005,17 +1003,17 @@ TEST_F(ChildLayerTest, DetachChildren) { TEST_F(ChildLayerTest, InheritNonTransformScalingFromParent) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); } { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + TransactionScope ts(*sFakeComposer); + ts.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); // We cause scaling by 2. - mFGSurfaceControl->setSize(128, 128); + ts.setSize(mFGSurfaceControl, 128, 128); } auto referenceFrame = mBaseFrame; @@ -1029,17 +1027,17 @@ TEST_F(ChildLayerTest, InheritNonTransformScalingFromParent) { // Regression test for b/37673612 TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { { - GlobalTransactionScope gts(*sFakeComposer); - mChild->show(); - mChild->setPosition(0, 0); - mFGSurfaceControl->setPosition(0, 0); + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); } // We set things up as in b/37673612 so that there is a mismatch between the buffer size and // the WM specified state size. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 64); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 64); } sp s = mFGSurfaceControl->getSurface(); @@ -1070,10 +1068,10 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction { - GlobalTransactionScope gts(*sFakeComposer); - mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(), + TransactionScope ts(*sFakeComposer); + ts.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), mFGSurfaceControl->getSurface()->getNextFrameNumber()); - mChild->show(); + ts.show(mChild); } // Render the foreground surface a few times @@ -1110,11 +1108,11 @@ protected: sFakeComposer->runVSyncAndWait(); } void restoreInitialState() { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(64, 64); - mFGSurfaceControl->setPosition(64, 64); - mFGSurfaceControl->setCrop(Rect(0, 0, 64, 64)); - mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 64, 64); + ts.setPosition(mFGSurfaceControl, 64, 64); + ts.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64)); + ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); } }; @@ -1122,9 +1120,9 @@ TEST_F(LatchingTest, SurfacePositionLatching) { // By default position can be updated even while // a resize is pending. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(32, 32); - mFGSurfaceControl->setPosition(100, 100); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 32, 32); + ts.setPosition(mFGSurfaceControl, 100, 100); } // The size should not have updated as we have not provided a new buffer. @@ -1137,10 +1135,10 @@ TEST_F(LatchingTest, SurfacePositionLatching) { // Now we repeat with setGeometryAppliesWithResize // and verify the position DOESN'T latch. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setSize(32, 32); - mFGSurfaceControl->setPosition(100, 100); + TransactionScope ts(*sFakeComposer); + ts.setGeometryAppliesWithResize(mFGSurfaceControl); + ts.setSize(mFGSurfaceControl, 32, 32); + ts.setPosition(mFGSurfaceControl, 100, 100); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1156,9 +1154,9 @@ TEST_F(LatchingTest, SurfacePositionLatching) { TEST_F(LatchingTest, CropLatching) { // Normally the crop applies immediately even while a resize is pending. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); } auto referenceFrame1 = mBaseFrame; @@ -1169,10 +1167,10 @@ TEST_F(LatchingTest, CropLatching) { restoreInitialState(); { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setGeometryAppliesWithResize(mFGSurfaceControl); + ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1188,9 +1186,9 @@ TEST_F(LatchingTest, CropLatching) { TEST_F(LatchingTest, FinalCropLatching) { // Normally the crop applies immediately even while a resize is pending. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1202,10 +1200,10 @@ TEST_F(LatchingTest, FinalCropLatching) { restoreInitialState(); { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setGeometryAppliesWithResize(mFGSurfaceControl); + ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1224,9 +1222,9 @@ TEST_F(LatchingTest, FinalCropLatching) { TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { // Normally the crop applies immediately even while a resize is pending. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1242,10 +1240,10 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { lockAndFillFGBuffer(); { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setGeometryAppliesWithResize(mFGSurfaceControl); + ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1271,15 +1269,15 @@ TEST_F(LatchingTest, FinalCropLatchingRegressionForb37531386) { // is still pending, and ensure we are successful. Success meaning the second crop // is the one which eventually latches and not the first. { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setSize(128, 128); - mFGSurfaceControl->setGeometryAppliesWithResize(); - mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127)); + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + ts.setGeometryAppliesWithResize(mFGSurfaceControl); + ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); } { - GlobalTransactionScope gts(*sFakeComposer); - mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1)); + TransactionScope ts(*sFakeComposer); + ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); -- cgit v1.2.3-59-g8ed1b From a76b271f0e14325fa0ebb98e1cac0a15adfea1cb Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 20 Sep 2017 12:02:26 -0700 Subject: Add captureLayers function to capture a layer and its children. The captureLayers function gets a root layer as its argument. It will capture the content for that layer and its descendants. The capture will set the root layer's transform back to (0, 0). Test: Transaction_test ScreenCaptureTest Change-Id: I84fb66a65cd91434cddc99506b1924cf9f950935 --- libs/gui/ISurfaceComposer.cpp | 24 ++ libs/gui/SurfaceComposerClient.cpp | 9 + libs/gui/include/gui/ISurfaceComposer.h | 5 + libs/gui/include/gui/SurfaceComposerClient.h | 3 + libs/gui/tests/Surface_test.cpp | 5 + services/surfaceflinger/Android.mk | 1 + services/surfaceflinger/ColorLayer.cpp | 7 +- services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/DisplayDevice.h | 31 ++ services/surfaceflinger/Layer.cpp | 85 +++--- services/surfaceflinger/Layer.h | 23 +- services/surfaceflinger/RenderArea.cpp | 34 +++ services/surfaceflinger/RenderArea.h | 40 +++ services/surfaceflinger/SurfaceFlinger.cpp | 326 +++++++++++---------- services/surfaceflinger/SurfaceFlinger.h | 43 +-- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 326 +++++++++++---------- services/surfaceflinger/Transform.cpp | 19 +- services/surfaceflinger/Transform.h | 4 + services/surfaceflinger/tests/Transaction_test.cpp | 159 ++++++++++ 19 files changed, 760 insertions(+), 386 deletions(-) create mode 100644 services/surfaceflinger/RenderArea.cpp create mode 100644 services/surfaceflinger/RenderArea.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 96771257c1..973302c226 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -122,6 +122,18 @@ public: return reply.readInt32(); } + virtual status_t captureLayers(const sp& layerHandleBinder, + const sp& producer, + ISurfaceComposer::Rotation rotation) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(layerHandleBinder); + data.writeStrongBinder(IInterface::asBinder(producer)); + data.writeInt32(static_cast(rotation)); + remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + return reply.readInt32(); + } + virtual bool authenticateSurfaceTexture( const sp& bufferProducer) const { @@ -588,6 +600,18 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(res); return NO_ERROR; } + case CAPTURE_LAYERS: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp layerHandleBinder = data.readStrongBinder(); + sp producer = + interface_cast(data.readStrongBinder()); + int32_t rotation = data.readInt32(); + + status_t res = captureLayers(layerHandleBinder, producer, + static_cast(rotation)); + reply->writeInt32(res); + return NO_ERROR; + } case AUTHENTICATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp bufferProducer = diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 40e319e28a..15c4c9a880 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -731,6 +731,15 @@ status_t ScreenshotClient::captureToBuffer(const sp& display, return ret; } +status_t ScreenshotClient::captureLayers(const sp& layerHandle, + const sp& producer, + uint32_t rotation) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + return s->captureLayers(layerHandle, producer, + static_cast(rotation)); +} + ScreenshotClient::ScreenshotClient() : mHaveBuffer(false) { memset(&mBuffer, 0, sizeof(mBuffer)); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index b2267426a8..13e7473d54 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -174,6 +174,10 @@ public: bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; + virtual status_t captureLayers(const sp& layerHandleBinder, + const sp& producer, + Rotation rotation = eRotateNone) = 0; + /* Clears the frame statistics for animations. * * Requires the ACCESS_SURFACE_FLINGER permission. @@ -226,6 +230,7 @@ public: SET_ACTIVE_CONFIG, CONNECT_DISPLAY, CAPTURE_SCREEN, + CAPTURE_LAYERS, CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, SET_POWER_MODE, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 00d593638d..d63dafea41 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,6 +297,9 @@ public: bool useIdentityTransform, uint32_t rotation, sp* outbuffer); + static status_t captureLayers(const sp& layerHandle, + const sp& producer, uint32_t rotation); + private: mutable sp mCpuConsumer; mutable sp mProducer; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 572760e77d..660680bf9e 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -529,6 +529,11 @@ public: int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } + virtual status_t captureLayers(const sp& /*parentHandle*/, + const sp& /*producer*/, + ISurfaceComposer::Rotation /*rotation*/) override { + return NO_ERROR; + } status_t clearAnimationFrameStats() override { return NO_ERROR; } status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override { return NO_ERROR; diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index d8152e08cc..d9bca04b0b 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -40,6 +40,7 @@ LOCAL_SRC_FILES := \ RenderEngine/Texture.cpp \ RenderEngine/GLES20RenderEngine.cpp \ LayerProtoHelper.cpp \ + RenderArea.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 6923782b27..32526dd29b 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -40,13 +40,12 @@ ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, : Layer(flinger, client, name, w, h, flags) { } -void ColorLayer::onDraw(const sp& hw, - const Region& /* clip */, bool useIdentityTransform) const -{ +void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, + bool useIdentityTransform) const { const State& s(getDrawingState()); if (s.color.a>0) { Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); - computeGeometry(hw, mesh, useIdentityTransform); + computeGeometry(renderArea, mesh, useIdentityTransform); RenderEngine& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, true /* disableTexture */, s.color); diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index ac3e2a95dc..cdf3eca60a 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -34,7 +34,7 @@ public: virtual ~ColorLayer() = default; virtual const char* getTypeId() const { return "ColorLayer"; } - virtual void onDraw(const sp& hw, const Region& clip, + virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const; virtual bool isOpaque(const Layer::State&) const { return false; } virtual bool isSecure() const { return false; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8636e2af79..49fef5805f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -37,7 +37,9 @@ #include #include +#include #include +#include "RenderArea.h" #ifdef USE_HWC2 #include @@ -300,6 +302,35 @@ struct DisplayDeviceState { bool isSecure = false; }; +class DisplayRenderArea : public RenderArea { +public: + DisplayRenderArea(const sp device, + ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) + : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(), + rotation) {} + DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqHeight, + uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {} + + const Transform& getTransform() const override { return mDevice->getTransform(); } + Rect getBounds() const override { return mDevice->getBounds(); } + int getHeight() const override { return mDevice->getHeight(); } + int getWidth() const override { return mDevice->getWidth(); } + bool isSecure() const override { return mDevice->isSecure(); } + bool needsFiltering() const override { return mDevice->needsFiltering(); } + Rect getSourceCrop() const override { return mSourceCrop; } +#ifdef USE_HWC2 + bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } + android_color_mode_t getActiveColorMode() const override { + return mDevice->getActiveColorMode(); + } +#endif + +private: + const sp mDevice; + const Rect mSourceCrop; +}; + }; // namespace android #endif // ANDROID_DISPLAY_DEVICE_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 27739ce074..56328c9b3d 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1063,17 +1063,16 @@ Rect Layer::getPosition( // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const sp& hw, const Region& clip) const { - onDraw(hw, clip, false); +void Layer::draw(const RenderArea& renderArea, const Region& clip) const { + onDraw(renderArea, clip, false); } -void Layer::draw(const sp& hw, - bool useIdentityTransform) const { - onDraw(hw, Region(hw->bounds()), useIdentityTransform); +void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const { + onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const sp& hw) const { - onDraw(hw, Region(hw->bounds()), false); +void Layer::draw(const RenderArea& renderArea) const { + onDraw(renderArea, Region(renderArea.getBounds()), false); } static constexpr mat4 inverseOrientation(uint32_t transform) { @@ -1097,7 +1096,7 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { /* * onDraw will draw the current layer onto the presentable buffer */ -void Layer::onDraw(const sp& hw, const Region& clip, +void Layer::onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const { ATRACE_CALL(); @@ -1119,12 +1118,12 @@ void Layer::onDraw(const sp& hw, const Region& clip, finished = true; return; } - under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); + under.orSelf(renderArea.getTransform().transform(layer->visibleRegion)); }); // if not everything below us is covered, we plug the holes! Region holes(clip.subtract(under)); if (!holes.isEmpty()) { - clearWithOpenGL(hw, 0, 0, 0, 1); + clearWithOpenGL(renderArea, 0, 0, 0, 1); } return; } @@ -1138,13 +1137,13 @@ void Layer::onDraw(const sp& hw, const Region& clip, // is probably going to have something visibly wrong. } - bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); + bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure()); RenderEngine& engine(mFlinger->getRenderEngine()); if (!blackOutLayer) { // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); + const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize(); // Query the texture matrix given our current filtering mode. float textureMatrix[16]; @@ -1190,31 +1189,29 @@ void Layer::onDraw(const sp& hw, const Region& clip, } else { engine.setupLayerBlackedOut(); } - drawWithOpenGL(hw, useIdentityTransform); + drawWithOpenGL(renderArea, useIdentityTransform); engine.disableTexturing(); } -void Layer::clearWithOpenGL(const sp& hw, +void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, float alpha) const { RenderEngine& engine(mFlinger->getRenderEngine()); - computeGeometry(hw, mMesh, false); + computeGeometry(renderArea, mMesh, false); engine.setupFillWithColor(red, green, blue, alpha); engine.drawMesh(mMesh); } -void Layer::clearWithOpenGL( - const sp& hw) const { - clearWithOpenGL(hw, 0,0,0,0); +void Layer::clearWithOpenGL(const RenderArea& renderArea) const { + clearWithOpenGL(renderArea, 0,0,0,0); } -void Layer::drawWithOpenGL(const sp& hw, - bool useIdentityTransform) const { +void Layer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { const State& s(getDrawingState()); - computeGeometry(hw, mMesh, useIdentityTransform); + computeGeometry(renderArea, mMesh, useIdentityTransform); /* * NOTE: the way we compute the texture coordinates here produces @@ -1440,12 +1437,11 @@ static void boundPoint(vec2* point, const Rect& crop) { } } -void Layer::computeGeometry(const sp& hw, Mesh& mesh, - bool useIdentityTransform) const -{ +void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, + bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); - const Transform hwTransform(hw->getTransform()); - const uint32_t hw_h = hw->getHeight(); + const Transform renderAreaTransform(renderArea.getTransform()); + const uint32_t height = renderArea.getHeight(); Rect win = computeBounds(); vec2 lt = vec2(win.left, win.top); @@ -1469,12 +1465,12 @@ void Layer::computeGeometry(const sp& hw, Mesh& mesh, } Mesh::VertexArray position(mesh.getPositionArray()); - position[0] = hwTransform.transform(lt); - position[1] = hwTransform.transform(lb); - position[2] = hwTransform.transform(rb); - position[3] = hwTransform.transform(rt); + position[0] = renderAreaTransform.transform(lt); + position[1] = renderAreaTransform.transform(lb); + position[2] = renderAreaTransform.transform(rb); + position[3] = renderAreaTransform.transform(rt); for (size_t i=0 ; i<4 ; i++) { - position[i].y = hw_h - position[i].y; + position[i].y = height - position[i].y; } } @@ -1512,8 +1508,8 @@ bool Layer::isCropped() const { return !mCurrentCrop.isEmpty(); } -bool Layer::needsFiltering(const sp& hw) const { - return mNeedsFiltering || hw->needsFiltering(); +bool Layer::needsFiltering(const RenderArea& renderArea) const { + return mNeedsFiltering || renderArea.needsFiltering(); } void Layer::setVisibleRegion(const Region& visibleRegion) { @@ -2773,6 +2769,29 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, } } +/** + * Traverse only children in z order, ignoring relative layers. + */ +void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + + size_t i = 0; + for (; i < children.size(); i++) { + const auto& relative = children[i]; + if (relative->getZ() >= 0) { + break; + } + relative->traverseChildrenInZOrder(stateSet, visitor); + } + visitor(this); + for (; i < children.size(); i++) { + const auto& relative = children[i]; + relative->traverseChildrenInZOrder(stateSet, visitor); + } +} + Transform Layer::getTransform() const { Transform t; const auto& p = mDrawingParent.promote(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 06c4863ce2..d75e175f5a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -50,6 +50,7 @@ #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" #include +#include "RenderArea.h" #include @@ -255,8 +256,7 @@ public: return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay); } - void computeGeometry(const sp& hw, Mesh& mesh, - bool useIdentityTransform) const; + void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const; Rect computeBounds(const Region& activeTransparentRegion) const; Rect computeBounds() const; @@ -312,7 +312,7 @@ protected: /* * onDraw - draws the surface. */ - virtual void onDraw(const sp& hw, const Region& clip, + virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const; public: @@ -379,9 +379,9 @@ public: * draw - performs some global clipping optimizations * and calls onDraw(). */ - void draw(const sp& hw, const Region& clip) const; - void draw(const sp& hw, bool useIdentityTransform) const; - void draw(const sp& hw) const; + void draw(const RenderArea& renderArea, const Region& clip) const; + void draw(const RenderArea& renderArea, bool useIdentityTransform) const; + void draw(const RenderArea& renderArea) const; /* * doTransaction - process the transaction. This is a good place to figure @@ -472,7 +472,7 @@ public: #endif // ----------------------------------------------------------------------- - void clearWithOpenGL(const sp& hw) const; + void clearWithOpenGL(const RenderArea& renderArea) const; void setFiltering(bool filtering); bool getFiltering() const; @@ -516,6 +516,9 @@ public: const LayerVector::Visitor& visitor); void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); + void traverseChildrenInZOrder(LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor); + size_t getChildrenCount() const; void addChild(const sp& layer); // Returns index if removed, or negative value otherwise @@ -569,7 +572,7 @@ private: void commitTransaction(const State& stateToCommit); // needsLinearFiltering - true if this surface's state requires filtering - bool needsFiltering(const sp& hw) const; + bool needsFiltering(const RenderArea& renderArea) const; uint32_t getEffectiveUsage(uint32_t usage) const; @@ -582,9 +585,9 @@ private: static bool getOpacityForFormat(uint32_t format); // drawing - void clearWithOpenGL(const sp& hw, + void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, float alpha) const; - void drawWithOpenGL(const sp& hw, + void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; // Temporary - Used only for LEGACY camera mode. diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp new file mode 100644 index 0000000000..6225df134d --- /dev/null +++ b/services/surfaceflinger/RenderArea.cpp @@ -0,0 +1,34 @@ +#include "RenderArea.h" + +namespace android { + +/* + * Checks that the requested width and height are valid and updates them to the render area + * dimensions if they are set to 0 + */ +status_t RenderArea::updateDimensions() { + // get screen geometry + + uint32_t width = getWidth(); + uint32_t height = getHeight(); + + if (mRotationFlags & Transform::ROT_90) { + std::swap(width, height); + } + + if ((mReqWidth > width) || (mReqHeight > height)) { + ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height); + return BAD_VALUE; + } + + if (mReqWidth == 0) { + mReqWidth = width; + } + if (mReqHeight == 0) { + mReqHeight = height; + } + + return NO_ERROR; +} + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h new file mode 100644 index 0000000000..faf1ec64f8 --- /dev/null +++ b/services/surfaceflinger/RenderArea.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Transform.h" + +namespace android { + +class RenderArea { +public: + RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + : mReqHeight(reqHeight), mReqWidth(reqWidth) { + mRotationFlags = Transform::fromRotation(rotation); + } + + virtual ~RenderArea() = default; + + virtual const Transform& getTransform() const = 0; + virtual Rect getBounds() const = 0; + virtual int getHeight() const = 0; + virtual int getWidth() const = 0; + virtual bool isSecure() const = 0; + virtual bool needsFiltering() const = 0; + virtual Rect getSourceCrop() const = 0; + + int getReqHeight() const { return mReqHeight; }; + int getReqWidth() const { return mReqWidth; }; + Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; +#ifdef USE_HWC2 + virtual bool getWideColorSupport() const = 0; + virtual android_color_mode_t getActiveColorMode() const = 0; +#endif + + status_t updateDimensions(); + +private: + uint32_t mReqHeight; + uint32_t mReqWidth; + Transform::orientation_flags mRotationFlags; +}; + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 05c76fce46..fe9409b35e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2650,6 +2650,7 @@ bool SurfaceFlinger::doComposeSurfaces( { ALOGV("doComposeSurfaces"); + const DisplayRenderArea renderArea(displayDevice); const auto hwcId = displayDevice->getHwcDisplayId(); mat4 oldColorMatrix; @@ -2759,12 +2760,12 @@ bool SurfaceFlinger::doComposeSurfaces( && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - layer->clearWithOpenGL(displayDevice); + layer->clearWithOpenGL(renderArea); } break; } case HWC2::Composition::Client: { - layer->draw(displayDevice, clip); + layer->draw(renderArea, clip); break; } default: @@ -2781,7 +2782,7 @@ bool SurfaceFlinger::doComposeSurfaces( const Region clip(dirty.intersect( displayTransform.transform(layer->visibleRegion))); if (!clip.isEmpty()) { - layer->draw(displayDevice, clip); + layer->draw(renderArea, clip); } } } @@ -4029,6 +4030,17 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { } break; } + case CAPTURE_LAYERS: { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) { + ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + break; + } } return OK; } @@ -4228,35 +4240,6 @@ void SurfaceFlinger::repaintEverything() { repaintEverythingLocked(); } -// Checks that the requested width and height are valid and updates them to the display dimensions -// if they are set to 0 -static status_t updateDimensionsLocked(const sp& displayDevice, - Transform::orientation_flags rotation, - uint32_t* requestedWidth, uint32_t* requestedHeight) { - // get screen geometry - uint32_t displayWidth = displayDevice->getWidth(); - uint32_t displayHeight = displayDevice->getHeight(); - - if (rotation & Transform::ROT_90) { - std::swap(displayWidth, displayHeight); - } - - if ((*requestedWidth > displayWidth) || (*requestedHeight > displayHeight)) { - ALOGE("size mismatch (%d, %d) > (%d, %d)", - *requestedWidth, *requestedHeight, displayWidth, displayHeight); - return BAD_VALUE; - } - - if (*requestedWidth == 0) { - *requestedWidth = displayWidth; - } - if (*requestedHeight == 0) { - *requestedHeight = displayHeight; - } - - return NO_ERROR; -} - // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope class WindowDisconnector { public: @@ -4305,50 +4288,86 @@ static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, } status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { + const sp& producer, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, + int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); - if (CC_UNLIKELY(display == 0)) - return BAD_VALUE; + if (CC_UNLIKELY(display == 0)) return BAD_VALUE; + + const sp device(getDisplayDeviceLocked(display)); + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); + + auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, + device, minLayerZ, maxLayerZ, std::placeholders::_1); + return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); +} + +status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, + const sp& producer, + ISurfaceComposer::Rotation rotation) { + ATRACE_CALL(); + + class LayerRenderArea : public RenderArea { + public: + LayerRenderArea(const sp& layer, ISurfaceComposer::Rotation rotation) + : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, + rotation), + mLayer(layer) {} + const Transform& getTransform() const override { + // Make the top level transform the inverse the transform and it's parent so it sets + // the whole capture back to 0,0 + return *new Transform(mLayer->getTransform().inverse()); + } + Rect getBounds() const override { + const Layer::State& layerState(mLayer->getDrawingState()); + return Rect(layerState.active.w, layerState.active.h); + } + int getHeight() const override { return mLayer->getDrawingState().active.h; } + int getWidth() const override { return mLayer->getDrawingState().active.w; } + bool isSecure() const override { return false; } + bool needsFiltering() const override { return false; } + + Rect getSourceCrop() const override { return getBounds(); } + bool getWideColorSupport() const override { return false; } + android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } + + private: + const sp& mLayer; + }; + + auto layerHandle = reinterpret_cast(layerHandleBinder.get()); + auto parent = layerHandle->owner.promote(); + + LayerRenderArea renderArea(parent, rotation); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { + parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + }; + return captureScreenCommon(renderArea, traverseLayers, producer, false); +} + +status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform) { + ATRACE_CALL(); if (CC_UNLIKELY(producer == 0)) return BAD_VALUE; + renderArea.updateDimensions(); + // if we have secure windows on this display, never allow the screen capture // unless the producer interface is local (i.e.: we can take a screenshot for // ourselves). bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - // Convert to surfaceflinger's internal rotation type. - Transform::orientation_flags rotationFlags; - switch (rotation) { - case ISurfaceComposer::eRotateNone: - rotationFlags = Transform::ROT_0; - break; - case ISurfaceComposer::eRotate90: - rotationFlags = Transform::ROT_90; - break; - case ISurfaceComposer::eRotate180: - rotationFlags = Transform::ROT_180; - break; - case ISurfaceComposer::eRotate270: - rotationFlags = Transform::ROT_270; - break; - default: - rotationFlags = Transform::ROT_0; - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - break; - } - - { // Autolock scope - Mutex::Autolock lock(mStateLock); - sp displayDevice(getDisplayDeviceLocked(display)); - updateDimensionsLocked(displayDevice, rotationFlags, &reqWidth, &reqHeight); - } - // create a surface (because we're a producer, and we need to // dequeue/queue a buffer) sp surface = new Surface(producer, false); @@ -4369,9 +4388,9 @@ status_t SurfaceFlinger::captureScreen(const sp& display, WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, reqWidth, reqHeight, - hasWideColorDisplay && !mForceNativeColorMode, - getRenderEngine().usesWideColor(), &buffer); + result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), + hasWideColorDisplay && !mForceNativeColorMode, + getRenderEngine().usesWideColor(), &buffer); if (result != NO_ERROR) { return result; } @@ -4399,10 +4418,8 @@ status_t SurfaceFlinger::captureScreen(const sp& display, int fd = -1; { Mutex::Autolock _l(mStateLock); - sp device(getDisplayDeviceLocked(display)); - result = captureScreenImplLocked(device, buffer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - rotationFlags, isLocalScreenshot, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, buffer, + useIdentityTransform, isLocalScreenshot, &fd); } { @@ -4431,84 +4448,66 @@ status_t SurfaceFlinger::captureScreen(const sp& display, // queueBuffer takes ownership of syncFd result = window->queueBuffer(window, buffer, syncFd); } - return result; } - -void SurfaceFlinger::renderScreenImplLocked( - const sp& hw, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) -{ +void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, bool yswap, + bool useIdentityTransform) { ATRACE_CALL(); + RenderEngine& engine(getRenderEngine()); // get screen geometry - const int32_t hw_w = hw->getWidth(); - const int32_t hw_h = hw->getHeight(); - const bool filtering = static_cast(reqWidth) != hw_w || - static_cast(reqHeight) != hw_h; + const auto raWidth = renderArea.getWidth(); + const auto raHeight = renderArea.getHeight(); + + const auto reqWidth = renderArea.getReqWidth(); + const auto reqHeight = renderArea.getReqHeight(); + Rect sourceCrop = renderArea.getSourceCrop(); + + const bool filtering = static_cast(reqWidth) != raWidth || + static_cast(reqHeight) != raHeight; // if a default or invalid sourceCrop is passed in, set reasonable values - if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || - !sourceCrop.isValid()) { + if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) { sourceCrop.setLeftTop(Point(0, 0)); - sourceCrop.setRightBottom(Point(hw_w, hw_h)); + sourceCrop.setRightBottom(Point(raWidth, raHeight)); } // ensure that sourceCrop is inside screen if (sourceCrop.left < 0) { ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left); } - if (sourceCrop.right > hw_w) { - ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w); + if (sourceCrop.right > raWidth) { + ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth); } if (sourceCrop.top < 0) { ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top); } - if (sourceCrop.bottom > hw_h) { - ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h); + if (sourceCrop.bottom > raHeight) { + ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } -#ifdef USE_HWC2 - engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode()); -#endif + engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); // set-up our viewport - engine.setViewportAndProjection( - reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); + engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap, + renderArea.getRotationFlags()); engine.disableTexturing(); // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - // We loop through the first level of layers without traversing, - // as we need to interpret min/max layer Z in the top level Z space. - for (const auto& layer : mDrawingState.layersSortedByZ) { - if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { - continue; - } - const Layer::State& state(layer->getDrawingState()); - if (state.z < minLayerZ || state.z > maxLayerZ) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->isVisible()) { - return; - } - if (filtering) layer->setFiltering(true); - layer->draw(hw, useIdentityTransform); - if (filtering) layer->setFiltering(false); - }); - } - - hw->setViewportAndProjection(); + traverseLayers([&](Layer* layer) { + if (filtering) layer->setFiltering(true); + layer->draw(renderArea, useIdentityTransform); + if (filtering) layer->setFiltering(false); + }); } // A simple RAII class that holds an EGLImage and destroys it either: @@ -4531,27 +4530,18 @@ private: EGLImageKHR mImage; }; -status_t SurfaceFlinger::captureScreenImplLocked(const sp& hw, - ANativeWindowBuffer* buffer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Transform::orientation_flags rotation, - bool isLocalScreenshot, int* outSyncFd) { +status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + ANativeWindowBuffer* buffer, + bool useIdentityTransform, bool isLocalScreenshot, + int* outSyncFd) { ATRACE_CALL(); bool secureLayerIsVisible = false; - for (const auto& layer : mDrawingState.layersSortedByZ) { - const Layer::State& state(layer->getDrawingState()); - if (!layer->belongsToDisplay(hw->getLayerStack(), false) || - (state.z < minLayerZ || state.z > maxLayerZ)) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) { - secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && - layer->isSecure()); - }); - } + + traverseLayers([&](Layer* layer) { + secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); + }); if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); @@ -4582,9 +4572,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp& // via an FBO, which means we didn't have to create // an EGLSurface and therefore we're not // dependent on the context's EGLConfig. - renderScreenImplLocked( - hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true, - useIdentityTransform, rotation); + renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); // Attempt to create a sync khr object that can produce a sync point. If that // isn't available, create a non-dupable sync object in the fallback path and @@ -4625,46 +4613,40 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp& *outSyncFd = syncFd; if (DEBUG_SCREENSHOTS) { + const auto reqWidth = renderArea.getReqWidth(); + const auto reqHeight = renderArea.getReqHeight(); + uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); - checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, - hw, minLayerZ, maxLayerZ); + checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, traverseLayers); delete [] pixels; } // destroy our image imageHolder.destroy(); - return NO_ERROR; } void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp& hw, int32_t minLayerZ, int32_t maxLayerZ) { + TraverseLayersFunction traverseLayers) { if (DEBUG_SCREENSHOTS) { - for (size_t y=0 ; ygetLayerStack()); + ALOGE("*** we just took a black screenshot ***"); size_t i = 0; - for (const auto& layer : mDrawingState.layersSortedByZ) { + traverseLayers([&](Layer* layer) { const Layer::State& state(layer->getDrawingState()); - if (layer->belongsToDisplay(hw->getLayerStack(), false) && state.z >= minLayerZ && - state.z <= maxLayerZ) { - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", - layer->isVisible() ? '+' : '-', - i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, static_cast(state.color.a)); - i++; - }); - } - } + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", + layer->isVisible() ? '+' : '-', i, layer->getName().string(), + layer->getLayerStack(), state.z, layer->isVisible(), state.flags, + static_cast(state.color.a)); + i++; + }); } } @@ -4678,6 +4660,28 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } +void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, int32_t minLayerZ, + int32_t maxLayerZ, + const LayerVector::Visitor& visitor) { + // We loop through the first level of layers without traversing, + // as we need to interpret min/max layer Z in the top level Z space. + for (const auto& layer : mDrawingState.layersSortedByZ) { + if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + continue; + } + const Layer::State& state(layer->getDrawingState()); + if (state.z < minLayerZ || state.z > maxLayerZ) { + continue; + } + layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + } +} + }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bd98c8f0e0..9975de9252 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -77,6 +77,7 @@ #include #include #include +#include "RenderArea.h" #include @@ -97,6 +98,8 @@ class EventControlThread; class VSyncSource; class InjectVSyncSource; +typedef std::function TraverseLayersFunction; + namespace dvr { class VrFlinger; } // namespace dvr @@ -303,6 +306,9 @@ private: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, + const sp& producer, + ISurfaceComposer::Rotation rotation); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, @@ -448,28 +454,26 @@ private: void startBootAnim(); - void renderScreenImplLocked( - const sp& hw, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation); + void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, + bool yswap, bool useIdentityTransform); + + status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform); #ifdef USE_HWC2 - status_t captureScreenImplLocked(const sp& device, - ANativeWindowBuffer* buffer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, - Transform::orientation_flags rotation, bool isLocalScreenshot, - int* outSyncFd); + status_t captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + ANativeWindowBuffer* buffer, bool useIdentityTransform, + bool isLocalScreenshot, int* outSyncFd); #else - status_t captureScreenImplLocked( - const sp& hw, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation, - bool isLocalScreenshot); + status_t captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform, bool isLocalScreenshot); #endif + void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, + int32_t maxLayerZ, const LayerVector::Visitor& visitor); sp mStartPropertySetThread = nullptr; @@ -613,8 +617,7 @@ private: bool startDdmConnection(); void appendSfConfigString(String8& result) const; void checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp& hw, - int32_t minLayerZ, int32_t maxLayerZ); + TraverseLayersFunction traverseLayers); void logFrameStats(); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index ed7641fe99..8c530e0f61 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -2212,6 +2212,8 @@ void SurfaceFlinger::doDisplayComposition(const sp& hw, bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty) { + DisplayRenderArea renderArea(hw); + RenderEngine& engine(getRenderEngine()); const int32_t id = hw->getHwcDisplayId(); HWComposer& hwc(getHwComposer()); @@ -2303,12 +2305,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const && hasGlesComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - layer->clearWithOpenGL(hw); + layer->clearWithOpenGL(renderArea); } break; } case HWC_FRAMEBUFFER: { - layer->draw(hw, clip); + layer->draw(renderArea, clip); break; } case HWC_FRAMEBUFFER_TARGET: { @@ -2328,7 +2330,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const const Region clip(dirty.intersect( tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { - layer->draw(hw, clip); + layer->draw(renderArea, clip); } } } @@ -3493,6 +3495,18 @@ status_t SurfaceFlinger::onTransact( } break; } + case CAPTURE_LAYERS: + { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) { + ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + break; + } } status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); @@ -3766,16 +3780,72 @@ public: } }; - status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { - + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { + ATRACE_CALL(); if (CC_UNLIKELY(display == 0)) return BAD_VALUE; + const sp device(getDisplayDeviceLocked(display)); + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); + + auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, + device, minLayerZ, maxLayerZ, std::placeholders::_1); + return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); +} + +status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, + const sp& producer, + ISurfaceComposer::Rotation rotation) { + ATRACE_CALL(); + class LayerRenderArea : public RenderArea { + public: + LayerRenderArea(const sp& layer, ISurfaceComposer::Rotation rotation) + : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, + rotation), + mLayer(layer) {} + const Transform& getTransform() const override { + // Make the top level transform the inverse the transform and it's parent so it sets + // the whole capture back to 0,0 + return *new Transform(mLayer->getTransform().inverse()); + } + Rect getBounds() const override { + const Layer::State& layerState(mLayer->getDrawingState()); + return Rect(layerState.active.w, layerState.active.h); + } + int getHeight() const override { return mLayer->getDrawingState().active.h; } + int getWidth() const override { return mLayer->getDrawingState().active.w; } + bool isSecure() const override { return false; } + bool needsFiltering() const override { return false; } + + Rect getSourceCrop() const override { return getBounds(); } + + private: + const sp& mLayer; + }; + + auto layerHandle = reinterpret_cast(layerHandleBinder.get()); + auto parent = layerHandle->owner.promote(); + + LayerRenderArea renderArea(parent, rotation); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { + parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + }; + return captureScreenCommon(renderArea, traverseLayers, producer, false); +} + +status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform) { if (CC_UNLIKELY(producer == 0)) return BAD_VALUE; @@ -3784,64 +3854,33 @@ status_t SurfaceFlinger::captureScreen(const sp& display, // ourselves). bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - // Convert to surfaceflinger's internal rotation type. - Transform::orientation_flags rotationFlags; - switch (rotation) { - case ISurfaceComposer::eRotateNone: - rotationFlags = Transform::ROT_0; - break; - case ISurfaceComposer::eRotate90: - rotationFlags = Transform::ROT_90; - break; - case ISurfaceComposer::eRotate180: - rotationFlags = Transform::ROT_180; - break; - case ISurfaceComposer::eRotate270: - rotationFlags = Transform::ROT_270; - break; - default: - rotationFlags = Transform::ROT_0; - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - break; - } - class MessageCaptureScreen : public MessageBase { SurfaceFlinger* flinger; - sp display; + const RenderArea* renderArea; + TraverseLayersFunction traverseLayers; sp producer; - Rect sourceCrop; - uint32_t reqWidth, reqHeight; - int32_t minLayerZ,maxLayerZ; bool useIdentityTransform; - Transform::orientation_flags rotation; status_t result; bool isLocalScreenshot; public: - MessageCaptureScreen(SurfaceFlinger* flinger, - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Transform::orientation_flags rotation, - bool isLocalScreenshot) - : flinger(flinger), display(display), producer(producer), - sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight), - minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), - useIdentityTransform(useIdentityTransform), - rotation(rotation), result(PERMISSION_DENIED), - isLocalScreenshot(isLocalScreenshot) - { - } + MessageCaptureScreen(SurfaceFlinger* flinger, const RenderArea* renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, bool useIdentityTransform, + bool isLocalScreenshot) + : flinger(flinger), + renderArea(renderArea), + traverseLayers(traverseLayers), + producer(producer), + useIdentityTransform(useIdentityTransform), + result(PERMISSION_DENIED), + isLocalScreenshot(isLocalScreenshot) {} status_t getResult() const { return result; } virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); - sp hw(flinger->getDisplayDeviceLocked(display)); - result = flinger->captureScreenImplLocked(hw, producer, - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotation, isLocalScreenshot); + result = flinger->captureScreenImplLocked(*renderArea, traverseLayers, producer, + useIdentityTransform, isLocalScreenshot); static_cast(IInterface::asBinder(producer).get())->exit(result); return true; } @@ -3855,9 +3894,8 @@ status_t SurfaceFlinger::captureScreen(const sp& display, // the asInterface() call below creates our "fake" BpGraphicBufferProducer // which does the marshaling work forwards to our "fake remote" above. sp msg = new MessageCaptureScreen(this, - display, IGraphicBufferProducer::asInterface( wrapper ), - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotationFlags, isLocalScreenshot); + &renderArea, traverseLayers, IGraphicBufferProducer::asInterface( wrapper ), + useIdentityTransform, isLocalScreenshot); status_t res = postMessageAsync(msg); if (res == NO_ERROR) { @@ -3866,41 +3904,42 @@ status_t SurfaceFlinger::captureScreen(const sp& display, return res; } - -void SurfaceFlinger::renderScreenImplLocked( - const sp& hw, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) +void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, + bool yswap, bool useIdentityTransform) { ATRACE_CALL(); RenderEngine& engine(getRenderEngine()); // get screen geometry - const int32_t hw_w = hw->getWidth(); - const int32_t hw_h = hw->getHeight(); - const bool filtering = static_cast(reqWidth) != hw_w || - static_cast(reqHeight) != hw_h; + const auto raWidth = renderArea.getWidth(); + const auto raHeight = renderArea.getHeight(); + + const auto reqWidth = renderArea.getReqWidth(); + const auto reqHeight = renderArea.getReqHeight(); + Rect sourceCrop = renderArea.getSourceCrop(); + + const bool filtering = static_cast(reqWidth) != raWidth || + static_cast(reqHeight) != raHeight; // if a default or invalid sourceCrop is passed in, set reasonable values if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) { sourceCrop.setLeftTop(Point(0, 0)); - sourceCrop.setRightBottom(Point(hw_w, hw_h)); + sourceCrop.setRightBottom(Point(raWidth, raHeight)); } // ensure that sourceCrop is inside screen if (sourceCrop.left < 0) { ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left); } - if (sourceCrop.right > hw_w) { - ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w); + if (sourceCrop.right > raWidth) { + ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth); } if (sourceCrop.top < 0) { ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top); } - if (sourceCrop.bottom > hw_h) { - ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h); + if (sourceCrop.bottom > raHeight) { + ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } // make sure to clear all GL error flags @@ -3908,77 +3947,35 @@ void SurfaceFlinger::renderScreenImplLocked( // set-up our viewport engine.setViewportAndProjection( - reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); + reqWidth, reqHeight, sourceCrop, raHeight, yswap, renderArea.getRotationFlags()); engine.disableTexturing(); // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - // We loop through the first level of layers without traversing, - // as we need to interpret min/max layer Z in the top level Z space. - for (const auto& layer : mDrawingState.layersSortedByZ) { - if (layer->getLayerStack() != hw->getLayerStack()) { - continue; - } - const Layer::State& state(layer->getDrawingState()); - if (state.z < minLayerZ || state.z > maxLayerZ) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->isVisible()) { - return; - } - if (filtering) layer->setFiltering(true); - layer->draw(hw, useIdentityTransform); - if (filtering) layer->setFiltering(false); - }); - } + traverseLayers([&](Layer* layer) { + if (filtering) layer->setFiltering(true); + layer->draw(renderArea, useIdentityTransform); + if (filtering) layer->setFiltering(false); + }); // compositionComplete is needed for older driver - hw->compositionComplete(); - hw->setViewportAndProjection(); +// hw->compositionComplete(); +// hw->setViewportAndProjection(); } - -status_t SurfaceFlinger::captureScreenImplLocked( - const sp& hw, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation, - bool isLocalScreenshot) -{ +status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform, + bool isLocalScreenshot) { ATRACE_CALL(); - // get screen geometry - uint32_t hw_w = hw->getWidth(); - uint32_t hw_h = hw->getHeight(); - - if (rotation & Transform::ROT_90) { - std::swap(hw_w, hw_h); - } - - if ((reqWidth > hw_w) || (reqHeight > hw_h)) { - ALOGE("size mismatch (%d, %d) > (%d, %d)", - reqWidth, reqHeight, hw_w, hw_h); - return BAD_VALUE; - } - - reqWidth = (!reqWidth) ? hw_w : reqWidth; - reqHeight = (!reqHeight) ? hw_h : reqHeight; - bool secureLayerIsVisible = false; - for (const auto& layer : mDrawingState.layersSortedByZ) { - const Layer::State& state(layer->getDrawingState()); - if ((layer->getLayerStack() != hw->getLayerStack()) || - (state.z < minLayerZ || state.z > maxLayerZ)) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) { - secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && - layer->isSecure()); - }); - } + traverseLayers([&](Layer *layer) { + secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && + layer->isSecure()); + }); if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); @@ -3996,7 +3993,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; int err = 0; - err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight); + err = native_window_set_buffers_dimensions(window, renderArea.getReqWidth(), + renderArea.getReqHeight()); err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); err |= native_window_set_usage(window, usage); @@ -4022,9 +4020,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( // via an FBO, which means we didn't have to create // an EGLSurface and therefore we're not // dependent on the context's EGLConfig. - renderScreenImplLocked( - hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true, - useIdentityTransform, rotation); + renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); // Attempt to create a sync khr object that can produce a sync point. If that // isn't available, create a non-dupable sync object in the fallback path and @@ -4064,10 +4060,12 @@ status_t SurfaceFlinger::captureScreenImplLocked( } } if (DEBUG_SCREENSHOTS) { - uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; - getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); - checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, - hw, minLayerZ, maxLayerZ); + uint32_t* pixels = new uint32_t[renderArea.getReqWidth() * + renderArea.getReqHeight()]; + getRenderEngine().readPixels(0, 0, renderArea.getReqWidth(), + renderArea.getReqHeight(), pixels); + checkScreenshot(renderArea.getReqWidth(), renderArea.getReqHeight(), + renderArea.getReqWidth(), pixels, traverseLayers); delete [] pixels; } @@ -4097,7 +4095,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( } void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp& hw, int32_t minLayerZ, int32_t maxLayerZ) { + TraverseLayersFunction traverseLayers) { if (DEBUG_SCREENSHOTS) { for (size_t y=0 ; ygetLayerStack()); + ALOGE("*** we just took a black screenshot ***"); + size_t i = 0; - for (const auto& layer : mDrawingState.layersSortedByZ) { + traverseLayers([&](Layer* layer) { const Layer::State& state(layer->getDrawingState()); - if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ && - state.z <= maxLayerZ) { - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", - layer->isVisible() ? '+' : '-', - i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, static_cast(state.color.a)); - i++; - }); - } - } + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", + layer->isVisible() ? '+' : '-', + i, layer->getName().string(), layer->getLayerStack(), state.z, + layer->isVisible(), state.flags, static_cast(state.color.a)); + i++; + }); } } @@ -4135,6 +4127,28 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } +void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, + int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor) { + + // We loop through the first level of layers without traversing, + // as we need to interpret min/max layer Z in the top level Z space. + for (const auto& layer : mDrawingState.layersSortedByZ) { + if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + continue; + } + const Layer::State& state(layer->getDrawingState()); + if (state.z < minLayerZ || state.z > maxLayerZ) { + continue; + } + layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + } +} + }; // namespace android diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 6be9ae2c5f..37925a1641 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -20,8 +20,8 @@ #include #include -#include "clz.h" #include "Transform.h" +#include "clz.h" // --------------------------------------------------------------------------- @@ -388,6 +388,23 @@ void Transform::dump(const char* name) const ALOGD("%.4f %.4f %.4f", m[0][2], m[1][2], m[2][2]); } +Transform::orientation_flags Transform::fromRotation(ISurfaceComposer::Rotation rotation) { + // Convert to surfaceflinger's internal rotation type. + switch (rotation) { + case ISurfaceComposer::eRotateNone: + return Transform::ROT_0; + case ISurfaceComposer::eRotate90: + return Transform::ROT_90; + case ISurfaceComposer::eRotate180: + return Transform::ROT_180; + case ISurfaceComposer::eRotate270: + return Transform::ROT_270; + default: + ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); + return Transform::ROT_0; + } +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h index 6640a13839..bfc66eccb9 100644 --- a/services/surfaceflinger/Transform.h +++ b/services/surfaceflinger/Transform.h @@ -25,6 +25,8 @@ #include #include +#include + #include namespace android { @@ -51,6 +53,8 @@ public: ROT_INVALID = 0x80 }; + static orientation_flags fromRotation(ISurfaceComposer::Rotation rotation); + enum type_mask { IDENTITY = 0, TRANSLATE = 0x1, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index f61a978487..ec87eeec77 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -116,6 +116,60 @@ private: CpuConsumer::LockedBuffer mBuf; }; +class CaptureLayer { +public: + static void captureScreen(std::unique_ptr* sc, sp& parentHandle) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); + sp display(sf->getBuiltInDisplay( + ISurfaceComposer::eDisplayIdMain)); + SurfaceComposerClient::Transaction().apply(true); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer)); + *sc = std::make_unique(cpuConsumer); + } + + void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); + const uint8_t* img = static_cast(mBuffer.data); + const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); + if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { + String8 err(String8::format("pixel @ (%3d, %3d): " + "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", + x, y, r, g, b, pixel[0], pixel[1], pixel[2])); + EXPECT_EQ(String8(), err) << err.string(); + } + } + + void expectFGColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 195, 63, 63); + } + + void expectBGColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 63, 63, 195); + } + + void expectChildColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 200, 200, 200); + } + + CaptureLayer(const sp& cc) : + mCC(cc) { + EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); + } + + ~CaptureLayer() { + mCC->unlockBuffer(mBuffer); + } + +private: + sp mCC; + CpuConsumer::LockedBuffer mBuffer; +}; + + class LayerUpdateTest : public ::testing::Test { protected: virtual void SetUp() { @@ -1431,4 +1485,109 @@ TEST_F(LayerColorTest, ColorLayerWithNoColor) { } } +class ScreenCaptureTest : public LayerUpdateTest { +protected: + std::unique_ptr mCapture; +}; + +TEST_F(ScreenCaptureTest, CaptureSingleLayer) { + auto bgHandle = mBGSurfaceControl->getHandle(); + CaptureLayer::captureScreen(&mCapture, bgHandle); + mCapture->expectBGColor(0, 0); + // Doesn't capture FG layer which is at 64, 64 + mCapture->expectBGColor(64, 64); +} + +TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction() + .show(child) + .apply(true); + + // Captures mFGSurfaceControl layer and its child. + CaptureLayer::captureScreen(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + + sp grandchild = mComposerClient->createSurface( + String8("Grandchild surface"), 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); + + fillSurfaceRGBA8(grandchild, 50, 50, 50); + SurfaceComposerClient::Transaction() + .show(child) + .setPosition(grandchild, 5, 5) + .show(grandchild) + .apply(true); + + // Captures mFGSurfaceControl, its child, and the grandchild. + CaptureLayer::captureScreen(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); + mCapture->checkPixel(5, 5, 50, 50, 50); +} + +TEST_F(ScreenCaptureTest, CaptureChildOnly) { + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + auto childHandle = child->getHandle(); + + SurfaceComposerClient::Transaction() + .setPosition(child, 5, 5) + .show(child) + .apply(true); + + // Captures only the child layer, and not the parent. + CaptureLayer::captureScreen(&mCapture, childHandle); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 9); +} + +TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + auto childHandle = child->getHandle(); + + sp grandchild = mComposerClient->createSurface( + String8("Grandchild surface"), 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); + fillSurfaceRGBA8(grandchild, 50, 50, 50); + + SurfaceComposerClient::Transaction() + .show(child) + .setPosition(grandchild, 5, 5) + .show(grandchild) + .apply(true); + + auto grandchildHandle = grandchild->getHandle(); + + // Captures only the grandchild. + CaptureLayer::captureScreen(&mCapture, grandchildHandle); + mCapture->checkPixel(0, 0, 50, 50, 50); + mCapture->checkPixel(4, 4, 50, 50, 50); +} + } -- cgit v1.2.3-59-g8ed1b From 2c5f6d2257075c8b5ced78b07ed8b2c2323f0df2 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 26 Sep 2017 12:30:35 -0700 Subject: SurfaceFlinger: Implement merging of transaction objects. Useful for WindowManager to collect multiple transactions from independent units. Test: Transaction_test.cpp Change-Id: I52e89b038e3b375493169991e41cb75b67550264 --- libs/gui/LayerState.cpp | 96 ++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 24 ++++++ libs/gui/include/gui/LayerState.h | 2 + libs/gui/include/gui/SurfaceComposerClient.h | 6 +- services/surfaceflinger/tests/Transaction_test.cpp | 24 ++++++ 5 files changed, 149 insertions(+), 3 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index bfc6f28704..b5295f2801 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -136,5 +136,101 @@ status_t DisplayState::read(const Parcel& input) { return NO_ERROR; } +void DisplayState::merge(const DisplayState& other) { + if (other.what & eSurfaceChanged) { + what |= eSurfaceChanged; + surface = other.surface; + } + if (other.what & eLayerStackChanged) { + what |= eLayerStackChanged; + layerStack = other.layerStack; + } + if (other.what & eDisplayProjectionChanged) { + what |= eDisplayProjectionChanged; + orientation = other.orientation; + viewport = other.viewport; + frame = other.frame; + } + if (other.what & eDisplaySizeChanged) { + what |= eDisplaySizeChanged; + width = other.width; + height = other.height; + } +} + +void layer_state_t::merge(const layer_state_t& other) { + if (other.what & ePositionChanged) { + what |= ePositionChanged; + x = other.x; + y = other.y; + } + if (other.what & eLayerChanged) { + what |= eLayerChanged; + z = other.z; + } + if (other.what & eSizeChanged) { + what |= eSizeChanged; + w = other.w; + h = other.h; + } + if (other.what & eAlphaChanged) { + what |= eAlphaChanged; + alpha = other.alpha; + } + if (other.what & eMatrixChanged) { + what |= eMatrixChanged; + matrix = other.matrix; + } + if (other.what & eTransparentRegionChanged) { + what |= eTransparentRegionChanged; + transparentRegion = other.transparentRegion; + } + if (other.what & eFlagsChanged) { + what |= eFlagsChanged; + flags = other.flags; + mask = other.mask; + } + if (other.what & eLayerStackChanged) { + what |= eLayerStackChanged; + layerStack = other.layerStack; + } + if (other.what & eCropChanged) { + what |= eCropChanged; + crop = other.crop; + } + if (other.what & eDeferTransaction) { + what |= eDeferTransaction; + barrierHandle = other.barrierHandle; + barrierGbp = other.barrierGbp; + frameNumber = other.frameNumber; + } + if (other.what & eFinalCropChanged) { + what |= eFinalCropChanged; + finalCrop = other.finalCrop; + } + if (other.what & eOverrideScalingModeChanged) { + what |= eOverrideScalingModeChanged; + overrideScalingMode = other.overrideScalingMode; + } + if (other.what & eGeometryAppliesWithResize) { + what |= eGeometryAppliesWithResize; + } + if (other.what & eReparentChildren) { + what |= eReparentChildren; + reparentHandle = other.reparentHandle; + } + if (other.what & eDetachChildren) { + what |= eDetachChildren; + } + if (other.what & eRelativeLayerChanged) { + what |= eRelativeLayerChanged; + z = other.z; + relativeLayerHandle = other.relativeLayerHandle; + } + if (other.what & eReparent) { + what |= eReparent; + parentHandleForChild = other.parentHandleForChild; + } +} }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 15c4c9a880..2adc273651 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -104,6 +104,30 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : mComposerStates = other.mComposerStates; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { + for (auto const& state : other.mComposerStates) { + ssize_t index = mComposerStates.indexOf(state); + if (index < 0) { + mComposerStates.add(state); + } else { + mComposerStates.editItemAt(static_cast(index)).state.merge(state.state); + } + } + other.mComposerStates.clear(); + + for (auto const& state : other.mDisplayStates) { + ssize_t index = mDisplayStates.indexOf(state); + if (index < 0) { + mDisplayStates.add(state); + } else { + mDisplayStates.editItemAt(static_cast(index)).merge(state); + } + } + other.mDisplayStates.clear(); + + return *this; +} + status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mStatus != NO_ERROR) { return mStatus; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index ae6965a0fc..f3fb82feb3 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -77,6 +77,7 @@ struct layer_state_t { matrix.dsdy = matrix.dtdx = 0.0f; } + void merge(const layer_state_t& other); status_t write(Parcel& output) const; status_t read(const Parcel& input); @@ -144,6 +145,7 @@ struct DisplayState { }; DisplayState(); + void merge(const DisplayState& other); uint32_t what; sp token; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index d63dafea41..87fdfae111 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -144,7 +144,9 @@ public: Transaction(Transaction const& other); status_t apply(bool synchronous = false); - + // Merge another transaction in to this one, clearing other + // as if it had been applied. + Transaction& merge(Transaction&& other); Transaction& show(const sp& sc); Transaction& hide(const sp& sc); Transaction& setPosition(const sp& sc, @@ -175,8 +177,6 @@ public: float alpha); Transaction& setMatrix(const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy); - Transaction& setOrientation(const sp& sc, - const Rect& crop); Transaction& setCrop(const sp& sc, const Rect& crop); Transaction& setFinalCrop(const sp& sc, const Rect& crop); Transaction& setLayerStack(const sp& sc, uint32_t layerStack); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ec87eeec77..16a16a53b1 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -891,6 +891,30 @@ TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { } } +TEST_F(LayerUpdateTest, MergingTransactions) { + sp sc; + { + SCOPED_TRACE("before move"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(0, 12); + sc->expectFGColor(75, 75); + sc->expectBGColor(145, 145); + } + + Transaction t1, t2; + t1.setPosition(mFGSurfaceControl, 128, 128); + t2.setPosition(mFGSurfaceControl, 0, 0); + // We expect that the position update from t2 now + // overwrites the position update from t1. + t1.merge(std::move(t2)); + t1.apply(); + + { + ScreenCapture::captureScreen(&sc); + sc->expectFGColor(1, 1); + } +} + class ChildLayerTest : public LayerUpdateTest { protected: void SetUp() override { -- cgit v1.2.3-59-g8ed1b From 7206d49b2963ce2e926a5f25fe94aca9c06471e6 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 10 Nov 2017 16:16:12 -0800 Subject: Add additional parameters for the captureLayer functions. 1. Added new captureLayers function that will return a GraphicBuffer instead of storing into a Surface. 2. Added crop to captureLayers function. 3. Added frameScale to allow captures to scale. 4. Removed rotation parameter from captureLayers since it will always be in the correct orientation. Test: Transaction_test ScreenCaptureTest.CaptureCrop, .CaptureSize Change-Id: Ib16d8575cf0c103126b9427ad32e2d28d568ea61 --- libs/gui/ISurfaceComposer.cpp | 12 +-- libs/gui/SurfaceComposerClient.cpp | 29 ++++++- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 +- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/RenderArea.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 42 ++++++++-- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 93 +++++++++++++++++++++- 9 files changed, 166 insertions(+), 25 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 973302c226..c21c5e3eb8 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -124,12 +124,13 @@ public: virtual status_t captureLayers(const sp& layerHandleBinder, const sp& producer, - ISurfaceComposer::Rotation rotation) { + const Rect& sourceCrop, float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); data.writeStrongBinder(IInterface::asBinder(producer)); - data.writeInt32(static_cast(rotation)); + data.write(sourceCrop); + data.writeFloat(frameScale); remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); return reply.readInt32(); } @@ -605,10 +606,11 @@ status_t BnSurfaceComposer::onTransact( sp layerHandleBinder = data.readStrongBinder(); sp producer = interface_cast(data.readStrongBinder()); - int32_t rotation = data.readInt32(); + Rect sourceCrop(Rect::EMPTY_RECT); + data.read(sourceCrop); + float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, - static_cast(rotation)); + status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); reply->writeInt32(res); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2adc273651..2466d2555a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -757,11 +757,34 @@ status_t ScreenshotClient::captureToBuffer(const sp& display, status_t ScreenshotClient::captureLayers(const sp& layerHandle, const sp& producer, - uint32_t rotation) { + Rect sourceCrop, float frameScale) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, - static_cast(rotation)); + return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); +} + +status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp gbpConsumer; + sp producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_SW_READ_NEVER | + GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); + if (ret != NO_ERROR) { + return ret; + } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; + return ret; } ScreenshotClient::ScreenshotClient() diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 13e7473d54..1e4c329e1e 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -176,7 +176,7 @@ public: virtual status_t captureLayers(const sp& layerHandleBinder, const sp& producer, - Rotation rotation = eRotateNone) = 0; + const Rect& sourceCrop, float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 87fdfae111..b0fa922cd9 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,8 +297,12 @@ public: bool useIdentityTransform, uint32_t rotation, sp* outbuffer); + static status_t captureLayers(const sp& layerHandle, - const sp& producer, uint32_t rotation); + const sp& producer, Rect sourceCrop, + float frameScale); + static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer); private: mutable sp mCpuConsumer; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 660680bf9e..ac4eb0cb1d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -531,7 +531,7 @@ public: Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, const sp& /*producer*/, - ISurfaceComposer::Rotation /*rotation*/) override { + const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 44b9dc9254..fa4df8360f 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -6,7 +6,8 @@ namespace android { class RenderArea { public: - RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + RenderArea(uint32_t reqHeight, uint32_t reqWidth, + ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) : mReqHeight(reqHeight), mReqWidth(reqWidth) { mRotationFlags = Transform::fromRotation(rotation); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ec2a459fb2..ea4f495d59 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4398,15 +4398,14 @@ status_t SurfaceFlinger::captureScreen(const sp& display, status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, const sp& producer, - ISurfaceComposer::Rotation rotation) { + const Rect& sourceCrop, float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: - LayerRenderArea(const sp& layer, ISurfaceComposer::Rotation rotation) - : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, - rotation), - mLayer(layer) {} + LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, + int32_t reqHeight) + : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets // the whole capture back to 0,0 @@ -4421,18 +4420,45 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } - Rect getSourceCrop() const override { return getBounds(); } + Rect getSourceCrop() const override { + if (mCrop.isEmpty()) { + return getBounds(); + } else { + return mCrop; + } + } bool getWideColorSupport() const override { return false; } android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } private: - const sp& mLayer; + const sp mLayer; + const Rect mCrop; }; auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - LayerRenderArea renderArea(parent, rotation); + if (parent == nullptr || parent->isPendingRemoval()) { + ALOGE("captureLayers called with a removed parent"); + return NAME_NOT_FOUND; + } + + Rect crop(sourceCrop); + if (sourceCrop.width() <= 0) { + crop.left = 0; + crop.right = parent->getCurrentState().active.w; + } + + if (sourceCrop.height() <= 0) { + crop.top = 0; + crop.bottom = parent->getCurrentState().active.h; + } + + int32_t reqWidth = crop.width() * frameScale; + int32_t reqHeight = crop.height() * frameScale; + + LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 386d42bef1..f61dc756c2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -298,7 +298,7 @@ private: bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, const sp& producer, - ISurfaceComposer::Rotation rotation); + const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 943fafd213..39aef8164c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -276,15 +276,15 @@ private: class CaptureLayer { public: - static void captureScreen(std::unique_ptr* sc, sp& parentHandle) { + static void captureScreen(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { sp producer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer); sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); - sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer)); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); *sc = std::make_unique(cpuConsumer); } @@ -2412,4 +2412,89 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { mCapture->checkPixel(4, 4, 50, 50, 50); } -} // namespace android +TEST_F(ScreenCaptureTest, CaptureCrop) { + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + Rect crop = Rect(0, 0, 30, 30); + CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + // Capturing the cropped screen, cropping out the shown red area, should leave only the blue + // area visible. + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureSize) { + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. + mCapture->checkPixel(14, 14, 0, 0, 255); + mCapture->checkPixel(15, 15, 255, 0, 0); + mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + + auto redLayerHandle = redLayer->getHandle(); + mComposerClient->destroySurface(redLayerHandle); + SurfaceComposerClient::Transaction().apply(true); + + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); + + // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); +} + +} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From a252d895816b3aa6c3bc2b2083113694ead6963d Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 20 Nov 2017 17:54:25 -0800 Subject: Use GraphicBuffer instead of GBP for screenshots. Migrate screenshot code to render the layers into a GraphicBuffer instead of creating a GraphicBufferProducer. This cleans up the code and makes rendering a screen capture simpler and clearer. Test: Screencaptures for Recents, manual screenshots, and "adb shell screencap" Test: Transaction_test Change-Id: Ifb463c0e98cfaa3f96ad27837b1a2e2921e253d1 --- libs/gui/ISurfaceComposer.cpp | 71 ++++--- libs/gui/Surface.cpp | 21 ++ libs/gui/SurfaceComposerClient.cpp | 174 +--------------- libs/gui/include/gui/ISurfaceComposer.h | 15 +- libs/gui/include/gui/Surface.h | 2 + libs/gui/include/gui/SurfaceComposerClient.h | 72 +------ libs/gui/tests/Surface_test.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.cpp | 112 +++------- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/Transaction_test.cpp | 229 +++++++++------------ 10 files changed, 227 insertions(+), 500 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c21c5e3eb8..5de84ecbab 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -100,17 +100,13 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) - { + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -118,21 +114,45 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); - remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + return err; } virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeFloat(frameScale); - remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + + return err; } virtual bool authenticateSurfaceTexture( @@ -583,8 +603,7 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); @@ -594,24 +613,28 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, producer, - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, - static_cast(rotation)); + status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case AUTHENTICATE_SURFACE: { diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e9393831c7..80216bc63e 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1760,4 +1760,25 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector>* out) return OK; } +status_t Surface::attachAndQueueBuffer(Surface* surface, sp buffer) { + if (buffer == nullptr) { + return BAD_VALUE; + } + int err = static_cast(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, + NATIVE_WINDOW_API_CPU); + if (err != OK) { + return err; + } + err = surface->attachBuffer(buffer->getNativeBuffer()); + if (err != OK) { + return err; + } + err = static_cast(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1); + if (err != OK) { + return err; + } + err = surface->disconnect(NATIVE_WINDOW_API_CPU); + return err; +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2466d2555a..0dbe786f1a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -717,181 +717,27 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { +status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureScreen(display, producer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); -} - -status_t ScreenshotClient::captureToBuffer(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - uint32_t rotation, - sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); + status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, + maxLayerZ, useIdentityTransform, + static_cast(rotation)); if (ret != NO_ERROR) { return ret; } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, - const sp& producer, - Rect sourceCrop, float frameScale) { +status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); -} - -status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | - GRALLOC_USAGE_SW_READ_NEVER | - GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); - if (ret != NO_ERROR) { - return ret; - } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); return ret; } - -ScreenshotClient::ScreenshotClient() - : mHaveBuffer(false) { - memset(&mBuffer, 0, sizeof(mBuffer)); -} - -ScreenshotClient::~ScreenshotClient() { - ScreenshotClient::release(); -} - -sp ScreenshotClient::getCpuConsumer() const { - if (mCpuConsumer == NULL) { - sp consumer; - BufferQueue::createBufferQueue(&mProducer, &consumer); - mCpuConsumer = new CpuConsumer(consumer, 1); - mCpuConsumer->setName(String8("ScreenshotClient")); - } - return mCpuConsumer; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - sp cpuConsumer = getCpuConsumer(); - - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - - status_t err = s->captureScreen(display, mProducer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); - - if (err == NO_ERROR) { - err = mCpuConsumer->lockNextBuffer(&mBuffer); - if (err == NO_ERROR) { - mHaveBuffer = true; - } - } - return err; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform) { - - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, 0, 0, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -void ScreenshotClient::release() { - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - mCpuConsumer.clear(); -} - -void const* ScreenshotClient::getPixels() const { - return mBuffer.data; -} - -uint32_t ScreenshotClient::getWidth() const { - return mBuffer.width; -} - -uint32_t ScreenshotClient::getHeight() const { - return mBuffer.height; -} - -PixelFormat ScreenshotClient::getFormat() const { - return mBuffer.format; -} - -uint32_t ScreenshotClient::getStride() const { - return mBuffer.stride; -} - -size_t ScreenshotClient::getSize() const { - return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); -} - -android_dataspace ScreenshotClient::getDataSpace() const { - return mBuffer.dataSpace; -} - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 1e4c329e1e..e26e332589 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -167,16 +168,14 @@ public: /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale = 1.0) = 0; + sp* outBuffer, const Rect& sourceCrop, + float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 3fe29d955b..354f23ab06 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -283,6 +283,8 @@ public: android_dataspace_t getBuffersDataSpace(); + static status_t attachAndQueueBuffer(Surface* surface, sp buffer); + protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b0fa922cd9..3f13946339 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -279,74 +279,16 @@ private: // --------------------------------------------------------------------------- -class ScreenshotClient -{ +class ScreenshotClient { public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - static status_t captureToBuffer( - const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - uint32_t rotation, - sp* outbuffer); - - static status_t captureLayers(const sp& layerHandle, - const sp& producer, Rect sourceCrop, - float frameScale); - static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer); - -private: - mutable sp mCpuConsumer; - mutable sp mProducer; - CpuConsumer::LockedBuffer mBuffer; - bool mHaveBuffer; - -public: - ScreenshotClient(); - ~ScreenshotClient(); - - // frees the previous screenshot and captures a new one - // if cropping isn't required, callers may pass in a default Rect, e.g.: - // update(display, Rect(), useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation); - - sp getCpuConsumer() const; - - // release memory occupied by the screenshot - void release(); - - // pixels are valid until this object is freed or - // release() or update() is called - void const* getPixels() const; - - uint32_t getWidth() const; - uint32_t getHeight() const; - PixelFormat getFormat() const; - uint32_t getStride() const; - // size of allocated memory in bytes - size_t getSize() const; - android_dataspace getDataSpace() const; + static status_t capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer); + static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, + sp* outBuffer); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ac4eb0cb1d..470a338639 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -116,14 +116,11 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp anw(mSurface); // Verify the screenshot works with no protected buffers. - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), @@ -154,7 +151,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); } @@ -524,13 +521,13 @@ public: status_t setActiveColorMode(const sp& /*display*/, android_color_mode_t /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, - const sp& /*producer*/, + sp* /*outBuffer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - const sp& /*producer*/, + sp* /*outBuffer*/, const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d81178c559..4acd448293 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4339,44 +4339,10 @@ private: const int mApi; }; -static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, - uint32_t requestedHeight, bool hasWideColorDisplay, - bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) { - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - - int err = 0; - err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight); - err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); - err |= native_window_set_usage(window, usage); - - if (hasWideColorDisplay) { - err |= native_window_set_buffers_data_space(window, - renderEngineUsesWideColor - ? HAL_DATASPACE_DISPLAY_P3 - : HAL_DATASPACE_V0_SRGB); - } - - if (err != NO_ERROR) { - return BAD_VALUE; - } - - /* TODO: Once we have the sync framework everywhere this can use - * server-side waits on the fence that dequeueBuffer returns. - */ - err = native_window_dequeue_buffer_and_wait(window, outBuffer); - if (err != NO_ERROR) { - return err; - } - - return NO_ERROR; -} - -status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, +status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -4387,18 +4353,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, device, minLayerZ, maxLayerZ, std::placeholders::_1); - return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) + int32_t reqHeight) : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets @@ -4461,51 +4427,21 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, producer, false); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform) { ATRACE_CALL(); - if (CC_UNLIKELY(producer == 0)) - return BAD_VALUE; - renderArea.updateDimensions(); - // if we have secure windows on this display, never allow the screen capture - // unless the producer interface is local (i.e.: we can take a screenshot for - // ourselves). - bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - - // create a surface (because we're a producer, and we need to - // dequeue/queue a buffer) - sp surface = new Surface(producer, false); - - // Put the screenshot Surface into async mode so that - // Layer::headFenceHasSignaled will always return true and we'll latch the - // first buffer regardless of whether or not its acquire fence has - // signaled. This is needed to avoid a race condition in the rotation - // animation. See b/30209608 - surface->setAsyncMode(true); - - ANativeWindow* window = surface.get(); - - status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - if (result != NO_ERROR) { - return result; - } - WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); - - ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), - hasWideColorDisplay && !mForceNativeColorMode, - getRenderEngine().usesWideColor(), &buffer); - if (result != NO_ERROR) { - return result; - } + const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; + *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -4530,8 +4466,8 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, buffer, - useIdentityTransform, isLocalScreenshot, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), + useIdentityTransform, &fd); } { @@ -4542,7 +4478,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } }); - result = postMessageAsync(message); + status_t result = postMessageAsync(message); if (result == NO_ERROR) { captureCondition.wait(captureLock, [&]() { return captureResult; }); while (*captureResult == EAGAIN) { @@ -4557,9 +4493,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } if (result == NO_ERROR) { - // queueBuffer takes ownership of syncFd - result = window->queueBuffer(window, buffer, syncFd); + sync_wait(syncFd, -1); + close(syncFd); } + return result; } @@ -4602,7 +4539,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE + : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); @@ -4645,7 +4583,7 @@ private: status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, - bool useIdentityTransform, bool isLocalScreenshot, + bool useIdentityTransform, int* outSyncFd) { ATRACE_CALL(); @@ -4655,7 +4593,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (!isLocalScreenshot && secureLayerIsVisible) { + if (secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -4804,4 +4742,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif +#endif \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f61dc756c2..a01d353a70 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -291,13 +291,11 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); - virtual status_t captureLayers(const sp& parentHandle, - const sp& producer, + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); @@ -436,15 +434,13 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool yswap, bool useIdentityTransform); - status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform); - status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - bool isLocalScreenshot, int* outSyncFd); + int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 39aef8164c..ff81dc9461 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -104,20 +104,22 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const } // Check if a region has the specified color. -void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect, +void expectBufferColor(const sp& outBuffer, uint8_t* pixels, const Rect& rect, const Color& color, uint8_t tolerance) { int32_t x = rect.left; int32_t y = rect.top; int32_t width = rect.right - rect.left; int32_t height = rect.bottom - rect.top; - if (x + width > int32_t(buffer.width)) { - x = std::min(x, int32_t(buffer.width)); - width = buffer.width - x; + int32_t bufferWidth = int32_t(outBuffer->getWidth()); + int32_t bufferHeight = int32_t(outBuffer->getHeight()); + if (x + width > bufferWidth) { + x = std::min(x, bufferWidth); + width = bufferWidth - x; } - if (y + height > int32_t(buffer.height)) { - y = std::min(y, int32_t(buffer.height)); - height = buffer.height - y; + if (y + height > bufferHeight) { + y = std::min(y, bufferHeight); + height = bufferHeight - y; } auto colorCompare = [tolerance](uint8_t a, uint8_t b) { @@ -125,8 +127,7 @@ void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect return tmp <= tolerance; }; for (int32_t j = 0; j < height; j++) { - const uint8_t* src = - static_cast(buffer.data) + (buffer.stride * (y + j) + x) * 4; + const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) @@ -170,30 +171,38 @@ class ScreenCapture : public RefBase { public: static void captureScreen(sp* sc, int32_t minLayerZ = 0, int32_t maxLayerZ = std::numeric_limits::max()) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); + sp outBuffer; ASSERT_EQ(NO_ERROR, - sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false)); - *sc = new ScreenCapture(cpuConsumer); + sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ, + false)); + *sc = new ScreenCapture(outBuffer); + } + + static void captureLayers(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); + *sc = std::make_unique(outBuffer); } void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - expectBufferColor(mBuf, rect, color, tolerance); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); } void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); const bool leftBorder = rect.left > 0; const bool topBorder = rect.top > 0; - const bool rightBorder = rect.right < int32_t(mBuf.width); - const bool bottomBorder = rect.bottom < int32_t(mBuf.height); + const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); + const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); if (topBorder) { Rect top(rect.left, rect.top - 1, rect.right, rect.top); @@ -246,9 +255,8 @@ public: } void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - const uint8_t* img = static_cast(mBuf.data); - const uint8_t* pixel = img + (4 * (y * mBuf.stride + x)); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { String8 err(String8::format("pixel @ (%3d, %3d): " "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", @@ -263,58 +271,15 @@ public: void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } -private: - ScreenCapture(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf)); + ScreenCapture(const sp& outBuffer) : mOutBuffer(outBuffer) { + mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&mPixels)); } - ~ScreenCapture() { mCC->unlockBuffer(mBuf); } - - sp mCC; - CpuConsumer::LockedBuffer mBuf; -}; - -class CaptureLayer { -public: - static void captureScreen(std::unique_ptr* sc, sp& parentHandle, - Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); - SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); - *sc = std::make_unique(cpuConsumer); - } - - void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); - const uint8_t* img = static_cast(mBuffer.data); - const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); - if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { - String8 err(String8::format("pixel @ (%3d, %3d): " - "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", - x, y, r, g, b, pixel[0], pixel[1], pixel[2])); - EXPECT_EQ(String8(), err) << err.string(); - } - } - - void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } - - void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } - - void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } - - CaptureLayer(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); - } - - ~CaptureLayer() { mCC->unlockBuffer(mBuffer); } + ~ScreenCapture() { mOutBuffer->unlock(); } private: - sp mCC; - CpuConsumer::LockedBuffer mBuffer; + sp mOutBuffer; + uint8_t* mPixels = NULL; }; class LayerTransactionTest : public ::testing::Test { @@ -858,21 +823,17 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); sp composer = ComposerService::getComposerService(); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - + sp outBuffer; Transaction() .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) .apply(true); ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); } @@ -1504,7 +1465,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } -class LayerUpdateTest : public ::testing::Test { +class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -2318,12 +2279,12 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { class ScreenCaptureTest : public LayerUpdateTest { protected: - std::unique_ptr mCapture; + std::unique_ptr mCapture; }; TEST_F(ScreenCaptureTest, CaptureSingleLayer) { auto bgHandle = mBGSurfaceControl->getHandle(); - CaptureLayer::captureScreen(&mCapture, bgHandle); + ScreenCapture::captureLayers(&mCapture, bgHandle); mCapture->expectBGColor(0, 0); // Doesn't capture FG layer which is at 64, 64 mCapture->expectBGColor(64, 64); @@ -2340,7 +2301,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { SurfaceComposerClient::Transaction().show(child).apply(true); // Captures mFGSurfaceControl layer and its child. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } @@ -2365,7 +2326,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { .apply(true); // Captures mFGSurfaceControl, its child, and the grandchild. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); mCapture->checkPixel(5, 5, 50, 50, 50); @@ -2381,7 +2342,7 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); // Captures only the child layer, and not the parent. - CaptureLayer::captureScreen(&mCapture, childHandle); + ScreenCapture::captureLayers(&mCapture, childHandle); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); } @@ -2407,94 +2368,96 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { auto grandchildHandle = grandchild->getHandle(); // Captures only the grandchild. - CaptureLayer::captureScreen(&mCapture, grandchildHandle); + ScreenCapture::captureLayers(&mCapture, grandchildHandle); mCapture->checkPixel(0, 0, 50, 50, 50); mCapture->checkPixel(4, 4, 50, 50, 50); } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); Rect crop = Rect(0, 0, 30, 30); - CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. - mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); - - CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + + ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->checkPixel(14, 14, 0, 0, 255); - mCapture->checkPixel(15, 15, 255, 0, 0); - mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); - fillSurfaceRGBA8(redLayer, 255, 0, 0); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); + sp outBuffer; // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); + sp sf(ComposerService::getComposerService()); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } -} \ No newline at end of file +} // namespace android -- cgit v1.2.3-59-g8ed1b From 707b8f3507fa4a3915844c7a4730e67f94eee2f7 Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Wed, 29 Nov 2017 21:25:51 +0000 Subject: Revert "Use GraphicBuffer instead of GBP for screenshots." This reverts commit a252d895816b3aa6c3bc2b2083113694ead6963d. Reason for revert: SystemUI and some other places need to be updated as well. Will resubmit with the other necessary changes Change-Id: I2dfb7b439c866f31ffa584e450d3208c75afecaa Bug: 69898957 --- libs/gui/ISurfaceComposer.cpp | 71 +++---- libs/gui/Surface.cpp | 21 -- libs/gui/SurfaceComposerClient.cpp | 174 +++++++++++++++- libs/gui/include/gui/ISurfaceComposer.h | 15 +- libs/gui/include/gui/Surface.h | 2 - libs/gui/include/gui/SurfaceComposerClient.h | 72 ++++++- libs/gui/tests/Surface_test.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.cpp | 112 +++++++--- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/Transaction_test.cpp | 229 ++++++++++++--------- 10 files changed, 500 insertions(+), 227 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5de84ecbab..c21c5e3eb8 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -100,13 +100,17 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) { + virtual status_t captureScreen(const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) + { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); + data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -114,45 +118,21 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); - status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - - if (err != NO_ERROR) { - return err; - } - - err = reply.readInt32(); - if (err != NO_ERROR) { - return err; - } - - *outBuffer = new GraphicBuffer(); - reply.read(**outBuffer); - return err; + remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + return reply.readInt32(); } virtual status_t captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + const sp& producer, + const Rect& sourceCrop, float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); + data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeFloat(frameScale); - status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - - if (err != NO_ERROR) { - return err; - } - - err = reply.readInt32(); - if (err != NO_ERROR) { - return err; - } - - *outBuffer = new GraphicBuffer(); - reply.read(**outBuffer); - - return err; + remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + return reply.readInt32(); } virtual bool authenticateSurfaceTexture( @@ -603,7 +583,8 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - sp outBuffer; + sp producer = + interface_cast(data.readStrongBinder()); Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); @@ -613,28 +594,24 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); + status_t res = captureScreen(display, producer, + sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, + useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); - if (res == NO_ERROR) { - reply->write(*outBuffer); - } return NO_ERROR; } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); - sp outBuffer; + sp producer = + interface_cast(data.readStrongBinder()); Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); reply->writeInt32(res); - if (res == NO_ERROR) { - reply->write(*outBuffer); - } return NO_ERROR; } case AUTHENTICATE_SURFACE: { diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 80216bc63e..e9393831c7 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1760,25 +1760,4 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector>* out) return OK; } -status_t Surface::attachAndQueueBuffer(Surface* surface, sp buffer) { - if (buffer == nullptr) { - return BAD_VALUE; - } - int err = static_cast(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, - NATIVE_WINDOW_API_CPU); - if (err != OK) { - return err; - } - err = surface->attachBuffer(buffer->getNativeBuffer()); - if (err != OK) { - return err; - } - err = static_cast(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1); - if (err != OK) { - return err; - } - err = surface->disconnect(NATIVE_WINDOW_API_CPU); - return err; -} - }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0dbe786f1a..2466d2555a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -717,27 +717,181 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation, - sp* outBuffer) { +status_t ScreenshotClient::capture( + const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, - maxLayerZ, useIdentityTransform, - static_cast(rotation)); + return s->captureScreen(display, producer, sourceCrop, + reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); +} + +status_t ScreenshotClient::captureToBuffer(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + uint32_t rotation, + sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp gbpConsumer; + sp producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); if (ret != NO_ERROR) { return ret; } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer) { +status_t ScreenshotClient::captureLayers(const sp& layerHandle, + const sp& producer, + Rect sourceCrop, float frameScale) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); + return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); +} + +status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp gbpConsumer; + sp producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_SW_READ_NEVER | + GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); + if (ret != NO_ERROR) { + return ret; + } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; return ret; } + +ScreenshotClient::ScreenshotClient() + : mHaveBuffer(false) { + memset(&mBuffer, 0, sizeof(mBuffer)); +} + +ScreenshotClient::~ScreenshotClient() { + ScreenshotClient::release(); +} + +sp ScreenshotClient::getCpuConsumer() const { + if (mCpuConsumer == NULL) { + sp consumer; + BufferQueue::createBufferQueue(&mProducer, &consumer); + mCpuConsumer = new CpuConsumer(consumer, 1); + mCpuConsumer->setName(String8("ScreenshotClient")); + } + return mCpuConsumer; +} + +status_t ScreenshotClient::update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + sp cpuConsumer = getCpuConsumer(); + + if (mHaveBuffer) { + mCpuConsumer->unlockBuffer(mBuffer); + memset(&mBuffer, 0, sizeof(mBuffer)); + mHaveBuffer = false; + } + + status_t err = s->captureScreen(display, mProducer, sourceCrop, + reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); + + if (err == NO_ERROR) { + err = mCpuConsumer->lockNextBuffer(&mBuffer); + if (err == NO_ERROR) { + mHaveBuffer = true; + } + } + return err; +} + +status_t ScreenshotClient::update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform) { + + return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone); +} + +status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, + bool useIdentityTransform) { + return ScreenshotClient::update(display, sourceCrop, 0, 0, + INT32_MIN, INT32_MAX, + useIdentityTransform, ISurfaceComposer::eRotateNone); +} + +status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { + return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, + INT32_MIN, INT32_MAX, + useIdentityTransform, ISurfaceComposer::eRotateNone); +} + +void ScreenshotClient::release() { + if (mHaveBuffer) { + mCpuConsumer->unlockBuffer(mBuffer); + memset(&mBuffer, 0, sizeof(mBuffer)); + mHaveBuffer = false; + } + mCpuConsumer.clear(); +} + +void const* ScreenshotClient::getPixels() const { + return mBuffer.data; +} + +uint32_t ScreenshotClient::getWidth() const { + return mBuffer.width; +} + +uint32_t ScreenshotClient::getHeight() const { + return mBuffer.height; +} + +PixelFormat ScreenshotClient::getFormat() const { + return mBuffer.format; +} + +uint32_t ScreenshotClient::getStride() const { + return mBuffer.stride; +} + +size_t ScreenshotClient::getSize() const { + return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); +} + +android_dataspace ScreenshotClient::getDataSpace() const { + return mBuffer.dataSpace; +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e26e332589..1e4c329e1e 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -29,7 +29,6 @@ #include #include -#include #include @@ -168,14 +167,16 @@ public: /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ - virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + virtual status_t captureScreen(const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; virtual status_t captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, - float frameScale = 1.0) = 0; + const sp& producer, + const Rect& sourceCrop, float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 354f23ab06..3fe29d955b 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -283,8 +283,6 @@ public: android_dataspace_t getBuffersDataSpace(); - static status_t attachAndQueueBuffer(Surface* surface, sp buffer); - protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3f13946339..b0fa922cd9 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -279,16 +279,74 @@ private: // --------------------------------------------------------------------------- -class ScreenshotClient { +class ScreenshotClient +{ public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation, - sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, - sp* outBuffer); + static status_t capture( + const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform); + static status_t captureToBuffer( + const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, + uint32_t rotation, + sp* outbuffer); + + static status_t captureLayers(const sp& layerHandle, + const sp& producer, Rect sourceCrop, + float frameScale); + static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer); + +private: + mutable sp mCpuConsumer; + mutable sp mProducer; + CpuConsumer::LockedBuffer mBuffer; + bool mHaveBuffer; + +public: + ScreenshotClient(); + ~ScreenshotClient(); + + // frees the previous screenshot and captures a new one + // if cropping isn't required, callers may pass in a default Rect, e.g.: + // update(display, Rect(), useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, bool useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + bool useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation); + + sp getCpuConsumer() const; + + // release memory occupied by the screenshot + void release(); + + // pixels are valid until this object is freed or + // release() or update() is called + void const* getPixels() const; + + uint32_t getWidth() const; + uint32_t getHeight() const; + PixelFormat getFormat() const; + uint32_t getStride() const; + // size of allocated memory in bytes + size_t getSize() const; + android_dataspace getDataSpace() const; }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 470a338639..ac4eb0cb1d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -116,11 +116,14 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp anw(mSurface); // Verify the screenshot works with no protected buffers. + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - sp outBuffer; - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 64, 64, 0, 0x7fffffff, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), @@ -151,7 +154,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 64, 64, 0, 0x7fffffff, false)); } @@ -521,13 +524,13 @@ public: status_t setActiveColorMode(const sp& /*display*/, android_color_mode_t /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, - sp* /*outBuffer*/, + const sp& /*producer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - sp* /*outBuffer*/, + const sp& /*producer*/, const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4acd448293..d81178c559 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4339,10 +4339,44 @@ private: const int mApi; }; -status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, +static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, + uint32_t requestedHeight, bool hasWideColorDisplay, + bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) { + const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; + + int err = 0; + err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight); + err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); + err |= native_window_set_usage(window, usage); + + if (hasWideColorDisplay) { + err |= native_window_set_buffers_data_space(window, + renderEngineUsesWideColor + ? HAL_DATASPACE_DISPLAY_P3 + : HAL_DATASPACE_V0_SRGB); + } + + if (err != NO_ERROR) { + return BAD_VALUE; + } + + /* TODO: Once we have the sync framework everywhere this can use + * server-side waits on the fence that dequeueBuffer returns. + */ + err = native_window_dequeue_buffer_and_wait(window, outBuffer); + if (err != NO_ERROR) { + return err; + } + + return NO_ERROR; +} + +status_t SurfaceFlinger::captureScreen(const sp& display, + const sp& producer, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, + int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -4353,18 +4387,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + const sp& producer, + const Rect& sourceCrop, float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) + int32_t reqHeight) : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets @@ -4427,21 +4461,51 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); + return captureScreenCommon(renderArea, traverseLayers, producer, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - sp* outBuffer, + const sp& producer, bool useIdentityTransform) { ATRACE_CALL(); + if (CC_UNLIKELY(producer == 0)) + return BAD_VALUE; + renderArea.updateDimensions(); - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); + // if we have secure windows on this display, never allow the screen capture + // unless the producer interface is local (i.e.: we can take a screenshot for + // ourselves). + bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); + + // create a surface (because we're a producer, and we need to + // dequeue/queue a buffer) + sp surface = new Surface(producer, false); + + // Put the screenshot Surface into async mode so that + // Layer::headFenceHasSignaled will always return true and we'll latch the + // first buffer regardless of whether or not its acquire fence has + // signaled. This is needed to avoid a race condition in the rotation + // animation. See b/30209608 + surface->setAsyncMode(true); + + ANativeWindow* window = surface.get(); + + status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); + if (result != NO_ERROR) { + return result; + } + WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); + + ANativeWindowBuffer* buffer = nullptr; + result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), + hasWideColorDisplay && !mForceNativeColorMode, + getRenderEngine().usesWideColor(), &buffer); + if (result != NO_ERROR) { + return result; + } // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -4466,8 +4530,8 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), - useIdentityTransform, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, buffer, + useIdentityTransform, isLocalScreenshot, &fd); } { @@ -4478,7 +4542,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } }); - status_t result = postMessageAsync(message); + result = postMessageAsync(message); if (result == NO_ERROR) { captureCondition.wait(captureLock, [&]() { return captureResult; }); while (*captureResult == EAGAIN) { @@ -4493,10 +4557,9 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } if (result == NO_ERROR) { - sync_wait(syncFd, -1); - close(syncFd); + // queueBuffer takes ownership of syncFd + result = window->queueBuffer(window, buffer, syncFd); } - return result; } @@ -4539,8 +4602,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE - : renderArea.getActiveColorMode()); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); @@ -4583,7 +4645,7 @@ private: status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, - bool useIdentityTransform, + bool useIdentityTransform, bool isLocalScreenshot, int* outSyncFd) { ATRACE_CALL(); @@ -4593,7 +4655,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (secureLayerIsVisible) { + if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -4742,4 +4804,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif \ No newline at end of file +#endif diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a01d353a70..f61dc756c2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -291,11 +291,13 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation); - virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, + virtual status_t captureScreen(const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, + const sp& producer, const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); @@ -434,13 +436,15 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool yswap, bool useIdentityTransform); + status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - sp* outBuffer, + const sp& producer, bool useIdentityTransform); + status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - int* outSyncFd); + bool isLocalScreenshot, int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ff81dc9461..39aef8164c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -104,22 +104,20 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const } // Check if a region has the specified color. -void expectBufferColor(const sp& outBuffer, uint8_t* pixels, const Rect& rect, +void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect, const Color& color, uint8_t tolerance) { int32_t x = rect.left; int32_t y = rect.top; int32_t width = rect.right - rect.left; int32_t height = rect.bottom - rect.top; - int32_t bufferWidth = int32_t(outBuffer->getWidth()); - int32_t bufferHeight = int32_t(outBuffer->getHeight()); - if (x + width > bufferWidth) { - x = std::min(x, bufferWidth); - width = bufferWidth - x; + if (x + width > int32_t(buffer.width)) { + x = std::min(x, int32_t(buffer.width)); + width = buffer.width - x; } - if (y + height > bufferHeight) { - y = std::min(y, bufferHeight); - height = bufferHeight - y; + if (y + height > int32_t(buffer.height)) { + y = std::min(y, int32_t(buffer.height)); + height = buffer.height - y; } auto colorCompare = [tolerance](uint8_t a, uint8_t b) { @@ -127,7 +125,8 @@ void expectBufferColor(const sp& outBuffer, uint8_t* pixels, cons return tmp <= tolerance; }; for (int32_t j = 0; j < height; j++) { - const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; + const uint8_t* src = + static_cast(buffer.data) + (buffer.stride * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) @@ -171,38 +170,30 @@ class ScreenCapture : public RefBase { public: static void captureScreen(sp* sc, int32_t minLayerZ = 0, int32_t maxLayerZ = std::numeric_limits::max()) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); - sp outBuffer; ASSERT_EQ(NO_ERROR, - sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ, - false)); - *sc = new ScreenCapture(outBuffer); - } - - static void captureLayers(std::unique_ptr* sc, sp& parentHandle, - Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { - sp sf(ComposerService::getComposerService()); - SurfaceComposerClient::Transaction().apply(true); - - sp outBuffer; - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); - *sc = std::make_unique(outBuffer); + sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false)); + *sc = new ScreenCapture(cpuConsumer); } void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); - expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + expectBufferColor(mBuf, rect, color, tolerance); } void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); const bool leftBorder = rect.left > 0; const bool topBorder = rect.top > 0; - const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); - const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); + const bool rightBorder = rect.right < int32_t(mBuf.width); + const bool bottomBorder = rect.bottom < int32_t(mBuf.height); if (topBorder) { Rect top(rect.left, rect.top - 1, rect.right, rect.top); @@ -255,8 +246,9 @@ public: } void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); - const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + const uint8_t* img = static_cast(mBuf.data); + const uint8_t* pixel = img + (4 * (y * mBuf.stride + x)); if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { String8 err(String8::format("pixel @ (%3d, %3d): " "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", @@ -271,15 +263,58 @@ public: void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } - ScreenCapture(const sp& outBuffer) : mOutBuffer(outBuffer) { - mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&mPixels)); +private: + ScreenCapture(const sp& cc) : mCC(cc) { + EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf)); } - ~ScreenCapture() { mOutBuffer->unlock(); } + ~ScreenCapture() { mCC->unlockBuffer(mBuf); } + + sp mCC; + CpuConsumer::LockedBuffer mBuf; +}; + +class CaptureLayer { +public: + static void captureScreen(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); + *sc = std::make_unique(cpuConsumer); + } + + void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); + const uint8_t* img = static_cast(mBuffer.data); + const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); + if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { + String8 err(String8::format("pixel @ (%3d, %3d): " + "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", + x, y, r, g, b, pixel[0], pixel[1], pixel[2])); + EXPECT_EQ(String8(), err) << err.string(); + } + } + + void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } + + void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } + + void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } + + CaptureLayer(const sp& cc) : mCC(cc) { + EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); + } + + ~CaptureLayer() { mCC->unlockBuffer(mBuffer); } private: - sp mOutBuffer; - uint8_t* mPixels = NULL; + sp mCC; + CpuConsumer::LockedBuffer mBuffer; }; class LayerTransactionTest : public ::testing::Test { @@ -823,17 +858,21 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); sp composer = ComposerService::getComposerService(); - sp outBuffer; + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + Transaction() .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) .apply(true); ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); } @@ -1465,7 +1504,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } -class LayerUpdateTest : public LayerTransactionTest { +class LayerUpdateTest : public ::testing::Test { protected: virtual void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -2279,12 +2318,12 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { class ScreenCaptureTest : public LayerUpdateTest { protected: - std::unique_ptr mCapture; + std::unique_ptr mCapture; }; TEST_F(ScreenCaptureTest, CaptureSingleLayer) { auto bgHandle = mBGSurfaceControl->getHandle(); - ScreenCapture::captureLayers(&mCapture, bgHandle); + CaptureLayer::captureScreen(&mCapture, bgHandle); mCapture->expectBGColor(0, 0); // Doesn't capture FG layer which is at 64, 64 mCapture->expectBGColor(64, 64); @@ -2301,7 +2340,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { SurfaceComposerClient::Transaction().show(child).apply(true); // Captures mFGSurfaceControl layer and its child. - ScreenCapture::captureLayers(&mCapture, fgHandle); + CaptureLayer::captureScreen(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } @@ -2326,7 +2365,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { .apply(true); // Captures mFGSurfaceControl, its child, and the grandchild. - ScreenCapture::captureLayers(&mCapture, fgHandle); + CaptureLayer::captureScreen(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); mCapture->checkPixel(5, 5, 50, 50, 50); @@ -2342,7 +2381,7 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); // Captures only the child layer, and not the parent. - ScreenCapture::captureLayers(&mCapture, childHandle); + CaptureLayer::captureScreen(&mCapture, childHandle); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); } @@ -2368,96 +2407,94 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { auto grandchildHandle = grandchild->getHandle(); // Captures only the grandchild. - ScreenCapture::captureLayers(&mCapture, grandchildHandle); + CaptureLayer::captureScreen(&mCapture, grandchildHandle); mCapture->checkPixel(0, 0, 50, 50, 50); mCapture->checkPixel(4, 4, 50, 50, 50); } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = - mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, - 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX - 1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - ScreenCapture::captureLayers(&mCapture, redLayerHandle); - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); Rect crop = Rect(0, 0, 30, 30); - ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); + CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + mCapture->checkPixel(29, 29, 0, 0, 255); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = - mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, - 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX - 1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - ScreenCapture::captureLayers(&mCapture, redLayerHandle); - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); - - ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); + mCapture->checkPixel(14, 14, 0, 0, 255); + mCapture->checkPixel(15, 15, 255, 0, 0); + mCapture->checkPixel(29, 29, 255, 0, 0); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + fillSurfaceRGBA8(redLayer, 255, 0, 0); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); - sp outBuffer; + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - sp sf(ComposerService::getComposerService()); - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); } -} // namespace android +} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 40482ff650751819d4104c10a30974838168438c Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Thu, 30 Nov 2017 01:51:40 +0000 Subject: Revert "Revert "Use GraphicBuffer instead of GBP for screenshots."" This reverts commit 707b8f3507fa4a3915844c7a4730e67f94eee2f7. Reason for revert: Ready to test out changes with SystemUI update Change-Id: I9fd0cb7ad9cc68d2366fc5ec4ab087fbe4c21f3b --- libs/gui/ISurfaceComposer.cpp | 71 ++++--- libs/gui/Surface.cpp | 21 ++ libs/gui/SurfaceComposerClient.cpp | 174 +--------------- libs/gui/include/gui/ISurfaceComposer.h | 15 +- libs/gui/include/gui/Surface.h | 2 + libs/gui/include/gui/SurfaceComposerClient.h | 72 +------ libs/gui/tests/Surface_test.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.cpp | 112 +++------- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/Transaction_test.cpp | 229 +++++++++------------ 10 files changed, 227 insertions(+), 500 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c21c5e3eb8..5de84ecbab 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -100,17 +100,13 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) - { + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -118,21 +114,45 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); - remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + return err; } virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeFloat(frameScale); - remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + + return err; } virtual bool authenticateSurfaceTexture( @@ -583,8 +603,7 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); @@ -594,24 +613,28 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, producer, - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, - static_cast(rotation)); + status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case AUTHENTICATE_SURFACE: { diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e9393831c7..80216bc63e 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1760,4 +1760,25 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector>* out) return OK; } +status_t Surface::attachAndQueueBuffer(Surface* surface, sp buffer) { + if (buffer == nullptr) { + return BAD_VALUE; + } + int err = static_cast(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, + NATIVE_WINDOW_API_CPU); + if (err != OK) { + return err; + } + err = surface->attachBuffer(buffer->getNativeBuffer()); + if (err != OK) { + return err; + } + err = static_cast(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1); + if (err != OK) { + return err; + } + err = surface->disconnect(NATIVE_WINDOW_API_CPU); + return err; +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2466d2555a..0dbe786f1a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -717,181 +717,27 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { +status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureScreen(display, producer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); -} - -status_t ScreenshotClient::captureToBuffer(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - uint32_t rotation, - sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); + status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, + maxLayerZ, useIdentityTransform, + static_cast(rotation)); if (ret != NO_ERROR) { return ret; } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, - const sp& producer, - Rect sourceCrop, float frameScale) { +status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); -} - -status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | - GRALLOC_USAGE_SW_READ_NEVER | - GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); - if (ret != NO_ERROR) { - return ret; - } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); return ret; } - -ScreenshotClient::ScreenshotClient() - : mHaveBuffer(false) { - memset(&mBuffer, 0, sizeof(mBuffer)); -} - -ScreenshotClient::~ScreenshotClient() { - ScreenshotClient::release(); -} - -sp ScreenshotClient::getCpuConsumer() const { - if (mCpuConsumer == NULL) { - sp consumer; - BufferQueue::createBufferQueue(&mProducer, &consumer); - mCpuConsumer = new CpuConsumer(consumer, 1); - mCpuConsumer->setName(String8("ScreenshotClient")); - } - return mCpuConsumer; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - sp cpuConsumer = getCpuConsumer(); - - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - - status_t err = s->captureScreen(display, mProducer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); - - if (err == NO_ERROR) { - err = mCpuConsumer->lockNextBuffer(&mBuffer); - if (err == NO_ERROR) { - mHaveBuffer = true; - } - } - return err; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform) { - - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, 0, 0, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -void ScreenshotClient::release() { - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - mCpuConsumer.clear(); -} - -void const* ScreenshotClient::getPixels() const { - return mBuffer.data; -} - -uint32_t ScreenshotClient::getWidth() const { - return mBuffer.width; -} - -uint32_t ScreenshotClient::getHeight() const { - return mBuffer.height; -} - -PixelFormat ScreenshotClient::getFormat() const { - return mBuffer.format; -} - -uint32_t ScreenshotClient::getStride() const { - return mBuffer.stride; -} - -size_t ScreenshotClient::getSize() const { - return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); -} - -android_dataspace ScreenshotClient::getDataSpace() const { - return mBuffer.dataSpace; -} - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 1e4c329e1e..e26e332589 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -167,16 +168,14 @@ public: /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale = 1.0) = 0; + sp* outBuffer, const Rect& sourceCrop, + float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 3fe29d955b..354f23ab06 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -283,6 +283,8 @@ public: android_dataspace_t getBuffersDataSpace(); + static status_t attachAndQueueBuffer(Surface* surface, sp buffer); + protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b0fa922cd9..3f13946339 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -279,74 +279,16 @@ private: // --------------------------------------------------------------------------- -class ScreenshotClient -{ +class ScreenshotClient { public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - static status_t captureToBuffer( - const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - uint32_t rotation, - sp* outbuffer); - - static status_t captureLayers(const sp& layerHandle, - const sp& producer, Rect sourceCrop, - float frameScale); - static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer); - -private: - mutable sp mCpuConsumer; - mutable sp mProducer; - CpuConsumer::LockedBuffer mBuffer; - bool mHaveBuffer; - -public: - ScreenshotClient(); - ~ScreenshotClient(); - - // frees the previous screenshot and captures a new one - // if cropping isn't required, callers may pass in a default Rect, e.g.: - // update(display, Rect(), useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation); - - sp getCpuConsumer() const; - - // release memory occupied by the screenshot - void release(); - - // pixels are valid until this object is freed or - // release() or update() is called - void const* getPixels() const; - - uint32_t getWidth() const; - uint32_t getHeight() const; - PixelFormat getFormat() const; - uint32_t getStride() const; - // size of allocated memory in bytes - size_t getSize() const; - android_dataspace getDataSpace() const; + static status_t capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer); + static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, + sp* outBuffer); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ac4eb0cb1d..470a338639 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -116,14 +116,11 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp anw(mSurface); // Verify the screenshot works with no protected buffers. - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), @@ -154,7 +151,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); } @@ -524,13 +521,13 @@ public: status_t setActiveColorMode(const sp& /*display*/, android_color_mode_t /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, - const sp& /*producer*/, + sp* /*outBuffer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - const sp& /*producer*/, + sp* /*outBuffer*/, const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d81178c559..4acd448293 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4339,44 +4339,10 @@ private: const int mApi; }; -static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, - uint32_t requestedHeight, bool hasWideColorDisplay, - bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) { - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - - int err = 0; - err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight); - err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); - err |= native_window_set_usage(window, usage); - - if (hasWideColorDisplay) { - err |= native_window_set_buffers_data_space(window, - renderEngineUsesWideColor - ? HAL_DATASPACE_DISPLAY_P3 - : HAL_DATASPACE_V0_SRGB); - } - - if (err != NO_ERROR) { - return BAD_VALUE; - } - - /* TODO: Once we have the sync framework everywhere this can use - * server-side waits on the fence that dequeueBuffer returns. - */ - err = native_window_dequeue_buffer_and_wait(window, outBuffer); - if (err != NO_ERROR) { - return err; - } - - return NO_ERROR; -} - -status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, +status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -4387,18 +4353,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, device, minLayerZ, maxLayerZ, std::placeholders::_1); - return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) + int32_t reqHeight) : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets @@ -4461,51 +4427,21 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, producer, false); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform) { ATRACE_CALL(); - if (CC_UNLIKELY(producer == 0)) - return BAD_VALUE; - renderArea.updateDimensions(); - // if we have secure windows on this display, never allow the screen capture - // unless the producer interface is local (i.e.: we can take a screenshot for - // ourselves). - bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - - // create a surface (because we're a producer, and we need to - // dequeue/queue a buffer) - sp surface = new Surface(producer, false); - - // Put the screenshot Surface into async mode so that - // Layer::headFenceHasSignaled will always return true and we'll latch the - // first buffer regardless of whether or not its acquire fence has - // signaled. This is needed to avoid a race condition in the rotation - // animation. See b/30209608 - surface->setAsyncMode(true); - - ANativeWindow* window = surface.get(); - - status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - if (result != NO_ERROR) { - return result; - } - WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); - - ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), - hasWideColorDisplay && !mForceNativeColorMode, - getRenderEngine().usesWideColor(), &buffer); - if (result != NO_ERROR) { - return result; - } + const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; + *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -4530,8 +4466,8 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, buffer, - useIdentityTransform, isLocalScreenshot, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), + useIdentityTransform, &fd); } { @@ -4542,7 +4478,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } }); - result = postMessageAsync(message); + status_t result = postMessageAsync(message); if (result == NO_ERROR) { captureCondition.wait(captureLock, [&]() { return captureResult; }); while (*captureResult == EAGAIN) { @@ -4557,9 +4493,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } if (result == NO_ERROR) { - // queueBuffer takes ownership of syncFd - result = window->queueBuffer(window, buffer, syncFd); + sync_wait(syncFd, -1); + close(syncFd); } + return result; } @@ -4602,7 +4539,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE + : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); @@ -4645,7 +4583,7 @@ private: status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, - bool useIdentityTransform, bool isLocalScreenshot, + bool useIdentityTransform, int* outSyncFd) { ATRACE_CALL(); @@ -4655,7 +4593,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (!isLocalScreenshot && secureLayerIsVisible) { + if (secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -4804,4 +4742,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif +#endif \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f61dc756c2..a01d353a70 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -291,13 +291,11 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); - virtual status_t captureLayers(const sp& parentHandle, - const sp& producer, + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); @@ -436,15 +434,13 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool yswap, bool useIdentityTransform); - status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform); - status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - bool isLocalScreenshot, int* outSyncFd); + int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 39aef8164c..ff81dc9461 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -104,20 +104,22 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const } // Check if a region has the specified color. -void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect, +void expectBufferColor(const sp& outBuffer, uint8_t* pixels, const Rect& rect, const Color& color, uint8_t tolerance) { int32_t x = rect.left; int32_t y = rect.top; int32_t width = rect.right - rect.left; int32_t height = rect.bottom - rect.top; - if (x + width > int32_t(buffer.width)) { - x = std::min(x, int32_t(buffer.width)); - width = buffer.width - x; + int32_t bufferWidth = int32_t(outBuffer->getWidth()); + int32_t bufferHeight = int32_t(outBuffer->getHeight()); + if (x + width > bufferWidth) { + x = std::min(x, bufferWidth); + width = bufferWidth - x; } - if (y + height > int32_t(buffer.height)) { - y = std::min(y, int32_t(buffer.height)); - height = buffer.height - y; + if (y + height > bufferHeight) { + y = std::min(y, bufferHeight); + height = bufferHeight - y; } auto colorCompare = [tolerance](uint8_t a, uint8_t b) { @@ -125,8 +127,7 @@ void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect return tmp <= tolerance; }; for (int32_t j = 0; j < height; j++) { - const uint8_t* src = - static_cast(buffer.data) + (buffer.stride * (y + j) + x) * 4; + const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) @@ -170,30 +171,38 @@ class ScreenCapture : public RefBase { public: static void captureScreen(sp* sc, int32_t minLayerZ = 0, int32_t maxLayerZ = std::numeric_limits::max()) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); + sp outBuffer; ASSERT_EQ(NO_ERROR, - sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false)); - *sc = new ScreenCapture(cpuConsumer); + sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ, + false)); + *sc = new ScreenCapture(outBuffer); + } + + static void captureLayers(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); + *sc = std::make_unique(outBuffer); } void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - expectBufferColor(mBuf, rect, color, tolerance); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); } void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); const bool leftBorder = rect.left > 0; const bool topBorder = rect.top > 0; - const bool rightBorder = rect.right < int32_t(mBuf.width); - const bool bottomBorder = rect.bottom < int32_t(mBuf.height); + const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); + const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); if (topBorder) { Rect top(rect.left, rect.top - 1, rect.right, rect.top); @@ -246,9 +255,8 @@ public: } void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - const uint8_t* img = static_cast(mBuf.data); - const uint8_t* pixel = img + (4 * (y * mBuf.stride + x)); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { String8 err(String8::format("pixel @ (%3d, %3d): " "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", @@ -263,58 +271,15 @@ public: void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } -private: - ScreenCapture(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf)); + ScreenCapture(const sp& outBuffer) : mOutBuffer(outBuffer) { + mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&mPixels)); } - ~ScreenCapture() { mCC->unlockBuffer(mBuf); } - - sp mCC; - CpuConsumer::LockedBuffer mBuf; -}; - -class CaptureLayer { -public: - static void captureScreen(std::unique_ptr* sc, sp& parentHandle, - Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); - SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); - *sc = std::make_unique(cpuConsumer); - } - - void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); - const uint8_t* img = static_cast(mBuffer.data); - const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); - if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { - String8 err(String8::format("pixel @ (%3d, %3d): " - "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", - x, y, r, g, b, pixel[0], pixel[1], pixel[2])); - EXPECT_EQ(String8(), err) << err.string(); - } - } - - void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } - - void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } - - void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } - - CaptureLayer(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); - } - - ~CaptureLayer() { mCC->unlockBuffer(mBuffer); } + ~ScreenCapture() { mOutBuffer->unlock(); } private: - sp mCC; - CpuConsumer::LockedBuffer mBuffer; + sp mOutBuffer; + uint8_t* mPixels = NULL; }; class LayerTransactionTest : public ::testing::Test { @@ -858,21 +823,17 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); sp composer = ComposerService::getComposerService(); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - + sp outBuffer; Transaction() .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) .apply(true); ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); } @@ -1504,7 +1465,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } -class LayerUpdateTest : public ::testing::Test { +class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -2318,12 +2279,12 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { class ScreenCaptureTest : public LayerUpdateTest { protected: - std::unique_ptr mCapture; + std::unique_ptr mCapture; }; TEST_F(ScreenCaptureTest, CaptureSingleLayer) { auto bgHandle = mBGSurfaceControl->getHandle(); - CaptureLayer::captureScreen(&mCapture, bgHandle); + ScreenCapture::captureLayers(&mCapture, bgHandle); mCapture->expectBGColor(0, 0); // Doesn't capture FG layer which is at 64, 64 mCapture->expectBGColor(64, 64); @@ -2340,7 +2301,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { SurfaceComposerClient::Transaction().show(child).apply(true); // Captures mFGSurfaceControl layer and its child. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } @@ -2365,7 +2326,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { .apply(true); // Captures mFGSurfaceControl, its child, and the grandchild. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); mCapture->checkPixel(5, 5, 50, 50, 50); @@ -2381,7 +2342,7 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); // Captures only the child layer, and not the parent. - CaptureLayer::captureScreen(&mCapture, childHandle); + ScreenCapture::captureLayers(&mCapture, childHandle); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); } @@ -2407,94 +2368,96 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { auto grandchildHandle = grandchild->getHandle(); // Captures only the grandchild. - CaptureLayer::captureScreen(&mCapture, grandchildHandle); + ScreenCapture::captureLayers(&mCapture, grandchildHandle); mCapture->checkPixel(0, 0, 50, 50, 50); mCapture->checkPixel(4, 4, 50, 50, 50); } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); Rect crop = Rect(0, 0, 30, 30); - CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. - mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); - - CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + + ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->checkPixel(14, 14, 0, 0, 255); - mCapture->checkPixel(15, 15, 255, 0, 0); - mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); - fillSurfaceRGBA8(redLayer, 255, 0, 0); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); + sp outBuffer; // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); + sp sf(ComposerService::getComposerService()); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } -} \ No newline at end of file +} // namespace android -- cgit v1.2.3-59-g8ed1b From f3cf4bcfa2c558f03e178f7044d3cb12fa0e73ed Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 30 Nov 2017 14:19:23 +0100 Subject: Make SurfaceControl parcelable (2/2) Bug: 69145041 Test: Send SurfaceControl over binder Change-Id: I47aa4a4bb39fab3ed4d1d30d4e472de7cbc5ca38 --- libs/gui/SurfaceComposerClient.cpp | 7 ++++++- libs/gui/SurfaceControl.cpp | 23 +++++++++++++++++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 1 + libs/gui/include/gui/SurfaceControl.h | 3 +++ 4 files changed, 33 insertions(+), 1 deletion(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2466d2555a..4c8cab24b6 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -543,9 +543,14 @@ SurfaceComposerClient::SurfaceComposerClient(const sp& r { } +SurfaceComposerClient::SurfaceComposerClient(const sp& client) + : mStatus(NO_ERROR), mClient(client) +{ +} + void SurfaceComposerClient::onFirstRef() { sp sf(ComposerService::getComposerService()); - if (sf != 0) { + if (sf != 0 && mStatus == NO_INIT) { auto rootProducer = mParent.promote(); sp conn; conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) : diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index f6a2b8fed6..f5fb8acf44 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -166,5 +166,28 @@ sp SurfaceControl::getClient() const return mClient; } +void SurfaceControl::writeToParcel(Parcel* parcel) +{ + parcel->writeStrongBinder(ISurfaceComposerClient::asBinder(mClient->getClient())); + parcel->writeStrongBinder(mHandle); + parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer)); +} + +sp SurfaceControl::readFromParcel(Parcel* parcel) +{ + sp client = parcel->readStrongBinder(); + sp handle = parcel->readStrongBinder(); + if (client == nullptr || handle == nullptr) + { + ALOGE("Invalid parcel"); + return nullptr; + } + sp gbp; + parcel->readNullableStrongBinder(&gbp); + return new SurfaceControl(new SurfaceComposerClient( + interface_cast(client)), + handle.get(), interface_cast(gbp)); +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b0fa922cd9..37c4dcf2e0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,6 +52,7 @@ class SurfaceComposerClient : public RefBase friend class Composer; public: SurfaceComposerClient(); + SurfaceComposerClient(const sp& client); SurfaceComposerClient(const sp& parent); virtual ~SurfaceComposerClient(); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index 384815dad8..1416d87110 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -44,6 +44,9 @@ class SurfaceComposerClient; class SurfaceControl : public RefBase { public: + static sp readFromParcel(Parcel* parcel); + void writeToParcel(Parcel* parcel); + static bool isValid(const sp& surface) { return (surface != 0) && surface->isValid(); } -- cgit v1.2.3-59-g8ed1b From 0b26710528eb69f3883f295f3e6146e6466fd082 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Mon, 29 Jan 2018 16:39:21 +0100 Subject: Fix issue with Surface loss Some remote animations didn't use all surfaces, meaning that these became unreachable objects in the object tree, meaning that they we're finalized during the animation, causing the leash to be destroyed in SurfaceFlinger, causing to suffering because the AWT surface got released, meaning that we can never allocate the main windows Surface anymore. Fix this by not releasing surfaces that you don't own. Test: go/wm-smoke Test: Notification launch animation over app Change-Id: Ia99b4e814bfb286ae1d3639c525fc8f6c42c0e0f Fixes: No bug yet, but expect to have a chaselist bug soon! --- libs/gui/SurfaceComposerClient.cpp | 2 +- libs/gui/SurfaceControl.cpp | 13 +++++++++---- libs/gui/include/gui/SurfaceControl.h | 4 +++- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 939a209c3f..c40cad3e99 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -615,7 +615,7 @@ sp SurfaceComposerClient::createSurface( windowType, ownerUid, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { - sur = new SurfaceControl(this, handle, gbp); + sur = new SurfaceControl(this, handle, gbp, true /* owned */); } } return sur; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index f5fb8acf44..5eafbb3555 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -48,8 +48,9 @@ namespace android { SurfaceControl::SurfaceControl( const sp& client, const sp& handle, - const sp& gbp) - : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp) + const sp& gbp, + bool owned) + : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned) { } @@ -60,7 +61,9 @@ SurfaceControl::~SurfaceControl() void SurfaceControl::destroy() { - if (isValid()) { + // Avoid destroying the server-side surface if we are not the owner of it, meaning that we + // retrieved it from another process. + if (isValid() && mOwned) { mClient->destroySurface(mHandle); } // clear all references and trigger an IPC now, to make sure things @@ -184,9 +187,11 @@ sp SurfaceControl::readFromParcel(Parcel* parcel) } sp gbp; parcel->readNullableStrongBinder(&gbp); + + // We aren't the original owner of the surface. return new SurfaceControl(new SurfaceComposerClient( interface_cast(client)), - handle.get(), interface_cast(gbp)); + handle.get(), interface_cast(gbp), false /* owned */); } // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index 1416d87110..bd987dd638 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -87,7 +87,8 @@ private: SurfaceControl( const sp& client, const sp& handle, - const sp& gbp); + const sp& gbp, + bool owned); ~SurfaceControl(); @@ -100,6 +101,7 @@ private: sp mGraphicBufferProducer; mutable Mutex mLock; mutable sp mSurfaceData; + bool mOwned; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From ca27f2500cff74ae1e08b3ae06f18e9b3414ffb7 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 6 Feb 2018 16:46:39 -0800 Subject: Allow destroySurface to get called in transaction. Previously, destroy was always initiated immediatley and could not be synchronized with a client transaction. This change allows destroySurface to be called in the same transaction as other client state updates. Test: Unit tests pass Test: Call from Java fixes bugs. Change-Id: I841359530538961a0187216cc455cc388c0ede77 Fixes: 72953020 Fixes: 71499373 --- libs/gui/LayerState.cpp | 3 + libs/gui/SurfaceComposerClient.cpp | 11 ++++ libs/gui/include/gui/LayerState.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 + services/surfaceflinger/SurfaceFlinger.cpp | 96 +++++++++++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 5 +- 6 files changed, 89 insertions(+), 31 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index b5295f2801..01acc2de20 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -231,6 +231,9 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eReparent; parentHandleForChild = other.parentHandleForChild; } + if (other.what & eDestroySurface) { + what |= eDestroySurface; + } } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c40cad3e99..0722038c5b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -472,6 +472,17 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( + const sp& sc) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDestroySurface; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index f3fb82feb3..788962e490 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -62,7 +62,8 @@ struct layer_state_t { eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, eReparent = 0x00010000, - eColorChanged = 0x00020000 + eColorChanged = 0x00020000, + eDestroySurface = 0x00040000 }; layer_state_t() diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 55b96ac93d..10caa76281 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -229,6 +229,8 @@ public: // freezing the total geometry of a surface until a resize is completed. Transaction& setGeometryAppliesWithResize(const sp& sc); + Transaction& destroySurface(const sp& sc); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 03f6bdc583..135bfbefa9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2901,7 +2901,11 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) { Mutex::Autolock _l(mStateLock); + return removeLayerLocked(mStateLock, layer, topLevelOnly); +} +status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, + bool topLevelOnly) { if (layer->isPendingRemoval()) { return NO_ERROR; } @@ -2965,8 +2969,30 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { return old; } +bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& states) { + for (const ComposerState& state : states) { + // Here we need to check that the interface we're given is indeed + // one of our own. A malicious client could give us a nullptr + // IInterface, or one of its own or even one of our own but a + // different type. All these situations would cause us to crash. + if (state.client == nullptr) { + return true; + } + + sp binder = IInterface::asBinder(state.client); + if (binder == nullptr) { + return true; + } + + if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) == nullptr) { + return true; + } + } + return false; +} + void SurfaceFlinger::setTransactionState( - const Vector& state, + const Vector& states, const Vector& displays, uint32_t flags) { @@ -2974,6 +3000,10 @@ void SurfaceFlinger::setTransactionState( Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; + if (containsAnyInvalidClientState(states)) { + return; + } + if (flags & eAnimation) { // For window updates that are part of an animation we must wait for // previous animation "frames" to be handled. @@ -2990,31 +3020,20 @@ void SurfaceFlinger::setTransactionState( } } - size_t count = displays.size(); - for (size_t i=0 ; i binder = IInterface::asBinder(s.client); - if (binder != nullptr) { - if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != nullptr) { - sp client( static_cast(s.client.get()) ); - transactionFlags |= setClientStateLocked(client, s.state); - } - } - } + for (const ComposerState& state : states) { + transactionFlags |= setClientStateLocked(state); + } + + // Iterate through all layers again to determine if any need to be destroyed. Marking layers + // as destroyed should only occur after setting all other states. This is to allow for a + // child re-parent to happen before marking its original parent as destroyed (which would + // then mark the child as destroyed). + for (const ComposerState& state : states) { + setDestroyStateLocked(state); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -3028,7 +3047,7 @@ void SurfaceFlinger::setTransactionState( if (transactionFlags) { if (mInterceptor.isEnabled()) { - mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags); + mInterceptor.saveTransaction(states, mCurrentState.displays, displays, flags); } // this triggers the transaction @@ -3105,10 +3124,10 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) return flags; } -uint32_t SurfaceFlinger::setClientStateLocked( - const sp& client, - const layer_state_t& s) -{ +uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) { + const layer_state_t& s = composerState.state; + sp client(static_cast(composerState.client.get())); + sp layer(client->getLayerUser(s.surface)); if (layer == nullptr) { return 0; @@ -3259,6 +3278,25 @@ uint32_t SurfaceFlinger::setClientStateLocked( return flags; } +void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { + const layer_state_t& state = composerState.state; + sp client(static_cast(composerState.client.get())); + + sp layer(client->getLayerUser(state.surface)); + if (layer == nullptr) { + return; + } + + if (layer->isPendingRemoval()) { + ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); + return; + } + + if (state.what & layer_state_t::eDestroySurface) { + removeLayerLocked(mStateLock, layer); + } +} + status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b7ebb1bcf3..08c4a5e3b1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -473,8 +473,10 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); void commitTransaction(); - uint32_t setClientStateLocked(const sp& client, const layer_state_t& s); + bool containsAnyInvalidClientState(const Vector& states); + uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); + void setDestroyStateLocked(const ComposerState& composerState); /* ------------------------------------------------------------------------ * Layer management @@ -506,6 +508,7 @@ private: // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); + status_t removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly = false); // add a layer to SurfaceFlinger status_t addClientLayer(const sp& client, -- cgit v1.2.3-59-g8ed1b From 763ef57459aa9f10f3587581b119fe8d4ece3cd3 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 22 Feb 2018 16:04:57 -0800 Subject: Rename getLayerState and getDisplayState functions. Both getLayerStateLocked and getDisplayStateLocked are named incorrectly since they do not require a lock to be held when called. Rename to avoid confusion. Test: Builds and runs Change-Id: Ia0a98fc4c1994ecc131c783fea478e3e7075044d --- libs/gui/SurfaceComposerClient.cpp | 52 ++++++++++++++-------------- libs/gui/include/gui/SurfaceComposerClient.h | 4 +-- 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0722038c5b..b7773c4f45 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -181,7 +181,7 @@ void SurfaceComposerClient::Transaction::setAnimationTransaction() { mAnimation = true; } -layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp& sc) { +layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { ComposerState s; s.client = sc->getClient()->mClient; s.state.surface = sc->getHandle(); @@ -198,7 +198,7 @@ layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp< SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( const sp& sc, float x, float y) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -221,7 +221,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::hide( SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( const sp& sc, uint32_t w, uint32_t h) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -238,7 +238,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer( const sp& sc, int32_t z) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -250,7 +250,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer(const sp& sc, const sp& relativeTo, int32_t z) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; } @@ -263,7 +263,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelat SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags( const sp& sc, uint32_t flags, uint32_t mask) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -282,7 +282,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransparentRegionHint( const sp& sc, const Region& transparentRegion) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -294,7 +294,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrans SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha( const sp& sc, float alpha) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -306,7 +306,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayerStack( const sp& sc, uint32_t layerStack) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -319,7 +319,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix( const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -336,7 +336,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatri SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( const sp& sc, const Rect& crop) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -347,7 +347,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp& sc, const Rect& crop) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -360,7 +360,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinal SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( const sp& sc, const sp& handle, uint64_t frameNumber) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -374,7 +374,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTra SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( const sp& sc, const sp& barrierSurface, uint64_t frameNumber) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -388,7 +388,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTra SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren( const sp& sc, const sp& newParentHandle) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -401,7 +401,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent( const sp& sc, const sp& newParentHandle) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -414,7 +414,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor( const sp& sc, const half3& color) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -426,7 +426,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp& sc) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; } @@ -436,7 +436,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachCh SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverrideScalingMode( const sp& sc, int32_t overrideScalingMode) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -463,7 +463,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverr SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize( const sp& sc) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -474,7 +474,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( const sp& sc) { - layer_state_t* s = getLayerStateLocked(sc); + layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; @@ -485,7 +485,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroyS // --------------------------------------------------------------------------- -DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp& token) { +DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { DisplayState s; s.token = token; ssize_t index = mDisplayStates.indexOf(s); @@ -510,7 +510,7 @@ status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp return err; } } - DisplayState& s(getDisplayStateLocked(token)); + DisplayState& s(getDisplayState(token)); s.surface = bufferProducer; s.what |= DisplayState::eSurfaceChanged; return NO_ERROR; @@ -518,7 +518,7 @@ status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp& token, uint32_t layerStack) { - DisplayState& s(getDisplayStateLocked(token)); + DisplayState& s(getDisplayState(token)); s.layerStack = layerStack; s.what |= DisplayState::eLayerStackChanged; } @@ -527,7 +527,7 @@ void SurfaceComposerClient::Transaction::setDisplayProjection(const sp& uint32_t orientation, const Rect& layerStackRect, const Rect& displayRect) { - DisplayState& s(getDisplayStateLocked(token)); + DisplayState& s(getDisplayState(token)); s.orientation = orientation; s.viewport = layerStackRect; s.frame = displayRect; @@ -536,7 +536,7 @@ void SurfaceComposerClient::Transaction::setDisplayProjection(const sp& } void SurfaceComposerClient::Transaction::setDisplaySize(const sp& token, uint32_t width, uint32_t height) { - DisplayState& s(getDisplayStateLocked(token)); + DisplayState& s(getDisplayState(token)); s.width = width; s.height = height; s.what |= DisplayState::eDisplaySizeChanged; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 10caa76281..e5156c6121 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -136,8 +136,8 @@ public: int mStatus = NO_ERROR; - layer_state_t* getLayerStateLocked(const sp& sc); - DisplayState& getDisplayStateLocked(const sp& token); + layer_state_t* getLayerState(const sp& sc); + DisplayState& getDisplayState(const sp& token); public: Transaction() = default; -- cgit v1.2.3-59-g8ed1b From 8e3fe5d6a78d92e0bcbd90ca98cf7b3f9de7512d Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 22 Feb 2018 10:55:42 -0800 Subject: Store SurfaceControl reference when creating transactions The SurfaceControl needs to be stored when adding a new transaction. This ensures the ref count is incremented so the SC isn't removed before the transaction is applied. Change-Id: I27a060e4c221c5dfa565ceb3a916574105fd1175 Fixes: 73448047 Test: DereferenceSurfaceControlTest --- libs/gui/SurfaceComposerClient.cpp | 29 +++++++------- libs/gui/include/gui/SurfaceComposerClient.h | 9 ++++- .../tests/SurfaceFlinger_test.filter | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 45 ++++++++++++++++++++++ 4 files changed, 68 insertions(+), 17 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b7773c4f45..92a24ad933 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -105,12 +105,11 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { - for (auto const& state : other.mComposerStates) { - ssize_t index = mComposerStates.indexOf(state); - if (index < 0) { - mComposerStates.add(state); + for (auto const& kv : other.mComposerStates) { + if (mComposerStates.count(kv.first) == 0) { + mComposerStates[kv.first] = kv.second; } else { - mComposerStates.editItemAt(static_cast(index)).state.merge(state.state); + mComposerStates[kv.first].state.merge(kv.second.state); } } other.mComposerStates.clear(); @@ -141,7 +140,10 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { mForceSynchronous |= synchronous; - composerStates = mComposerStates; + for (auto const& kv : mComposerStates){ + composerStates.add(kv.second); + } + mComposerStates.clear(); displayStates = mDisplayStates; @@ -182,18 +184,15 @@ void SurfaceComposerClient::Transaction::setAnimationTransaction() { } layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { - ComposerState s; - s.client = sc->getClient()->mClient; - s.state.surface = sc->getHandle(); - - ssize_t index = mComposerStates.indexOf(s); - if (index < 0) { + if (mComposerStates.count(sc) == 0) { // we don't have it, add an initialized layer_state to our list - index = mComposerStates.add(s); + ComposerState s; + s.client = sc->getClient()->mClient; + s.state.surface = sc->getHandle(); + mComposerStates[sc] = s; } - ComposerState* const out = mComposerStates.editArray(); - return &(out[index].state); + return &(mComposerStates[sc].state); } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e5156c6121..3fe66356bf 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -19,6 +19,7 @@ #include #include +#include #include @@ -127,8 +128,14 @@ public: static status_t injectVSync(nsecs_t when); + struct SCHash { + std::size_t operator()(const sp& sc) const { + return std::hash{}(sc.get()); + } + }; + class Transaction { - SortedVector mComposerStates; + std::unordered_map, ComposerState, SCHash> mComposerStates; SortedVector mDisplayStates; uint32_t mForceSynchronous = 0; uint32_t mTransactionNestCount = 0; diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index be4127c915..36424b9c5e 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*" + "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*" } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ac8a2ad868..92c26af9eb 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2460,4 +2460,49 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } + +class DereferenceSurfaceControlTest : public LayerTransactionTest { +protected: + void SetUp() override { + LayerTransactionTest::SetUp(); + bgLayer = createLayer("BG layer", 20, 20); + fillLayerColor(bgLayer, Color::RED); + fgLayer = createLayer("FG layer", 20, 20); + fillLayerColor(fgLayer, Color::BLUE); + Transaction().setLayer(fgLayer, mLayerZBase + 1).apply(); + { + SCOPED_TRACE("before anything"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE); + } + } + void TearDown() override { + LayerTransactionTest::TearDown(); + bgLayer = 0; + fgLayer = 0; + } + + sp bgLayer; + sp fgLayer; +}; + +TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) { + fgLayer = nullptr; + { + SCOPED_TRACE("after setting null"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 20, 20), Color::RED); + } +} + +TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) { + auto transaction = Transaction().show(fgLayer); + fgLayer = nullptr; + { + SCOPED_TRACE("after setting null"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE); + } +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From 578038fc49f83c4c8c4accdce49df404ecd6ad02 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 9 Mar 2018 12:25:24 -0800 Subject: SurfaceFlinger: Add childLayersOnly variant of capture layers. Currently captureLayers is being used to capture children of abstract buffer-less layers, for example we capture the node representing a Task. Because of animations, etc, the node may have been scaled when we want to take the screenshot, so we solved this problem with an inverse transform in LayerRenderArea. However we have parallel problems for crop, visibility, etc...It seems what we really want from captureLayers is the ability to capture all child layers while ignoring the parent imposed state as if in a parallel hierarchy. I initially considered implementing a parallel hierarchy with layer clones but it seemed much less risky for P to instead reparent the existing hierarchy to a parallel abstract parent on the server side. Bug: 72760590 Test: Existing tests pass. Quickstep works with new implementation. New transaction tests. Change-Id: Ifd2b2f9ed45351d8ed0d7f09be1cd9806ec4abe8 --- libs/gui/ISurfaceComposer.cpp | 7 +- libs/gui/SurfaceComposerClient.cpp | 12 +++- libs/gui/include/gui/ISurfaceComposer.h | 5 +- libs/gui/include/gui/SurfaceComposerClient.h | 4 +- libs/gui/tests/Surface_test.cpp | 4 +- services/surfaceflinger/ContainerLayer.cpp | 14 ++-- services/surfaceflinger/ContainerLayer.h | 10 +-- services/surfaceflinger/Layer.cpp | 6 ++ services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/RenderArea.h | 4 ++ services/surfaceflinger/SurfaceFlinger.cpp | 81 +++++++++++++++++----- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 78 +++++++++++++++++++++ 13 files changed, 191 insertions(+), 38 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5de84ecbab..beda778396 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -132,12 +132,13 @@ public: virtual status_t captureLayers(const sp& layerHandleBinder, sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + float frameScale, bool childrenOnly) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); data.write(sourceCrop); data.writeFloat(frameScale); + data.writeBool(childrenOnly); status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); if (err != NO_ERROR) { @@ -629,8 +630,10 @@ status_t BnSurfaceComposer::onTransact( Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); + bool childrenOnly = data.readBool(); - status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale, + childrenOnly); reply->writeInt32(res); if (res == NO_ERROR) { reply->write(*outBuffer); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 92a24ad933..0d7ffc3d71 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -751,7 +751,17 @@ status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect so float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, + false /* childrenOnly */); + return ret; +} + +status_t ScreenshotClient::captureChildLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, + true /* childrenOnly */); return ret; } // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e26e332589..5ab64454e5 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -173,9 +173,12 @@ public: int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; + /** + * Capture a subtree of the layer hierarchy, potentially ignoring the root node. + */ virtual status_t captureLayers(const sp& layerHandleBinder, sp* outBuffer, const Rect& sourceCrop, - float frameScale = 1.0) = 0; + float frameScale = 1.0, bool childrenOnly = false) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3fe66356bf..fe46146ff5 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,8 +297,10 @@ public: uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, uint32_t rotation, sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, + static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float frameScale, sp* outBuffer); + static status_t captureChildLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 8060b6e7c5..4fb51e1b96 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -593,8 +593,8 @@ public: bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - sp* /*outBuffer*/, - const Rect& /*sourceCrop*/, float /*frameScale*/) override { + sp* /*outBuffer*/, const Rect& /*sourceCrop*/, + float /*frameScale*/, bool /*childrenOnly*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 2f89cc1d76..f259d93c3f 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -16,24 +16,24 @@ // #define LOG_NDEBUG 0 #undef LOG_TAG -#define LOG_TAG "AbstractLayer" +#define LOG_TAG "ContainerLayer" -#include "AbstractLayer.h" +#include "ContainerLayer.h" namespace android { -AbstractLayer::AbstractLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags) +ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) : Layer(flinger, client, name, w, h, flags) { mDrawingState = mCurrentState; } -void AbstractLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} +void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} -bool AbstractLayer::isVisible() const { +bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); } -void AbstractLayer::setPerFrameData(const sp&) {} +void ContainerLayer::setPerFrameData(const sp&) {} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 808ae3367d..543f60a624 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -23,13 +23,13 @@ namespace android { -class AbstractLayer : public Layer { +class ContainerLayer : public Layer { public: - AbstractLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags); - virtual ~AbstractLayer() = default; + ContainerLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + virtual ~ContainerLayer() = default; - const char* getTypeId() const override { return "AbstractLayer"; } + const char* getTypeId() const override { return "ContainerLayer"; } void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const override; bool isVisible() const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 78dd40b32f..44e60edb37 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1594,6 +1594,12 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return true; } +void Layer::reparentChildrenForDrawing(const sp& newParent) { + for (const sp& child : mDrawingChildren) { + child->mDrawingParent = newParent; + } +} + bool Layer::reparent(const sp& newParentHandle) { if (newParentHandle == nullptr) { return false; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ab004f2a6f..996d686371 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -287,7 +287,7 @@ public: bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp& layer); - bool reparentChildrenForDrawing(const sp& layer); + void reparentChildrenForDrawing(const sp& layer); bool reparent(const sp& newParentHandle); bool detachChildren(); diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index fa4df8360f..940a34ce1c 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -2,6 +2,8 @@ #include "Transform.h" +#include + namespace android { class RenderArea { @@ -22,6 +24,8 @@ public: virtual bool needsFiltering() const = 0; virtual Rect getSourceCrop() const = 0; + virtual void render(std::function drawLayers) { drawLayers(); } + int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cb410a14e1..38b93b110b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -61,20 +61,21 @@ #include #include +#include "BufferLayer.h" #include "Client.h" -#include "clz.h" +#include "ColorLayer.h" #include "Colorizer.h" +#include "ContainerLayer.h" #include "DdmConnection.h" -#include "DisplayDevice.h" #include "DispSync.h" +#include "DisplayDevice.h" #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" -#include "BufferLayer.h" #include "LayerVector.h" -#include "ColorLayer.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "clz.h" #include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/FramebufferSurface.h" @@ -4418,19 +4419,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp& layerHandleBinder, sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + float frameScale, bool childrenOnly) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: - LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) - : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} - const Transform& getTransform() const override { - // Make the top level transform the inverse the transform and it's parent so it sets - // the whole capture back to 0,0 - return *new Transform(mLayer->getTransform().inverse()); - } + LayerRenderArea(SurfaceFlinger* flinger, const sp& layer, const Rect crop, + int32_t reqWidth, int32_t reqHeight, bool childrenOnly) + : RenderArea(reqHeight, reqWidth), + mLayer(layer), + mCrop(crop), + mFlinger(flinger), + mChildrenOnly(childrenOnly) {} Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); return Rect(layerState.active.w, layerState.active.h); @@ -4439,6 +4439,34 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, int getWidth() const override { return mLayer->getDrawingState().active.w; } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } + const Transform& getTransform() const { return mTransform; } + + class ReparentForDrawing { + public: + const sp& oldParent; + const sp& newParent; + + ReparentForDrawing(const sp& oldParent, const sp& newParent) + : oldParent(oldParent), newParent(newParent) { + oldParent->reparentChildrenForDrawing(newParent); + } + ~ReparentForDrawing() { newParent->reparentChildrenForDrawing(oldParent); } + }; + + void render(std::function drawLayers) override { + if (!mChildrenOnly) { + mTransform = mLayer->getTransform().inverse(); + drawLayers(); + } else { + Rect bounds = getBounds(); + screenshotParentLayer = + new ContainerLayer(mFlinger, nullptr, String8("Screenshot Parent"), + bounds.getWidth(), bounds.getHeight(), 0); + + ReparentForDrawing reparent(mLayer, screenshotParentLayer); + drawLayers(); + } + } Rect getSourceCrop() const override { if (mCrop.isEmpty()) { @@ -4453,6 +4481,14 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, private: const sp mLayer; const Rect mCrop; + + // In the "childrenOnly" case we reparent the children to a screenshot + // layer which has no properties set and which does not draw. + sp screenshotParentLayer; + Transform mTransform; + + SurfaceFlinger* mFlinger; + const bool mChildrenOnly; }; auto layerHandle = reinterpret_cast(layerHandleBinder.get()); @@ -4463,6 +4499,13 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, return NAME_NOT_FOUND; } + const int uid = IPCThreadState::self()->getCallingUid(); + const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; + if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) { + ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); + return PERMISSION_DENIED; + } + Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; @@ -4477,12 +4520,14 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, int32_t reqWidth = crop.width() * frameScale; int32_t reqHeight = crop.height() * frameScale; - LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight); + LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly); - auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { + auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { return; + } else if (childrenOnly && layer == parent.get()) { + return; } visitor(layer); }); @@ -4529,8 +4574,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), - useIdentityTransform, forSystem, &fd); + renderArea.render([&]() { + result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), + useIdentityTransform, forSystem, &fd); + }); } { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 392acaa0a6..33786e8558 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -387,7 +387,7 @@ private: int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, - const Rect& sourceCrop, float frameScale); + const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 92c26af9eb..fd219913df 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -192,6 +192,16 @@ public: *sc = std::make_unique(outBuffer); } + static void captureChildLayers(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale, true)); + *sc = std::make_unique(outBuffer); + } + void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); @@ -2306,6 +2316,74 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { mCapture->expectChildColor(0, 0); } +TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + // Captures mFGSurfaceControl's child + ScreenCapture::captureChildLayers(&mCapture, fgHandle); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->expectChildColor(0, 0); +} + + +// In the following tests we verify successful skipping of a parent layer, +// so we use the same verification logic and only change how we mutate +// the parent layer to verify that various properties are ignored. +class ScreenCaptureChildOnlyTest : public LayerUpdateTest { +public: + void SetUp() override { + LayerUpdateTest::SetUp(); + + mChild = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(mChild, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(mChild).apply(true); + } + + void verify() { + auto fgHandle = mFGSurfaceControl->getHandle(); + ScreenCapture::captureChildLayers(&mCapture, fgHandle); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->expectChildColor(0, 0); + } + + std::unique_ptr mCapture; + sp mChild; +}; + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { + + SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true); + + // Even though the parent is hidden we should still capture the child. + verify(); +} + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { + + SurfaceComposerClient::Transaction().setCrop(mFGSurfaceControl, Rect(0, 0, 1, 1)).apply(true); + + // Even though the parent is cropped out we should still capture the child. + verify(); +} + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) { + + SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2); + + // We should not inherit the parent scaling. + verify(); +} + TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { auto fgHandle = mFGSurfaceControl->getHandle(); -- cgit v1.2.3-59-g8ed1b From 3b382ed2e8a6a79698fb8e65913946bba109d836 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 14 Mar 2018 13:49:41 -0700 Subject: Propagate error codes from createSurface Without an error code it's impossible to distinguish OOM from missing parent, causing the WM to start killing applications in the case of a missing parent. Bug: 73664284 Test: Manual. Change-Id: Ida6a30b41d1e856dfa9dceb80a432a30353d2764 --- libs/gui/SurfaceComposerClient.cpp | 24 +++++++++++++++++++++--- libs/gui/include/gui/SurfaceComposerClient.h | 12 ++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 92a24ad933..364f27bdac 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -611,8 +611,26 @@ sp SurfaceComposerClient::createSurface( SurfaceControl* parent, uint32_t windowType, uint32_t ownerUid) +{ + sp s; + createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid); + return s; +} + +status_t SurfaceComposerClient::createSurfaceChecked( + const String8& name, + uint32_t w, + uint32_t h, + PixelFormat format, + sp* outSurface, + uint32_t flags, + SurfaceControl* parent, + uint32_t windowType, + uint32_t ownerUid) { sp sur; + status_t err = NO_ERROR; + if (mStatus == NO_ERROR) { sp handle; sp parentHandle; @@ -621,14 +639,14 @@ sp SurfaceComposerClient::createSurface( if (parent != nullptr) { parentHandle = parent->getHandle(); } - status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle, + err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { - sur = new SurfaceControl(this, handle, gbp, true /* owned */); + *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */); } } - return sur; + return err; } status_t SurfaceComposerClient::destroySurface(const sp& sid) { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3fe66356bf..9aebf8f8af 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -114,6 +114,18 @@ public: uint32_t ownerUid = 0 // UID of the task ); + status_t createSurfaceChecked( + const String8& name,// name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + sp* outSurface, + uint32_t flags = 0, // usage flags + SurfaceControl* parent = nullptr, // parent + uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + uint32_t ownerUid = 0 // UID of the task + ); + //! Create a virtual display static sp createDisplay(const String8& displayName, bool secure); -- cgit v1.2.3-59-g8ed1b From a52f0295622a42849f5ef81c44589b816b2ccacb Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 14 Mar 2018 17:26:31 -0700 Subject: [Native] Replace android_color_mode usage with ColorMode. To ease the pain when we add color mode v1.1, we replace all current android_color_mode usage in framework native with ColorMode directly from HAL. BUG: 73824924 Test: Build & flash Change-Id: I4436fc225c7807506825c7148bc794cb99f278dc --- libs/gui/Android.bp | 2 + libs/gui/ISurfaceComposer.cpp | 26 +++++----- libs/gui/Surface.cpp | 10 ++-- libs/gui/SurfaceComposerClient.cpp | 6 +-- libs/gui/include/gui/ISurfaceComposer.h | 7 +-- libs/gui/include/gui/SurfaceComposerClient.h | 7 +-- libs/gui/tests/Surface_test.cpp | 8 +-- libs/ui/DebugUtils.cpp | 43 ++++++++-------- libs/ui/include/ui/DebugUtils.h | 4 +- libs/ui/include/ui/GraphicsTypes.h | 26 ++++++++++ services/surfaceflinger/DisplayDevice.cpp | 6 +-- services/surfaceflinger/DisplayDevice.h | 9 ++-- services/surfaceflinger/DisplayHardware/HWC2.cpp | 11 ++-- services/surfaceflinger/DisplayHardware/HWC2.h | 5 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 8 +-- .../surfaceflinger/DisplayHardware/HWComposer.h | 5 +- services/surfaceflinger/RenderArea.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 58 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 10 ++-- services/surfaceflinger/layerproto/Android.bp | 1 + services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 46 +++++++++-------- 21 files changed, 170 insertions(+), 132 deletions(-) create mode 100644 libs/ui/include/ui/GraphicsTypes.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index a1a0928154..2768ad8560 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -122,6 +122,7 @@ cc_library_shared { ], shared_libs: [ + "android.hardware.graphics.common@1.1", "libsync", "libbinder", "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui. @@ -154,6 +155,7 @@ cc_library_shared { "libui", "android.hidl.token@1.0-utils", "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.common@1.1", ], export_header_lib_headers: [ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index beda778396..0244bb512e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -350,7 +350,7 @@ public: } virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) { + Vector* outColorModes) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -373,34 +373,34 @@ public: outColorModes->clear(); outColorModes->resize(numModes); for (size_t i = 0; i < numModes; ++i) { - outColorModes->replaceAt(static_cast(reply.readInt32()), i); + outColorModes->replaceAt(static_cast(reply.readInt32()), i); } } return result; } - virtual android_color_mode_t getActiveColorMode(const sp& display) { + virtual ColorMode getActiveColorMode(const sp& display) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result); - return static_cast(result); + return static_cast(result); } result = data.writeStrongBinder(display); if (result != NO_ERROR) { ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result); - return static_cast(result); + return static_cast(result); } result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply); if (result != NO_ERROR) { ALOGE("getActiveColorMode failed to transact: %d", result); - return static_cast(result); + return static_cast(result); } - return static_cast(reply.readInt32()); + return static_cast(reply.readInt32()); } virtual status_t setActiveColorMode(const sp& display, - android_color_mode_t colorMode) { + ColorMode colorMode) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -412,7 +412,7 @@ public: ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result); return result; } - result = data.writeInt32(colorMode); + result = data.writeInt32(static_cast(colorMode)); if (result != NO_ERROR) { ALOGE("setActiveColorMode failed to writeInt32: %d", result); return result; @@ -739,7 +739,7 @@ status_t BnSurfaceComposer::onTransact( } case GET_DISPLAY_COLOR_MODES: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector colorModes; + Vector colorModes; sp display = nullptr; status_t result = data.readStrongBinder(&display); if (result != NO_ERROR) { @@ -751,7 +751,7 @@ status_t BnSurfaceComposer::onTransact( if (result == NO_ERROR) { reply->writeUint32(static_cast(colorModes.size())); for (size_t i = 0; i < colorModes.size(); ++i) { - reply->writeInt32(colorModes[i]); + reply->writeInt32(static_cast(colorModes[i])); } } return NO_ERROR; @@ -764,7 +764,7 @@ status_t BnSurfaceComposer::onTransact( ALOGE("getActiveColorMode failed to readStrongBinder: %d", result); return result; } - android_color_mode_t colorMode = getActiveColorMode(display); + ColorMode colorMode = getActiveColorMode(display); result = reply->writeInt32(static_cast(colorMode)); return result; } @@ -783,7 +783,7 @@ status_t BnSurfaceComposer::onTransact( return result; } result = setActiveColorMode(display, - static_cast(colorModeInt)); + static_cast(colorModeInt)); result = reply->writeInt32(result); return result; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e08d6b0bae..2e1c24b755 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -326,7 +326,7 @@ status_t Surface::getWideColorSupport(bool* supported) { sp display( composerService()->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); - Vector colorModes; + Vector colorModes; status_t err = composerService()->getDisplayColorModes(display, &colorModes); @@ -338,11 +338,11 @@ status_t Surface::getWideColorSupport(bool* supported) { &ISurfaceFlingerConfigs::hasWideColorDisplay>(false); *supported = false; - for (android_color_mode_t colorMode : colorModes) { + for (ColorMode colorMode : colorModes) { switch (colorMode) { - case HAL_COLOR_MODE_DISPLAY_P3: - case HAL_COLOR_MODE_ADOBE_RGB: - case HAL_COLOR_MODE_DCI_P3: + case ColorMode::DISPLAY_P3: + case ColorMode::ADOBE_RGB: + case ColorMode::DCI_P3: if (wideColorBoardConfig) { *supported = true; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0d7ffc3d71..61ed976fcc 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -698,16 +698,16 @@ status_t SurfaceComposerClient::setActiveConfig(const sp& display, int } status_t SurfaceComposerClient::getDisplayColorModes(const sp& display, - Vector* outColorModes) { + Vector* outColorModes) { return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes); } -android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp& display) { +ColorMode SurfaceComposerClient::getActiveColorMode(const sp& display) { return ComposerService::getComposerService()->getActiveColorMode(display); } status_t SurfaceComposerClient::setActiveColorMode(const sp& display, - android_color_mode_t colorMode) { + ColorMode colorMode) { return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 5ab64454e5..afe9358c0a 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -160,10 +161,10 @@ public: virtual status_t setActiveConfig(const sp& display, int id) = 0; virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) = 0; - virtual android_color_mode_t getActiveColorMode(const sp& display) = 0; + Vector* outColorModes) = 0; + virtual ColorMode getActiveColorMode(const sp& display) = 0; virtual status_t setActiveColorMode(const sp& display, - android_color_mode_t colorMode) = 0; + ColorMode colorMode) = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index fe46146ff5..162fe6e4e6 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -88,13 +89,13 @@ public: // Gets the list of supported color modes for the given display static status_t getDisplayColorModes(const sp& display, - Vector* outColorModes); + Vector* outColorModes); // Gets the active color mode for the given display - static android_color_mode_t getActiveColorMode(const sp& display); + static ColorMode getActiveColorMode(const sp& display); // Sets the active color mode for the given display - static status_t setActiveColorMode(const sp& display, android_color_mode_t colorMode); + static status_t setActiveColorMode(const sp& display, ColorMode colorMode); /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 4fb51e1b96..66d5595fb9 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -577,15 +577,15 @@ public: return NO_ERROR; } status_t getDisplayColorModes(const sp& /*display*/, - Vector* /*outColorModes*/) override { + Vector* /*outColorModes*/) override { return NO_ERROR; } - android_color_mode_t getActiveColorMode(const sp& /*display*/) + ColorMode getActiveColorMode(const sp& /*display*/) override { - return HAL_COLOR_MODE_NATIVE; + return ColorMode::NATIVE; } status_t setActiveColorMode(const sp& /*display*/, - android_color_mode_t /*colorMode*/) override { return NO_ERROR; } + ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, sp* /*outBuffer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index 17ebf80329..d7e191db89 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -22,6 +22,7 @@ #include using android::base::StringPrintf; +using android::ColorMode; std::string decodeStandard(android_dataspace dataspace) { const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK); @@ -197,37 +198,37 @@ std::string dataspaceDetails(android_dataspace dataspace) { decodeRange(dataspace).c_str()); } -std::string decodeColorMode(android_color_mode colorMode) { +std::string decodeColorMode(ColorMode colorMode) { switch (colorMode) { - case HAL_COLOR_MODE_NATIVE: - return std::string("HAL_COLOR_MODE_NATIVE"); + case ColorMode::NATIVE: + return std::string("ColorMode::NATIVE"); - case HAL_COLOR_MODE_STANDARD_BT601_625: - return std::string("HAL_COLOR_MODE_BT601_625"); + case ColorMode::STANDARD_BT601_625: + return std::string("ColorMode::BT601_625"); - case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED: - return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED"); + case ColorMode::STANDARD_BT601_625_UNADJUSTED: + return std::string("ColorMode::BT601_625_UNADJUSTED"); - case HAL_COLOR_MODE_STANDARD_BT601_525: - return std::string("HAL_COLOR_MODE_BT601_525"); + case ColorMode::STANDARD_BT601_525: + return std::string("ColorMode::BT601_525"); - case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED: - return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED"); + case ColorMode::STANDARD_BT601_525_UNADJUSTED: + return std::string("ColorMode::BT601_525_UNADJUSTED"); - case HAL_COLOR_MODE_STANDARD_BT709: - return std::string("HAL_COLOR_MODE_BT709"); + case ColorMode::STANDARD_BT709: + return std::string("ColorMode::BT709"); - case HAL_COLOR_MODE_DCI_P3: - return std::string("HAL_COLOR_MODE_DCI_P3"); + case ColorMode::DCI_P3: + return std::string("ColorMode::DCI_P3"); - case HAL_COLOR_MODE_SRGB: - return std::string("HAL_COLOR_MODE_SRGB"); + case ColorMode::SRGB: + return std::string("ColorMode::SRGB"); - case HAL_COLOR_MODE_ADOBE_RGB: - return std::string("HAL_COLOR_MODE_ADOBE_RGB"); + case ColorMode::ADOBE_RGB: + return std::string("ColorMode::ADOBE_RGB"); - case HAL_COLOR_MODE_DISPLAY_P3: - return std::string("HAL_COLOR_MODE_DISPLAY_P3"); + case ColorMode::DISPLAY_P3: + return std::string("ColorMode::DISPLAY_P3"); } return android::base::StringPrintf("Unknown color mode %d", colorMode); diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index dad9446b3a..33701070a9 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include @@ -29,6 +29,6 @@ std::string decodeStandard(android_dataspace dataspace); std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); -std::string decodeColorMode(android_color_mode colormode); +std::string decodeColorMode(android::ColorMode colormode); std::string decodePixelFormat(android::PixelFormat format); std::string to_string(const android::Rect& rect); diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicsTypes.h new file mode 100644 index 0000000000..fa9a812d97 --- /dev/null +++ b/libs/ui/include/ui/GraphicsTypes.h @@ -0,0 +1,26 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace android { + +using android::hardware::graphics::common::V1_0::ColorMode; + +} // namespace android diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d40666e6f1..92d5e21f34 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -99,7 +99,7 @@ DisplayDevice::DisplayDevice( mNativeWindow = surface = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); - mActiveColorMode = HAL_COLOR_MODE_NATIVE; + mActiveColorMode = ColorMode::NATIVE; mDisplayHasWideColor = supportWideColor; mDisplayHasHdr = supportHdr; @@ -292,11 +292,11 @@ int DisplayDevice::getActiveConfig() const { } // ---------------------------------------------------------------------------- -void DisplayDevice::setActiveColorMode(android_color_mode_t mode) { +void DisplayDevice::setActiveColorMode(ColorMode mode) { mActiveColorMode = mode; } -android_color_mode_t DisplayDevice::getActiveColorMode() const { +ColorMode DisplayDevice::getActiveColorMode() const { return mActiveColorMode; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d5ed15fa28..737971f83d 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -31,6 +31,7 @@ #include #include +#include #include "RenderArea.h" #include "RenderEngine/Surface.h" @@ -155,8 +156,8 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; - android_color_mode_t getActiveColorMode() const; - void setActiveColorMode(android_color_mode_t mode); + ColorMode getActiveColorMode() const; + void setActiveColorMode(ColorMode mode); void setCompositionDataSpace(android_dataspace dataspace); /* ------------------------------------------------------------------------ @@ -230,7 +231,7 @@ private: // Current active config int mActiveConfig; // current active color mode - android_color_mode_t mActiveColorMode; + ColorMode mActiveColorMode; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. @@ -279,7 +280,7 @@ public: bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } - android_color_mode_t getActiveColorMode() const override { + ColorMode getActiveColorMode() const override { return mDevice->getActiveColorMode(); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index f14c2fe10b..b7bf964f29 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -362,9 +362,9 @@ Error Display::getChangedCompositionTypes( return Error::None; } -Error Display::getColorModes(std::vector* outModes) const +Error Display::getColorModes(std::vector* outModes) const { - std::vector modes; + std::vector modes; auto intError = mComposer.getColorModes(mId, &modes); uint32_t numModes = modes.size(); auto error = static_cast(intError); @@ -374,7 +374,7 @@ Error Display::getColorModes(std::vector* outModes) const outModes->resize(numModes); for (size_t i = 0; i < numModes; i++) { - (*outModes)[i] = static_cast(modes[i]); + (*outModes)[i] = modes[i]; } return Error::None; } @@ -537,10 +537,9 @@ Error Display::setClientTarget(uint32_t slot, const sp& target, return static_cast(intError); } -Error Display::setColorMode(android_color_mode_t mode) +Error Display::setColorMode(android::ColorMode mode) { - auto intError = mComposer.setColorMode( - mId, static_cast(mode)); + auto intError = mComposer.setColorMode(mId, mode); return static_cast(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index e74f00dccc..0fc37ece56 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -209,7 +210,7 @@ public: [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( - std::vector* outModes) const; + std::vector* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector> getConfigs() const; @@ -233,7 +234,7 @@ public: uint32_t slot, const android::sp& target, const android::sp& acquireFence, android_dataspace_t dataspace); - [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode); + [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 2cafd8e9f9..6d5917db2f 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -311,8 +311,8 @@ std::shared_ptr return config; } -std::vector HWComposer::getColorModes(int32_t displayId) const { - std::vector modes; +std::vector HWComposer::getColorModes(int32_t displayId) const { + std::vector modes; if (!isValidDisplay(displayId)) { ALOGE("getColorModes: Attempted to access invalid display %d", @@ -324,13 +324,13 @@ std::vector HWComposer::getColorModes(int32_t displayId) c if (error != HWC2::Error::None) { ALOGE("getColorModes failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast(error)); - return std::vector(); + return std::vector(); } return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) { +status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) { if (!isValidDisplay(displayId)) { ALOGE("setActiveColorMode: Display %d is not valid", displayId); return BAD_INDEX; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index b75dc6adf7..c442b2f191 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -158,9 +159,9 @@ public: std::shared_ptr getActiveConfig(int32_t displayId) const; - std::vector getColorModes(int32_t displayId) const; + std::vector getColorModes(int32_t displayId) const; - status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode); + status_t setActiveColorMode(int32_t displayId, ColorMode mode); bool isUsingVrComposer() const; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 940a34ce1c..b9c4909d5a 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "Transform.h" #include @@ -30,7 +32,7 @@ public: int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; virtual bool getWideColorSupport() const = 0; - virtual android_color_mode_t getActiveColorMode() const = 0; + virtual ColorMode getActiveColorMode() const = 0; status_t updateDimensions(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 38b93b110b..5dd5d7c9f2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -913,7 +913,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { return NO_ERROR; } status_t SurfaceFlinger::getDisplayColorModes(const sp& display, - Vector* outColorModes) { + Vector* outColorModes) { if ((outColorModes == nullptr) || (display.get() == nullptr)) { return BAD_VALUE; } @@ -934,7 +934,7 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp& display, return type; } - std::vector modes; + std::vector modes; { ConditionalLock _l(mStateLock, std::this_thread::get_id() != mMainThreadId); @@ -946,18 +946,18 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp& display, return NO_ERROR; } -android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp& display) { +ColorMode SurfaceFlinger::getActiveColorMode(const sp& display) { sp device(getDisplayDevice(display)); if (device != nullptr) { return device->getActiveColorMode(); } - return static_cast(BAD_VALUE); + return static_cast(BAD_VALUE); } void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, - android_color_mode_t mode) { + ColorMode mode) { int32_t type = hw->getDisplayType(); - android_color_mode_t currentMode = hw->getActiveColorMode(); + ColorMode currentMode = hw->getActiveColorMode(); if (mode == currentMode) { return; @@ -977,20 +977,20 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, status_t SurfaceFlinger::setActiveColorMode(const sp& display, - android_color_mode_t colorMode) { + ColorMode colorMode) { class MessageSetActiveColorMode: public MessageBase { SurfaceFlinger& mFlinger; sp mDisplay; - android_color_mode_t mMode; + ColorMode mMode; public: MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp& disp, - android_color_mode_t mode) : + ColorMode mode) : mFlinger(flinger), mDisplay(disp) { mMode = mode; } virtual bool handler() { - Vector modes; + Vector modes; mFlinger.getDisplayColorModes(mDisplay, &modes); bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes); - if (mMode < 0 || !exists) { + if (mMode < ColorMode::NATIVE || !exists) { ALOGE("Attempt to set invalid active color mode %s (%d) for display %p", decodeColorMode(mMode).c_str(), mMode, mDisplay.get()); return true; @@ -1783,9 +1783,9 @@ mat4 SurfaceFlinger::computeSaturationMatrix() const { // pickColorMode translates a given dataspace into the best available color mode. // Currently only support sRGB and Display-P3. -android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { +ColorMode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { if (mForceNativeColorMode) { - return HAL_COLOR_MODE_NATIVE; + return ColorMode::NATIVE; } switch (dataSpace) { @@ -1794,18 +1794,18 @@ android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) co case HAL_DATASPACE_UNKNOWN: case HAL_DATASPACE_SRGB: case HAL_DATASPACE_V0_SRGB: - return HAL_COLOR_MODE_SRGB; + return ColorMode::SRGB; break; case HAL_DATASPACE_DISPLAY_P3: - return HAL_COLOR_MODE_DISPLAY_P3; + return ColorMode::DISPLAY_P3; break; default: // TODO (courtneygo): Do we want to assert an error here? ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(), dataSpace); - return HAL_COLOR_MODE_SRGB; + return ColorMode::SRGB; break; } } @@ -1927,7 +1927,7 @@ void SurfaceFlinger::setUpHWComposer() { } if (hasWideColorDisplay) { - android_color_mode newColorMode; + ColorMode newColorMode; android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { @@ -2269,13 +2269,13 @@ void SurfaceFlinger::processDisplayChangesLocked() { if (dispSurface != nullptr) { bool hasWideColorSupport = false; if (hasWideColorDisplay) { - std::vector modes = + std::vector modes = getHwComposer().getColorModes(state.type); - for (android_color_mode_t colorMode : modes) { + for (ColorMode colorMode : modes) { switch (colorMode) { - case HAL_COLOR_MODE_DISPLAY_P3: - case HAL_COLOR_MODE_ADOBE_RGB: - case HAL_COLOR_MODE_DCI_P3: + case ColorMode::DISPLAY_P3: + case ColorMode::ADOBE_RGB: + case ColorMode::DCI_P3: hasWideColorSupport = true; break; default: @@ -2298,9 +2298,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { dispSurface, producer, hasWideColorSupport, hasHdrSupport); - android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; + ColorMode defaultColorMode = ColorMode::NATIVE; if (hasWideColorSupport) { - defaultColorMode = HAL_COLOR_MODE_SRGB; + defaultColorMode = ColorMode::SRGB; } setActiveColorModeInternal(hw, defaultColorMode); hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); @@ -2741,7 +2741,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; if (displayDevice->getWideColorSupport() && - displayDevice->getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { + displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) { outputDataspace = HAL_DATASPACE_DISPLAY_P3; } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); @@ -3879,12 +3879,12 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { } result.appendFormat("Display %d color modes:\n", hwcId); - std::vector modes = getHwComposer().getColorModes(hwcId); + std::vector modes = getHwComposer().getColorModes(hwcId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } - android_color_mode_t currentMode = displayDevice->getActiveColorMode(); + ColorMode currentMode = displayDevice->getActiveColorMode(); result.appendFormat(" Current color mode: %s (%d)\n", decodeColorMode(currentMode).c_str(), currentMode); } @@ -4476,7 +4476,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, } } bool getWideColorSupport() const override { return false; } - android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } + ColorMode getActiveColorMode() const override { return ColorMode::NATIVE; } private: const sp mLayer; @@ -4650,7 +4650,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; if (renderArea.getWideColorSupport() && - renderArea.getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { + renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) { outputDataspace = HAL_DATASPACE_DISPLAY_P3; } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 33786e8558..104adef4d3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -394,9 +394,9 @@ private: Vector* configs); virtual int getActiveConfig(const sp& display); virtual status_t getDisplayColorModes(const sp& display, - Vector* configs); - virtual android_color_mode_t getActiveColorMode(const sp& display); - virtual status_t setActiveColorMode(const sp& display, android_color_mode_t colorMode); + Vector* configs); + virtual ColorMode getActiveColorMode(const sp& display); + virtual status_t setActiveColorMode(const sp& display, ColorMode colorMode); virtual void setPowerMode(const sp& display, int mode); virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); @@ -446,7 +446,7 @@ private: bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp& hw, android_color_mode_t colorMode); + void setActiveColorModeInternal(const sp& hw, ColorMode colorMode); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -619,7 +619,7 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. - android_color_mode pickColorMode(android_dataspace dataSpace) const; + ColorMode pickColorMode(android_dataspace dataSpace) const; android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b, bool hasHdr) const; diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index 485090c778..ac147fe182 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -10,6 +10,7 @@ cc_library_shared { ], shared_libs: [ + "android.hardware.graphics.common@1.1", "libui", "libprotobuf-cpp-lite", "libbase", diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 4878c140ed..86e2e1ec30 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 @@ -34,6 +35,8 @@ #include "Hwc2TestClientTarget.h" #include "Hwc2TestVirtualDisplay.h" +using android::ColorMode; + void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, @@ -865,7 +868,7 @@ public: } void getColorModes(hwc2_display_t display, - std::vector* outColorModes, + std::vector* outColorModes, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( @@ -892,7 +895,7 @@ public: } } - void setColorMode(hwc2_display_t display, android_color_mode_t colorMode, + void setColorMode(hwc2_display_t display, ColorMode colorMode, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( @@ -905,7 +908,7 @@ public: *outErr = err; } else { ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode " - << colorMode; + << static_cast(colorMode); } } @@ -4252,33 +4255,33 @@ TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display) EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } -static const std::array androidColorModes = {{ - HAL_COLOR_MODE_NATIVE, - HAL_COLOR_MODE_STANDARD_BT601_625, - HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED, - HAL_COLOR_MODE_STANDARD_BT601_525, - HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED, - HAL_COLOR_MODE_STANDARD_BT709, - HAL_COLOR_MODE_DCI_P3, - HAL_COLOR_MODE_SRGB, - HAL_COLOR_MODE_ADOBE_RGB, +static const std::array androidColorModes = {{ + ColorMode::NATIVE, + ColorMode::STANDARD_BT601_625, + ColorMode::STANDARD_BT601_625_UNADJUSTED, + ColorMode::STANDARD_BT601_525, + ColorMode::STANDARD_BT601_525_UNADJUSTED, + ColorMode::STANDARD_BT709, + ColorMode::DCI_P3, + ColorMode::SRGB, + ColorMode::ADOBE_RGB, }}; /* TESTCASE: Tests that the HWC2 can get the color modes for a display. The - * display must support HAL_COLOR_MODE_NATIVE */ + * display must support ColorMode::NATIVE */ TEST_F(Hwc2Test, GET_COLOR_MODES) { ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( [] (Hwc2Test* test, hwc2_display_t display) { - std::vector colorModes; + std::vector colorModes; ASSERT_NO_FATAL_FAILURE(test->getColorModes(display, &colorModes)); EXPECT_NE(std::count(colorModes.begin(), colorModes.end(), - HAL_COLOR_MODE_NATIVE), 0) << "all displays" - " must support HAL_COLOR_MODE_NATIVE"; + ColorMode::NATIVE), 0) << "all displays" + " must support ColorMode::NATIVE"; } )); } @@ -4287,7 +4290,7 @@ TEST_F(Hwc2Test, GET_COLOR_MODES) TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display) { hwc2_display_t display; - std::vector colorModes; + std::vector colorModes; hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); @@ -4302,7 +4305,7 @@ TEST_F(Hwc2Test, SET_COLOR_MODES) ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( [] (Hwc2Test* test, hwc2_display_t display) { - const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE; + const ColorMode colorMode = ColorMode::NATIVE; EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode)); } @@ -4313,7 +4316,7 @@ TEST_F(Hwc2Test, SET_COLOR_MODES) TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display) { hwc2_display_t display; - const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE; + const ColorMode colorMode = ColorMode::NATIVE; hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); @@ -4328,8 +4331,7 @@ TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter) ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( [] (Hwc2Test* test, hwc2_display_t display) { - const android_color_mode_t colorMode = - static_cast(-1); + const ColorMode colorMode = static_cast(-1); hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode, -- cgit v1.2.3-59-g8ed1b From ccd348460ca25890a8fb709e82e6f780e3ce878e Mon Sep 17 00:00:00 2001 From: rongliu Date: Wed, 14 Mar 2018 12:26:23 -0700 Subject: Pass correct window type and app id to hw composer. 1. Set -1 as default value for window type and app id. 2. When send layer information to hal, layers inherit type and app id from parent node when parent node has valid type/appId. 3. Add window type and app id to SurfaceFlinger dumpsys. Bug: 74622357 Test: Manual test. Several things verified: 1. Android settings layer, status bar layer, nav bar layer have valid window type and appId when start android settings. 2. Layers without buffer have window type -1 and app id -1. 3. When send layers to hal, Chrome SurfaceView layer inherit type and app id from its parent (MainActivity layer). Change-Id: I8d6ad274ca18b61d1bbf6b28f7def5160b55b1e7 Merged-In: I8d6ad274ca18b61d1bbf6b28f7def5160b55b1e7 --- libs/gui/ISurfaceComposerClient.cpp | 4 ++-- libs/gui/SurfaceComposerClient.cpp | 8 ++++---- libs/gui/include/gui/ISurfaceComposerClient.h | 4 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 8 ++++---- services/surfaceflinger/Client.cpp | 8 ++++---- services/surfaceflinger/Client.h | 2 +- services/surfaceflinger/Layer.cpp | 10 +++++++--- services/surfaceflinger/Layer.h | 6 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/layerproto/LayerProtoParser.cpp | 5 ++++- .../layerproto/include/layerproto/LayerProtoParser.h | 2 ++ services/surfaceflinger/layerproto/layers.proto | 2 ++ 13 files changed, 37 insertions(+), 26 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 679f44b57b..a6890eeb19 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -47,8 +47,8 @@ public: ~BpSurfaceComposerClient() override; status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 38f0eb7422..3cf49d6723 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -609,8 +609,8 @@ sp SurfaceComposerClient::createSurface( PixelFormat format, uint32_t flags, SurfaceControl* parent, - uint32_t windowType, - uint32_t ownerUid) + int32_t windowType, + int32_t ownerUid) { sp s; createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid); @@ -625,8 +625,8 @@ status_t SurfaceComposerClient::createSurfaceChecked( sp* outSurface, uint32_t flags, SurfaceControl* parent, - uint32_t windowType, - uint32_t ownerUid) + int32_t windowType, + int32_t ownerUid) { sp sur; status_t err = NO_ERROR; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index d5bbef25f8..8dfc99a4b7 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -49,8 +49,8 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) = 0; /* diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 5ce20adb89..b45ce4f86c 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -111,8 +111,8 @@ public: PixelFormat format, // pixel-format desired uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - uint32_t ownerUid = 0 // UID of the task + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); status_t createSurfaceChecked( @@ -123,8 +123,8 @@ public: sp* outSurface, uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - uint32_t ownerUid = 0 // UID of the task + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); //! Create a virtual display diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 0c9f0e21e1..c90024b863 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -143,7 +143,7 @@ status_t Client::onTransact( status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - const sp& parentHandle, uint32_t windowType, uint32_t ownerUid, + const sp& parentHandle, int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp) { @@ -180,13 +180,13 @@ status_t Client::createSurface( PixelFormat format; uint32_t flags; sp* parent; - uint32_t windowType; - uint32_t ownerUid; + int32_t windowType; + int32_t ownerUid; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp* handle, uint32_t windowType, uint32_t ownerUid, + sp* handle, int32_t windowType, int32_t ownerUid, sp* gbp, sp* parent) : flinger(flinger), client(client), diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 2aab28f37d..c7df9f780f 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -58,7 +58,7 @@ private: virtual status_t createSurface( const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, - const sp& parent, uint32_t windowType, uint32_t ownerUid, + const sp& parent, int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 44e60edb37..6bd187f820 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -587,8 +587,10 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z sp parent = mDrawingParent.promote(); if (parent.get()) { auto& parentState = parent->getDrawingState(); - type = parentState.type; - appId = parentState.appId; + if (parentState.type >= 0 || parentState.appId >= 0) { + type = parentState.type; + appId = parentState.appId; + } } error = hwcLayer->setInfo(type, appId); @@ -1313,7 +1315,7 @@ bool Layer::setOverrideScalingMode(int32_t scalingMode) { return true; } -void Layer::setInfo(uint32_t type, uint32_t appId) { +void Layer::setInfo(int32_t type, int32_t appId) { mCurrentState.appId = appId; mCurrentState.type = type; mCurrentState.modified = true; @@ -1919,6 +1921,8 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); + layerInfo->set_window_type(state.type); + layerInfo->set_app_id(state.appId); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 996d686371..f2fa5b9321 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -203,8 +203,8 @@ public: Region requestedTransparentRegion; android_dataspace dataSpace; - uint32_t appId; - uint32_t type; + int32_t appId; + int32_t type; // If non-null, a Surface this Surface's Z-order is interpreted relative to. wp zOrderRelativeOf; @@ -285,7 +285,7 @@ public: void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); - void setInfo(uint32_t type, uint32_t appId); + void setInfo(int32_t type, int32_t appId); bool reparentChildren(const sp& layer); void reparentChildrenForDrawing(const sp& layer); bool reparent(const sp& newParentHandle); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a6e0a9ec98..472e45f16f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3318,7 +3318,7 @@ status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - uint32_t windowType, uint32_t ownerUid, sp* handle, + int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent) { if (int32_t(w|h) < 0) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51001e599d..333dcbcd17 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -485,7 +485,7 @@ private: */ status_t createLayer(const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - uint32_t windowType, uint32_t ownerUid, sp* handle, + int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent); status_t createBufferLayer(const sp& client, const String8& name, diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index c9b7fe55b8..47e5d1ff0b 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -106,6 +106,8 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); layer->queuedFrames = layerProto.queued_frames(); layer->refreshPending = layerProto.refresh_pending(); + layer->windowType = layerProto.window_type(); + layer->appId = layerProto.app_id(); return layer; } @@ -281,7 +283,8 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, " zOrderRelativeOf=%s\n", zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); - StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending); + StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending); + StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId); return result; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index b81a9595d2..b56a6fbb97 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -96,6 +96,8 @@ public: LayerProtoParser::ActiveBuffer activeBuffer; int32_t queuedFrames; bool refreshPending; + int32_t windowType; + int32_t appId; std::string to_string() const; }; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index d27dc9b2ea..f18386b1ac 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -64,6 +64,8 @@ message LayerProto { // The number of frames available. optional int32 queued_frames = 28; optional bool refresh_pending = 29; + optional int32 window_type = 30; + optional int32 app_id = 31; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From 740eaf09b41c0e47c492ae34dc84ccef3ad54bf5 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 27 Mar 2018 12:59:18 -0700 Subject: SurfaceComposerClient: Ensure createSurface returns error codes. If SurfaceComposerClient::mStatus is not equal to NO_ERROR (for example because we have attempted to construct a rooted-connection to a destroyed surface, and initialization has failed) then it is possible for createSurface to return NO_ERROR while failing to assign a value to outSurface. This violates the expectations of the JNI layer which expects that NO_ERROR will result in a valid surface. Bug: 76231383 Test: Surface_test.cpp (libgui_test) Change-Id: Ie68aafad01674c43e13af09bc144cc673b84ac1b --- libs/gui/SurfaceComposerClient.cpp | 2 +- libs/gui/tests/Surface_test.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 38f0eb7422..1f3ee61299 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -629,7 +629,7 @@ status_t SurfaceComposerClient::createSurfaceChecked( uint32_t ownerUid) { sp sur; - status_t err = NO_ERROR; + status_t err = mStatus; if (mStatus == NO_ERROR) { sp handle; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 66d5595fb9..df391ed4bb 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -58,7 +58,6 @@ static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits::max(); class SurfaceTest : public ::testing::Test { protected: - SurfaceTest() { ProcessState::self()->startThreadPool(); } @@ -93,6 +92,16 @@ protected: sp mSurfaceControl; }; +TEST_F(SurfaceTest, CreateSurfaceReturnsErrorBadClient) { + mComposerClient->dispose(); + ASSERT_EQ(NO_INIT, mComposerClient->initCheck()); + + sp sc; + status_t err = mComposerClient->createSurfaceChecked( + String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, &sc, 0); + ASSERT_EQ(NO_INIT, err); +} + TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenVisible) { sp anw(mSurface); int result = -123; -- cgit v1.2.3-59-g8ed1b From fd997e0969100418b4df8b8d97d21d497afa76c3 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 28 Mar 2018 15:29:00 -0700 Subject: Add proper namespace to GraphicTypes. Renamed GraphicsTypes.h to GraphicTypes.h and added proper namespace to avoid naming conflict. BUG: 77156734 Test: Build and flash Change-Id: Ibd9f454b5b72d5f8c6d94a3869a60a1bf821f106 Merged-In: Ibd9f454b5b72d5f8c6d94a3869a60a1bf821f106 --- libs/gui/ISurfaceComposer.cpp | 2 ++ libs/gui/Surface.cpp | 2 ++ libs/gui/SurfaceComposerClient.cpp | 2 ++ libs/gui/include/gui/ISurfaceComposer.h | 8 +++--- libs/gui/include/gui/SurfaceComposerClient.h | 9 ++++--- libs/gui/tests/Surface_test.cpp | 1 + libs/ui/DebugUtils.cpp | 2 +- libs/ui/include/ui/DebugUtils.h | 4 +-- libs/ui/include/ui/GraphicTypes.h | 30 ++++++++++++++++++++++ libs/ui/include/ui/GraphicsTypes.h | 26 ------------------- services/surfaceflinger/DisplayDevice.cpp | 7 ++--- services/surfaceflinger/DisplayDevice.h | 10 ++++---- services/surfaceflinger/DisplayHardware/HWC2.cpp | 18 +++---------- services/surfaceflinger/DisplayHardware/HWC2.h | 11 ++++---- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 8 +++--- .../surfaceflinger/DisplayHardware/HWComposer.h | 6 ++--- services/surfaceflinger/RenderArea.h | 4 +-- services/surfaceflinger/SurfaceFlinger.cpp | 1 + services/surfaceflinger/SurfaceFlinger.h | 10 ++++---- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 4 +-- 20 files changed, 85 insertions(+), 80 deletions(-) create mode 100644 libs/ui/include/ui/GraphicTypes.h delete mode 100644 libs/ui/include/ui/GraphicsTypes.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 0244bb512e..e22bc708c9 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -43,6 +43,8 @@ namespace android { +using ui::ColorMode; + class BpSurfaceComposer : public BpInterface { public: diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 2e1c24b755..6a1aebd6d6 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -44,6 +44,8 @@ namespace android { +using ui::ColorMode; + Surface::Surface(const sp& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4c041bc4f5..bbf681ea90 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -43,6 +43,8 @@ #include namespace android { + +using ui::ColorMode; // --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index afe9358c0a..3591090172 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include @@ -161,10 +161,10 @@ public: virtual status_t setActiveConfig(const sp& display, int id) = 0; virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) = 0; - virtual ColorMode getActiveColorMode(const sp& display) = 0; + Vector* outColorModes) = 0; + virtual ui::ColorMode getActiveColorMode(const sp& display) = 0; virtual status_t setActiveColorMode(const sp& display, - ColorMode colorMode) = 0; + ui::ColorMode colorMode) = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b45ce4f86c..ffc22f6437 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -89,13 +89,14 @@ public: // Gets the list of supported color modes for the given display static status_t getDisplayColorModes(const sp& display, - Vector* outColorModes); + Vector* outColorModes); // Gets the active color mode for the given display - static ColorMode getActiveColorMode(const sp& display); + static ui::ColorMode getActiveColorMode(const sp& display); // Sets the active color mode for the given display - static status_t setActiveColorMode(const sp& display, ColorMode colorMode); + static status_t setActiveColorMode(const sp& display, + ui::ColorMode colorMode); /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index df391ed4bb..2c02ba657d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -42,6 +42,7 @@ using namespace std::chrono_literals; // retrieve wide-color and hdr settings from configstore using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using ui::ColorMode; using Transaction = SurfaceComposerClient::Transaction; diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index d7e191db89..d7d8618703 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -22,7 +22,7 @@ #include using android::base::StringPrintf; -using android::ColorMode; +using android::ui::ColorMode; std::string decodeStandard(android_dataspace dataspace) { const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK); diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index 33701070a9..6350d0cf95 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include @@ -29,6 +29,6 @@ std::string decodeStandard(android_dataspace dataspace); std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); -std::string decodeColorMode(android::ColorMode colormode); +std::string decodeColorMode(android::ui::ColorMode colormode); std::string decodePixelFormat(android::PixelFormat format); std::string to_string(const android::Rect& rect); diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h new file mode 100644 index 0000000000..39893b268a --- /dev/null +++ b/libs/ui/include/ui/GraphicTypes.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +// android::ui::* in this header file will alias different types as +// the HIDL interface is updated. +namespace android { +namespace ui { + +using android::hardware::graphics::common::V1_0::ColorMode; + +} // namespace ui +} // namespace android diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicsTypes.h deleted file mode 100644 index fa9a812d97..0000000000 --- a/libs/ui/include/ui/GraphicsTypes.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -namespace android { - -using android::hardware::graphics::common::V1_0::ColorMode; - -} // namespace android diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index fe0b30ba35..bab6a71057 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -49,13 +49,12 @@ #include #include -// ---------------------------------------------------------------------------- -using namespace android; -// ---------------------------------------------------------------------------- +namespace android { // retrieve triple buffer setting from configstore using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using android::ui::ColorMode; /* * Initialize the display to the specified values. @@ -474,3 +473,5 @@ DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isS viewport.makeInvalid(); frame.makeInvalid(); } + +} // namespace android diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index fbb0d462f3..df729f5ce9 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include "RenderArea.h" #include "RenderEngine/Surface.h" @@ -161,8 +161,8 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; - ColorMode getActiveColorMode() const; - void setActiveColorMode(ColorMode mode); + ui::ColorMode getActiveColorMode() const; + void setActiveColorMode(ui::ColorMode mode); void setCompositionDataSpace(android_dataspace dataspace); /* ------------------------------------------------------------------------ @@ -236,7 +236,7 @@ private: // Current active config int mActiveConfig; // current active color mode - ColorMode mActiveColorMode; + ui::ColorMode mActiveColorMode; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. @@ -285,7 +285,7 @@ public: bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } - ColorMode getActiveColorMode() const override { + ui::ColorMode getActiveColorMode() const override { return mDevice->getActiveColorMode(); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 0c77aba498..98daec3e47 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -362,20 +362,10 @@ Error Display::getChangedCompositionTypes( return Error::None; } -Error Display::getColorModes(std::vector* outModes) const +Error Display::getColorModes(std::vector* outModes) const { - std::vector modes; - auto intError = mComposer.getColorModes(mId, &modes); - uint32_t numModes = modes.size(); - auto error = static_cast(intError); - if (error != Error::None) { - return error; - } - - outModes->resize(numModes); - for (size_t i = 0; i < numModes; i++) { - (*outModes)[i] = modes[i]; - } + auto intError = mComposer.getColorModes(mId, outModes); + return static_cast(intError); return Error::None; } @@ -537,7 +527,7 @@ Error Display::setClientTarget(uint32_t slot, const sp& target, return static_cast(intError); } -Error Display::setColorMode(android::ColorMode mode) +Error Display::setColorMode(android::ui::ColorMode mode) { auto intError = mComposer.setColorMode(mId, mode); return static_cast(intError); diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 5b53b54d71..71c094a035 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -211,7 +211,7 @@ public: [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( - std::vector* outModes) const; + std::vector* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector> getConfigs() const; @@ -235,7 +235,8 @@ public: uint32_t slot, const android::sp& target, const android::sp& acquireFence, android_dataspace_t dataspace); - [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode); + [[clang::warn_unused_result]] Error setColorMode( + android::ui::ColorMode mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( @@ -246,8 +247,8 @@ public: [[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests); [[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes, - uint32_t* outNumRequests, - android::sp* outPresentFence, uint32_t* state); + uint32_t* outNumRequests, + android::sp* outPresentFence, uint32_t* state); // Other Display methods diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 6d5917db2f..6bf2ee9362 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -311,8 +311,8 @@ std::shared_ptr return config; } -std::vector HWComposer::getColorModes(int32_t displayId) const { - std::vector modes; +std::vector HWComposer::getColorModes(int32_t displayId) const { + std::vector modes; if (!isValidDisplay(displayId)) { ALOGE("getColorModes: Attempted to access invalid display %d", @@ -324,13 +324,13 @@ std::vector HWComposer::getColorModes(int32_t displayId) const { if (error != HWC2::Error::None) { ALOGE("getColorModes failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast(error)); - return std::vector(); + return std::vector(); } return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) { +status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode) { if (!isValidDisplay(displayId)) { ALOGE("setActiveColorMode: Display %d is not valid", displayId); return BAD_INDEX; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index c442b2f191..0366a0d164 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include @@ -159,9 +159,9 @@ public: std::shared_ptr getActiveConfig(int32_t displayId) const; - std::vector getColorModes(int32_t displayId) const; + std::vector getColorModes(int32_t displayId) const; - status_t setActiveColorMode(int32_t displayId, ColorMode mode); + status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode); bool isUsingVrComposer() const; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index b9c4909d5a..bf0707f13b 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "Transform.h" @@ -32,7 +32,7 @@ public: int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; virtual bool getWideColorSupport() const = 0; - virtual ColorMode getActiveColorMode() const = 0; + virtual ui::ColorMode getActiveColorMode() const = 0; status_t updateDimensions(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5c69b98b98..09e67b62cb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -104,6 +104,7 @@ namespace android { using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using ui::ColorMode; namespace { class ConditionalLock { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 42d8112b90..448509bc8f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -410,9 +410,9 @@ private: Vector* configs); virtual int getActiveConfig(const sp& display); virtual status_t getDisplayColorModes(const sp& display, - Vector* configs); - virtual ColorMode getActiveColorMode(const sp& display); - virtual status_t setActiveColorMode(const sp& display, ColorMode colorMode); + Vector* configs); + virtual ui::ColorMode getActiveColorMode(const sp& display); + virtual status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode); virtual void setPowerMode(const sp& display, int mode); virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); @@ -462,7 +462,7 @@ private: bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp& hw, ColorMode colorMode); + void setActiveColorModeInternal(const sp& hw, ui::ColorMode colorMode); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -635,7 +635,7 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. - ColorMode pickColorMode(android_dataspace dataSpace) const; + ui::ColorMode pickColorMode(android_dataspace dataSpace) const; android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b, bool hasHdr) const; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 86e2e1ec30..b3f1b69f71 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 @@ -35,7 +35,7 @@ #include "Hwc2TestClientTarget.h" #include "Hwc2TestVirtualDisplay.h" -using android::ColorMode; +using android::ui::ColorMode; void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); -- cgit v1.2.3-59-g8ed1b From 2713c30843816d3511b39b85a2c268a2b7682047 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Wed, 28 Mar 2018 17:07:36 -0700 Subject: Early wake-up for transitions (1/2) On some devices it's very likely that we fall into GL comp during app transitions. However, SF offsets are chosen in a way such that the time to finish a frame is just too tight to be completely jank free when hitting GL composition in SurfaceFlinger. Thus, we introduce the concept of a separate early offset, and wakeup SurfaceFlinger at that time if we think that hitting GL comp is likely, or we already hit GL comp in the last frame. Test: Open app, check vsync offsets in systrace Test: Open many dialogs/apps to fall into GPU comp. Bug: 75985430 Change-Id: Ie17e30c4575359fa11bb8912f68dcafe3e569ddb Merged-In: Ie17e30c4575359fa11bb8912f68dcafe3e569ddb --- libs/gui/SurfaceComposerClient.cpp | 11 ++- libs/gui/include/gui/ISurfaceComposer.h | 5 + libs/gui/include/gui/SurfaceComposerClient.h | 2 + services/surfaceflinger/BufferLayer.cpp | 1 + services/surfaceflinger/BufferLayerConsumer.cpp | 1 + services/surfaceflinger/DispSync.cpp | 27 ++++++ services/surfaceflinger/DispSync.h | 5 + .../RenderEngine/GLES20RenderEngine.cpp | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 41 +++++---- services/surfaceflinger/SurfaceFlinger.h | 6 ++ services/surfaceflinger/VSyncModulator.h | 101 +++++++++++++++++++++ 11 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 services/surfaceflinger/VSyncModulator.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index bbf681ea90..63560c4b89 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -101,7 +101,8 @@ void ComposerService::composerServiceDied() SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : mForceSynchronous(other.mForceSynchronous), mTransactionNestCount(other.mTransactionNestCount), - mAnimation(other.mAnimation) { + mAnimation(other.mAnimation), + mEarlyWakeup(other.mEarlyWakeup) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; } @@ -157,9 +158,13 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mAnimation) { flags |= ISurfaceComposer::eAnimation; } + if (mEarlyWakeup) { + flags |= ISurfaceComposer::eEarlyWakeup; + } mForceSynchronous = false; mAnimation = false; + mEarlyWakeup = false; sf->setTransactionState(composerStates, displayStates, flags); mStatus = NO_ERROR; @@ -185,6 +190,10 @@ void SurfaceComposerClient::Transaction::setAnimationTransaction() { mAnimation = true; } +void SurfaceComposerClient::Transaction::setEarlyWakeup() { + mEarlyWakeup = true; +} + layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { if (mComposerStates.count(sc) == 0) { // we don't have it, add an initialized layer_state to our list diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3591090172..e40157206d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -61,6 +61,11 @@ public: enum { eSynchronous = 0x01, eAnimation = 0x02, + + // Indicates that this transaction will likely result in a lot of layers being composed, and + // thus, SurfaceFlinger should wake-up earlier to avoid missing frame deadlines. In this + // case SurfaceFlinger will wake up at (sf vsync offset - debug.sf.early_phase_offset_ns) + eEarlyWakeup = 0x04 }; enum { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index ffc22f6437..377fe68c41 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -154,6 +154,7 @@ public: uint32_t mForceSynchronous = 0; uint32_t mTransactionNestCount = 0; bool mAnimation = false; + bool mEarlyWakeup = false; int mStatus = NO_ERROR; @@ -273,6 +274,7 @@ public: const Rect& displayRect); void setDisplaySize(const sp& token, uint32_t width, uint32_t height); void setAnimationTransaction(); + void setEarlyWakeup(); }; status_t destroySurface(const sp& id); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 82300e679f..2aa4cd3578 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -778,6 +778,7 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { } void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { + ATRACE_CALL(); const State& s(getDrawingState()); computeGeometry(renderArea, getBE().mMesh, useIdentityTransform); diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 6b4f5dbfb0..87333d0ffd 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -356,6 +356,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } status_t BufferLayerConsumer::bindTextureImageLocked() { + ATRACE_CALL(); mRE.checkErrors(); if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) { diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 9e01fd0d8d..7acbd11bc5 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -209,6 +209,28 @@ public: return BAD_VALUE; } + status_t changePhaseOffset(DispSync::Callback* callback, nsecs_t phase) { + if (kTraceDetailedInfo) ATRACE_CALL(); + Mutex::Autolock lock(mMutex); + + for (size_t i = 0; i < mEventListeners.size(); i++) { + if (mEventListeners[i].mCallback == callback) { + EventListener& listener = mEventListeners.editItemAt(i); + const nsecs_t oldPhase = listener.mPhase; + listener.mPhase = phase; + + // Pretend that the last time this event was handled at the same frame but with the + // new offset to allow for a seamless offset change without double-firing or + // skipping. + listener.mLastEventTime -= (oldPhase - phase); + mCond.signal(); + return NO_ERROR; + } + } + + return BAD_VALUE; + } + // This method is only here to handle the !SurfaceFlinger::hasSyncFramework // case. bool hasAnyEventListeners() { @@ -487,6 +509,11 @@ status_t DispSync::removeEventListener(Callback* callback) { return mThread->removeEventListener(callback); } +status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { + Mutex::Autolock lock(mMutex); + return mThread->changePhaseOffset(callback, phase); +} + void DispSync::setPeriod(nsecs_t period) { Mutex::Autolock lock(mMutex); mPeriod = period; diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 9336f4dd86..077256ac11 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -113,6 +113,11 @@ public: // DispSync object. status_t removeEventListener(Callback* callback); + // changePhaseOffset changes the phase offset of an already-registered event callback. The + // method will make sure that there is no skipping or double-firing on the listener per frame, + // even when changing the offsets multiple times. + status_t changePhaseOffset(Callback* callback, nsecs_t phase); + // computeNextRefresh computes when the next refresh is expected to begin. // The periodOffset value can be used to move forward or backward; an // offset of zero is the next refresh, -1 is the previous refresh, 1 is diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 1fc310025d..0fb3d28d05 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -293,6 +293,7 @@ void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) } void GLES20RenderEngine::drawMesh(const Mesh& mesh) { + ATRACE_CALL(); if (mesh.getTexCoordsSize()) { glEnableVertexAttribArray(Program::texCoords); glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5be7951972..183c1eb07c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -296,6 +296,12 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; + property_get("debug.sf.early_phase_offset_ns", value, "0"); + const int earlyWakeupOffsetOffsetNs = atoi(value); + ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset"); + mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs, + sfVsyncPhaseOffsetNs); + // We should be reading 'persist.sys.sf.color_saturation' here // but since /data may be encrypted, we need to wait until after vold // comes online to attempt to read the property. The property is @@ -522,19 +528,10 @@ public: return; } - // Remove the listener with the old offset - status_t err = mDispSync->removeEventListener( - static_cast(this)); + status_t err = mDispSync->changePhaseOffset(static_cast(this), + mPhaseOffset); if (err != NO_ERROR) { - ALOGE("error unregistering vsync callback: %s (%d)", - strerror(-err), err); - } - - // Add a listener with the new offset - err = mDispSync->addEventListener(mName, mPhaseOffset, - static_cast(this)); - if (err != NO_ERROR) { - ALOGE("error registering vsync callback: %s (%d)", + ALOGE("error changing vsync offset: %s (%d)", strerror(-err), err); } } @@ -623,6 +620,7 @@ void SurfaceFlinger::init() { mSFEventThread = std::make_unique(mSfEventThreadSource.get(), *this, true, "sfEventThread"); mEventQueue->setEventThread(mSFEventThread.get()); + mVsyncModulator.setEventThread(mSFEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) getBE().mRenderEngine = @@ -1498,6 +1496,7 @@ void SurfaceFlinger::handleMessageRefresh() { mHadClientComposition = mHadClientComposition || getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); } + mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition); mLayersWithQueuedFrames.clear(); } @@ -2122,6 +2121,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // with mStateLock held to guarantee that mCurrentState won't change // until the transaction is committed. + mVsyncModulator.setTransactionStart(VSyncModulator::TransactionStart::NORMAL); transactionFlags = getTransactionFlags(eTransactionMask); handleTransactionLocked(transactionFlags); @@ -3070,7 +3070,13 @@ uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { } uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { + return setTransactionFlags(flags, VSyncModulator::TransactionStart::NORMAL); +} + +uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, + VSyncModulator::TransactionStart transactionStart) { uint32_t old = android_atomic_or(flags, &mTransactionFlags); + mVsyncModulator.setTransactionStart(transactionStart); if ((old & flags)==0) { // wake the server up signalTransaction(); } @@ -3159,7 +3165,10 @@ void SurfaceFlinger::setTransactionState( } // this triggers the transaction - setTransactionFlags(transactionFlags); + const auto start = (flags & eEarlyWakeup) + ? VSyncModulator::TransactionStart::EARLY + : VSyncModulator::TransactionStart::NORMAL; + setTransactionFlags(transactionFlags, start); // if this is a synchronous transaction, wait for it to take effect // before returning. @@ -4099,9 +4108,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.append("DispSync configuration: "); colorizer.reset(result); - result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, " - "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, + result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64 + " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)", + vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(), dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); result.append("\n"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 89c9cfda19..a29d1d7475 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,7 @@ #include "Barrier.h" #include "DisplayDevice.h" #include "DispSync.h" +#include "EventThread.h" #include "FrameTracker.h" #include "LayerStats.h" #include "LayerVector.h" @@ -61,6 +63,7 @@ #include "SurfaceInterceptor.h" #include "SurfaceTracing.h" #include "StartPropertySetThread.h" +#include "VSyncModulator.h" #include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" @@ -492,6 +495,7 @@ private: uint32_t peekTransactionFlags(); // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); + uint32_t setTransactionFlags(uint32_t flags, VSyncModulator::TransactionStart transactionStart); void commitTransaction(); bool containsAnyInvalidClientState(const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); @@ -765,6 +769,8 @@ private: std::unique_ptr mEventControlThread; sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; + VSyncModulator mVsyncModulator; + // Can only accessed from the main thread, these members // don't need synchronization State mDrawingState{LayerVector::StateSet::Drawing}; diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h new file mode 100644 index 0000000000..3126debed4 --- /dev/null +++ b/services/surfaceflinger/VSyncModulator.h @@ -0,0 +1,101 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +using namespace android::surfaceflinger; + +namespace android { + +/* + * Modulates the vsync-offsets depending on current SurfaceFlinger state. + */ +class VSyncModulator { +public: + + enum TransactionStart { + EARLY, + NORMAL + }; + + // Sets the phase offsets + // + // early: the phase offset when waking up early. May be the same as late, in which case we don't + // shift offsets. + // late: the regular sf phase offset. + void setPhaseOffsets(nsecs_t early, nsecs_t late) { + mEarlyPhaseOffset = early; + mLatePhaseOffset = late; + mPhaseOffset = late; + } + + nsecs_t getEarlyPhaseOffset() const { + return mEarlyPhaseOffset; + } + + void setEventThread(EventThread* eventThread) { + mEventThread = eventThread; + } + + void setTransactionStart(TransactionStart transactionStart) { + if (transactionStart == mTransactionStart) return; + mTransactionStart = transactionStart; + updatePhaseOffsets(); + } + + void setLastFrameUsedRenderEngine(bool re) { + if (re == mLastFrameUsedRenderEngine) return; + mLastFrameUsedRenderEngine = re; + updatePhaseOffsets(); + } + +private: + + void updatePhaseOffsets() { + + // Do not change phase offsets if disabled. + if (mEarlyPhaseOffset == mLatePhaseOffset) return; + + if (mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine) { + if (mPhaseOffset != mEarlyPhaseOffset) { + if (mEventThread) { + mEventThread->setPhaseOffset(mEarlyPhaseOffset); + } + mPhaseOffset = mEarlyPhaseOffset; + } + } else { + if (mPhaseOffset != mLatePhaseOffset) { + if (mEventThread) { + mEventThread->setPhaseOffset(mLatePhaseOffset); + } + mPhaseOffset = mLatePhaseOffset; + } + } + } + + nsecs_t mLatePhaseOffset = 0; + nsecs_t mEarlyPhaseOffset = 0; + EventThread* mEventThread = nullptr; + std::atomic mPhaseOffset = 0; + std::atomic mTransactionStart = TransactionStart::NORMAL; + std::atomic mLastFrameUsedRenderEngine = false; +}; + +} // namespace android -- cgit v1.2.3-59-g8ed1b