From cfb187b458858013453019f62c8cbf29a0a8d623 Mon Sep 17 00:00:00 2001 From: rongliu Date: Wed, 14 Mar 2018 12:26:23 -0700 Subject: Manual merge of ag/3738015 because of conflicts. Conflicts are in layers.proto, LayerProtoParser.h and LayerProtoPraser.cpp as master has more fields in layer proto than pi-dev. Original cl: 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 --- libs/gui/SurfaceComposerClient.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') 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; -- cgit v1.2.3-59-g8ed1b From 9f034475d961892e4c10e6ff7ecee96e464be00c 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 --- 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 d5654ccfe3..58fed84ea8 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 769009317f..5e5df43740 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,7 +29,7 @@ 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 decodeColorTransform(android_color_transform colorTransform); 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 e4161bbdb9..e1d7f81656 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. @@ -485,3 +484,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 c1ef2e890a..31bb4d0778 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -33,7 +33,7 @@ #include #include -#include +#include #include "RenderArea.h" #include "RenderEngine/Surface.h" @@ -163,8 +163,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); android_color_transform_t getColorTransform() const; void setColorTransform(const mat4& transform); void setCompositionDataSpace(android_dataspace dataspace); @@ -240,7 +240,7 @@ private: // Current active config int mActiveConfig; // current active color mode - ColorMode mActiveColorMode; + ui::ColorMode mActiveColorMode; // Current color transform android_color_transform_t mColorTransform; @@ -291,7 +291,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 b9e5d3fcdf..82b8bc099a 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 99bbb13211..b3f39b721a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -413,9 +413,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(); @@ -465,7 +465,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(); @@ -638,7 +638,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 84d619e03848f51d87114a03a607c2bba7f305a7 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 --- 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 1cbd602730..b53c73ac54 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -764,6 +764,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 18b2f682ca..50495ec7c3 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 477ace5f2c..01f1ac34bc 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,7 @@ #include "Barrier.h" #include "DisplayDevice.h" #include "DispSync.h" +#include "EventThread.h" #include "FrameTracker.h" #include "LayerStats.h" #include "LayerVector.h" @@ -63,6 +65,7 @@ #include "SurfaceTracing.h" #include "StartPropertySetThread.h" #include "LayerBE.h" +#include "VSyncModulator.h" #include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" @@ -494,6 +497,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); @@ -767,6 +771,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 From 48a619f8332e06ea1cd96d82719cdf5e05c69630 Mon Sep 17 00:00:00 2001 From: Yi Kong Date: Tue, 5 Jun 2018 16:34:59 -0700 Subject: Replace NULL/0 with nullptr Fixes -Wzero-as-null-pointer-constant warning. clang-tidy -checks=modernize-use-nullptr -p compile_commands.json -fix ... Test: m Bug: 68236239 Change-Id: I3a8e982ba40f9b029bafef78437b146a878f56a9 --- libs/gui/BufferItem.cpp | 16 ++++++------ libs/gui/BufferItemConsumer.cpp | 2 +- libs/gui/BufferQueue.cpp | 32 +++++++++++------------ libs/gui/BufferQueueConsumer.cpp | 24 ++++++++--------- libs/gui/BufferQueueProducer.cpp | 52 ++++++++++++++++++------------------- libs/gui/ConsumerBase.cpp | 12 ++++----- libs/gui/DisplayEventReceiver.cpp | 12 ++++----- libs/gui/GLConsumer.cpp | 24 ++++++++--------- libs/gui/IGraphicBufferProducer.cpp | 18 ++++++------- libs/gui/StreamSplitter.cpp | 6 ++--- libs/gui/Surface.cpp | 36 ++++++++++++------------- libs/gui/SurfaceComposerClient.cpp | 18 ++++++------- libs/gui/SurfaceControl.cpp | 10 +++---- libs/gui/SyncFeatures.cpp | 2 +- 14 files changed, 132 insertions(+), 132 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index f50379b3ed..5beba02e63 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -39,8 +39,8 @@ static inline constexpr T to64(const uint32_t lo, const uint32_t hi) { } BufferItem::BufferItem() : - mGraphicBuffer(NULL), - mFence(NULL), + mGraphicBuffer(nullptr), + mFence(nullptr), mCrop(Rect::INVALID_RECT), mTransform(0), mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), @@ -91,11 +91,11 @@ size_t BufferItem::getPodSize() const { size_t BufferItem::getFlattenedSize() const { size_t size = sizeof(uint32_t); // Flags - if (mGraphicBuffer != 0) { + if (mGraphicBuffer != nullptr) { size += mGraphicBuffer->getFlattenedSize(); size = FlattenableUtils::align<4>(size); } - if (mFence != 0) { + if (mFence != nullptr) { size += mFence->getFlattenedSize(); size = FlattenableUtils::align<4>(size); } @@ -107,10 +107,10 @@ size_t BufferItem::getFlattenedSize() const { size_t BufferItem::getFdCount() const { size_t count = 0; - if (mGraphicBuffer != 0) { + if (mGraphicBuffer != nullptr) { count += mGraphicBuffer->getFdCount(); } - if (mFence != 0) { + if (mFence != nullptr) { count += mFence->getFdCount(); } return count; @@ -137,13 +137,13 @@ status_t BufferItem::flatten( FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); flags = 0; - if (mGraphicBuffer != 0) { + if (mGraphicBuffer != nullptr) { status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); if (err) return err; size -= FlattenableUtils::align<4>(buffer); flags |= 1; } - if (mFence != 0) { + if (mFence != nullptr) { status_t err = mFence->flatten(buffer, size, fds, count); if (err) return err; size -= FlattenableUtils::align<4>(buffer); diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp index 89bc0c4c2d..f50bc203e8 100644 --- a/libs/gui/BufferItemConsumer.cpp +++ b/libs/gui/BufferItemConsumer.cpp @@ -107,7 +107,7 @@ status_t BufferItemConsumer::releaseBuffer(const BufferItem &item, void BufferItemConsumer::freeBufferLocked(int slotIndex) { sp listener = mBufferFreedListener.promote(); - if (listener != NULL && mSlots[slotIndex].mGraphicBuffer != NULL) { + if (listener != nullptr && mSlots[slotIndex].mGraphicBuffer != nullptr) { // Fire callback if we have a listener registered and the buffer being freed is valid. BI_LOGV("actually calling onBufferFreed"); listener->onBufferFreed(mSlots[slotIndex].mGraphicBuffer); diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index a8da1347cb..5fb3f0b80f 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -38,7 +38,7 @@ BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} void BufferQueue::ProxyConsumerListener::onDisconnect() { sp listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onDisconnect(); } } @@ -46,7 +46,7 @@ void BufferQueue::ProxyConsumerListener::onDisconnect() { void BufferQueue::ProxyConsumerListener::onFrameAvailable( const BufferItem& item) { sp listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onFrameAvailable(item); } } @@ -54,21 +54,21 @@ void BufferQueue::ProxyConsumerListener::onFrameAvailable( void BufferQueue::ProxyConsumerListener::onFrameReplaced( const BufferItem& item) { sp listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onFrameReplaced(item); } } void BufferQueue::ProxyConsumerListener::onBuffersReleased() { sp listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } } void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { sp listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onSidebandStreamChanged(); } } @@ -85,21 +85,21 @@ void BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps( void BufferQueue::createBufferQueue(sp* outProducer, sp* outConsumer, bool consumerIsSurfaceFlinger) { - LOG_ALWAYS_FATAL_IF(outProducer == NULL, + LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BufferQueue: outProducer must not be NULL"); - LOG_ALWAYS_FATAL_IF(outConsumer == NULL, + LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BufferQueue: outConsumer must not be NULL"); sp core(new BufferQueueCore()); - LOG_ALWAYS_FATAL_IF(core == NULL, + LOG_ALWAYS_FATAL_IF(core == nullptr, "BufferQueue: failed to create BufferQueueCore"); sp producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger)); - LOG_ALWAYS_FATAL_IF(producer == NULL, + LOG_ALWAYS_FATAL_IF(producer == nullptr, "BufferQueue: failed to create BufferQueueProducer"); sp consumer(new BufferQueueConsumer(core)); - LOG_ALWAYS_FATAL_IF(consumer == NULL, + LOG_ALWAYS_FATAL_IF(consumer == nullptr, "BufferQueue: failed to create BufferQueueConsumer"); *outProducer = producer; @@ -109,8 +109,8 @@ void BufferQueue::createBufferQueue(sp* outProducer, #ifndef NO_BUFFERHUB void BufferQueue::createBufferHubQueue(sp* outProducer, sp* outConsumer) { - LOG_ALWAYS_FATAL_IF(outProducer == NULL, "BufferQueue: outProducer must not be NULL"); - LOG_ALWAYS_FATAL_IF(outConsumer == NULL, "BufferQueue: outConsumer must not be NULL"); + LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BufferQueue: outProducer must not be NULL"); + LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BufferQueue: outConsumer must not be NULL"); sp producer; sp consumer; @@ -118,16 +118,16 @@ void BufferQueue::createBufferHubQueue(sp* outProducer, dvr::ProducerQueueConfigBuilder configBuilder; std::shared_ptr producerQueue = dvr::ProducerQueue::Create(configBuilder.Build(), dvr::UsagePolicy{}); - LOG_ALWAYS_FATAL_IF(producerQueue == NULL, "BufferQueue: failed to create ProducerQueue."); + LOG_ALWAYS_FATAL_IF(producerQueue == nullptr, "BufferQueue: failed to create ProducerQueue."); std::shared_ptr consumerQueue = producerQueue->CreateConsumerQueue(); - LOG_ALWAYS_FATAL_IF(consumerQueue == NULL, "BufferQueue: failed to create ConsumerQueue."); + LOG_ALWAYS_FATAL_IF(consumerQueue == nullptr, "BufferQueue: failed to create ConsumerQueue."); producer = BufferHubProducer::Create(producerQueue); consumer = BufferHubConsumer::Create(consumerQueue); - LOG_ALWAYS_FATAL_IF(producer == NULL, "BufferQueue: failed to create BufferQueueProducer"); - LOG_ALWAYS_FATAL_IF(consumer == NULL, "BufferQueue: failed to create BufferQueueConsumer"); + LOG_ALWAYS_FATAL_IF(producer == nullptr, "BufferQueue: failed to create BufferQueueProducer"); + LOG_ALWAYS_FATAL_IF(consumer == nullptr, "BufferQueue: failed to create BufferQueueConsumer"); *outProducer = producer; *outConsumer = consumer; diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index d70e1422b0..3837c3e11a 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -255,7 +255,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer // on the consumer side if (outBuffer->mAcquireCalled) { - outBuffer->mGraphicBuffer = NULL; + outBuffer->mGraphicBuffer = nullptr; } mCore->mQueue.erase(front); @@ -272,7 +272,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, VALIDATE_CONSISTENCY(); } - if (listener != NULL) { + if (listener != nullptr) { for (int i = 0; i < numDroppedBuffers; ++i) { listener->onBufferReleased(); } @@ -321,10 +321,10 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, const sp& buffer) { ATRACE_CALL(); - if (outSlot == NULL) { + if (outSlot == nullptr) { BQ_LOGE("attachBuffer: outSlot must not be NULL"); return BAD_VALUE; - } else if (buffer == NULL) { + } else if (buffer == nullptr) { BQ_LOGE("attachBuffer: cannot attach NULL buffer"); return BAD_VALUE; } @@ -413,7 +413,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, ATRACE_BUFFER_INDEX(slot); if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS || - releaseFence == NULL) { + releaseFence == nullptr) { BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot, releaseFence.get()); return BAD_VALUE; @@ -465,7 +465,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBufferReleased(); } @@ -476,7 +476,7 @@ status_t BufferQueueConsumer::connect( const sp& consumerListener, bool controlledByApp) { ATRACE_CALL(); - if (consumerListener == NULL) { + if (consumerListener == nullptr) { BQ_LOGE("connect: consumerListener may not be NULL"); return BAD_VALUE; } @@ -504,13 +504,13 @@ status_t BufferQueueConsumer::disconnect() { Mutex::Autolock lock(mCore->mMutex); - if (mCore->mConsumerListener == NULL) { + if (mCore->mConsumerListener == nullptr) { BQ_LOGE("disconnect: no consumer is connected"); return BAD_VALUE; } mCore->mIsAbandoned = true; - mCore->mConsumerListener = NULL; + mCore->mConsumerListener = nullptr; mCore->mQueue.clear(); mCore->freeAllBuffersLocked(); mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; @@ -521,7 +521,7 @@ status_t BufferQueueConsumer::disconnect() { status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) { ATRACE_CALL(); - if (outSlotMask == NULL) { + if (outSlotMask == nullptr) { BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL"); return BAD_VALUE; } @@ -673,7 +673,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount( } } // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -772,7 +772,7 @@ status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResul if (uid != shellUid) { #endif android_errorWriteWithInfoLog(0x534e4554, "27046057", - static_cast(uid), NULL, 0); + static_cast(uid), nullptr, 0); return PERMISSION_DENIED; } diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index c8021e4d54..ce3a90a483 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -166,7 +166,7 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount( } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -221,7 +221,7 @@ status_t BufferQueueProducer::setAsyncMode(bool async) { } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } return NO_ERROR; @@ -450,11 +450,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou mSlots[found].mBufferState.dequeue(); - if ((buffer == NULL) || + if ((buffer == nullptr) || buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { mSlots[found].mAcquireCalled = false; - mSlots[found].mGraphicBuffer = NULL; + mSlots[found].mGraphicBuffer = nullptr; mSlots[found].mRequestBufferCalled = false; mSlots[found].mEglDisplay = EGL_NO_DISPLAY; mSlots[found].mEglFence = EGL_NO_SYNC_KHR; @@ -472,7 +472,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64, mCore->mBufferAge); - if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { + if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) { BQ_LOGE("dequeueBuffer: about to return a NULL fence - " "slot=%d w=%d h=%d format=%u", found, buffer->width, buffer->height, buffer->format); @@ -613,7 +613,7 @@ status_t BufferQueueProducer::detachBuffer(int slot) { listener = mCore->mConsumerListener; } - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -624,10 +624,10 @@ status_t BufferQueueProducer::detachNextBuffer(sp* outBuffer, sp* outFence) { ATRACE_CALL(); - if (outBuffer == NULL) { + if (outBuffer == nullptr) { BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); return BAD_VALUE; - } else if (outFence == NULL) { + } else if (outFence == nullptr) { BQ_LOGE("detachNextBuffer: outFence must not be NULL"); return BAD_VALUE; } @@ -671,7 +671,7 @@ status_t BufferQueueProducer::detachNextBuffer(sp* outBuffer, listener = mCore->mConsumerListener; } - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -682,10 +682,10 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot, const sp& buffer) { ATRACE_CALL(); - if (outSlot == NULL) { + if (outSlot == nullptr) { BQ_LOGE("attachBuffer: outSlot must not be NULL"); return BAD_VALUE; - } else if (buffer == NULL) { + } else if (buffer == nullptr) { BQ_LOGE("attachBuffer: cannot attach NULL buffer"); return BAD_VALUE; } @@ -767,7 +767,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, const Region& surfaceDamage = input.getSurfaceDamage(); const HdrMetadata& hdrMetadata = input.getHdrMetadata(); - if (acquireFence == NULL) { + if (acquireFence == nullptr) { BQ_LOGE("queueBuffer: fence is NULL"); return BAD_VALUE; } @@ -973,9 +973,9 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCallbackCondition.wait(mCallbackMutex); } - if (frameAvailableListener != NULL) { + if (frameAvailableListener != nullptr) { frameAvailableListener->onFrameAvailable(item); - } else if (frameReplacedListener != NULL) { + } else if (frameReplacedListener != nullptr) { frameReplacedListener->onFrameReplaced(item); } @@ -1040,7 +1040,7 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp& fence) { BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " "(state = %s)", slot, mSlots[slot].mBufferState.string()); return BAD_VALUE; - } else if (fence == NULL) { + } else if (fence == nullptr) { BQ_LOGE("cancelBuffer: fence is NULL"); return BAD_VALUE; } @@ -1070,7 +1070,7 @@ int BufferQueueProducer::query(int what, int *outValue) { ATRACE_CALL(); Mutex::Autolock lock(mCore->mMutex); - if (outValue == NULL) { + if (outValue == nullptr) { BQ_LOGE("query: outValue was NULL"); return BAD_VALUE; } @@ -1146,12 +1146,12 @@ status_t BufferQueueProducer::connect(const sp& listener, return NO_INIT; } - if (mCore->mConsumerListener == NULL) { + if (mCore->mConsumerListener == nullptr) { BQ_LOGE("connect: BufferQueue has no consumer"); return NO_INIT; } - if (output == NULL) { + if (output == nullptr) { BQ_LOGE("connect: output was NULL"); return BAD_VALUE; } @@ -1189,10 +1189,10 @@ status_t BufferQueueProducer::connect(const sp& listener, output->nextFrameNumber = mCore->mFrameCounter + 1; output->bufferReplaced = false; - if (listener != NULL) { + if (listener != nullptr) { // Set up a death notification so that we can disconnect // automatically if the remote producer dies - if (IInterface::asBinder(listener)->remoteBinder() != NULL) { + if (IInterface::asBinder(listener)->remoteBinder() != nullptr) { status = IInterface::asBinder(listener)->linkToDeath( static_cast(this)); if (status != NO_ERROR) { @@ -1269,7 +1269,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { mCore->freeAllBuffersLocked(); // Remove our death notification callback if we have one - if (mCore->mLinkedToDeath != NULL) { + if (mCore->mLinkedToDeath != nullptr) { sp token = IInterface::asBinder(mCore->mLinkedToDeath); // This can fail if we're here because of the death @@ -1279,8 +1279,8 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { } mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; - mCore->mLinkedToDeath = NULL; - mCore->mConnectedProducerListener = NULL; + mCore->mLinkedToDeath = nullptr; + mCore->mConnectedProducerListener = nullptr; mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; mCore->mConnectedPid = -1; mCore->mSidebandStream.clear(); @@ -1303,7 +1303,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); listener->onDisconnect(); } @@ -1319,7 +1319,7 @@ status_t BufferQueueProducer::setSidebandStream(const sp& stream) listener = mCore->mConsumerListener; } // Autolock scope - if (listener != NULL) { + if (listener != nullptr) { listener->onSidebandStreamChanged(); } return NO_ERROR; @@ -1535,7 +1535,7 @@ void BufferQueueProducer::addAndGetFrameTimestamps( Mutex::Autolock lock(mCore->mMutex); listener = mCore->mConsumerListener; } - if (listener != NULL) { + if (listener != nullptr) { listener->addAndGetFrameTimestamps(newTimestamps, outDelta); } } diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index f9e292e199..abd9921fa9 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -96,7 +96,7 @@ void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) { void ConsumerBase::freeBufferLocked(int slotIndex) { CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); - mSlots[slotIndex].mGraphicBuffer = 0; + mSlots[slotIndex].mGraphicBuffer = nullptr; mSlots[slotIndex].mFence = Fence::NO_FENCE; mSlots[slotIndex].mFrameNumber = 0; } @@ -110,7 +110,7 @@ void ConsumerBase::onFrameAvailable(const BufferItem& item) { listener = mFrameAvailableListener.promote(); } - if (listener != NULL) { + if (listener != nullptr) { CB_LOGV("actually calling onFrameAvailable"); listener->onFrameAvailable(item); } @@ -125,7 +125,7 @@ void ConsumerBase::onFrameReplaced(const BufferItem &item) { listener = mFrameAvailableListener.promote(); } - if (listener != NULL) { + if (listener != nullptr) { CB_LOGV("actually calling onFrameReplaced"); listener->onFrameReplaced(item); } @@ -352,8 +352,8 @@ status_t ConsumerBase::acquireBufferLocked(BufferItem *item, return err; } - if (item->mGraphicBuffer != NULL) { - if (mSlots[item->mSlot].mGraphicBuffer != NULL) { + if (item->mGraphicBuffer != nullptr) { + if (mSlots[item->mSlot].mGraphicBuffer != nullptr) { freeBufferLocked(item->mSlot); } mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer; @@ -468,7 +468,7 @@ bool ConsumerBase::stillTracking(int slot, if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) { return false; } - return (mSlots[slot].mGraphicBuffer != NULL && + return (mSlots[slot].mGraphicBuffer != nullptr && mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle); } diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index 1757ec1cd3..f5cf1c4d5a 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -34,9 +34,9 @@ namespace android { DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) { sp sf(ComposerService::getComposerService()); - if (sf != NULL) { + if (sf != nullptr) { mEventConnection = sf->createDisplayEventConnection(vsyncSource); - if (mEventConnection != NULL) { + if (mEventConnection != nullptr) { mDataChannel = std::make_unique(); mEventConnection->stealReceiveChannel(mDataChannel.get()); } @@ -47,13 +47,13 @@ DisplayEventReceiver::~DisplayEventReceiver() { } status_t DisplayEventReceiver::initCheck() const { - if (mDataChannel != NULL) + if (mDataChannel != nullptr) return NO_ERROR; return NO_INIT; } int DisplayEventReceiver::getFd() const { - if (mDataChannel == NULL) + if (mDataChannel == nullptr) return NO_INIT; return mDataChannel->getFd(); @@ -63,7 +63,7 @@ status_t DisplayEventReceiver::setVsyncRate(uint32_t count) { if (int32_t(count) < 0) return BAD_VALUE; - if (mEventConnection != NULL) { + if (mEventConnection != nullptr) { mEventConnection->setVsyncRate(count); return NO_ERROR; } @@ -71,7 +71,7 @@ status_t DisplayEventReceiver::setVsyncRate(uint32_t count) { } status_t DisplayEventReceiver::requestNextVsync() { - if (mEventConnection != NULL) { + if (mEventConnection != nullptr) { mEventConnection->requestNextVsync(); return NO_ERROR; } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 885efec9b9..8efbef5404 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -291,7 +291,7 @@ status_t GLConsumer::releaseTexImage() { return err; } - if (mReleasedTexImage == NULL) { + if (mReleasedTexImage == nullptr) { mReleasedTexImage = new EglImage(getDebugTexImageBuffer()); } @@ -321,7 +321,7 @@ status_t GLConsumer::releaseTexImage() { sp GLConsumer::getDebugTexImageBuffer() { Mutex::Autolock _l(sStaticInitLock); - if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) { + if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) { // The first time, create the debug texture in case the application // continues to use it. sp buffer = new GraphicBuffer( @@ -357,7 +357,7 @@ status_t GLConsumer::acquireBufferLocked(BufferItem *item, // If item->mGraphicBuffer is not null, this buffer has not been acquired // before, so any prior EglImage created is using a stale buffer. This // replaces any old EglImage with a new one (using the new buffer). - if (item->mGraphicBuffer != NULL) { + if (item->mGraphicBuffer != nullptr) { int slot = item->mSlot; mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer); } @@ -431,7 +431,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item, GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, mCurrentTextureImage != NULL ? - mCurrentTextureImage->graphicBufferHandle() : 0, + mCurrentTextureImage->graphicBufferHandle() : nullptr, slot, mSlots[slot].mGraphicBuffer->handle); // Hang onto the pointer so that it isn't freed in the call to @@ -491,7 +491,7 @@ status_t GLConsumer::bindTextureImageLocked() { glBindTexture(mTexTarget, mTexName); if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && - mCurrentTextureImage == NULL) { + mCurrentTextureImage == nullptr) { GLC_LOGE("bindTextureImage: no currently-bound texture"); return NO_INIT; } @@ -655,7 +655,7 @@ status_t GLConsumer::attachToContext(uint32_t tex) { mTexName = tex; mAttached = true; - if (mCurrentTextureImage != NULL) { + if (mCurrentTextureImage != nullptr) { // This may wait for a buffer a second time. This is likely required if // this is a different context, since otherwise the wait could be skipped // by bouncing through another context. For the same context the extra @@ -676,7 +676,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (SyncFeatures::getInstance().useNativeFenceSync()) { EGLSyncKHR sync = eglCreateSyncKHR(dpy, - EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); if (sync == EGL_NO_SYNC_KHR) { GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError()); @@ -720,7 +720,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { // Create a fence for the outstanding accesses in the current // OpenGL ES context. - fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); + fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr); if (fence == EGL_NO_SYNC_KHR) { GLC_LOGE("syncForReleaseLocked: error creating fence: %#x", eglGetError()); @@ -752,11 +752,11 @@ void GLConsumer::setFilteringEnabled(bool enabled) { bool needsRecompute = mFilteringEnabled != enabled; mFilteringEnabled = enabled; - if (needsRecompute && mCurrentTextureImage==NULL) { + if (needsRecompute && mCurrentTextureImage==nullptr) { GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); } - if (needsRecompute && mCurrentTextureImage != NULL) { + if (needsRecompute && mCurrentTextureImage != nullptr) { computeCurrentTransformMatrixLocked(); } } @@ -938,7 +938,7 @@ sp GLConsumer::getCurrentBuffer(int* outSlot) const { } return (mCurrentTextureImage == nullptr) ? - NULL : mCurrentTextureImage->graphicBuffer(); + nullptr : mCurrentTextureImage->graphicBuffer(); } Rect GLConsumer::getCurrentCrop() const { @@ -1150,7 +1150,7 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, attrs[3] = attrs[11]; attrs[4] = EGL_NONE; } - eglInitialize(dpy, 0, 0); + eglInitialize(dpy, nullptr, nullptr); EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); if (image == EGL_NO_IMAGE_KHR) { diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 0749fde1ad..3693d2cb21 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -190,10 +190,10 @@ public: virtual status_t detachNextBuffer(sp* outBuffer, sp* outFence) { - if (outBuffer == NULL) { + if (outBuffer == nullptr) { ALOGE("detachNextBuffer: outBuffer must not be NULL"); return BAD_VALUE; - } else if (outFence == NULL) { + } else if (outFence == nullptr) { ALOGE("detachNextBuffer: outFence must not be NULL"); return BAD_VALUE; } @@ -301,7 +301,7 @@ public: int api, bool producerControlledByApp, QueueBufferOutput* output) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); - if (listener != NULL) { + if (listener != nullptr) { data.writeInt32(1); data.writeStrongBinder(IInterface::asBinder(listener)); } else { @@ -738,8 +738,8 @@ status_t BnGraphicBufferProducer::onTransact( int bufferIdx = data.readInt32(); sp buffer; int result = requestBuffer(bufferIdx, &buffer); - reply->writeInt32(buffer != 0); - if (buffer != 0) { + reply->writeInt32(buffer != nullptr); + if (buffer != nullptr) { reply->write(*buffer); } reply->writeInt32(result); @@ -797,12 +797,12 @@ status_t BnGraphicBufferProducer::onTransact( int32_t result = detachNextBuffer(&buffer, &fence); reply->writeInt32(result); if (result == NO_ERROR) { - reply->writeInt32(buffer != NULL); - if (buffer != NULL) { + reply->writeInt32(buffer != nullptr); + if (buffer != nullptr) { reply->write(*buffer); } - reply->writeInt32(fence != NULL); - if (fence != NULL) { + reply->writeInt32(fence != nullptr); + if (fence != nullptr) { reply->write(*fence); } } diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp index 52c906775e..2f8e104ea0 100644 --- a/libs/gui/StreamSplitter.cpp +++ b/libs/gui/StreamSplitter.cpp @@ -38,11 +38,11 @@ namespace android { status_t StreamSplitter::createSplitter( const sp& inputQueue, sp* outSplitter) { - if (inputQueue == NULL) { + if (inputQueue == nullptr) { ALOGE("createSplitter: inputQueue must not be NULL"); return BAD_VALUE; } - if (outSplitter == NULL) { + if (outSplitter == nullptr) { ALOGE("createSplitter: outSplitter must not be NULL"); return BAD_VALUE; } @@ -74,7 +74,7 @@ StreamSplitter::~StreamSplitter() { status_t StreamSplitter::addOutput( const sp& outputQueue) { - if (outputQueue == NULL) { + if (outputQueue == nullptr) { ALOGE("addOutput: outputQueue must not be NULL"); return BAD_VALUE; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 339bd0fa4e..7bddaaf3b6 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -156,7 +156,7 @@ status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) { ATRACE_CALL(); DisplayStatInfo stats; - status_t result = composerService()->getDisplayStats(NULL, &stats); + status_t result = composerService()->getDisplayStats(nullptr, &stats); if (result != NO_ERROR) { return result; } @@ -497,7 +497,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot != BufferItem::INVALID_BUFFER_SLOT) { sp& gbuf(mSlots[mSharedBufferSlot].buffer); - if (gbuf != NULL) { + if (gbuf != nullptr) { *buffer = gbuf.get(); *fenceFd = -1; return OK; @@ -537,7 +537,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { sp& gbuf(mSlots[buf].buffer); // this should never happen - ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); + ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) { freeAllBuffers(); @@ -615,7 +615,7 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer, int Surface::getSlotFromBufferLocked( android_native_buffer_t* buffer) const { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].buffer != NULL && + if (mSlots[i].buffer != nullptr && mSlots[i].buffer->handle == buffer->handle) { return i; } @@ -1264,7 +1264,7 @@ int Surface::detachNextBuffer(sp* outBuffer, ATRACE_CALL(); ALOGV("Surface::detachNextBuffer"); - if (outBuffer == NULL || outFence == NULL) { + if (outBuffer == nullptr || outFence == nullptr) { return BAD_VALUE; } @@ -1273,8 +1273,8 @@ int Surface::detachNextBuffer(sp* outBuffer, mRemovedBuffers.clear(); } - sp buffer(NULL); - sp fence(NULL); + sp buffer(nullptr); + sp fence(nullptr); status_t result = mGraphicBufferProducer->detachNextBuffer( &buffer, &fence); if (result != NO_ERROR) { @@ -1282,19 +1282,19 @@ int Surface::detachNextBuffer(sp* outBuffer, } *outBuffer = buffer; - if (fence != NULL && fence->isValid()) { + if (fence != nullptr && fence->isValid()) { *outFence = fence; } else { *outFence = Fence::NO_FENCE; } for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].buffer != NULL && + if (mSlots[i].buffer != nullptr && mSlots[i].buffer->getId() == buffer->getId()) { if (mReportRemovedBuffers) { mRemovedBuffers.push_back(mSlots[i].buffer); } - mSlots[i].buffer = NULL; + mSlots[i].buffer = nullptr; } } @@ -1345,7 +1345,7 @@ int Surface::setCrop(Rect const* rect) ATRACE_CALL(); Rect realRect(Rect::EMPTY_RECT); - if (rect == NULL || rect->isEmpty()) { + if (rect == nullptr || rect->isEmpty()) { realRect.clear(); } else { realRect = *rect; @@ -1572,7 +1572,7 @@ Dataspace Surface::getBuffersDataSpace() { void Surface::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i].buffer = 0; + mSlots[i].buffer = nullptr; } } @@ -1612,12 +1612,12 @@ static status_t copyBlt( // src and dst with, height and format must be identical. no verification // is done here. status_t err; - uint8_t* src_bits = NULL; + uint8_t* src_bits = nullptr; err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), reinterpret_cast(&src_bits)); ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); - uint8_t* dst_bits = NULL; + uint8_t* dst_bits = nullptr; err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), reinterpret_cast(&dst_bits), *dstFenceFd); ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); @@ -1665,7 +1665,7 @@ static status_t copyBlt( status_t Surface::lock( ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) { - if (mLockedBuffer != 0) { + if (mLockedBuffer != nullptr) { ALOGE("Surface::lock failed, already locked"); return INVALID_OPERATION; } @@ -1697,7 +1697,7 @@ status_t Surface::lock( // figure out if we can copy the frontbuffer back const sp& frontBuffer(mPostedBuffer); - const bool canCopyBack = (frontBuffer != 0 && + const bool canCopyBack = (frontBuffer != nullptr && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && backBuffer->format == frontBuffer->format); @@ -1759,7 +1759,7 @@ status_t Surface::lock( status_t Surface::unlockAndPost() { - if (mLockedBuffer == 0) { + if (mLockedBuffer == nullptr) { ALOGE("Surface::unlockAndPost failed, no locked buffer"); return INVALID_OPERATION; } @@ -1773,7 +1773,7 @@ status_t Surface::unlockAndPost() mLockedBuffer->handle, strerror(-err)); mPostedBuffer = mLockedBuffer; - mLockedBuffer = 0; + mLockedBuffer = nullptr; return err; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 63560c4b89..d2b472b52f 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -81,7 +81,7 @@ void ComposerService::connectLocked() { /*static*/ sp ComposerService::getComposerService() { ComposerService& instance = ComposerService::getInstance(); Mutex::Autolock _l(instance.mLock); - if (instance.mComposerService == NULL) { + if (instance.mComposerService == nullptr) { ComposerService::getInstance().connectLocked(); assert(instance.mComposerService != NULL); ALOGD("ComposerService reconnected"); @@ -92,8 +92,8 @@ void ComposerService::connectLocked() { void ComposerService::composerServiceDied() { Mutex::Autolock _l(mLock); - mComposerService = NULL; - mDeathObserver = NULL; + mComposerService = nullptr; + mDeathObserver = nullptr; } // --------------------------------------------------------------------------- @@ -571,12 +571,12 @@ SurfaceComposerClient::SurfaceComposerClient(const sp& c void SurfaceComposerClient::onFirstRef() { sp sf(ComposerService::getComposerService()); - if (sf != 0 && mStatus == NO_INIT) { + if (sf != nullptr && mStatus == NO_INIT) { auto rootProducer = mParent.promote(); sp conn; conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) : sf->createConnection(); - if (conn != 0) { + if (conn != nullptr) { mClient = conn; mStatus = NO_ERROR; } @@ -606,7 +606,7 @@ void SurfaceComposerClient::dispose() { // this can be called more than once. sp client; Mutex::Autolock _lm(mLock); - if (mClient != 0) { + if (mClient != nullptr) { client = mClient; // hold ref while lock is held mClient.clear(); } @@ -766,7 +766,7 @@ status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, bool useIdentityTransform, uint32_t rotation, sp* outBuffer) { sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; + if (s == nullptr) return NO_INIT; status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, static_cast(rotation)); @@ -779,7 +779,7 @@ status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; + if (s == nullptr) return NO_INIT; status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, false /* childrenOnly */); return ret; @@ -788,7 +788,7 @@ status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect so status_t ScreenshotClient::captureChildLayers(const sp& layerHandle, Rect sourceCrop, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; + if (s == nullptr) return NO_INIT; status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, true /* childrenOnly */); return ret; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 5eafbb3555..19ad31b8c7 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -86,7 +86,7 @@ void SurfaceControl::clear() } void SurfaceControl::disconnect() { - if (mGraphicBufferProducer != NULL) { + if (mGraphicBufferProducer != nullptr) { mGraphicBufferProducer->disconnect( BufferQueueCore::CURRENTLY_CONNECTED_API); } @@ -95,7 +95,7 @@ void SurfaceControl::disconnect() { bool SurfaceControl::isSameSurface( const sp& lhs, const sp& rhs) { - if (lhs == 0 || rhs == 0) + if (lhs == nullptr || rhs == nullptr) return false; return lhs->mHandle == rhs->mHandle; } @@ -116,7 +116,7 @@ status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const { status_t SurfaceControl::validate() const { - if (mHandle==0 || mClient==0) { + if (mHandle==nullptr || mClient==nullptr) { ALOGE("invalid handle (%p) or client (%p)", mHandle.get(), mClient.get()); return NO_INIT; @@ -128,7 +128,7 @@ status_t SurfaceControl::writeSurfaceToParcel( const sp& control, Parcel* parcel) { sp bp; - if (control != NULL) { + if (control != nullptr) { bp = control->mGraphicBufferProducer; } return parcel->writeStrongBinder(IInterface::asBinder(bp)); @@ -146,7 +146,7 @@ sp SurfaceControl::generateSurfaceLocked() const sp SurfaceControl::getSurface() const { Mutex::Autolock _l(mLock); - if (mSurfaceData == 0) { + if (mSurfaceData == nullptr) { return generateSurfaceLocked(); } return mSurfaceData; diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp index afa15c5cda..fcae05c8ad 100644 --- a/libs/gui/SyncFeatures.cpp +++ b/libs/gui/SyncFeatures.cpp @@ -41,7 +41,7 @@ SyncFeatures::SyncFeatures() : Singleton(), // This can only be called after EGL has been initialized; otherwise the // check below will abort. const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS); - LOG_ALWAYS_FATAL_IF(exts == NULL, "eglQueryStringImplementationANDROID failed"); + LOG_ALWAYS_FATAL_IF(exts == nullptr, "eglQueryStringImplementationANDROID failed"); if (strstr(exts, "EGL_ANDROID_native_fence_sync")) { // This makes GLConsumer use the EGL_ANDROID_native_fence_sync // extension to create Android native fences to signal when all -- cgit v1.2.3-59-g8ed1b From a03e044aa198feaac79ae634b5244e69db7d826f Mon Sep 17 00:00:00 2001 From: Yi Kong Date: Tue, 17 Jul 2018 11:16:57 -0700 Subject: [gui] Modernize codebase by replacing NULL with nullptr Fixes -Wzero-as-null-pointer-constant warning. Test: m Bug: 68236239 Change-Id: I7b39bde2d13690d46d96ae0e0737d19b11a1da9a --- libs/gui/BufferQueueCore.cpp | 8 ++++---- libs/gui/GLConsumer.cpp | 2 +- libs/gui/SurfaceComposerClient.cpp | 4 ++-- libs/gui/include/gui/CpuConsumer.h | 6 +++--- libs/gui/include/gui/GLConsumer.h | 2 +- libs/gui/include/gui/IGraphicBufferProducer.h | 2 +- libs/gui/include/gui/Surface.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 +- libs/gui/include/gui/SurfaceControl.h | 4 ++-- libs/gui/tests/BufferQueue_test.cpp | 18 +++++++++--------- libs/gui/tests/CpuConsumer_test.cpp | 12 ++++++------ libs/gui/tests/FillBuffer.cpp | 4 ++-- libs/gui/tests/GLTest.cpp | 16 ++++++++-------- libs/gui/tests/GLTest.h | 2 +- libs/gui/tests/IGraphicBufferProducer_test.cpp | 12 ++++++------ libs/gui/tests/MultiTextureConsumer_test.cpp | 4 ++-- libs/gui/tests/SurfaceTextureClient_test.cpp | 16 ++++++++-------- libs/gui/tests/SurfaceTextureFBO.h | 2 +- libs/gui/tests/SurfaceTextureFBO_test.cpp | 6 +++--- libs/gui/tests/SurfaceTextureGLThreadToGL.h | 4 ++-- libs/gui/tests/SurfaceTextureGLToGL.h | 2 +- libs/gui/tests/SurfaceTextureGL_test.cpp | 22 +++++++++++----------- libs/gui/tests/Surface_test.cpp | 6 +++--- 23 files changed, 79 insertions(+), 79 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index bb703da3dd..960b1948c2 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -349,7 +349,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer != NULL) { + if (mSlots[slot].mGraphicBuffer != nullptr) { BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer", slot); usleep(PAUSE_TIME); @@ -371,7 +371,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer != NULL) { + if (mSlots[slot].mGraphicBuffer != nullptr) { BQ_LOGE("Slot %d is in mFreeSlots but has a buffer", slot); usleep(PAUSE_TIME); @@ -394,7 +394,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer == NULL) { + if (mSlots[slot].mGraphicBuffer == nullptr) { BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot); usleep(PAUSE_TIME); } @@ -418,7 +418,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) { + if (mSlots[slot].mGraphicBuffer == nullptr && !mIsAllocating) { BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot); usleep(PAUSE_TIME); } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 6237aa09c2..5532db43ad 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -405,7 +405,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item, } GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", - mCurrentTexture, mCurrentTextureImage != NULL ? + mCurrentTexture, mCurrentTextureImage != nullptr ? mCurrentTextureImage->graphicBufferHandle() : nullptr, slot, mSlots[slot].mGraphicBuffer->handle); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d2b472b52f..fc076d2ea5 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -60,7 +60,7 @@ void ComposerService::connectLocked() { while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); } - assert(mComposerService != NULL); + assert(mComposerService != nullptr); // Create the death listener. class DeathObserver : public IBinder::DeathRecipient { @@ -83,7 +83,7 @@ void ComposerService::connectLocked() { Mutex::Autolock _l(instance.mLock); if (instance.mComposerService == nullptr) { ComposerService::getInstance().connectLocked(); - assert(instance.mComposerService != NULL); + assert(instance.mComposerService != nullptr); ALOGD("ComposerService reconnected"); } return instance.mComposerService; diff --git a/libs/gui/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h index d375611e5b..806fbe8aa0 100644 --- a/libs/gui/include/gui/CpuConsumer.h +++ b/libs/gui/include/gui/CpuConsumer.h @@ -70,7 +70,7 @@ class CpuConsumer : public ConsumerBase uint32_t chromaStep; LockedBuffer() : - data(NULL), + data(nullptr), width(0), height(0), format(PIXEL_FORMAT_NONE), @@ -82,8 +82,8 @@ class CpuConsumer : public ConsumerBase dataSpace(HAL_DATASPACE_UNKNOWN), frameNumber(0), flexFormat(PIXEL_FORMAT_NONE), - dataCb(NULL), - dataCr(NULL), + dataCb(nullptr), + dataCr(nullptr), chromaStride(0), chromaStep(0) {} diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h index 25f9d6b3f2..46a99e124c 100644 --- a/libs/gui/include/gui/GLConsumer.h +++ b/libs/gui/include/gui/GLConsumer.h @@ -314,7 +314,7 @@ private: const sp& graphicBuffer() { return mGraphicBuffer; } const native_handle* graphicBufferHandle() { - return mGraphicBuffer == NULL ? NULL : mGraphicBuffer->handle; + return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle; } private: diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 887654e05b..8ff8d81cf6 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -345,7 +345,7 @@ public: *outScalingMode = scalingMode; *outTransform = transform; *outFence = fence; - if (outStickyTransform != NULL) { + if (outStickyTransform != nullptr) { *outStickyTransform = stickyTransform; } if (outGetFrameTimestamps) { diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 9aeafae198..32ee595d45 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -80,7 +80,7 @@ public: /* convenience function to check that the given surface is non NULL as * well as its IGraphicBufferProducer */ static bool isValid(const sp& surface) { - return surface != NULL && surface->getIGraphicBufferProducer() != NULL; + return surface != nullptr && surface->getIGraphicBufferProducer() != nullptr; } /* Attaches a sideband buffer stream to the Surface's IGraphicBufferProducer. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 377fe68c41..34708c755f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -69,7 +69,7 @@ public: // callback when the composer is dies status_t linkToComposerDeath(const sp& recipient, - void* cookie = NULL, uint32_t flags = 0); + void* cookie = nullptr, uint32_t flags = 0); // Get a list of supported configurations for a given display static status_t getDisplayConfigs(const sp& display, diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index bd987dd638..ccb30fa8e7 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -48,11 +48,11 @@ public: void writeToParcel(Parcel* parcel); static bool isValid(const sp& surface) { - return (surface != 0) && surface->isValid(); + return (surface != nullptr) && surface->isValid(); } bool isValid() { - return mHandle!=0 && mClient!=0; + return mHandle!=nullptr && mClient!=nullptr; } static bool isSameSurface( diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 9a208593ab..119e888edb 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -61,7 +61,7 @@ protected: } void GetMinUndequeuedBufferCount(int* bufferCount) { - ASSERT_TRUE(bufferCount != NULL); + ASSERT_TRUE(bufferCount != nullptr); ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, bufferCount)); ASSERT_GE(*bufferCount, 0); @@ -82,7 +82,7 @@ protected: sp fence; input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, - &scalingMode, &transform, &fence, NULL); + &scalingMode, &transform, &fence, nullptr); ASSERT_EQ(timestamp, item.mTimestamp); ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp); ASSERT_EQ(dataSpace, item.mDataSpace); @@ -128,17 +128,17 @@ TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) { sp binderProducer = serviceManager->getService(PRODUCER_NAME); mProducer = interface_cast(binderProducer); - EXPECT_TRUE(mProducer != NULL); + EXPECT_TRUE(mProducer != nullptr); sp binderConsumer = serviceManager->getService(CONSUMER_NAME); mConsumer = interface_cast(binderConsumer); - EXPECT_TRUE(mConsumer != NULL); + EXPECT_TRUE(mConsumer != nullptr); sp dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); IGraphicBufferProducer::QueueBufferOutput output; ASSERT_EQ(OK, - mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output)); + mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output)); int slot; sp fence; @@ -353,8 +353,8 @@ TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) { ASSERT_EQ(OK, buffer->unlock()); int newSlot; - ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer)); - ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL)); + ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer)); + ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr)); ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer)); IGraphicBufferProducer::QueueBufferInput input(0, false, @@ -412,8 +412,8 @@ TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { int newSlot; sp safeToClobberBuffer; - ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer)); - ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL)); + ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer)); + ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr)); ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer)); ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY, diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp index 36be7d9368..00e32d9124 100644 --- a/libs/gui/tests/CpuConsumer_test.cpp +++ b/libs/gui/tests/CpuConsumer_test.cpp @@ -484,12 +484,12 @@ void produceOneFrame(const sp& anw, err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); ASSERT_NO_ERROR(err, "dequeueBuffer error: "); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp buf(GraphicBuffer::from(anb)); *stride = buf->getStride(); - uint8_t* img = NULL; + uint8_t* img = nullptr; ALOGVV("Lock buffer from %p for write", anw.get()); err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); @@ -554,7 +554,7 @@ TEST_P(CpuConsumerTest, FromCpuSingle) { err = mCC->lockNextBuffer(&b); ASSERT_NO_ERROR(err, "getNextBuffer error: "); - ASSERT_TRUE(b.data != NULL); + ASSERT_TRUE(b.data != nullptr); EXPECT_EQ(params.width, b.width); EXPECT_EQ(params.height, b.height); EXPECT_EQ(params.format, b.format); @@ -595,7 +595,7 @@ TEST_P(CpuConsumerTest, FromCpuManyInQueue) { err = mCC->lockNextBuffer(&b); ASSERT_NO_ERROR(err, "getNextBuffer error: "); - ASSERT_TRUE(b.data != NULL); + ASSERT_TRUE(b.data != nullptr); EXPECT_EQ(params.width, b.width); EXPECT_EQ(params.height, b.height); EXPECT_EQ(params.format, b.format); @@ -637,7 +637,7 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { err = mCC->lockNextBuffer(&b[i]); ASSERT_NO_ERROR(err, "getNextBuffer error: "); - ASSERT_TRUE(b[i].data != NULL); + ASSERT_TRUE(b[i].data != nullptr); EXPECT_EQ(params.width, b[i].width); EXPECT_EQ(params.height, b[i].height); EXPECT_EQ(params.format, b[i].format); @@ -660,7 +660,7 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { err = mCC->lockNextBuffer(&bTooMuch); ASSERT_NO_ERROR(err, "Did not allow new lock after unlock"); - ASSERT_TRUE(bTooMuch.data != NULL); + ASSERT_TRUE(bTooMuch.data != nullptr); EXPECT_EQ(params.width, bTooMuch.width); EXPECT_EQ(params.height, bTooMuch.height); EXPECT_EQ(params.format, bTooMuch.format); diff --git a/libs/gui/tests/FillBuffer.cpp b/libs/gui/tests/FillBuffer.cpp index ccd674fcb8..b60995a624 100644 --- a/libs/gui/tests/FillBuffer.cpp +++ b/libs/gui/tests/FillBuffer.cpp @@ -93,11 +93,11 @@ void produceOneRGBA8Frame(const sp& anw) { android_native_buffer_t* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp buf(GraphicBuffer::from(anb)); - uint8_t* img = NULL; + uint8_t* img = nullptr; ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img))); fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride()); diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp index a91552f7fe..a1405fcb11 100644 --- a/libs/gui/tests/GLTest.cpp +++ b/libs/gui/tests/GLTest.cpp @@ -50,7 +50,7 @@ void GLTest::SetUp() { ASSERT_EQ(EGL_SUCCESS, eglGetError()); char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS"); - if (displaySecsEnv != NULL) { + if (displaySecsEnv != nullptr) { mDisplaySecs = atoi(displaySecsEnv); if (mDisplaySecs < 0) { mDisplaySecs = 0; @@ -67,7 +67,7 @@ void GLTest::SetUp() { String8("Test Surface"), getSurfaceWidth(), getSurfaceHeight(), PIXEL_FORMAT_RGB_888, 0); - ASSERT_TRUE(mSurfaceControl != NULL); + ASSERT_TRUE(mSurfaceControl != nullptr); ASSERT_TRUE(mSurfaceControl->isValid()); Transaction t; @@ -117,7 +117,7 @@ void GLTest::TearDown() { sleep(mDisplaySecs); } - if (mComposerClient != NULL) { + if (mComposerClient != nullptr) { mComposerClient->dispose(); } if (mEglContext != EGL_NO_CONTEXT) { @@ -171,7 +171,7 @@ EGLint GLTest::getSurfaceHeight() { EGLSurface GLTest::createWindowSurface(EGLDisplay display, EGLConfig config, sp& window) const { - return eglCreateWindowSurface(display, config, window.get(), NULL); + return eglCreateWindowSurface(display, config, window.get(), nullptr); } ::testing::AssertionResult GLTest::checkPixel(int x, int y, @@ -256,7 +256,7 @@ void GLTest::loadShader(GLenum shaderType, const char* pSource, GLuint shader = glCreateShader(shaderType); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); if (shader) { - glShaderSource(shader, 1, &pSource, NULL); + glShaderSource(shader, 1, &pSource, nullptr); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); glCompileShader(shader); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); @@ -270,7 +270,7 @@ void GLTest::loadShader(GLenum shaderType, const char* pSource, if (infoLen) { char* buf = (char*) malloc(infoLen); if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); + glGetShaderInfoLog(shader, infoLen, nullptr, buf); printf("Shader compile log:\n%s\n", buf); free(buf); FAIL(); @@ -278,7 +278,7 @@ void GLTest::loadShader(GLenum shaderType, const char* pSource, } else { char* buf = (char*) malloc(0x1000); if (buf) { - glGetShaderInfoLog(shader, 0x1000, NULL, buf); + glGetShaderInfoLog(shader, 0x1000, nullptr, buf); printf("Shader compile log:\n%s\n", buf); free(buf); FAIL(); @@ -322,7 +322,7 @@ void GLTest::createProgram(const char* pVertexSource, if (bufLength) { char* buf = (char*) malloc(bufLength); if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); + glGetProgramInfoLog(program, bufLength, nullptr, buf); printf("Program link log:\n%s\n", buf); free(buf); FAIL(); diff --git a/libs/gui/tests/GLTest.h b/libs/gui/tests/GLTest.h index f0d27a8a34..f290b3c68d 100644 --- a/libs/gui/tests/GLTest.h +++ b/libs/gui/tests/GLTest.h @@ -39,7 +39,7 @@ protected: mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT), - mGlConfig(NULL) { + mGlConfig(nullptr) { } virtual void SetUp(); diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp index c20e8fca21..6d03374810 100644 --- a/libs/gui/tests/IGraphicBufferProducer_test.cpp +++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp @@ -228,9 +228,9 @@ protected: void setupDequeueRequestBuffer(int *slot, sp *fence, sp *buffer) { - ASSERT_TRUE(slot != NULL); - ASSERT_TRUE(fence != NULL); - ASSERT_TRUE(buffer != NULL); + ASSERT_TRUE(slot != nullptr); + ASSERT_TRUE(fence != nullptr); + ASSERT_TRUE(buffer != nullptr); ASSERT_NO_FATAL_FAILURE(ConnectProducer()); @@ -263,7 +263,7 @@ TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) { EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, TEST_API, TEST_CONTROLLED_BY_APP, - /*output*/NULL)); + /*output*/nullptr)); // Invalid API returns bad value EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, @@ -359,7 +359,7 @@ TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) { // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP // Value was NULL - EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/NULL)); + EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/nullptr)); ASSERT_OK(mConsumer->consumerDisconnect()); @@ -465,7 +465,7 @@ TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) { // Fence was NULL { - sp nullFence = NULL; + sp nullFence = nullptr; IGraphicBufferProducer::QueueBufferInput input = QueueBufferInputBuilder().setFence(nullFence).build(); diff --git a/libs/gui/tests/MultiTextureConsumer_test.cpp b/libs/gui/tests/MultiTextureConsumer_test.cpp index 3a25ac59ca..7d3d4aa412 100644 --- a/libs/gui/tests/MultiTextureConsumer_test.cpp +++ b/libs/gui/tests/MultiTextureConsumer_test.cpp @@ -47,7 +47,7 @@ protected: GLTest::TearDown(); } virtual EGLint const* getContextAttribs() { - return NULL; + return nullptr; } virtual EGLint const* getConfigAttribs() { static EGLint sDefaultConfigAttribs[] = { @@ -105,7 +105,7 @@ TEST_F(MultiTextureConsumerTest, EGLImageTargetWorks) { glClear(GL_COLOR_BUFFER_BIT); for (int i=0 ; i<8 ; i++) { - mSurface->lock(&buffer, NULL); + mSurface->lock(&buffer, nullptr); memset(buffer.bits, (i&7) * 0x20, buffer.stride * buffer.height * 4); mSurface->unlockAndPost(); diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index d8c9bcff84..65e09f2540 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -38,7 +38,7 @@ protected: mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT), - mEglConfig(NULL) { + mEglConfig(nullptr) { } virtual void SetUp() { @@ -81,7 +81,7 @@ protected: ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_SURFACE, mEglSurface); - mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0); + mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_CONTEXT, mEglContext); @@ -126,7 +126,7 @@ protected: TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) { sp ist(mSTC->getIGraphicBufferProducer()); - ASSERT_TRUE(ist != NULL); + ASSERT_TRUE(ist != nullptr); } TEST_F(SurfaceTextureClientTest, QueuesToWindowCompositorIsFalse) { @@ -154,7 +154,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { EXPECT_TRUE(eglInitialize(dpy, &majorVersion, &minorVersion)); ASSERT_EQ(EGL_SUCCESS, eglGetError()); - EGLConfig myConfig = {0}; + EGLConfig myConfig = {nullptr}; EGLint numConfigs = 0; EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, @@ -171,7 +171,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { ASSERT_EQ(EGL_SUCCESS, eglGetError()); EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, mANW.get(), - NULL); + nullptr); EXPECT_NE(EGL_NO_SURFACE, eglSurface); EXPECT_EQ(EGL_SUCCESS, eglGetError()); @@ -184,7 +184,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { TEST_F(SurfaceTextureClientTest, EglSwapBuffersAbandonErrorIsEglBadSurface) { - EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mANW.get(), NULL); + EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mANW.get(), nullptr); EXPECT_NE(EGL_NO_SURFACE, eglSurface); EXPECT_EQ(EGL_SUCCESS, eglGetError()); @@ -738,7 +738,7 @@ protected: ASSERT_EQ(EGL_SUCCESS, eglGetError()); mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, - 0); + nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_CONTEXT, mEglContext); @@ -750,7 +750,7 @@ protected: GLConsumer::TEXTURE_EXTERNAL, true, false)); sp stc(new Surface(producer)); mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig, - static_cast(stc.get()), NULL); + static_cast(stc.get()), nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_SURFACE, mEglSurfaces[i]); } diff --git a/libs/gui/tests/SurfaceTextureFBO.h b/libs/gui/tests/SurfaceTextureFBO.h index 7f1ae84c48..70f988de11 100644 --- a/libs/gui/tests/SurfaceTextureFBO.h +++ b/libs/gui/tests/SurfaceTextureFBO.h @@ -34,7 +34,7 @@ protected: glGenTextures(1, &mFboTex); glBindTexture(GL_TEXTURE_2D, mFboTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(), - getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, 0); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp index 0134273a07..f34561f668 100644 --- a/libs/gui/tests/SurfaceTextureFBO_test.cpp +++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp @@ -39,12 +39,12 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { android_native_buffer_t* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp buf(GraphicBuffer::from(anb)); // Fill the buffer with green - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255, 0, 255); @@ -63,7 +63,7 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); buf = GraphicBuffer::from(anb); diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h index 2ce20eb2b1..03975b1261 100644 --- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h +++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h @@ -158,7 +158,7 @@ protected: } virtual void TearDown() { - if (mProducerThread != NULL) { + if (mProducerThread != nullptr) { mProducerThread->requestExitAndWait(); } mProducerThread.clear(); @@ -167,7 +167,7 @@ protected: } void runProducerThread(const sp producerThread) { - ASSERT_TRUE(mProducerThread == NULL); + ASSERT_TRUE(mProducerThread == nullptr); mProducerThread = producerThread; producerThread->setEglObjects(mEglDisplay, mProducerEglSurface, mProducerEglContext); diff --git a/libs/gui/tests/SurfaceTextureGLToGL.h b/libs/gui/tests/SurfaceTextureGLToGL.h index 5d43a48898..3a87c12cf6 100644 --- a/libs/gui/tests/SurfaceTextureGLToGL.h +++ b/libs/gui/tests/SurfaceTextureGLToGL.h @@ -38,7 +38,7 @@ protected: void SetUpWindowAndContext() { mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, - mANW.get(), NULL); + mANW.get(), nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface); diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp index 56392867ea..e2b4f3d035 100644 --- a/libs/gui/tests/SurfaceTextureGL_test.cpp +++ b/libs/gui/tests/SurfaceTextureGL_test.cpp @@ -40,12 +40,12 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp buf(GraphicBuffer::from(anb)); // Fill the buffer with the a checkerboard pattern - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); buf->unlock(); @@ -90,12 +90,12 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp buf(GraphicBuffer::from(anb)); // Fill the buffer with the a checkerboard pattern - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); buf->unlock(); @@ -155,11 +155,11 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp buf(GraphicBuffer::from(anb)); - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop); buf->unlock(); @@ -234,7 +234,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } @@ -248,7 +248,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2; int yuvTexStrideU = yuvTexStrideV; - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); // Gray out all the test pixels first, so we're more likely to @@ -457,7 +457,7 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } if (mANW->queueBuffer(mANW.get(), anb, -1) @@ -641,7 +641,7 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } if (mANW->queueBuffer(mANW.get(), anb, -1) @@ -654,7 +654,7 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } if (mANW->queueBuffer(mANW.get(), anb, -1) diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 2c02ba657d..3542aba83f 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -72,7 +72,7 @@ protected: mSurfaceControl = mComposerClient->createSurface( String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mSurfaceControl != NULL); + ASSERT_TRUE(mSurfaceControl != nullptr); ASSERT_TRUE(mSurfaceControl->isValid()); Transaction t; @@ -81,7 +81,7 @@ protected: .apply()); mSurface = mSurfaceControl->getSurface(); - ASSERT_TRUE(mSurface != NULL); + ASSERT_TRUE(mSurface != nullptr); } virtual void TearDown() { @@ -145,7 +145,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), GRALLOC_USAGE_PROTECTED)); ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); - ANativeWindowBuffer* buf = 0; + ANativeWindowBuffer* buf = nullptr; status_t err = native_window_dequeue_buffer_and_wait(anw.get(), &buf); if (err) { -- cgit v1.2.3-59-g8ed1b From f58c14b3d51f2face21c9759149b5c9412bcafd5 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 24 Jul 2018 10:50:43 -0700 Subject: blast: Append "_legacy" to old buffer state values As we move from BufferQueueLayer to BufferStateLayer, some layer state fields are used by both layer types and some are used exclusively by one type of layer. Append "_legacy" to all fields that are NOT used by BufferStateLayer. Bug: 80477568 Test: Transaction_test.cpp Change-Id: Id8bf27f5b68c00592136e4336442a5d388f35779 --- cmds/surfacereplayer/replayer/Replayer.cpp | 6 +- libs/gui/LayerState.cpp | 43 ++-- libs/gui/SurfaceComposerClient.cpp | 39 +-- libs/gui/include/gui/LayerState.h | 22 +- libs/gui/include/gui/SurfaceComposerClient.h | 17 +- services/surfaceflinger/BufferLayer.cpp | 14 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/Layer.cpp | 261 +++++++++++---------- services/surfaceflinger/Layer.h | 28 +-- services/surfaceflinger/LayerRejecter.cpp | 49 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 34 +-- services/surfaceflinger/SurfaceInterceptor.cpp | 43 ++-- .../tests/SurfaceInterceptor_test.cpp | 7 +- services/surfaceflinger/tests/Transaction_test.cpp | 78 +++--- .../tests/fakehwc/SFFakeHwc_test.cpp | 44 ++-- 15 files changed, 353 insertions(+), 336 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 4140f40888..d9ff4ba59f 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -489,7 +489,7 @@ void Replayer::setCrop(SurfaceComposerClient::Transaction& t, Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(), cc.rectangle().bottom()); - t.setCrop(mLayers[id], r); + t.setCrop_legacy(mLayers[id], r); } void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, @@ -499,7 +499,7 @@ void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, fcc.rectangle().bottom()); Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), fcc.rectangle().bottom()); - t.setFinalCrop(mLayers[id], r); + t.setFinalCrop_legacy(mLayers[id], r); } void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, @@ -570,7 +570,7 @@ void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, auto handle = mLayers[dtc.layer_id()]->getHandle(); - t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number()); + t.deferTransactionUntil_legacy(mLayers[id], handle, dtc.frame_number()); } void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 01acc2de20..0414a486e6 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -37,13 +37,13 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint32(mask); *reinterpret_cast( output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; - output.write(crop); - output.write(finalCrop); - output.writeStrongBinder(barrierHandle); + output.write(crop_legacy); + output.write(finalCrop_legacy); + output.writeStrongBinder(barrierHandle_legacy); output.writeStrongBinder(reparentHandle); - output.writeUint64(frameNumber); + output.writeUint64(frameNumber_legacy); output.writeInt32(overrideScalingMode); - output.writeStrongBinder(IInterface::asBinder(barrierGbp)); + output.writeStrongBinder(IInterface::asBinder(barrierGbp_legacy)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); output.writeFloat(color.r); @@ -72,14 +72,13 @@ status_t layer_state_t::read(const Parcel& input) } else { return BAD_VALUE; } - input.read(crop); - input.read(finalCrop); - barrierHandle = input.readStrongBinder(); + input.read(crop_legacy); + input.read(finalCrop_legacy); + barrierHandle_legacy = input.readStrongBinder(); reparentHandle = input.readStrongBinder(); - frameNumber = input.readUint64(); + frameNumber_legacy = input.readUint64(); overrideScalingMode = input.readInt32(); - barrierGbp = - interface_cast(input.readStrongBinder()); + barrierGbp_legacy = interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); color.r = input.readFloat(); @@ -194,19 +193,19 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eLayerStackChanged; layerStack = other.layerStack; } - if (other.what & eCropChanged) { - what |= eCropChanged; - crop = other.crop; + if (other.what & eCropChanged_legacy) { + what |= eCropChanged_legacy; + crop_legacy = other.crop_legacy; } - if (other.what & eDeferTransaction) { - what |= eDeferTransaction; - barrierHandle = other.barrierHandle; - barrierGbp = other.barrierGbp; - frameNumber = other.frameNumber; + if (other.what & eDeferTransaction_legacy) { + what |= eDeferTransaction_legacy; + barrierHandle_legacy = other.barrierHandle_legacy; + barrierGbp_legacy = other.barrierGbp_legacy; + frameNumber_legacy = other.frameNumber_legacy; } - if (other.what & eFinalCropChanged) { - what |= eFinalCropChanged; - finalCrop = other.finalCrop; + if (other.what & eFinalCropChanged_legacy) { + what |= eFinalCropChanged_legacy; + finalCrop_legacy = other.finalCrop_legacy; } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index fc076d2ea5..3ff0ec20ea 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -344,54 +344,57 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatri return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop_legacy( const sp& sc, const Rect& crop) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eCropChanged; - s->crop = crop; + s->what |= layer_state_t::eCropChanged_legacy; + s->crop_legacy = crop; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp& sc, const Rect& crop) { +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop_legacy( + const sp& sc, const Rect& crop) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eFinalCropChanged; - s->finalCrop = crop; + s->what |= layer_state_t::eFinalCropChanged_legacy; + s->finalCrop_legacy = crop; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( - const sp& sc, - const sp& handle, uint64_t frameNumber) { +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, + const sp& handle, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eDeferTransaction; - s->barrierHandle = handle; - s->frameNumber = frameNumber; + s->what |= layer_state_t::eDeferTransaction_legacy; + s->barrierHandle_legacy = handle; + s->frameNumber_legacy = frameNumber; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( - const sp& sc, - const sp& barrierSurface, uint64_t frameNumber) { +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, + const sp& barrierSurface, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eDeferTransaction; - s->barrierGbp = barrierSurface->getIGraphicBufferProducer(); - s->frameNumber = frameNumber; + s->what |= layer_state_t::eDeferTransaction_legacy; + s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); + s->frameNumber_legacy = frameNumber; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index a343c2f0f5..b88b7fe118 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -51,9 +51,9 @@ struct layer_state_t { eTransparentRegionChanged = 0x00000020, eFlagsChanged = 0x00000040, eLayerStackChanged = 0x00000080, - eCropChanged = 0x00000100, - eDeferTransaction = 0x00000200, - eFinalCropChanged = 0x00000400, + eCropChanged_legacy = 0x00000100, + eDeferTransaction_legacy = 0x00000200, + eFinalCropChanged_legacy = 0x00000400, eOverrideScalingModeChanged = 0x00000800, eGeometryAppliesWithResize = 0x00001000, eReparentChildren = 0x00002000, @@ -76,9 +76,9 @@ struct layer_state_t { flags(0), mask(0), reserved(0), - crop(Rect::INVALID_RECT), - finalCrop(Rect::INVALID_RECT), - frameNumber(0), + crop_legacy(Rect::INVALID_RECT), + finalCrop_legacy(Rect::INVALID_RECT), + frameNumber_legacy(0), overrideScalingMode(-1) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; @@ -107,14 +107,14 @@ struct layer_state_t { uint8_t mask; uint8_t reserved; matrix22_t matrix; - Rect crop; - Rect finalCrop; - sp barrierHandle; + Rect crop_legacy; + Rect finalCrop_legacy; + sp barrierHandle_legacy; sp reparentHandle; - uint64_t frameNumber; + uint64_t frameNumber_legacy; int32_t overrideScalingMode; - sp barrierGbp; + sp barrierGbp_legacy; sp relativeLayerHandle; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 34708c755f..278a642c91 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -200,22 +200,21 @@ public: float alpha); Transaction& setMatrix(const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy); - Transaction& setCrop(const sp& sc, const Rect& crop); - Transaction& setFinalCrop(const sp& sc, const Rect& crop); + Transaction& setCrop_legacy(const sp& sc, const Rect& crop); + Transaction& setFinalCrop_legacy(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 + Transaction& deferTransactionUntil_legacy(const sp& sc, + const sp& handle, uint64_t frameNumber); + // A variant of deferTransactionUntil_legacy 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); + Transaction& deferTransactionUntil_legacy(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); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 7246c8e890..64842450fa 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -518,7 +518,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // FIXME: postedRegion should be dirty & bounds // transform the dirty region to window-manager space - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); } // transaction @@ -641,9 +641,9 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT Transform t = getTransform(); Rect win = bounds; - if (!s.finalCrop.isEmpty()) { + if (!s.finalCrop_legacy.isEmpty()) { win = t.transform(win); - if (!win.intersect(s.finalCrop, &win)) { + if (!win.intersect(s.finalCrop_legacy, &win)) { win.clear(); } win = t.inverse().transform(win); @@ -652,10 +652,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT } } - float left = float(win.left) / float(s.active.w); - float top = float(win.top) / float(s.active.h); - float right = float(win.right) / float(s.active.w); - float bottom = float(win.bottom) / float(s.active.h); + float left = float(win.left) / float(s.active_legacy.w); + float top = float(win.top) / float(s.active_legacy.h); + float right = float(win.right) / float(s.active_legacy.w); + float bottom = float(win.bottom) / float(s.active_legacy.h); // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d5a94b7c6a..1bf9cf275b 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -38,7 +38,7 @@ BufferQueueLayer::BufferQueueLayer(SurfaceFlinger* flinger, const sp& cl mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mQueuedFrames(0), mSidebandStreamChanged(false) { - mCurrentState.requested = mCurrentState.active; + mCurrentState.requested_legacy = mCurrentState.active_legacy; } // ----------------------------------------------------------------------- @@ -219,7 +219,7 @@ std::optional BufferQueueLayer::latchSidebandStream(bool& recomputeVisib recomputeVisibleRegions = true; const State& s(getDrawingState()); - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); } return {}; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b58269eb32..eeee0ae863 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -99,19 +99,19 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mName = name; mTransactionName = String8("TX - ") + mName; - mCurrentState.active.w = w; - mCurrentState.active.h = h; + mCurrentState.active_legacy.w = w; + mCurrentState.active_legacy.h = h; mCurrentState.flags = layerFlags; - mCurrentState.active.transform.set(0, 0); - mCurrentState.crop.makeInvalid(); - mCurrentState.finalCrop.makeInvalid(); - mCurrentState.requestedFinalCrop = mCurrentState.finalCrop; - mCurrentState.requestedCrop = mCurrentState.crop; + mCurrentState.active_legacy.transform.set(0, 0); + mCurrentState.crop_legacy.makeInvalid(); + mCurrentState.finalCrop_legacy.makeInvalid(); + mCurrentState.requestedFinalCrop_legacy = mCurrentState.finalCrop_legacy; + mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy; mCurrentState.z = 0; mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; mCurrentState.sequence = 0; - mCurrentState.requested = mCurrentState.active; + mCurrentState.requested_legacy = mCurrentState.active_legacy; mCurrentState.appId = 0; mCurrentState.type = 0; @@ -293,17 +293,17 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active.w, s.active.h); + Rect win(s.active_legacy.w, s.active_legacy.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + if (!s.crop_legacy.isEmpty()) { + win.intersect(s.crop_legacy, &win); } Transform t = getTransform(); win = t.transform(win); - if (!s.finalCrop.isEmpty()) { - win.intersect(s.finalCrop, &win); + if (!s.finalCrop_legacy.isEmpty()) { + win.intersect(s.finalCrop_legacy, &win); } const sp& p = mDrawingParent.promote(); @@ -322,7 +322,7 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { } if (reduceTransparentRegion) { - auto const screenTransparentRegion = t.transform(s.activeTransparentRegion); + auto const screenTransparentRegion = t.transform(s.activeTransparentRegion_legacy); win = reduce(win, screenTransparentRegion); } @@ -331,15 +331,15 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { FloatRect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); - return computeBounds(s.activeTransparentRegion); + return computeBounds(s.activeTransparentRegion_legacy); } FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active.w, s.active.h); + Rect win(s.active_legacy.w, s.active_legacy.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + if (!s.crop_legacy.isEmpty()) { + win.intersect(s.crop_legacy, &win); } const auto& p = mDrawingParent.promote(); @@ -351,15 +351,14 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { parentBounds = p->computeBounds(Region()); } - Transform t = s.active.transform; + Transform t = s.active_legacy.transform; - - if (p != nullptr || !s.finalCrop.isEmpty()) { + if (p != nullptr || !s.finalCrop_legacy.isEmpty()) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); - if (!s.finalCrop.isEmpty()) { - floatWin = floatWin.intersect(s.finalCrop.toFloatRect()); + if (!s.finalCrop_legacy.isEmpty()) { + floatWin = floatWin.intersect(s.finalCrop_legacy.toFloatRect()); } floatWin = t.inverse().transform(floatWin); } @@ -380,9 +379,9 @@ Rect Layer::computeInitialCrop(const sp& display) const { // FIXME: the 3 lines below can produce slightly incorrect clipping when we have // a viewport clipping and a window transform. we should use floating point to fix this. - Rect activeCrop(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - activeCrop.intersect(s.crop, &activeCrop); + Rect activeCrop(s.active_legacy.w, s.active_legacy.h); + if (!s.crop_legacy.isEmpty()) { + activeCrop.intersect(s.crop_legacy, &activeCrop); } Transform t = getTransform(); @@ -390,8 +389,8 @@ Rect Layer::computeInitialCrop(const sp& display) const { if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - if (!s.finalCrop.isEmpty()) { - if (!activeCrop.intersect(s.finalCrop, &activeCrop)) { + if (!s.finalCrop_legacy.isEmpty()) { + if (!activeCrop.intersect(s.finalCrop_legacy, &activeCrop)) { activeCrop.clear(); } } @@ -425,12 +424,12 @@ FloatRect Layer::computeCrop(const sp& display) const { // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(s.active_legacy.w, s.active_legacy.h), &activeCrop)) { activeCrop.clear(); } // subtract the transparent region and snap to the bounds - activeCrop = reduce(activeCrop, s.activeTransparentRegion); + activeCrop = reduce(activeCrop, s.activeTransparentRegion_legacy); // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -450,8 +449,8 @@ FloatRect Layer::computeCrop(const sp& display) const { invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } - int winWidth = s.active.w; - int winHeight = s.active.h; + int winWidth = s.active_legacy.w; + int winHeight = s.active_legacy.h; if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { // If the activeCrop has been rotate the ends are rotated but not // the space itself so when transforming ends back we can't rely on @@ -463,10 +462,10 @@ FloatRect Layer::computeCrop(const sp& display) const { if (is_h_flipped == is_v_flipped) { invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - winWidth = s.active.h; - winHeight = s.active.w; + winWidth = s.active_legacy.h; + winHeight = s.active_legacy.w; } - const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h); + const Rect winCrop = activeCrop.transform(invTransform, s.active_legacy.w, s.active_legacy.h); // below, crop is intersected with winCrop expressed in crop's coordinate space float xScale = crop.getWidth() / float(winWidth); @@ -519,10 +518,10 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Region activeTransparentRegion(s.activeTransparentRegion); + Region activeTransparentRegion(s.activeTransparentRegion_legacy); Transform t = getTransform(); - if (!s.crop.isEmpty()) { - Rect activeCrop(s.crop); + if (!s.crop_legacy.isEmpty()) { + Rect activeCrop(s.crop_legacy); activeCrop = t.transform(activeCrop); if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); @@ -534,22 +533,23 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(s.active_legacy.w, s.active_legacy.h), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent - activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top)); - activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h)); + activeTransparentRegion.orSelf(Rect(0, 0, s.active_legacy.w, activeCrop.top)); + activeTransparentRegion.orSelf( + Rect(0, activeCrop.bottom, s.active_legacy.w, s.active_legacy.h)); activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); activeTransparentRegion.orSelf( - Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); + Rect(activeCrop.right, activeCrop.top, s.active_legacy.w, activeCrop.bottom)); } // computeBounds returns a FloatRect to provide more accuracy during the // transformation. We then round upon constructing 'frame'. Rect frame{t.transform(computeBounds(activeTransparentRegion))}; - if (!s.finalCrop.isEmpty()) { - if (!frame.intersect(s.finalCrop, &frame)) { + if (!s.finalCrop_legacy.isEmpty()) { + if (!frame.intersect(s.finalCrop_legacy, &frame)) { frame.clear(); } } @@ -682,16 +682,16 @@ void Layer::updateCursorPosition(const sp& display) { // Apply the layer's transform, followed by the display's global transform // Here we're guaranteed that the layer's transform preserves rects - Rect win(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + Rect win(s.active_legacy.w, s.active_legacy.h); + if (!s.crop_legacy.isEmpty()) { + win.intersect(s.crop_legacy, &win); } // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion); + Rect bounds = reduce(win, s.activeTransparentRegion_legacy); Rect frame(getTransform().transform(bounds)); frame.intersect(display->getViewport(), &frame); - if (!s.finalCrop.isEmpty()) { - frame.intersect(s.finalCrop, &frame); + if (!s.finalCrop_legacy.isEmpty()) { + frame.intersect(s.finalCrop_legacy, &frame); } auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); @@ -844,11 +844,11 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, rt = layerTransform.transform(rt); } - if (!s.finalCrop.isEmpty()) { - boundPoint(<, s.finalCrop); - boundPoint(&lb, s.finalCrop); - boundPoint(&rb, s.finalCrop); - boundPoint(&rt, s.finalCrop); + if (!s.finalCrop_legacy.isEmpty()) { + boundPoint(<, s.finalCrop_legacy); + boundPoint(&lb, s.finalCrop_legacy); + boundPoint(&rb, s.finalCrop_legacy); + boundPoint(&rt, s.finalCrop_legacy); } Mesh::VertexArray position(mesh.getPositionArray()); @@ -898,22 +898,22 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - if (mCurrentState.barrierLayer != nullptr) { - sp barrierLayer = mCurrentState.barrierLayer.promote(); + if (mCurrentState.barrierLayer_legacy != nullptr) { + sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). - mCurrentState.barrierLayer = nullptr; + mCurrentState.barrierLayer_legacy = nullptr; } else { - auto syncPoint = std::make_shared(mCurrentState.frameNumber); + auto syncPoint = std::make_shared(mCurrentState.frameNumber_legacy); if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { // We already missed the frame we're supposed to synchronize // on, so go ahead and apply the state update - mCurrentState.barrierLayer = nullptr; + mCurrentState.barrierLayer_legacy = nullptr; } } @@ -935,7 +935,7 @@ void Layer::popPendingState(State* stateToCommit) { bool Layer::applyPendingStates(State* stateToCommit) { bool stateUpdateAvailable = false; while (!mPendingStates.empty()) { - if (mPendingStates[0].barrierLayer != nullptr) { + if (mPendingStates[0].barrierLayer_legacy != nullptr) { if (mRemoteSyncPoints.empty()) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting @@ -946,7 +946,8 @@ bool Layer::applyPendingStates(State* stateToCommit) { continue; } - if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) { + if (mRemoteSyncPoints.front()->getFrameNumber() != + mPendingStates[0].frameNumber_legacy) { ALOGE("[%s] Unexpected sync point frame number found", mName.string()); // Signal our end of the sync point and then dispose of it @@ -994,7 +995,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& s(getDrawingState()); - const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); + const bool sizeChanged = (c.requested_legacy.w != s.requested_legacy.w) || + (c.requested_legacy.h != s.requested_legacy.h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer @@ -1004,16 +1006,17 @@ uint32_t Layer::doTransaction(uint32_t flags) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, - getEffectiveScalingMode(), c.active.w, c.active.h, c.crop.left, c.crop.top, - c.crop.right, c.crop.bottom, c.crop.getWidth(), c.crop.getHeight(), c.requested.w, - c.requested.h, s.active.w, s.active.h, s.crop.left, s.crop.top, s.crop.right, - s.crop.bottom, s.crop.getWidth(), s.crop.getHeight(), s.requested.w, - s.requested.h); + this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), + c.active_legacy.w, c.active_legacy.h, c.crop_legacy.left, c.crop_legacy.top, + c.crop_legacy.right, c.crop_legacy.bottom, c.crop_legacy.getWidth(), + c.crop_legacy.getHeight(), c.requested_legacy.w, c.requested_legacy.h, + s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, + s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), + s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(c.requested.w, c.requested.h); + setDefaultBufferSize(c.requested_legacy.w, c.requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1034,7 +1037,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { // resizePending state is to avoid applying the state of the new buffer // to the old buffer. However in the state where we don't have an old buffer // there is no such concern but we may still be being used as a parent layer. - const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && + const bool resizePending = ((c.requested_legacy.w != c.active_legacy.w) || + (c.requested_legacy.h != c.active_legacy.h)) && (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { @@ -1061,18 +1065,18 @@ uint32_t Layer::doTransaction(uint32_t flags) { // Careful that "c" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. if (mFreezeGeometryUpdates) { - float tx = c.active.transform.tx(); - float ty = c.active.transform.ty(); - c.active = c.requested; - c.active.transform.set(tx, ty); - editCurrentState.active = c.active; + float tx = c.active_legacy.transform.tx(); + float ty = c.active_legacy.transform.ty(); + c.active_legacy = c.requested_legacy; + c.active_legacy.transform.set(tx, ty); + editCurrentState.active_legacy = c.active_legacy; } else { - editCurrentState.active = editCurrentState.requested; - c.active = c.requested; + editCurrentState.active_legacy = editCurrentState.requested_legacy; + c.active_legacy = c.requested_legacy; } } - if (s.active != c.active) { + if (s.active_legacy != c.active_legacy) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } @@ -1083,8 +1087,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { this->contentDirty = true; // we may use linear filtering, if the matrix scales us - const uint8_t type = c.active.transform.getType(); - mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE)); + const uint8_t type = c.active_legacy.transform.getType(); + mNeedsFiltering = + (!c.active_legacy.transform.preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1112,20 +1117,21 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { } bool Layer::setPosition(float x, float y, bool immediate) { - if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y) + if (mCurrentState.requested_legacy.transform.tx() == x && + mCurrentState.requested_legacy.transform.ty() == y) return false; mCurrentState.sequence++; // We update the requested and active position simultaneously because // we want to apply the position portion of the transform matrix immediately, // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. - mCurrentState.requested.transform.set(x, y); + mCurrentState.requested_legacy.transform.set(x, y); if (immediate && !mFreezeGeometryUpdates) { // Here we directly update the active state // unlike other setters, because we store it within // the transform, but use different latching rules. // b/38182305 - mCurrentState.active.transform.set(x, y); + mCurrentState.active_legacy.transform.set(x, y); } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1225,9 +1231,10 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; - mCurrentState.requested.w = w; - mCurrentState.requested.h = h; + if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h) + return false; + mCurrentState.requested_legacy.w = w; + mCurrentState.requested_legacy.h = h; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1265,13 +1272,14 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, return false; } mCurrentState.sequence++; - mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, + matrix.dsdy); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setTransparentRegionHint(const Region& transparent) { - mCurrentState.requestedTransparentRegion = transparent; + mCurrentState.requestedTransparentRegion_legacy = transparent; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1286,12 +1294,12 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { return true; } -bool Layer::setCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedCrop == crop) return false; +bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { + if (mCurrentState.requestedCrop_legacy == crop) return false; mCurrentState.sequence++; - mCurrentState.requestedCrop = crop; + mCurrentState.requestedCrop_legacy = crop; if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.crop = crop; + mCurrentState.crop_legacy = crop; } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1300,12 +1308,12 @@ bool Layer::setCrop(const Rect& crop, bool immediate) { return true; } -bool Layer::setFinalCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop == crop) return false; +bool Layer::setFinalCrop_legacy(const Rect& crop, bool immediate) { + if (mCurrentState.requestedFinalCrop_legacy == crop) return false; mCurrentState.sequence++; - mCurrentState.requestedFinalCrop = crop; + mCurrentState.requestedFinalCrop_legacy = crop; if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.finalCrop = crop; + mCurrentState.finalCrop_legacy = crop; } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1345,24 +1353,23 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } -void Layer::deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber) { - mCurrentState.barrierLayer = barrierLayer; - mCurrentState.frameNumber = frameNumber; +void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { + mCurrentState.barrierLayer_legacy = barrierLayer; + mCurrentState.frameNumber_legacy = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral // request without any other state updates shouldn't actually induce a delay mCurrentState.modified = true; pushPendingState(); - mCurrentState.barrierLayer = nullptr; - mCurrentState.frameNumber = 0; + mCurrentState.barrierLayer_legacy = nullptr; + mCurrentState.frameNumber_legacy = 0; mCurrentState.modified = false; } -void Layer::deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber) { +void Layer::deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber) { sp handle = static_cast(barrierHandle.get()); - deferTransactionUntil(handle->owner.promote(), frameNumber); + deferTransactionUntil_legacy(handle->owner.promote(), frameNumber); } - // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- @@ -1415,25 +1422,25 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { sp parent = getParent(); info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); info.mType = String8(getTypeId()); - info.mTransparentRegion = ds.activeTransparentRegion; + info.mTransparentRegion = ds.activeTransparentRegion_legacy; info.mVisibleRegion = visibleRegion; info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); - info.mX = ds.active.transform.tx(); - info.mY = ds.active.transform.ty(); + info.mX = ds.active_legacy.transform.tx(); + info.mY = ds.active_legacy.transform.ty(); info.mZ = ds.z; - info.mWidth = ds.active.w; - info.mHeight = ds.active.h; - info.mCrop = ds.crop; - info.mFinalCrop = ds.finalCrop; + info.mWidth = ds.active_legacy.w; + info.mHeight = ds.active_legacy.h; + info.mCrop = ds.crop_legacy; + info.mFinalCrop = ds.finalCrop_legacy; info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); info.mDataSpace = static_cast(mCurrentDataSpace); - info.mMatrix[0][0] = ds.active.transform[0][0]; - info.mMatrix[0][1] = ds.active.transform[0][1]; - info.mMatrix[1][0] = ds.active.transform[1][0]; - info.mMatrix[1][1] = ds.active.transform[1][1]; + info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; + info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; + info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; + info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { sp buffer = mActiveBuffer; if (buffer != 0) { @@ -1882,14 +1889,14 @@ Transform Layer::getTransform() const { bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } - float sx = p->getDrawingState().active.w / static_cast(bufferWidth); - float sy = p->getDrawingState().active.h / static_cast(bufferHeight); + float sx = p->getDrawingState().active_legacy.w / static_cast(bufferWidth); + float sy = p->getDrawingState().active_legacy.h / static_cast(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; } } - return t * getDrawingState().active.transform; + return t * getDrawingState().active_legacy.transform; } half Layer::getAlpha() const { @@ -1918,7 +1925,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - Transform requestedTransform = state.active.transform; + Transform requestedTransform = state.active_legacy.transform; Transform transform = getTransform(); layerInfo->set_id(sequence); @@ -1936,7 +1943,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) } } - LayerProtoHelper::writeToProto(state.activeTransparentRegion, + LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy, layerInfo->mutable_transparent_region()); LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region()); LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region()); @@ -1953,11 +1960,11 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) requestedPosition->set_y(requestedTransform.ty()); SizeProto* size = layerInfo->mutable_size(); - size->set_w(state.active.w); - size->set_h(state.active.h); + size->set_w(state.active_legacy.w); + size->set_h(state.active_legacy.h); - LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop()); - LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop()); + LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop()); + LayerProtoHelper::writeToProto(state.finalCrop_legacy, layerInfo->mutable_final_crop()); layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); @@ -1998,11 +2005,11 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_curr_frame(mCurrentFrameNumber); for (const auto& pendingState : mPendingStates) { - auto barrierLayer = pendingState.barrierLayer.promote(); + auto barrierLayer = pendingState.barrierLayer_legacy.promote(); if (barrierLayer != nullptr) { BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.frameNumber); + barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); } } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 94f086cafe..96ec84b269 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -111,8 +111,8 @@ public: }; struct State { - Geometry active; - Geometry requested; + Geometry active_legacy; + Geometry requested_legacy; int32_t z; // The identifier of the layer stack this layer belongs to. A layer can @@ -128,23 +128,23 @@ public: bool modified; // Crop is expressed in layer space coordinate. - Rect crop; - Rect requestedCrop; + Rect crop_legacy; + Rect requestedCrop_legacy; // finalCrop is expressed in display space coordinate. - Rect finalCrop; - Rect requestedFinalCrop; + Rect finalCrop_legacy; + Rect requestedFinalCrop_legacy; // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber - wp barrierLayer; - uint64_t frameNumber; + wp barrierLayer_legacy; + uint64_t frameNumber_legacy; // the transparentRegion hint is a bit special, it's latched only // when we receive a buffer -- this is because it's "content" // dependent. - Region activeTransparentRegion; - Region requestedTransparentRegion; + Region activeTransparentRegion_legacy; + Region requestedTransparentRegion_legacy; int32_t appId; int32_t type; @@ -207,9 +207,9 @@ public: // space for top-level layers. bool setPosition(float x, float y, bool immediate); // Buffer space - bool setCrop(const Rect& crop, bool immediate); + bool setCrop_legacy(const Rect& crop, bool immediate); // Parent buffer space/display space - bool setFinalCrop(const Rect& crop, bool immediate); + bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? @@ -223,8 +223,8 @@ public: bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); uint32_t getLayerStack() const; - void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); - void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); + void deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber); + void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(int32_t type, int32_t appId); bool reparentChildren(const sp& layer); diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 381ea4aad3..fd0ca822c6 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -65,20 +65,21 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode; bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; - if (mFront.active != mFront.requested) { - if (isFixedSize || (bufWidth == mFront.requested.w && bufHeight == mFront.requested.h)) { + if (mFront.active_legacy != mFront.requested_legacy) { + if (isFixedSize || + (bufWidth == mFront.requested_legacy.w && bufHeight == mFront.requested_legacy.h)) { // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed // in this thread, no need to have it locked - mFront.active = mFront.requested; + mFront.active_legacy = mFront.requested_legacy; // We also need to update the current state so that // we don't end-up overwriting the drawing state with // this stale current state during the next transaction // // NOTE: We don't need to hold the transaction lock here - // because State::active is only accessed from this thread. - mCurrent.active = mFront.active; + // because State::active_legacy is only accessed from this thread. + mCurrent.active_legacy = mFront.active_legacy; mCurrent.modified = true; // recompute visible region @@ -86,14 +87,14 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) mFreezeGeometryUpdates = false; - if (mFront.crop != mFront.requestedCrop) { - mFront.crop = mFront.requestedCrop; - mCurrent.crop = mFront.requestedCrop; + if (mFront.crop_legacy != mFront.requestedCrop_legacy) { + mFront.crop_legacy = mFront.requestedCrop_legacy; + mCurrent.crop_legacy = mFront.requestedCrop_legacy; mRecomputeVisibleRegions = true; } - if (mFront.finalCrop != mFront.requestedFinalCrop) { - mFront.finalCrop = mFront.requestedFinalCrop; - mCurrent.finalCrop = mFront.requestedFinalCrop; + if (mFront.finalCrop_legacy != mFront.requestedFinalCrop_legacy) { + mFront.finalCrop_legacy = mFront.requestedFinalCrop_legacy; + mCurrent.finalCrop_legacy = mFront.requestedFinalCrop_legacy; mRecomputeVisibleRegions = true; } } @@ -102,19 +103,20 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) " "}\n" - " requested={ wh={%4u,%4u} }}\n", - mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active.w, - mFront.active.h, mFront.crop.left, mFront.crop.top, mFront.crop.right, - mFront.crop.bottom, mFront.crop.getWidth(), mFront.crop.getHeight(), - mFront.requested.w, mFront.requested.h); + " requested_legacy={ wh={%4u,%4u} }}\n", + mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, + mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left, + mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom, + mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(), + mFront.requested_legacy.w, mFront.requested_legacy.h); } if (!isFixedSize && !mStickyTransformSet) { - if (mFront.active.w != bufWidth || mFront.active.h != bufHeight) { + if (mFront.active_legacy.w != bufWidth || mFront.active_legacy.h != bufHeight) { // reject this buffer ALOGE("[%s] rejecting buffer: " - "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}", - mName, bufWidth, bufHeight, mFront.active.w, mFront.active.h); + "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}", + mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h); return true; } } @@ -127,16 +129,17 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // We latch the transparent region here, instead of above where we latch // the rest of the geometry because it is only content but not necessarily // resize dependent. - if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) { - mFront.activeTransparentRegion = mFront.requestedTransparentRegion; + if (!mFront.activeTransparentRegion_legacy.isTriviallyEqual( + mFront.requestedTransparentRegion_legacy)) { + mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy; // We also need to update the current state so that // we don't end-up overwriting the drawing state with // this stale current state during the next transaction // // NOTE: We don't need to hold the transaction lock here - // because State::active is only accessed from this thread. - mCurrent.activeTransparentRegion = mFront.activeTransparentRegion; + // because State::active_legacy is only accessed from this thread. + mCurrent.activeTransparentRegion_legacy = mFront.activeTransparentRegion_legacy; // recompute visible region mRecomputeVisibleRegions = true; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 64520d0979..64f1eaf463 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2766,7 +2766,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa if (translucent) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.activeTransparentRegion); + transparentRegion = tr.transform(s.activeTransparentRegion_legacy); } else { // transformation too complex, can't do the // transparent region optimization. @@ -3400,7 +3400,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState // If we are deferring transaction, make sure to push the pending state, as otherwise the // pending state will also be deferred. - if (what & layer_state_t::eDeferTransaction) { + if (what & layer_state_t::eDeferTransaction_legacy) { layer->pushPendingState(); } @@ -3485,12 +3485,12 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setFlags(s.flags, s.mask)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eCropChanged) { - if (layer->setCrop(s.crop, !geometryAppliesWithResize)) + if (what & layer_state_t::eCropChanged_legacy) { + if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFinalCropChanged) { - if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize)) + if (what & layer_state_t::eFinalCropChanged_legacy) { + if (layer->setFinalCrop_legacy(s.finalCrop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } if (what & layer_state_t::eLayerStackChanged) { @@ -3512,15 +3512,15 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState flags |= eTransactionNeeded|eTraversalNeeded|eDisplayLayerStackChanged; } } - if (what & layer_state_t::eDeferTransaction) { - if (s.barrierHandle != nullptr) { - layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); - } else if (s.barrierGbp != nullptr) { - const sp& gbp = s.barrierGbp; + if (what & layer_state_t::eDeferTransaction_legacy) { + if (s.barrierHandle_legacy != nullptr) { + layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.frameNumber_legacy); + } else if (s.barrierGbp_legacy != nullptr) { + const sp& gbp = s.barrierGbp_legacy; if (authenticateSurfaceTextureLocked(gbp)) { const auto& otherLayer = (static_cast(gbp.get()))->getLayer(); - layer->deferTransactionUntil(otherLayer, s.frameNumber); + layer->deferTransactionUntil_legacy(otherLayer, s.frameNumber_legacy); } else { ALOGE("Attempt to defer transaction to to an" " unrecognized GraphicBufferProducer"); @@ -4864,10 +4864,10 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, const Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); - return Rect(layerState.active.w, layerState.active.h); + return Rect(layerState.active_legacy.w, layerState.active_legacy.h); } - int getHeight() const override { return mLayer->getDrawingState().active.h; } - int getWidth() const override { return mLayer->getDrawingState().active.w; } + int getHeight() const override { return mLayer->getDrawingState().active_legacy.h; } + int getWidth() const override { return mLayer->getDrawingState().active_legacy.w; } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } Rect getSourceCrop() const override { @@ -4935,12 +4935,12 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; - crop.right = parent->getCurrentState().active.w; + crop.right = parent->getCurrentState().active_legacy.w; } if (sourceCrop.height() <= 0) { crop.top = 0; - crop.bottom = parent->getCurrentState().active.h; + crop.bottom = parent->getCurrentState().active_legacy.h; } int32_t reqWidth = crop.width() * frameScale; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index e70506daac..c42213a28d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -99,18 +99,20 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); - addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), - layer->mCurrentState.active.transform.ty()); + addPositionLocked(transaction, layerId, layer->mCurrentState.active_legacy.transform.tx(), + layer->mCurrentState.active_legacy.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a); - addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); + addTransparentRegionLocked(transaction, layerId, + layer->mCurrentState.activeTransparentRegion_legacy); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); - addCropLocked(transaction, layerId, layer->mCurrentState.crop); - if (layer->mCurrentState.barrierLayer != nullptr) { - addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer.promote(), - layer->mCurrentState.frameNumber); + addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy); + if (layer->mCurrentState.barrierLayer_legacy != nullptr) { + addDeferTransactionLocked(transaction, layerId, + layer->mCurrentState.barrierLayer_legacy.promote(), + layer->mCurrentState.frameNumber_legacy); } - addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop); + addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop_legacy); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } @@ -353,25 +355,26 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eLayerStackChanged) { addLayerStackLocked(transaction, layerId, state.layerStack); } - if (state.what & layer_state_t::eCropChanged) { - addCropLocked(transaction, layerId, state.crop); + if (state.what & layer_state_t::eCropChanged_legacy) { + addCropLocked(transaction, layerId, state.crop_legacy); } - if (state.what & layer_state_t::eDeferTransaction) { + if (state.what & layer_state_t::eDeferTransaction_legacy) { sp otherLayer = nullptr; - if (state.barrierHandle != nullptr) { - otherLayer = static_cast(state.barrierHandle.get())->owner.promote(); - } else if (state.barrierGbp != nullptr) { - auto const& gbp = state.barrierGbp; + if (state.barrierHandle_legacy != nullptr) { + otherLayer = + static_cast(state.barrierHandle_legacy.get())->owner.promote(); + } else if (state.barrierGbp_legacy != nullptr) { + auto const& gbp = state.barrierGbp_legacy; if (mFlinger->authenticateSurfaceTextureLocked(gbp)) { otherLayer = (static_cast(gbp.get()))->getLayer(); } else { ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); } } - addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber); + addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); } - if (state.what & layer_state_t::eFinalCropChanged) { - addFinalCropLocked(transaction, layerId, state.finalCrop); + if (state.what & layer_state_t::eFinalCropChanged_legacy) { + addFinalCropLocked(transaction, layerId, state.finalCrop_legacy); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); @@ -422,8 +425,8 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); creation->set_name(getLayerName(layer)); - creation->set_w(layer->mCurrentState.active.w); - creation->set_h(layer->mCurrentState.active.h); + creation->set_w(layer->mCurrentState.active_legacy.w); + creation->set_h(layer->mCurrentState.active_legacy.h); } void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment, diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 135d2afea2..8ac2c87b9e 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -320,11 +320,11 @@ void SurfaceInterceptorTest::layerUpdate(Transaction& t) { } void SurfaceInterceptorTest::cropUpdate(Transaction& t) { - t.setCrop(mBGSurfaceControl, CROP_UPDATE); + t.setCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) { - t.setFinalCrop(mBGSurfaceControl, CROP_UPDATE); + t.setFinalCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { @@ -357,7 +357,8 @@ void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) { } void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { - t.deferTransactionUntil(mBGSurfaceControl, mBGSurfaceControl->getHandle(), DEFERRED_UPDATE); + t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl->getHandle(), + DEFERRED_UPDATE); } void SurfaceInterceptorTest::displayCreation(Transaction&) { diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 5108279043..2ce32b5967 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1188,7 +1188,7 @@ TEST_F(LayerTransactionTest, SetCropBasic) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); const Rect crop(8, 8, 24, 24); - Transaction().setCrop(layer, crop).apply(); + Transaction().setCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop, Color::RED); shot->expectBorder(crop, Color::BLACK); @@ -1201,13 +1201,13 @@ TEST_F(LayerTransactionTest, SetCropEmpty) { { SCOPED_TRACE("empty rect"); - Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); + Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); - Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); + Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1217,7 +1217,7 @@ TEST_F(LayerTransactionTest, SetCropOutOfBounds) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply(); + Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); shot->expectColor(Rect(0, 0, 32, 32), Color::RED); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); @@ -1230,7 +1230,7 @@ TEST_F(LayerTransactionTest, SetCropWithTranslation) { const Point position(32, 32); const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply(); + Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop + position, Color::RED); shot->expectBorder(crop + position, Color::BLACK); @@ -1244,7 +1244,7 @@ TEST_F(LayerTransactionTest, SetCropWithScale) { // crop is affected by matrix Transaction() .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setCrop(layer, Rect(8, 8, 24, 24)) + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) .apply(); auto shot = screenshot(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1256,8 +1256,8 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - // setCrop is applied immediately by default, with or without resize pending - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); @@ -1279,14 +1279,17 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - // request setCrop to be applied with the next resize - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); + // request setCrop_legacy to be applied with the next resize + Transaction() + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) + .setGeometryAppliesWithResize(layer) + .apply(); { SCOPED_TRACE("waiting for next resize"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } - Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); + Transaction().setCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); { SCOPED_TRACE("pending crop modified"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); @@ -1313,9 +1316,9 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - // setCrop is not immediate even with SCALE_TO_WINDOW override + // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override Transaction() - .setCrop(layer, Rect(4, 4, 12, 12)) + .setCrop_legacy(layer, Rect(4, 4, 12, 12)) .setSize(layer, 16, 16) .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) .setGeometryAppliesWithResize(layer) @@ -1346,7 +1349,7 @@ TEST_F(LayerTransactionTest, SetFinalCropBasic) { const Rect crop(8, 8, 24, 24); // same as in SetCropBasic - Transaction().setFinalCrop(layer, crop).apply(); + Transaction().setFinalCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop, Color::RED); shot->expectBorder(crop, Color::BLACK); @@ -1360,13 +1363,13 @@ TEST_F(LayerTransactionTest, SetFinalCropEmpty) { // same as in SetCropEmpty { SCOPED_TRACE("empty rect"); - Transaction().setFinalCrop(layer, Rect(8, 8, 8, 8)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); - Transaction().setFinalCrop(layer, Rect(8, 8, 0, 0)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1377,7 +1380,7 @@ TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); // same as in SetCropOutOfBounds - Transaction().setFinalCrop(layer, Rect(-128, -64, 128, 64)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); shot->expectColor(Rect(0, 0, 32, 32), Color::RED); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); @@ -1389,7 +1392,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); // final crop is applied post-translation - Transaction().setPosition(layer, 16, 16).setFinalCrop(layer, Rect(8, 8, 24, 24)).apply(); + Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); auto shot = screenshot(); shot->expectColor(Rect(16, 16, 24, 24), Color::RED); shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); @@ -1403,7 +1406,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithScale) { // final crop is not affected by matrix Transaction() .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setFinalCrop(layer, Rect(8, 8, 24, 24)) + .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) .apply(); auto shot = screenshot(); shot->expectColor(Rect(8, 8, 24, 24), Color::RED); @@ -1416,7 +1419,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); // same as in SetCropWithResize - Transaction().setFinalCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); @@ -1440,7 +1443,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { // same as in SetCropWithNextResize Transaction() - .setFinalCrop(layer, Rect(8, 8, 24, 24)) + .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) .setGeometryAppliesWithResize(layer) .apply(); { @@ -1448,7 +1451,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } - Transaction().setFinalCrop(layer, Rect(4, 4, 12, 12)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); { SCOPED_TRACE("pending final crop modified"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); @@ -1477,7 +1480,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { // same as in SetCropWithNextResizeScaleToWindow Transaction() - .setFinalCrop(layer, Rect(4, 4, 12, 12)) + .setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)) .setSize(layer, 16, 16) .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) .setGeometryAppliesWithResize(layer) @@ -1649,8 +1652,8 @@ protected: 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)); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); }); EXPECT_INITIAL_STATE("After restoring initial state"); @@ -1686,7 +1689,7 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { // Normally the crop applies immediately even while a resize is pending. asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 128); - t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); }); EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); @@ -1700,7 +1703,7 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 128); t.setGeometryAppliesWithResize(mFGSurfaceControl); - t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); }); EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); @@ -1729,14 +1732,14 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { // set up two deferred transactions on different frames asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.75); - t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber()); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber()); }); asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 128, 128); - t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); }); { @@ -1881,7 +1884,7 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { t.show(mChild); t.setPosition(mChild, 0, 0); t.setPosition(mFGSurfaceControl, 0, 0); - t.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); }); { @@ -1897,7 +1900,7 @@ TEST_F(ChildLayerTest, ChildLayerFinalCropping) { t.show(mChild); t.setPosition(mChild, 0, 0); t.setPosition(mFGSurfaceControl, 0, 0); - t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); }); { @@ -2166,8 +2169,8 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction asTransaction([&](Transaction& t) { - t.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); + t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); t.show(mChild); }); @@ -2465,8 +2468,9 @@ TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { } TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { - - SurfaceComposerClient::Transaction().setCrop(mFGSurfaceControl, Rect(0, 0, 1, 1)).apply(true); + SurfaceComposerClient::Transaction() + .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1)) + .apply(true); // Even though the parent is cropped out we should still capture the child. verify(); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 070bd51802..7fafab9302 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -624,7 +624,7 @@ TEST_F(TransactionTest, LayerCrop) { { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setCrop(mFGSurfaceControl, cropRect); + ts.setCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -639,7 +639,7 @@ TEST_F(TransactionTest, LayerFinalCrop) { { TransactionScope ts(*sFakeComposer); Rect cropRect(32, 32, 32 + 64, 32 + 64); - ts.setFinalCrop(mFGSurfaceControl, cropRect); + ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -657,7 +657,7 @@ TEST_F(TransactionTest, LayerFinalCropEmpty) { { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setFinalCrop(mFGSurfaceControl, cropRect); + ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -847,18 +847,16 @@ TEST_F(TransactionTest, DeferredTransaction) { { TransactionScope ts(*sFakeComposer); ts.setAlpha(mFGSurfaceControl, 0.75); - ts.deferTransactionUntil(mFGSurfaceControl, - syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber()); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber()); } EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { TransactionScope ts(*sFakeComposer); ts.setPosition(mFGSurfaceControl, 128, 128); - ts.deferTransactionUntil(mFGSurfaceControl, - syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); } EXPECT_EQ(4, sFakeComposer->getFrameCount()); EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); @@ -981,7 +979,7 @@ TEST_F(ChildLayerTest, Cropping) { ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setCrop_legacy(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 @@ -1000,7 +998,7 @@ TEST_F(ChildLayerTest, FinalCropping) { ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; @@ -1238,8 +1236,8 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction { TransactionScope ts(*sFakeComposer); - ts.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); + ts.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); ts.show(mChild); } @@ -1355,8 +1353,8 @@ protected: 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)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } }; @@ -1400,7 +1398,7 @@ TEST_F(LatchingTest, CropLatching) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); } auto referenceFrame1 = mBaseFrame; @@ -1414,7 +1412,7 @@ TEST_F(LatchingTest, CropLatching) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1432,7 +1430,7 @@ TEST_F(LatchingTest, FinalCropLatching) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1447,7 +1445,7 @@ TEST_F(LatchingTest, FinalCropLatching) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1468,7 +1466,7 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1487,7 +1485,7 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1516,12 +1514,12 @@ TEST_F(LatchingTest, FinalCropLatchingRegressionForb37531386) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } { TransactionScope ts(*sFakeComposer); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); -- cgit v1.2.3-59-g8ed1b From 61c58627dd748baa699bab62e80a7972f2030f60 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Wed, 18 Jul 2018 10:12:20 -0700 Subject: blast: BufferStateLayer Adds the initial foundation for supporting buffers on transactions as well as the other metadata that had been passed over BufferQueue. Bug: 80477568 Test: Transaction_test.cpp Change-Id: I61e44462c66c1a912adbabf62015e66bde44c216 --- libs/gui/LayerState.cpp | 85 ++ libs/gui/SurfaceComposerClient.cpp | 121 +++ libs/gui/include/gui/ISurfaceComposerClient.h | 3 +- libs/gui/include/gui/LayerState.h | 33 +- libs/gui/include/gui/SurfaceComposerClient.h | 14 + services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferLayer.cpp | 19 +- services/surfaceflinger/BufferLayer.h | 9 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferQueueLayer.h | 4 +- services/surfaceflinger/BufferStateLayer.cpp | 545 ++++++++++ services/surfaceflinger/BufferStateLayer.h | 142 +++ services/surfaceflinger/ColorLayer.cpp | 4 +- services/surfaceflinger/ColorLayer.h | 4 +- services/surfaceflinger/ContainerLayer.cpp | 4 +- services/surfaceflinger/ContainerLayer.h | 4 +- services/surfaceflinger/Layer.cpp | 184 ++-- services/surfaceflinger/Layer.h | 103 +- services/surfaceflinger/LayerBE.h | 1 + services/surfaceflinger/LayerRejecter.cpp | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 61 +- services/surfaceflinger/SurfaceFlinger.h | 5 + services/surfaceflinger/SurfaceInterceptor.cpp | 1 + services/surfaceflinger/tests/Transaction_test.cpp | 1038 ++++++++++++++++---- 24 files changed, 2071 insertions(+), 321 deletions(-) create mode 100644 services/surfaceflinger/BufferStateLayer.cpp create mode 100644 services/surfaceflinger/BufferStateLayer.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 0414a486e6..931c446275 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -50,6 +50,32 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.g); output.writeFloat(color.b); output.write(transparentRegion); + output.writeUint32(transform); + output.writeBool(transformToDisplayInverse); + output.write(crop); + if (buffer) { + output.writeBool(true); + output.write(*buffer); + } else { + output.writeBool(false); + } + if (acquireFence) { + output.writeBool(true); + output.write(*acquireFence); + } else { + output.writeBool(false); + } + output.writeUint32(static_cast(dataspace)); + output.write(hdrMetadata); + output.write(surfaceDamageRegion); + output.writeInt32(api); + if (sidebandStream) { + output.writeBool(true); + output.writeNativeHandle(sidebandStream->handle()); + } else { + output.writeBool(false); + } + return NO_ERROR; } @@ -85,6 +111,25 @@ status_t layer_state_t::read(const Parcel& input) color.g = input.readFloat(); color.b = input.readFloat(); input.read(transparentRegion); + transform = input.readUint32(); + transformToDisplayInverse = input.readBool(); + input.read(crop); + buffer = new GraphicBuffer(); + if (input.readBool()) { + input.read(*buffer); + } + acquireFence = new Fence(); + if (input.readBool()) { + input.read(*acquireFence); + } + dataspace = static_cast(input.readUint32()); + input.read(hdrMetadata); + input.read(surfaceDamageRegion); + api = input.readInt32(); + if (input.readBool()) { + sidebandStream = NativeHandle::create(input.readNativeHandle(), true); + } + return NO_ERROR; } @@ -233,6 +278,46 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eDestroySurface) { what |= eDestroySurface; } + if (other.what & eTransformChanged) { + what |= eTransformChanged; + transform = other.transform; + } + if (other.what & eTransformToDisplayInverseChanged) { + what |= eTransformToDisplayInverseChanged; + transformToDisplayInverse = other.transformToDisplayInverse; + } + if (other.what & eCropChanged) { + what |= eCropChanged; + crop = other.crop; + } + if (other.what & eBufferChanged) { + what |= eBufferChanged; + buffer = other.buffer; + } + if (other.what & eAcquireFenceChanged) { + what |= eAcquireFenceChanged; + acquireFence = other.acquireFence; + } + if (other.what & eDataspaceChanged) { + what |= eDataspaceChanged; + dataspace = other.dataspace; + } + if (other.what & eHdrMetadataChanged) { + what |= eHdrMetadataChanged; + hdrMetadata = other.hdrMetadata; + } + if (other.what & eSurfaceDamageRegionChanged) { + what |= eSurfaceDamageRegionChanged; + surfaceDamageRegion = other.surfaceDamageRegion; + } + if (other.what & eApiChanged) { + what |= eApiChanged; + api = other.api; + } + if (other.what & eSidebandStreamChanged) { + what |= eSidebandStreamChanged; + sidebandStream = other.sidebandStream; + } } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3ff0ec20ea..17cff546e0 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -437,6 +437,127 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransform( + const sp& sc, uint32_t transform) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eTransformChanged; + s->transform = transform; + return *this; +} + +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, + bool transformToDisplayInverse) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eTransformToDisplayInverseChanged; + s->transformToDisplayInverse = transformToDisplayInverse; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( + const sp& sc, const Rect& crop) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eCropChanged; + s->crop = crop; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( + const sp& sc, const sp& buffer) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eBufferChanged; + s->buffer = buffer; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence( + const sp& sc, const sp& fence) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eAcquireFenceChanged; + s->acquireFence = fence; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace( + const sp& sc, ui::Dataspace dataspace) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDataspaceChanged; + s->dataspace = dataspace; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setHdrMetadata( + const sp& sc, const HdrMetadata& hdrMetadata) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eHdrMetadataChanged; + s->hdrMetadata = hdrMetadata; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSurfaceDamageRegion( + const sp& sc, const Region& surfaceDamageRegion) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eSurfaceDamageRegionChanged; + s->surfaceDamageRegion = surfaceDamageRegion; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApi( + const sp& sc, int32_t api) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eApiChanged; + s->api = api; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSidebandStream( + const sp& sc, const sp& sidebandStream) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eSidebandStreamChanged; + s->sidebandStream = sidebandStream; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp& sc) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 8dfc99a4b7..11261c307c 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -40,8 +40,9 @@ public: eProtectedByDRM = 0x00001000, eCursorWindow = 0x00002000, - eFXSurfaceNormal = 0x00000000, + eFXSurfaceBufferQueue = 0x00000000, eFXSurfaceColor = 0x00020000, + eFXSurfaceBufferState = 0x00040000, eFXSurfaceMask = 0x000F0000, }; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index b88b7fe118..098179864a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -61,7 +62,17 @@ struct layer_state_t { eRelativeLayerChanged = 0x00008000, eReparent = 0x00010000, eColorChanged = 0x00020000, - eDestroySurface = 0x00040000 + eDestroySurface = 0x00040000, + eTransformChanged = 0x00100000, + eTransformToDisplayInverseChanged = 0x00200000, + eCropChanged = 0x00400000, + eBufferChanged = 0x00800000, + eAcquireFenceChanged = 0x01000000, + eDataspaceChanged = 0x02000000, + eHdrMetadataChanged = 0x04000000, + eSurfaceDamageRegionChanged = 0x08000000, + eApiChanged = 0x10000000, + eSidebandStreamChanged = 0x20000000, }; layer_state_t() @@ -79,9 +90,16 @@ struct layer_state_t { crop_legacy(Rect::INVALID_RECT), finalCrop_legacy(Rect::INVALID_RECT), frameNumber_legacy(0), - overrideScalingMode(-1) { + overrideScalingMode(-1), + transform(0), + transformToDisplayInverse(false), + crop(Rect::INVALID_RECT), + dataspace(ui::Dataspace::UNKNOWN), + surfaceDamageRegion(), + api(-1) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; + hdrMetadata.validTypes = 0; } void merge(const layer_state_t& other); @@ -124,6 +142,17 @@ struct layer_state_t { // non POD must be last. see write/read Region transparentRegion; + + uint32_t transform; + bool transformToDisplayInverse; + Rect crop; + sp buffer; + sp acquireFence; + ui::Dataspace dataspace; + HdrMetadata hdrMetadata; + Region surfaceDamageRegion; + int32_t api; + sp sidebandStream; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 278a642c91..4907866d0f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -227,6 +227,20 @@ public: Transaction& setColor(const sp& sc, const half3& color); + Transaction& setTransform(const sp& sc, uint32_t transform); + Transaction& setTransformToDisplayInverse(const sp& sc, + bool transformToDisplayInverse); + Transaction& setCrop(const sp& sc, const Rect& crop); + Transaction& setBuffer(const sp& sc, const sp& buffer); + Transaction& setAcquireFence(const sp& sc, const sp& fence); + Transaction& setDataspace(const sp& sc, ui::Dataspace dataspace); + Transaction& setHdrMetadata(const sp& sc, const HdrMetadata& hdrMetadata); + Transaction& setSurfaceDamageRegion(const sp& sc, + const Region& surfaceDamageRegion); + Transaction& setApi(const sp& sc, int32_t api); + Transaction& setSidebandStream(const sp& sc, + const sp& sidebandStream); + // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. // The child SurfaceControls will not throw exceptions or return errors, diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 0be1fd7d93..3fa1311ce9 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -92,6 +92,7 @@ filegroup { "BufferLayer.cpp", "BufferLayerConsumer.cpp", "BufferQueueLayer.cpp", + "BufferStateLayer.cpp", "Client.cpp", "ColorLayer.cpp", "ContainerLayer.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 64842450fa..e7246665dd 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -136,7 +136,7 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { * onDraw will draw the current layer onto the presentable buffer */ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const { + bool useIdentityTransform) { ATRACE_CALL(); CompositionInfo& compositionInfo = getBE().compositionInfo; @@ -232,7 +232,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, engine.disableTexturing(); } -void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) const { +void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) { CompositionInfo& compositionInfo = getBE().compositionInfo; auto& engine(mFlinger->getRenderEngine()); @@ -518,7 +518,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // FIXME: postedRegion should be dirty & bounds // transform the dirty region to window-manager space - return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); + return getTransform().transform(Region(Rect(getActiveWidth(s), getActiveHeight(s)))); } // transaction @@ -641,9 +641,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT Transform t = getTransform(); Rect win = bounds; - if (!s.finalCrop_legacy.isEmpty()) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { win = t.transform(win); - if (!win.intersect(s.finalCrop_legacy, &win)) { + if (!win.intersect(finalCrop, &win)) { win.clear(); } win = t.inverse().transform(win); @@ -652,10 +653,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT } } - float left = float(win.left) / float(s.active_legacy.w); - float top = float(win.top) / float(s.active_legacy.h); - float right = float(win.right) / float(s.active_legacy.w); - float bottom = float(win.bottom) / float(s.active_legacy.h); + float left = float(win.left) / float(getActiveWidth(s)); + float top = float(win.top) / float(getActiveHeight(s)); + float right = float(win.right) / float(getActiveWidth(s)); + float bottom = float(win.bottom) / float(getActiveHeight(s)); // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 6ffcff4a2a..13f4e83b44 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -78,8 +78,8 @@ public: // onDraw - draws the surface. void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const override; - void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const; + bool useIdentityTransform) override; + void drawNow(const RenderArea& renderArea, bool useIdentityTransform); bool isHdrY410() const override; @@ -102,7 +102,6 @@ public: bool hasReadyFrame() const override; -private: // Returns the current scaling mode, unless mOverrideScalingMode // is set, in which case, it returns mOverrideScalingMode uint32_t getEffectiveScalingMode() const override; @@ -117,7 +116,7 @@ private: virtual nsecs_t getDesiredPresentTime() = 0; virtual std::shared_ptr getCurrentFenceTime() const = 0; - virtual void getDrawingTransformMatrix(float matrix[16]) const = 0; + virtual void getDrawingTransformMatrix(float *matrix) = 0; virtual uint32_t getDrawingTransform() const = 0; virtual ui::Dataspace getDrawingDataSpace() const = 0; virtual Rect getDrawingCrop() const = 0; @@ -136,7 +135,7 @@ private: virtual bool hasDrawingBuffer() const = 0; - virtual void setFilteringEnabled(bool enabled) const = 0; + virtual void setFilteringEnabled(bool enabled) = 0; virtual status_t bindTextureImage() const = 0; virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 1bf9cf275b..0913de419e 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -152,7 +152,7 @@ std::shared_ptr BufferQueueLayer::getCurrentFenceTime() const { return mConsumer->getCurrentFenceTime(); } -void BufferQueueLayer::getDrawingTransformMatrix(float matrix[16]) const { +void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) { return mConsumer->getTransformMatrix(matrix); } @@ -228,7 +228,7 @@ bool BufferQueueLayer::hasDrawingBuffer() const { return mQueuedFrames > 0; } -void BufferQueueLayer::setFilteringEnabled(bool enabled) const { +void BufferQueueLayer::setFilteringEnabled(bool enabled) { return mConsumer->setFilteringEnabled(enabled); } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 7454e2058a..579ed81f7e 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -68,7 +68,7 @@ private: nsecs_t getDesiredPresentTime() override; std::shared_ptr getCurrentFenceTime() const override; - void getDrawingTransformMatrix(float matrix[16]) const override; + void getDrawingTransformMatrix(float *matrix) override; uint32_t getDrawingTransform() const override; ui::Dataspace getDrawingDataSpace() const override; Rect getDrawingCrop() const override; @@ -87,7 +87,7 @@ private: bool hasDrawingBuffer() const override; - void setFilteringEnabled(bool enabled) const override; + void setFilteringEnabled(bool enabled) override; status_t bindTextureImage() const override; status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp new file mode 100644 index 0000000000..2e411f1ab8 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -0,0 +1,545 @@ +/* + * Copyright (C) 2017 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 "BufferStateLayer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BufferStateLayer.h" +#include "RenderEngine/Image.h" +#include "clz.h" + +#include + +namespace android { + +static const std::array IDENTITY_MATRIX{1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + +BufferStateLayer::BufferStateLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : BufferLayer(flinger, client, name, w, h, flags), + mSidebandStreamChanged(false), + mFrameNumber(0) { + mTransformMatrix = IDENTITY_MATRIX; +} + +// ----------------------------------------------------------------------- +// Interface implementation for Layer +// ----------------------------------------------------------------------- +void BufferStateLayer::onLayerDisplayed(const sp& /*releaseFence*/) { + // TODO(marissaw): send the release fence back to buffer owner + return; +} + +void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { + // TODO(marissaw): send the transform hint to buffer owner + return; +} + +void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { + // TODO(marissaw): use this to signal the buffer owner + return; +} + +bool BufferStateLayer::shouldPresentNow(const DispSync& /*dispSync*/) const { + if (getSidebandStreamChanged() || getAutoRefresh()) { + return true; + } + + return hasDrawingBuffer(); +} + +bool BufferStateLayer::getTransformToDisplayInverse() const { + return mCurrentState.transformToDisplayInverse; +} + +void BufferStateLayer::pushPendingState() { + if (!mCurrentState.modified) { + return; + } + mPendingStates.push_back(mCurrentState); + ATRACE_INT(mTransactionName.string(), mPendingStates.size()); +} + +bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { + const bool stateUpdateAvailable = !mPendingStates.empty(); + while (!mPendingStates.empty()) { + popPendingState(stateToCommit); + } + mCurrentState.modified = false; + return stateUpdateAvailable; +} + +Rect BufferStateLayer::getCrop(const Layer::State& s) const { + return (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) + ? GLConsumer::scaleDownCrop(s.crop, s.active.w, s.active.h) + : s.crop; +} + +bool BufferStateLayer::setTransform(uint32_t transform) { + if (mCurrentState.transform == transform) return false; + mCurrentState.sequence++; + mCurrentState.transform = transform; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) { + if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false; + mCurrentState.sequence++; + mCurrentState.transformToDisplayInverse = transformToDisplayInverse; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setCrop(const Rect& crop) { + if (mCurrentState.crop == crop) return false; + mCurrentState.sequence++; + mCurrentState.crop = crop; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setBuffer(sp buffer) { + mCurrentState.sequence++; + mCurrentState.buffer = buffer; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setAcquireFence(const sp& fence) { + mCurrentState.acquireFence = fence; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) { + if (mCurrentState.dataspace == dataspace) return false; + mCurrentState.sequence++; + mCurrentState.dataspace = dataspace; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) { + if (mCurrentState.hdrMetadata == hdrMetadata) return false; + mCurrentState.sequence++; + mCurrentState.hdrMetadata = hdrMetadata; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) { + mCurrentState.sequence++; + mCurrentState.surfaceDamageRegion = surfaceDamage; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setApi(int32_t api) { + if (mCurrentState.api == api) return false; + mCurrentState.sequence++; + mCurrentState.api = api; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) { + if (mCurrentState.sidebandStream == sidebandStream) return false; + mCurrentState.sequence++; + mCurrentState.sidebandStream = sidebandStream; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + + if (!mSidebandStreamChanged.exchange(true)) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } + return true; +} + +bool BufferStateLayer::setSize(uint32_t w, uint32_t h) { + if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false; + mCurrentState.active.w = w; + mCurrentState.active.h = h; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setPosition(float x, float y, bool /*immediate*/) { + if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y) + return false; + + mCurrentState.active.transform.set(x, y); + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { + mCurrentState.transparentRegionHint = transparent; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored"); + return false; + } + + mCurrentState.sequence++; + mCurrentState.active.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} +// ----------------------------------------------------------------------- + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayer +// ----------------------------------------------------------------------- +bool BufferStateLayer::fenceHasSignaled() const { + if (latchUnsignaledBuffers()) { + return true; + } + + return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled; +} + +nsecs_t BufferStateLayer::getDesiredPresentTime() { + // TODO(marissaw): support an equivalent to desiredPresentTime for timestats metrics + return 0; +} + +std::shared_ptr BufferStateLayer::getCurrentFenceTime() const { + return std::make_shared(getDrawingState().acquireFence); +} + +void BufferStateLayer::getDrawingTransformMatrix(float *matrix) { + std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix); +} + +uint32_t BufferStateLayer::getDrawingTransform() const { + return getDrawingState().transform; +} + +ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { + return getDrawingState().dataspace; +} + +Rect BufferStateLayer::getDrawingCrop() const { + return Rect::INVALID_RECT; +} + +uint32_t BufferStateLayer::getDrawingScalingMode() const { + return NATIVE_WINDOW_SCALING_MODE_FREEZE; +} + +Region BufferStateLayer::getDrawingSurfaceDamage() const { + return getDrawingState().surfaceDamageRegion; +} + +const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const { + return getDrawingState().hdrMetadata; +} + +int BufferStateLayer::getDrawingApi() const { + return getDrawingState().api; +} + +PixelFormat BufferStateLayer::getPixelFormat() const { + return mActiveBuffer->format; +} + +uint64_t BufferStateLayer::getFrameNumber() const { + return mFrameNumber; +} + +bool BufferStateLayer::getAutoRefresh() const { + // TODO(marissaw): support shared buffer mode + return false; +} + +bool BufferStateLayer::getSidebandStreamChanged() const { + return mSidebandStreamChanged.load(); +} + +std::optional BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { + if (mSidebandStreamChanged.exchange(false)) { + const State& s(getDrawingState()); + // mSidebandStreamChanged was true + // replicated in LayerBE until FE/BE is ready to be synchronized + getBE().compositionInfo.hwc.sidebandStream = s.sidebandStream; + if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + recomputeVisibleRegions = true; + + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + } + return {}; +} + +bool BufferStateLayer::hasDrawingBuffer() const { + return getDrawingState().buffer != nullptr; +} + +void BufferStateLayer::setFilteringEnabled(bool enabled) { + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop, + mCurrentTransform, enabled); +} + +status_t BufferStateLayer::bindTextureImage() const { + const State& s(getDrawingState()); + auto& engine(mFlinger->getRenderEngine()); + + if (!engine.isCurrent()) { + ALOGE("RenderEngine is not current"); + return INVALID_OPERATION; + } + + engine.checkErrors(); + + if (!mTextureImage) { + ALOGE("no currently-bound texture"); + engine.bindExternalTextureImage(mTextureName, *engine.createImage()); + return NO_INIT; + } + + bool created = + mTextureImage->setNativeWindowBuffer(s.buffer->getNativeBuffer(), + s.buffer->getUsage() & GRALLOC_USAGE_PROTECTED); + if (!created) { + ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d", + s.buffer->getWidth(), s.buffer->getHeight(), s.buffer->getStride(), + s.buffer->getUsage(), s.buffer->getPixelFormat()); + engine.bindExternalTextureImage(mTextureName, *engine.createImage()); + return NO_INIT; + } + + engine.bindExternalTextureImage(mTextureName, *mTextureImage); + + // Wait for the new buffer to be ready. + if (s.acquireFence->isValid()) { + if (SyncFeatures::getInstance().useWaitSync()) { + base::unique_fd fenceFd(s.acquireFence->dup()); + if (fenceFd == -1) { + ALOGE("error dup'ing fence fd: %d", errno); + return -errno; + } + if (!engine.waitFence(std::move(fenceFd))) { + ALOGE("failed to wait on fence fd"); + return UNKNOWN_ERROR; + } + } else { + status_t err = s.acquireFence->waitForever("BufferStateLayer::bindTextureImage"); + if (err != NO_ERROR) { + ALOGE("error waiting for fence: %d", err); + return err; + } + } + } + + return NO_ERROR; +} + +status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) { + const State& s(getDrawingState()); + + if (!s.buffer) { + return NO_ERROR; + } + + auto& engine(mFlinger->getRenderEngine()); + if (!engine.isCurrent()) { + ALOGE("RenderEngine is not current"); + return INVALID_OPERATION; + } + engine.checkErrors(); + + // TODO(marissaw): once buffers are cached, don't create a new image everytime + mTextureImage = engine.createImage(); + + // Reject if the layer is invalid + uint32_t bufferWidth = s.buffer->width; + uint32_t bufferHeight = s.buffer->height; + + if (s.transform & Transform::ROT_90) { + swap(bufferWidth, bufferHeight); + } + + if (s.transformToDisplayInverse) { + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + if (invTransform & Transform::ROT_90) { + swap(bufferWidth, bufferHeight); + } + } + + if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE && + (s.active.w != bufferWidth || s.active.h != bufferHeight)) { + ALOGE("[%s] rejecting buffer: " + "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", + mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); + mTimeStats.removeTimeRecord(getName().c_str(), getFrameNumber()); + return BAD_VALUE; + } + + // Handle sync fences + if (SyncFeatures::getInstance().useNativeFenceSync()) { + base::unique_fd fenceFd = engine.flush(); + if (fenceFd == -1) { + ALOGE("failed to flush RenderEngine"); + mTimeStats.clearLayerRecord(getName().c_str()); + return UNKNOWN_ERROR; + } + + sp fence(new Fence(std::move(fenceFd))); + + // Check status of fences first because merging is expensive. + // Merging an invalid fence with any other fence results in an + // invalid fence. + auto currentStatus = s.acquireFence->getStatus(); + if (currentStatus == Fence::Status::Invalid) { + ALOGE("Existing fence has invalid state"); + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + + auto incomingStatus = fence->getStatus(); + if (incomingStatus == Fence::Status::Invalid) { + ALOGE("New fence has invalid state"); + mDrawingState.acquireFence = fence; + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (currentStatus == incomingStatus) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber); + sp mergedFence = Fence::merge(fenceName, mDrawingState.acquireFence, fence); + if (!mergedFence.get()) { + ALOGE("failed to merge release fences"); + // synchronization is broken, the best we can do is hope fences + // signal in order so the new fence will act like a union + mDrawingState.acquireFence = fence; + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + mDrawingState.acquireFence = mergedFence; + } else if (incomingStatus == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + mDrawingState.acquireFence = fence; + } + } else { + // Bind the new buffer to the GL texture. + // + // Older devices require the "implicit" synchronization provided + // by glEGLImageTargetTexture2DOES, which this method calls. Newer + // devices will either call this in Layer::onDraw, or (if it's not + // a GL-composited layer) not at all. + status_t err = bindTextureImage(); + if (err != NO_ERROR) { + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + } + + // TODO(marissaw): properly support mTimeStats + const std::string layerName(getName().c_str()); + mTimeStats.setPostTime(getName().c_str(), getFrameNumber(), latchTime); + mTimeStats.setAcquireFence(layerName, getFrameNumber(), getCurrentFenceTime()); + mTimeStats.setLatchTime(layerName, getFrameNumber(), latchTime); + + return NO_ERROR; +} + +status_t BufferStateLayer::updateActiveBuffer() { + const State& s(getDrawingState()); + + if (s.buffer == nullptr) { + return BAD_VALUE; + } + + mActiveBuffer = s.buffer; + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.mBufferSlot = 0; + + return NO_ERROR; +} + +status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { + // TODO(marissaw): support frame history events + mCurrentFrameNumber = mFrameNumber; + return NO_ERROR; +} + +void BufferStateLayer::setHwcLayerBuffer(const sp& display) { + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + + const State& s(getDrawingState()); + + // TODO(marissaw): support more than one slot + uint32_t hwcSlot = 0; + + auto error = hwcLayer->setBuffer(hwcSlot, s.buffer, s.acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + s.buffer->handle, to_string(error).c_str(), static_cast(error)); + } + + mFrameNumber++; +} + +void BufferStateLayer::onFirstRef() { + if (const auto display = mFlinger->getDefaultDisplayDevice()) { + updateTransformHint(display); + } +} + +} // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h new file mode 100644 index 0000000000..4d7396ef81 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayer.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 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 "RenderEngine/Image.h" +#include "RenderEngine/RenderEngine.h" + +#include "BufferLayer.h" +#include "Layer.h" + +#include +#include +#include + +namespace android { + +class BufferStateLayer : public BufferLayer { +public: + BufferStateLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + + // ----------------------------------------------------------------------- + // Interface implementation for Layer + // ----------------------------------------------------------------------- + void onLayerDisplayed(const sp& releaseFence) override; + void setTransformHint(uint32_t orientation) const override; + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; + + bool shouldPresentNow(const DispSync& dispSync) const override; + + bool getTransformToDisplayInverse() const override; + + uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { + return flags; + } + void pushPendingState() override; + bool applyPendingStates(Layer::State* stateToCommit) override; + + uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; } + uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; } + Transform getActiveTransform(const Layer::State& s) const override { + return s.active.transform; + } + Region getActiveTransparentRegion(const Layer::State& s) const override { + return s.transparentRegionHint; + } + Rect getCrop(const Layer::State& s) const; + Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; } + + bool setTransform(uint32_t transform) override; + bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; + bool setCrop(const Rect& crop) override; + bool setBuffer(sp buffer) override; + bool setAcquireFence(const sp& fence) override; + bool setDataspace(ui::Dataspace dataspace) override; + bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; + bool setSurfaceDamageRegion(const Region& surfaceDamage) override; + bool setApi(int32_t api) override; + bool setSidebandStream(const sp& sidebandStream) override; + + bool setSize(uint32_t w, uint32_t h) override; + bool setPosition(float x, float y, bool immediate) override; + bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) override; + + // Override to ignore legacy layer state properties that are not used by BufferStateLayer + bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, + uint64_t /*frameNumber*/) override {} + void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, + uint64_t /*frameNumber*/) override {} + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayer + // ----------------------------------------------------------------------- + bool fenceHasSignaled() const override; + +private: + nsecs_t getDesiredPresentTime() override; + std::shared_ptr getCurrentFenceTime() const override; + + void getDrawingTransformMatrix(float *matrix) override; + uint32_t getDrawingTransform() const override; + ui::Dataspace getDrawingDataSpace() const override; + Rect getDrawingCrop() const override; + uint32_t getDrawingScalingMode() const override; + Region getDrawingSurfaceDamage() const override; + const HdrMetadata& getDrawingHdrMetadata() const override; + int getDrawingApi() const override; + PixelFormat getPixelFormat() const override; + + uint64_t getFrameNumber() const override; + + bool getAutoRefresh() const override; + bool getSidebandStreamChanged() const override; + + std::optional latchSidebandStream(bool& recomputeVisibleRegions) override; + + bool hasDrawingBuffer() const override; + + void setFilteringEnabled(bool enabled) override; + + status_t bindTextureImage() const override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + + status_t updateActiveBuffer() override; + status_t updateFrameNumber(nsecs_t latchTime) override; + + void setHwcLayerBuffer(const sp& display) override; + // ----------------------------------------------------------------------- +private: + void onFirstRef() override; + + std::unique_ptr mTextureImage; + + std::array mTransformMatrix; + + std::atomic mSidebandStreamChanged; + + uint32_t mFrameNumber; + + // TODO(marissaw): support sticky transform for LEGACY camera mode +}; + +} // namespace android diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 10075ae35f..bac46a38b4 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -43,7 +43,7 @@ ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, const } void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, - bool useIdentityTransform) const { + bool useIdentityTransform) { half4 color = getColor(); if (color.a > 0) { computeGeometry(renderArea, getBE().mMesh, useIdentityTransform); @@ -54,7 +54,7 @@ void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, } } -void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) const { +void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) { CompositionInfo& compositionInfo = getBE().compositionInfo; auto& engine(mFlinger->getRenderEngine()); diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 8417135ed2..429ad79a05 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -31,8 +31,8 @@ public: virtual const char* getTypeId() const { return "ColorLayer"; } virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const; - void drawNow(const RenderArea& , bool ) const; + bool useIdentityTransform); + void drawNow(const RenderArea&, bool); bool isVisible() const override; void setPerFrameData(const sp& display) override; diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 320c0df86a..5ad5d562a8 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -28,9 +28,9 @@ ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp& client mDrawingState = mCurrentState; } -void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} +void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {} -void ContainerLayer::drawNow(const RenderArea&, bool) const {} +void ContainerLayer::drawNow(const RenderArea&, bool) {} bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 29a5c3a569..051e76523c 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -31,8 +31,8 @@ public: const char* getTypeId() const override { return "ContainerLayer"; } void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const override; - void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const override; + bool useIdentityTransform) override; + void drawNow(const RenderArea& renderArea, bool useIdentityTransform) override; bool isVisible() const override; void setPerFrameData(const sp& display) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index eeee0ae863..ee9ee78fae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -114,6 +114,17 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.requested_legacy = mCurrentState.active_legacy; mCurrentState.appId = 0; mCurrentState.type = 0; + mCurrentState.active.w = 0; + mCurrentState.active.h = 0; + mCurrentState.active.transform.set(0, 0); + mCurrentState.transform = 0; + mCurrentState.transformToDisplayInverse = false; + mCurrentState.crop.makeInvalid(); + mCurrentState.acquireFence = new Fence(-1); + mCurrentState.dataspace = ui::Dataspace::UNKNOWN; + mCurrentState.hdrMetadata.validTypes = 0; + mCurrentState.surfaceDamageRegion.clear(); + mCurrentState.api = -1; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -293,17 +304,19 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active_legacy.w, s.active_legacy.h); + Rect win(getActiveWidth(s), getActiveHeight(s)); - if (!s.crop_legacy.isEmpty()) { - win.intersect(s.crop_legacy, &win); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } Transform t = getTransform(); win = t.transform(win); - if (!s.finalCrop_legacy.isEmpty()) { - win.intersect(s.finalCrop_legacy, &win); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + win.intersect(finalCrop, &win); } const sp& p = mDrawingParent.promote(); @@ -322,7 +335,7 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { } if (reduceTransparentRegion) { - auto const screenTransparentRegion = t.transform(s.activeTransparentRegion_legacy); + auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s)); win = reduce(win, screenTransparentRegion); } @@ -331,15 +344,16 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { FloatRect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); - return computeBounds(s.activeTransparentRegion_legacy); + return computeBounds(getActiveTransparentRegion(s)); } FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active_legacy.w, s.active_legacy.h); + Rect win(getActiveWidth(s), getActiveHeight(s)); - if (!s.crop_legacy.isEmpty()) { - win.intersect(s.crop_legacy, &win); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } const auto& p = mDrawingParent.promote(); @@ -379,9 +393,10 @@ Rect Layer::computeInitialCrop(const sp& display) const { // FIXME: the 3 lines below can produce slightly incorrect clipping when we have // a viewport clipping and a window transform. we should use floating point to fix this. - Rect activeCrop(s.active_legacy.w, s.active_legacy.h); - if (!s.crop_legacy.isEmpty()) { - activeCrop.intersect(s.crop_legacy, &activeCrop); + Rect activeCrop(getActiveWidth(s), getActiveHeight(s)); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + activeCrop.intersect(crop, &activeCrop); } Transform t = getTransform(); @@ -389,8 +404,9 @@ Rect Layer::computeInitialCrop(const sp& display) const { if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - if (!s.finalCrop_legacy.isEmpty()) { - if (!activeCrop.intersect(s.finalCrop_legacy, &activeCrop)) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + if (!activeCrop.intersect(finalCrop, &activeCrop)) { activeCrop.clear(); } } @@ -424,12 +440,12 @@ FloatRect Layer::computeCrop(const sp& display) const { // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(s.active_legacy.w, s.active_legacy.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { activeCrop.clear(); } // subtract the transparent region and snap to the bounds - activeCrop = reduce(activeCrop, s.activeTransparentRegion_legacy); + activeCrop = reduce(activeCrop, getActiveTransparentRegion(s)); // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -449,8 +465,8 @@ FloatRect Layer::computeCrop(const sp& display) const { invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } - int winWidth = s.active_legacy.w; - int winHeight = s.active_legacy.h; + int winWidth = getActiveWidth(s); + int winHeight = getActiveHeight(s); if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { // If the activeCrop has been rotate the ends are rotated but not // the space itself so when transforming ends back we can't rely on @@ -462,10 +478,10 @@ FloatRect Layer::computeCrop(const sp& display) const { if (is_h_flipped == is_v_flipped) { invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - winWidth = s.active_legacy.h; - winHeight = s.active_legacy.w; + winWidth = getActiveHeight(s); + winHeight = getActiveWidth(s); } - const Rect winCrop = activeCrop.transform(invTransform, s.active_legacy.w, s.active_legacy.h); + const Rect winCrop = activeCrop.transform(invTransform, getActiveWidth(s), getActiveHeight(s)); // below, crop is intersected with winCrop expressed in crop's coordinate space float xScale = crop.getWidth() / float(winWidth); @@ -518,10 +534,10 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Region activeTransparentRegion(s.activeTransparentRegion_legacy); + Region activeTransparentRegion(getActiveTransparentRegion(s)); Transform t = getTransform(); - if (!s.crop_legacy.isEmpty()) { - Rect activeCrop(s.crop_legacy); + Rect activeCrop = getCrop(s); + if (!activeCrop.isEmpty()) { activeCrop = t.transform(activeCrop); if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); @@ -533,23 +549,24 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(s.active_legacy.w, s.active_legacy.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent - activeTransparentRegion.orSelf(Rect(0, 0, s.active_legacy.w, activeCrop.top)); + activeTransparentRegion.orSelf(Rect(0, 0, getActiveWidth(s), activeCrop.top)); activeTransparentRegion.orSelf( - Rect(0, activeCrop.bottom, s.active_legacy.w, s.active_legacy.h)); + Rect(0, activeCrop.bottom, getActiveWidth(s), getActiveHeight(s))); activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); activeTransparentRegion.orSelf( - Rect(activeCrop.right, activeCrop.top, s.active_legacy.w, activeCrop.bottom)); + Rect(activeCrop.right, activeCrop.top, getActiveWidth(s), activeCrop.bottom)); } // computeBounds returns a FloatRect to provide more accuracy during the // transformation. We then round upon constructing 'frame'. Rect frame{t.transform(computeBounds(activeTransparentRegion))}; - if (!s.finalCrop_legacy.isEmpty()) { - if (!frame.intersect(s.finalCrop_legacy, &frame)) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + if (!frame.intersect(finalCrop, &frame)) { frame.clear(); } } @@ -682,16 +699,18 @@ void Layer::updateCursorPosition(const sp& display) { // Apply the layer's transform, followed by the display's global transform // Here we're guaranteed that the layer's transform preserves rects - Rect win(s.active_legacy.w, s.active_legacy.h); - if (!s.crop_legacy.isEmpty()) { - win.intersect(s.crop_legacy, &win); + Rect win(getActiveWidth(s), getActiveHeight(s)); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion_legacy); + Rect bounds = reduce(win, getActiveTransparentRegion(s)); Rect frame(getTransform().transform(bounds)); frame.intersect(display->getViewport(), &frame); - if (!s.finalCrop_legacy.isEmpty()) { - frame.intersect(s.finalCrop_legacy, &frame); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + frame.intersect(finalCrop, &frame); } auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); @@ -709,15 +728,15 @@ void Layer::updateCursorPosition(const sp& display) { // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const RenderArea& renderArea, const Region& clip) const { +void Layer::draw(const RenderArea& renderArea, const Region& clip) { onDraw(renderArea, clip, false); } -void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const { +void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) { onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const RenderArea& renderArea) const { +void Layer::draw(const RenderArea& renderArea) { onDraw(renderArea, Region(renderArea.getBounds()), false); } @@ -844,11 +863,12 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, rt = layerTransform.transform(rt); } - if (!s.finalCrop_legacy.isEmpty()) { - boundPoint(<, s.finalCrop_legacy); - boundPoint(&lb, s.finalCrop_legacy); - boundPoint(&rb, s.finalCrop_legacy); - boundPoint(&rt, s.finalCrop_legacy); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + boundPoint(<, finalCrop); + boundPoint(&lb, finalCrop); + boundPoint(&rb, finalCrop); + boundPoint(&rt, finalCrop); } Mesh::VertexArray position(mesh.getPositionArray()); @@ -984,19 +1004,11 @@ bool Layer::applyPendingStates(State* stateToCommit) { return stateUpdateAvailable; } -uint32_t Layer::doTransaction(uint32_t flags) { - ATRACE_CALL(); - - pushPendingState(); - Layer::State c = getCurrentState(); - if (!applyPendingStates(&c)) { - return 0; - } - +uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const Layer::State& s(getDrawingState()); - const bool sizeChanged = (c.requested_legacy.w != s.requested_legacy.w) || - (c.requested_legacy.h != s.requested_legacy.h); + const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) || + (stateToCommit->requested_legacy.h != s.requested_legacy.h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer @@ -1007,16 +1019,18 @@ uint32_t Layer::doTransaction(uint32_t flags) { " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), - c.active_legacy.w, c.active_legacy.h, c.crop_legacy.left, c.crop_legacy.top, - c.crop_legacy.right, c.crop_legacy.bottom, c.crop_legacy.getWidth(), - c.crop_legacy.getHeight(), c.requested_legacy.w, c.requested_legacy.h, + stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, + stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, + stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, + stateToCommit->crop_legacy.getWidth(), stateToCommit->crop_legacy.getHeight(), + stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h, s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(c.requested_legacy.w, c.requested_legacy.h); + setDefaultBufferSize(stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1037,8 +1051,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { // resizePending state is to avoid applying the state of the new buffer // to the old buffer. However in the state where we don't have an old buffer // there is no such concern but we may still be being used as a parent layer. - const bool resizePending = ((c.requested_legacy.w != c.active_legacy.w) || - (c.requested_legacy.h != c.active_legacy.h)) && + const bool resizePending = + ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || + (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { @@ -1062,21 +1077,37 @@ uint32_t Layer::doTransaction(uint32_t flags) { // being stored in the same data structure while having different latching rules. // b/38182305 // - // Careful that "c" and editCurrentState may not begin as equivalent due to + // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. if (mFreezeGeometryUpdates) { - float tx = c.active_legacy.transform.tx(); - float ty = c.active_legacy.transform.ty(); - c.active_legacy = c.requested_legacy; - c.active_legacy.transform.set(tx, ty); - editCurrentState.active_legacy = c.active_legacy; + float tx = stateToCommit->active_legacy.transform.tx(); + float ty = stateToCommit->active_legacy.transform.ty(); + stateToCommit->active_legacy = stateToCommit->requested_legacy; + stateToCommit->active_legacy.transform.set(tx, ty); + editCurrentState.active_legacy = stateToCommit->active_legacy; } else { editCurrentState.active_legacy = editCurrentState.requested_legacy; - c.active_legacy = c.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; } } - if (s.active_legacy != c.active_legacy) { + return flags; +} + +uint32_t Layer::doTransaction(uint32_t flags) { + ATRACE_CALL(); + + pushPendingState(); + Layer::State c = getCurrentState(); + if (!applyPendingStates(&c)) { + return 0; + } + + flags = doTransactionResize(flags, &c); + + const Layer::State& s(getDrawingState()); + + if (getActiveGeometry(c) != getActiveGeometry(s)) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } @@ -1087,9 +1118,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { this->contentDirty = true; // we may use linear filtering, if the matrix scales us - const uint8_t type = c.active_legacy.transform.getType(); - mNeedsFiltering = - (!c.active_legacy.transform.preserveRects() || (type >= Transform::SCALE)); + const uint8_t type = getActiveTransform(c).getType(); + mNeedsFiltering = (!getActiveTransform(c).preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1278,6 +1308,7 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, setTransactionFlags(eTransactionNeeded); return true; } + bool Layer::setTransparentRegionHint(const Region& transparent) { mCurrentState.requestedTransparentRegion_legacy = transparent; mCurrentState.modified = true; @@ -1415,6 +1446,7 @@ void Layer::updateTransformHint(const sp& display) const { // debugging // ---------------------------------------------------------------------------- +// TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { LayerDebugInfo info; const Layer::State& ds = getDrawingState(); @@ -1889,14 +1921,14 @@ Transform Layer::getTransform() const { bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } - float sx = p->getDrawingState().active_legacy.w / static_cast(bufferWidth); - float sy = p->getDrawingState().active_legacy.h / static_cast(bufferHeight); + float sx = p->getActiveWidth(p->getDrawingState()) / static_cast(bufferWidth); + float sy = p->getActiveHeight(p->getDrawingState()) / static_cast(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; } } - return t * getDrawingState().active_legacy.transform; + return t * getActiveTransform(getDrawingState()); } half Layer::getAlpha() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 96ec84b269..a48cdffd8b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -156,6 +156,24 @@ public: SortedVector> zOrderRelatives; half4 color; + + // The fields below this point are only used by BufferStateLayer + Geometry active; + + uint32_t transform; + bool transformToDisplayInverse; + + Rect crop; + Region transparentRegionHint; + + sp buffer; + sp acquireFence; + ui::Dataspace dataspace; + HdrMetadata hdrMetadata; + Region surfaceDamageRegion; + int32_t api; + + sp sidebandStream; }; Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, @@ -191,11 +209,12 @@ public: // also the rendered size of the layer prior to any transformations. Parent // or local matrix transformations will not affect the size of the buffer, // but may affect it's on-screen size or clipping. - bool setSize(uint32_t w, uint32_t h); + virtual bool setSize(uint32_t w, uint32_t h); // Set a 2x2 transformation matrix on the layer. This transform // will be applied after parent transforms, but before any final // producer specified transform. - bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms); + virtual bool setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms); // This second set of geometry attributes are controlled by // setGeometryAppliesWithResize, and their default mode is to be @@ -205,32 +224,45 @@ public: // setPosition operates in parent buffer space (pre parent-transform) or display // space for top-level layers. - bool setPosition(float x, float y, bool immediate); + virtual bool setPosition(float x, float y, bool immediate); // Buffer space - bool setCrop_legacy(const Rect& crop, bool immediate); + virtual bool setCrop_legacy(const Rect& crop, bool immediate); // Parent buffer space/display space - bool setFinalCrop_legacy(const Rect& crop, bool immediate); + virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? // ----------------------------------------------------------------------- - bool setLayer(int32_t z); - bool setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ); - - bool setAlpha(float alpha); - bool setColor(const half3& color); - bool setTransparentRegionHint(const Region& transparent); - bool setFlags(uint8_t flags, uint8_t mask); - bool setLayerStack(uint32_t layerStack); - uint32_t getLayerStack() const; - void deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber); - void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); - bool setOverrideScalingMode(int32_t overrideScalingMode); - void setInfo(int32_t type, int32_t appId); - bool reparentChildren(const sp& layer); - void setChildrenDrawingParent(const sp& layer); - bool reparent(const sp& newParentHandle); - bool detachChildren(); + virtual bool setLayer(int32_t z); + virtual bool setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ); + + virtual bool setAlpha(float alpha); + virtual bool setColor(const half3& color); + virtual bool setTransparentRegionHint(const Region& transparent); + virtual bool setFlags(uint8_t flags, uint8_t mask); + virtual bool setLayerStack(uint32_t layerStack); + virtual uint32_t getLayerStack() const; + virtual void deferTransactionUntil_legacy(const sp& barrierHandle, + uint64_t frameNumber); + virtual void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); + virtual bool setOverrideScalingMode(int32_t overrideScalingMode); + virtual void setInfo(int32_t type, int32_t appId); + virtual bool reparentChildren(const sp& layer); + virtual void setChildrenDrawingParent(const sp& layer); + virtual bool reparent(const sp& newParentHandle); + virtual bool detachChildren(); + + // Used only to set BufferStateLayer state + virtual bool setTransform(uint32_t /*transform*/) { return false; }; + virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; + virtual bool setCrop(const Rect& /*crop*/) { return false; }; + virtual bool setBuffer(sp /*buffer*/) { return false; }; + virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; + virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; }; + virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; }; + virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; + virtual bool setApi(int32_t /*api*/) { return false; }; + virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } @@ -310,12 +342,24 @@ public: void writeToProto(LayerProto* layerInfo, int32_t displayId); + virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } + virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } + virtual uint32_t getActiveHeight(const Layer::State& s) const { return s.active_legacy.h; } + virtual Transform getActiveTransform(const Layer::State& s) const { + return s.active_legacy.transform; + } + virtual Region getActiveTransparentRegion(const Layer::State& s) const { + return s.activeTransparentRegion_legacy; + } + virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } + virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; } + protected: /* * onDraw - draws the surface. */ virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const = 0; + bool useIdentityTransform) = 0; public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} @@ -369,9 +413,9 @@ public: * draw - performs some global clipping optimizations * and calls onDraw(). */ - void draw(const RenderArea& renderArea, const Region& clip) const; - void draw(const RenderArea& renderArea, bool useIdentityTransform) const; - void draw(const RenderArea& renderArea) const; + void draw(const RenderArea& renderArea, const Region& clip); + void draw(const RenderArea& renderArea, bool useIdentityTransform); + void draw(const RenderArea& renderArea); /* * drawNow uses the renderEngine to draw the layer. This is different than the @@ -381,7 +425,7 @@ public: * is used for screen captures which happens separately from the frame * compositing path. */ - virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const = 0; + virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) = 0; /* * doTransaction - process the transaction. This is a good place to figure @@ -536,7 +580,7 @@ public: // SurfaceFlinger to complete a transaction. void commitChildList(); int32_t getZ() const; - void pushPendingState(); + virtual void pushPendingState(); protected: // constant @@ -620,7 +664,8 @@ protected: bool addSyncPoint(const std::shared_ptr& point); void popPendingState(State* stateToCommit); - bool applyPendingStates(State* stateToCommit); + virtual bool applyPendingStates(State* stateToCommit); + virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); void clearSyncPoints(); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 8b371705f1..b5acebafb1 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -78,6 +78,7 @@ public: friend class Layer; friend class BufferLayer; friend class BufferQueueLayer; + friend class BufferStateLayer; friend class ColorLayer; friend class SurfaceFlinger; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index fd0ca822c6..70558d4cc8 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -101,7 +101,8 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) ALOGD_IF(DEBUG_RESIZE, "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" - " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) " + " drawing={ active_legacy ={ wh={%4u,%4u} crop_legacy={%4d,%4d,%4d,%4d} " + "(%4d,%4d) " "}\n" " requested_legacy={ wh={%4u,%4u} }}\n", mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 64f1eaf463..399fbd83bc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -64,6 +64,7 @@ #include "BufferLayer.h" #include "BufferQueueLayer.h" +#include "BufferStateLayer.h" #include "Client.h" #include "ColorLayer.h" #include "Colorizer.h" @@ -2766,7 +2767,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa if (translucent) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.activeTransparentRegion_legacy); + transparentRegion = tr.transform(layer->getActiveTransparentRegion(s)); } else { // transformation too complex, can't do the // transparent region optimization. @@ -3551,6 +3552,37 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } + if (what & layer_state_t::eTransformChanged) { + if (layer->setTransform(s.transform)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eTransformToDisplayInverseChanged) { + if (layer->setTransformToDisplayInverse(s.transformToDisplayInverse)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eCropChanged) { + if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eBufferChanged) { + if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eAcquireFenceChanged) { + if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eDataspaceChanged) { + if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eHdrMetadataChanged) { + if (layer->setHdrMetadata(s.hdrMetadata)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eSurfaceDamageRegionChanged) { + if (layer->setSurfaceDamageRegion(s.surfaceDamageRegion)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eApiChanged) { + if (layer->setApi(s.api)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eSidebandStreamChanged) { + if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; + } return flags; } @@ -3593,10 +3625,13 @@ status_t SurfaceFlinger::createLayer( String8 uniqueName = getUniqueLayerName(name); switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { - case ISurfaceComposerClient::eFXSurfaceNormal: + case ISurfaceComposerClient::eFXSurfaceBufferQueue: result = createBufferQueueLayer(client, uniqueName, w, h, flags, format, handle, gbp, &layer); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + result = createBufferStateLayer(client, uniqueName, w, h, flags, handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, @@ -3687,6 +3722,16 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const return err; } +status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, + sp* handle, sp* outLayer) { + sp layer = new BufferStateLayer(this, client, name, w, h, flags); + *handle = layer->getHandle(); + *outLayer = layer; + + return NO_ERROR; +} + status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* outLayer) @@ -4864,10 +4909,12 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, const Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); - return Rect(layerState.active_legacy.w, layerState.active_legacy.h); + return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState)); + } + int getHeight() const override { + return mLayer->getActiveHeight(mLayer->getDrawingState()); } - int getHeight() const override { return mLayer->getDrawingState().active_legacy.h; } - int getWidth() const override { return mLayer->getDrawingState().active_legacy.w; } + int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } Rect getSourceCrop() const override { @@ -4935,12 +4982,12 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; - crop.right = parent->getCurrentState().active_legacy.w; + crop.right = parent->getActiveWidth(parent->getCurrentState()); } if (sourceCrop.height() <= 0) { crop.top = 0; - crop.bottom = parent->getCurrentState().active_legacy.h; + crop.bottom = parent->getActiveHeight(parent->getCurrentState()); } int32_t reqWidth = crop.width() * frameScale; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a750636520..eaaf7420f1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -356,6 +356,7 @@ private: friend class Layer; friend class BufferLayer; friend class BufferQueueLayer; + friend class BufferStateLayer; friend class MonitoredProducer; // For unit tests @@ -535,6 +536,10 @@ private: sp* outHandle, sp* outGbp, sp* outLayer); + status_t createBufferStateLayer(const sp& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags, sp* outHandle, + sp* outLayer); + status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* outHandle, sp* outLayer); diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index c42213a28d..f504c13a97 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -30,6 +30,7 @@ namespace android { // ---------------------------------------------------------------------------- +// TODO(marissaw): add new layer state values to SurfaceInterceptor SurfaceInterceptor::~SurfaceInterceptor() = default; diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 2ce32b5967..bde6614b61 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -62,38 +62,54 @@ const Color Color::WHITE{255, 255, 255, 255}; const Color Color::BLACK{0, 0, 0, 255}; const Color Color::TRANSPARENT{0, 0, 0, 0}; +using android::hardware::graphics::common::V1_1::BufferUsage; + std::ostream& operator<<(std::ostream& os, const Color& color) { os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a); return os; } // Fill a region with the specified color. -void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) { - 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 < 0) { - width += x; - x = 0; +void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, + const Color& color) { + Rect r(0, 0, buffer.width, buffer.height); + if (!r.intersect(rect, &r)) { + return; } - if (y < 0) { - height += y; - y = 0; - } - if (x + width > buffer.width) { - x = std::min(x, buffer.width); - width = buffer.width - x; + + int32_t width = r.right - r.left; + int32_t height = r.bottom - r.top; + + for (int32_t row = 0; row < height; row++) { + uint8_t* dst = + static_cast(buffer.bits) + (buffer.stride * (r.top + row) + r.left) * 4; + for (int32_t column = 0; column < width; column++) { + dst[0] = color.r; + dst[1] = color.g; + dst[2] = color.b; + dst[3] = color.a; + dst += 4; + } } - if (y + height > buffer.height) { - y = std::min(y, buffer.height); - height = buffer.height - y; +} + +// Fill a region with the specified color. +void fillGraphicBufferColor(const sp& buffer, const Rect& rect, const Color& color) { + Rect r(0, 0, buffer->width, buffer->height); + if (!r.intersect(rect, &r)) { + return; } - for (int32_t j = 0; j < height; j++) { - uint8_t* dst = static_cast(buffer.bits) + (buffer.stride * (y + j) + x) * 4; - for (int32_t i = 0; i < width; i++) { + int32_t width = r.right - r.left; + int32_t height = r.bottom - r.top; + + uint8_t* pixels; + buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); + + for (int32_t row = 0; row < height; row++) { + uint8_t* dst = pixels + (buffer->getStride() * (r.top + row) + r.left) * 4; + for (int32_t column = 0; column < width; column++) { dst[0] = color.r; dst[1] = color.g; dst[2] = color.b; @@ -101,6 +117,7 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const dst += 4; } } + buffer->unlock(); } // Check if a region has the specified color. @@ -301,8 +318,8 @@ protected: ASSERT_NO_FATAL_FAILURE(SetUpDisplay()); } - sp createLayer(const char* name, uint32_t width, uint32_t height, - uint32_t flags = 0) { + virtual sp createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0) { auto layer = mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags); EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; @@ -319,7 +336,7 @@ protected: return layer; } - ANativeWindow_Buffer getLayerBuffer(const sp& layer) { + ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp& layer) { // wait for previous transactions (such as setSize) to complete Transaction().apply(true); @@ -329,35 +346,103 @@ protected: return buffer; } - void postLayerBuffer(const sp& layer) { + void postBufferQueueLayerBuffer(const sp& layer) { ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost()); // wait for the newly posted buffer to be latched waitForLayerBuffers(); } - void fillLayerColor(const sp& layer, const Color& color) { + virtual void fillBufferQueueLayerColor(const sp& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - fillBufferColor(buffer, Rect(0, 0, buffer.width, buffer.height), color); - postLayerBuffer(layer); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + fillANativeWindowBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); + postBufferQueueLayerBuffer(layer); + } + + virtual void fillBufferStateLayerColor(const sp& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + sp buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); + } + + void fillLayerColor(uint32_t mLayerType, const sp& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } } - void fillLayerQuadrant(const sp& layer, const Color& topLeft, + void fillLayerQuadrant(uint32_t mLayerType, const sp& layer, + int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft, const Color& topRight, const Color& bottomLeft, const Color& bottomRight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } + } + + virtual void fillBufferQueueLayerQuadrant(const sp& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_TRUE(buffer.width % 2 == 0 && buffer.height % 2 == 0); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight); + fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft); + fillANativeWindowBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), + bottomRight); + + postBufferQueueLayerBuffer(layer); + } - const int32_t halfW = buffer.width / 2; - const int32_t halfH = buffer.height / 2; - fillBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); - fillBufferColor(buffer, Rect(halfW, 0, buffer.width, halfH), topRight); - fillBufferColor(buffer, Rect(0, halfH, halfW, buffer.height), bottomLeft); - fillBufferColor(buffer, Rect(halfW, halfH, buffer.width, buffer.height), bottomRight); + virtual void fillBufferStateLayerQuadrant(const sp& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { + sp buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); - postLayerBuffer(layer); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight); + fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft); + fillGraphicBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), bottomRight); + + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); } sp screenshot() { @@ -376,6 +461,10 @@ protected: // leave room for ~256 layers const int32_t mLayerZBase = std::numeric_limits::max() - 256; + void setPositionWithResizeHelper(uint32_t layerType); + void setSizeBasicHelper(uint32_t layerType); + void setMatrixWithResizeHelper(uint32_t layerType); + private: void SetUpDisplay() { mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain); @@ -404,10 +493,48 @@ private: int32_t mBufferPostDelay; }; -TEST_F(LayerTransactionTest, SetPositionBasic) { +class LayerTypeTransactionTest : public LayerTransactionTest, + public ::testing::WithParamInterface { +public: + LayerTypeTransactionTest() { mLayerType = GetParam(); } + + sp createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0) override { + // if the flags already have a layer type specified, return an error + if (flags & ISurfaceComposerClient::eFXSurfaceMask) { + return nullptr; + } + return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType); + } + + void fillLayerColor(const sp& layer, const Color& color, int32_t bufferWidth, + int32_t bufferHeight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color, + bufferWidth, bufferHeight)); + } + + void fillLayerQuadrant(const sp& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, const Color& topRight, + const Color& bottomLeft, const Color& bottomRight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer, + bufferWidth, bufferHeight, + topLeft, topRight, + bottomLeft, bottomRight)); + } + +protected: + uint32_t mLayerType; +}; + +INSTANTIATE_TEST_CASE_P( + LayerTypeTransactionTests, LayerTypeTransactionTest, + ::testing::Values(static_cast(ISurfaceComposerClient::eFXSurfaceBufferQueue), + static_cast(ISurfaceComposerClient::eFXSurfaceBufferState))); + +TEST_P(LayerTypeTransactionTest, SetPositionBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("default position"); @@ -425,10 +552,10 @@ TEST_F(LayerTransactionTest, SetPositionBasic) { } } -TEST_F(LayerTransactionTest, SetPositionRounding) { +TEST_P(LayerTypeTransactionTest, SetPositionRounding) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // GLES requires only 4 bits of subpixel precision during rasterization // XXX GLES composition does not match HWC composition due to precision @@ -447,10 +574,10 @@ TEST_F(LayerTransactionTest, SetPositionRounding) { } } -TEST_F(LayerTransactionTest, SetPositionOutOfBounds) { +TEST_P(LayerTypeTransactionTest, SetPositionOutOfBounds) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setPosition(layer, -32, -32).apply(); { @@ -465,10 +592,10 @@ TEST_F(LayerTransactionTest, SetPositionOutOfBounds) { } } -TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) { +TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // partially out of bounds Transaction().setPosition(layer, -30, -30).apply(); @@ -486,10 +613,10 @@ TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) { } } -TEST_F(LayerTransactionTest, SetPositionWithResize) { +void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); // setPosition is applied immediately by default, with or without resize // pending @@ -497,21 +624,43 @@ TEST_F(LayerTransactionTest, SetPositionWithResize) { { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(5, 10, 37, 42), Color::RED); - shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {5, 10, 37, 42}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {5, 10, 69, 74}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithNextResize) { +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) { + ASSERT_NO_FATAL_FAILURE( + setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferState) { + ASSERT_NO_FATAL_FAILURE( + setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_F(LayerTransactionTest, SetPositionWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // request setPosition to be applied with the next resize Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply(); @@ -533,17 +682,17 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResize) { } // finally resize and latch the buffer - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("new position applied"); screenshot()->expectColor(Rect(15, 20, 79, 84), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setPosition is not immediate even with SCALE_TO_WINDOW override Transaction() @@ -557,27 +706,38 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("new position applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetSizeBasic) { +void LayerTransactionTest::setSizeBasicHelper(uint32_t layerType) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); Transaction().setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {0, 0, 32, 32}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {0, 0, 64, 64}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -586,14 +746,22 @@ TEST_F(LayerTransactionTest, SetSizeBasic) { } } -TEST_F(LayerTransactionTest, SetSizeInvalid) { +TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) { + setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue); +} + +TEST_F(LayerTransactionTest, SetSizeBasic_BufferState) { + setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState); +} + +TEST_P(LayerTypeTransactionTest, SetSizeInvalid) { // cannot test robustness against invalid sizes (zero or really huge) } -TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) { +TEST_P(LayerTypeTransactionTest, SetSizeWithScaleToWindow) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -603,13 +771,13 @@ TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED); } -TEST_F(LayerTransactionTest, SetZBasic) { +TEST_P(LayerTypeTransactionTest, SetZBasic) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction().setLayer(layerR, mLayerZBase + 1).apply(); { @@ -624,13 +792,13 @@ TEST_F(LayerTransactionTest, SetZBasic) { } } -TEST_F(LayerTransactionTest, SetZNegative) { +TEST_P(LayerTypeTransactionTest, SetZNegative) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); { @@ -649,13 +817,13 @@ TEST_F(LayerTransactionTest, SetZNegative) { } } -TEST_F(LayerTransactionTest, SetRelativeZBasic) { +TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setPosition(layerG, 16, 16) @@ -677,16 +845,16 @@ TEST_F(LayerTransactionTest, SetRelativeZBasic) { } } -TEST_F(LayerTransactionTest, SetRelativeZNegative) { +TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { sp layerR; sp layerG; sp layerB; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); @@ -697,16 +865,16 @@ TEST_F(LayerTransactionTest, SetRelativeZNegative) { screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); } -TEST_F(LayerTransactionTest, SetRelativeZGroup) { +TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) { sp layerR; sp layerG; sp layerB; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); // layerR = 0, layerG = layerR + 3, layerB = 2 Transaction() @@ -764,14 +932,14 @@ TEST_F(LayerTransactionTest, SetRelativeZGroup) { } } -TEST_F(LayerTransactionTest, SetRelativeZBug64572777) { +TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setPosition(layerG, 16, 16) @@ -783,10 +951,10 @@ TEST_F(LayerTransactionTest, SetRelativeZBug64572777) { screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } -TEST_F(LayerTransactionTest, SetFlagsHidden) { +TEST_P(LayerTypeTransactionTest, SetFlagsHidden) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply(); { @@ -801,14 +969,14 @@ TEST_F(LayerTransactionTest, SetFlagsHidden) { } } -TEST_F(LayerTransactionTest, SetFlagsOpaque) { +TEST_P(LayerTypeTransactionTest, SetFlagsOpaque) { const Color translucentRed = {100, 0, 0, 100}; sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setLayer(layerR, mLayerZBase + 1) @@ -827,10 +995,10 @@ TEST_F(LayerTransactionTest, SetFlagsOpaque) { } } -TEST_F(LayerTransactionTest, SetFlagsSecure) { +TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); sp composer = ComposerService::getComposerService(); sp outBuffer; @@ -847,19 +1015,19 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { false)); } -TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferQueue) { const Rect top(0, 0, 32, 16); const Rect bottom(0, 16, 32, 32); sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::RED)); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::RED)); // setTransparentRegionHint always applies to the following buffer Transaction().setTransparentRegionHint(layer, Region(top)).apply(); - ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); { SCOPED_TRACE("top transparent"); auto shot = screenshot(); @@ -875,10 +1043,10 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { shot->expectColor(bottom, Color::RED); } - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); { SCOPED_TRACE("bottom transparent"); auto shot = screenshot(); @@ -887,7 +1055,58 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { } } -TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) { + const Rect top(0, 0, 32, 16); + const Rect bottom(0, 16, 32, 32); + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::RED)); + Transaction() + .setTransparentRegionHint(layer, Region(top)) + .setBuffer(layer, buffer) + .setSize(layer, 32, 32) + .apply(); + { + SCOPED_TRACE("top transparent"); + auto shot = screenshot(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::RED); + } + + Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); + { + SCOPED_TRACE("transparent region hint intermediate"); + auto shot = screenshot(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::BLACK); + } + + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT)); + Transaction().setBuffer(layer, buffer).setSize(layer, 32, 32).apply(); + { + SCOPED_TRACE("bottom transparent"); + auto shot = screenshot(); + shot->expectColor(top, Color::RED); + shot->expectColor(bottom, Color::BLACK); + } +} + +TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) { sp layerTransparent; sp layerR; ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); @@ -900,18 +1119,18 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) { .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED); } -TEST_F(LayerTransactionTest, SetAlphaBasic) { +TEST_P(LayerTypeTransactionTest, SetAlphaBasic) { sp layer1; sp layer2; ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32)); ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255})); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255})); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}, 32, 32)); Transaction() .setAlpha(layer1, 0.25f) @@ -931,11 +1150,11 @@ TEST_F(LayerTransactionTest, SetAlphaBasic) { } } -TEST_F(LayerTransactionTest, SetAlphaClamped) { +TEST_P(LayerTypeTransactionTest, SetAlphaClamped) { const Color color = {64, 0, 0, 255}; sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32)); Transaction().setAlpha(layer, 2.0f).apply(); { @@ -954,7 +1173,7 @@ TEST_F(LayerTransactionTest, SetColorBasic) { sp bufferLayer; sp colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -989,7 +1208,7 @@ TEST_F(LayerTransactionTest, SetColorWithAlpha) { sp bufferLayer; sp colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -1014,7 +1233,7 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { sp colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer( "childWithColor", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -1034,20 +1253,20 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { tolerance); } -TEST_F(LayerTransactionTest, SetColorWithBuffer) { +TEST_P(LayerTypeTransactionTest, SetColorWithBuffer) { sp bufferLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32)); // color is ignored Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } -TEST_F(LayerTransactionTest, SetLayerStackBasic) { +TEST_P(LayerTypeTransactionTest, SetLayerStackBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply(); { @@ -1062,11 +1281,11 @@ TEST_F(LayerTransactionTest, SetLayerStackBasic) { } } -TEST_F(LayerTransactionTest, SetMatrixBasic) { +TEST_P(LayerTypeTransactionTest, SetMatrixBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply(); { @@ -1104,11 +1323,11 @@ TEST_F(LayerTransactionTest, SetMatrixBasic) { } } -TEST_F(LayerTransactionTest, SetMatrixRot45) { +TEST_P(LayerTypeTransactionTest, SetMatrixRot45) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); const float rot = M_SQRT1_2; // 45 degrees const float trans = M_SQRT2 * 16.0f; @@ -1127,31 +1346,52 @@ TEST_F(LayerTransactionTest, SetMatrixRot45) { shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE); } -TEST_F(LayerTransactionTest, SetMatrixWithResize) { +void LayerTransactionTest::setMatrixWithResizeHelper(uint32_t layerType) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); // setMatrix is applied after any pending resize, unlike setPosition Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {0, 0, 32, 32}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {0, 0, 128, 128}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } } -TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) { +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) { + ASSERT_NO_FATAL_FAILURE( + setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferState) { + ASSERT_NO_FATAL_FAILURE( + setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -1162,11 +1402,11 @@ TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } -TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) { +TEST_P(LayerTypeTransactionTest, SetOverrideScalingModeBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); // XXX SCALE_CROP is not respected; calling setSize and // setOverrideScalingMode in separate transactions does not work @@ -1182,10 +1422,10 @@ TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) { } } -TEST_F(LayerTransactionTest, SetCropBasic) { +TEST_F(LayerTransactionTest, SetCropBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Rect crop(8, 8, 24, 24); Transaction().setCrop_legacy(layer, crop).apply(); @@ -1194,10 +1434,23 @@ TEST_F(LayerTransactionTest, SetCropBasic) { shot->expectBorder(crop, Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropEmpty) { +TEST_F(LayerTransactionTest, SetCropBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect crop(8, 8, 24, 24); + + Transaction().setCrop(layer, crop).apply(); + auto shot = screenshot(); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropEmpty_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("empty rect"); @@ -1212,10 +1465,29 @@ TEST_F(LayerTransactionTest, SetCropEmpty) { } } -TEST_F(LayerTransactionTest, SetCropOutOfBounds) { +TEST_F(LayerTransactionTest, SetCropEmpty_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("empty rect"); + Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + { + SCOPED_TRACE("negative rect"); + Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } +} + +TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); @@ -1223,10 +1495,22 @@ TEST_F(LayerTransactionTest, SetCropOutOfBounds) { shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithTranslation) { +TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply(); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Point position(32, 32); const Rect crop(8, 8, 24, 24); @@ -1236,10 +1520,24 @@ TEST_F(LayerTransactionTest, SetCropWithTranslation) { shot->expectBorder(crop + position, Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithScale) { +TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + const Point position(32, 32); + const Rect crop(8, 8, 24, 24); + Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply(); + auto shot = screenshot(); + shot->expectColor(crop + position, Color::RED); + shot->expectBorder(crop + position, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // crop is affected by matrix Transaction() @@ -1251,10 +1549,26 @@ TEST_F(LayerTransactionTest, SetCropWithScale) { shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithResize) { +TEST_F(LayerTransactionTest, SetCropWithScale_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // crop is affected by matrix + Transaction() + .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) + .setCrop(layer, Rect(8, 8, 24, 24)) + .apply(); + auto shot = screenshot(); + shot->expectColor(Rect(16, 16, 48, 48), Color::RED); + shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setCrop_legacy is applied immediately by default, with or without resize pending Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); @@ -1265,7 +1579,7 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -1274,10 +1588,34 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResize) { +TEST_F(LayerTransactionTest, SetCropWithResize_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("new buffer pending"); + auto shot = screenshot(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("new buffer"); + auto shot = screenshot(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // request setCrop_legacy to be applied with the next resize Transaction() @@ -1302,7 +1640,7 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { } // finally resize - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("new crop applied"); auto shot = screenshot(); @@ -1311,10 +1649,45 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // request setCrop_legacy to be applied with the next resize + Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); + { + SCOPED_TRACE("set crop 1"); + screenshot()->expectColor(Rect(8, 8, 24, 24), Color::RED); + } + + Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); + { + SCOPED_TRACE("set crop 2"); + screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); + } + + Transaction().setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("resize"); + screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); + } + + // finally resize + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("new buffer"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override Transaction() @@ -1332,7 +1705,38 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { // XXX crop is never latched without other geometry change (b/69315677) Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); + Transaction().setPosition(layer, 0, 0).apply(); + { + SCOPED_TRACE("new crop applied"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // all properties are applied immediate so setGeometryAppliesWithResize has no effect + Transaction() + .setCrop(layer, Rect(4, 4, 12, 12)) + .setSize(layer, 16, 16) + .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) + .setGeometryAppliesWithResize(layer) + .apply(); + { + SCOPED_TRACE("new crop pending"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } + + Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); Transaction().setPosition(layer, 0, 0).apply(); { SCOPED_TRACE("new crop applied"); @@ -1342,10 +1746,10 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { } } -TEST_F(LayerTransactionTest, SetFinalCropBasic) { +TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Rect crop(8, 8, 24, 24); // same as in SetCropBasic @@ -1355,10 +1759,10 @@ TEST_F(LayerTransactionTest, SetFinalCropBasic) { shot->expectBorder(crop, Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropEmpty) { +TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropEmpty { @@ -1374,10 +1778,10 @@ TEST_F(LayerTransactionTest, SetFinalCropEmpty) { } } -TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { +TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropOutOfBounds Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); @@ -1386,10 +1790,10 @@ TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { +TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // final crop is applied post-translation Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); @@ -1398,10 +1802,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithScale) { +TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // final crop is not affected by matrix Transaction() @@ -1413,10 +1817,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithScale) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithResize) { +TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithResize Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); @@ -1427,7 +1831,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -1436,10 +1840,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { } } -TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { +TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithNextResize Transaction() @@ -1464,7 +1868,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { } // finally resize - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("new final crop applied"); auto shot = screenshot(); @@ -1473,10 +1877,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { } } -TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithNextResizeScaleToWindow Transaction() @@ -1494,7 +1898,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { // XXX final crop is never latched without other geometry change (b/69315677) Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); Transaction().setPosition(layer, 0, 0).apply(); { SCOPED_TRACE("new final crop applied"); @@ -1504,6 +1908,282 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } +TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetBufferMultipleBuffers_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 1"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set buffer 2"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 3"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetBufferMultipleLayers_BufferState) { + sp layer1; + ASSERT_NO_FATAL_FAILURE( + layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp layer2; + ASSERT_NO_FATAL_FAILURE( + layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + + { + SCOPED_TRACE("set layer 1 buffer red"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer blue"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::RED); + shot->expectColor(Rect(0, 32, 32, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64)); + { + SCOPED_TRACE("set layer 1 buffer green"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer white"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } +} + +TEST_F(LayerTransactionTest, SetTransformRotate90_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE, + Color::GREEN, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformFlipH_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE, + Color::BLUE, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformFlipV_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED, + Color::GREEN, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction().setTransformToDisplayInverse(layer, false).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32)); + + Transaction().setTransformToDisplayInverse(layer, true).apply(); +} + +TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + sp fence = new Fence(-1); + + Transaction() + .setBuffer(layer, buffer) + .setAcquireFence(layer, fence) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetDataspaceBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction() + .setBuffer(layer, buffer) + .setDataspace(layer, ui::Dataspace::UNKNOWN) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetHdrMetadataBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + HdrMetadata hdrMetadata; + hdrMetadata.validTypes = 0; + Transaction() + .setBuffer(layer, buffer) + .setHdrMetadata(layer, hdrMetadata) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Region region; + region.set(32, 32); + Transaction() + .setBuffer(layer, buffer) + .setSurfaceDamageRegion(layer, region) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetApiBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction() + .setBuffer(layer, buffer) + .setApi(layer, NATIVE_WINDOW_API_CPU) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + // verify this doesn't cause a crash + Transaction().setSidebandStream(layer, nullptr).apply(); +} + class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { @@ -2569,8 +3249,8 @@ TEST_F(ScreenCaptureTest, CaptureCrop) { 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)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); SurfaceComposerClient::Transaction() .setLayer(redLayer, INT32_MAX - 1) @@ -2603,8 +3283,8 @@ TEST_F(ScreenCaptureTest, CaptureSize) { 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)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); SurfaceComposerClient::Transaction() .setLayer(redLayer, INT32_MAX - 1) @@ -2636,7 +3316,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); @@ -2655,9 +3335,9 @@ protected: void SetUp() override { LayerTransactionTest::SetUp(); bgLayer = createLayer("BG layer", 20, 20); - fillLayerColor(bgLayer, Color::RED); + fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20); fgLayer = createLayer("FG layer", 20, 20); - fillLayerColor(fgLayer, Color::BLUE); + fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20); Transaction().setLayer(fgLayer, mLayerZBase + 1).apply(); { SCOPED_TRACE("before anything"); -- cgit v1.2.3-59-g8ed1b From d01c4437b143b5f7ee5f35344da44806d76440f9 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 13 Aug 2018 10:38:47 -0700 Subject: SF: Set the buffer size immediately when applying a transaction If deferred transactions changes the buffer size as well, then the client will not receive the correct buffer size to render its contents. Bug: 111504081, 110763772 Test: go/wm-smoke Test: mmma frameworks/native/services/surfaceflinger/tests/ && \ mmma frameworks/native/libs/gui/tests/ && adb sync data && \ adb shell /data/nativetest/libgui_test/libgui_test && \ adb shell /data/nativetest/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest/SurfaceParcelable_test/SurfaceParcelable_test && \ adb shell /data/nativetest/sffakehwc_test/sffakehwc_test && \ adb shell /data/nativetest64/libgui_test/libgui_test && \ adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \ adb shell /data/nativetest64/sffakehwc_test/sffakehwc_test && \ echo "ALL TESTS PASSED" Change-Id: Id7c9662d9b755645b4cfadab2add285964adf4a4 --- libs/gui/SurfaceComposerClient.cpp | 3 --- services/surfaceflinger/Layer.cpp | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 17cff546e0..d0ac8de7a2 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -240,9 +240,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( s->w = w; s->h = h; - // Resizing a surface makes the transaction synchronous. - mForceSynchronous = true; - return *this; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f7f3fac934..04beae0c55 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1013,10 +1013,6 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); - - // record the new size, form this point on, when the client request - // a buffer, it'll get the new size. - setDefaultBufferSize(stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1253,6 +1249,10 @@ bool Layer::setSize(uint32_t w, uint32_t h) { mCurrentState.requested_legacy.h = h; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + + // record the new size, from this point on, when the client request + // a buffer, it'll get the new size. + setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h); return true; } bool Layer::setAlpha(float alpha) { -- cgit v1.2.3-59-g8ed1b From cd3f9e92f6dd1d4dc0fbabe248ccbfe3c56c7cdf Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Tue, 21 Aug 2018 15:15:42 -0700 Subject: Add getDisplayViewport for screenrecord tool Bug: b/112869712 Test: adb shell screenrecord Change-Id: I9f3f99de1a5bafc5318b24484f1916d28dcdfaa7 --- libs/gui/ISurfaceComposer.cpp | 48 ++++++++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 4 +++ libs/gui/include/gui/ISurfaceComposer.h | 6 +++- libs/gui/include/gui/SurfaceComposerClient.h | 3 ++ libs/gui/tests/Surface_test.cpp | 3 ++ services/surfaceflinger/SurfaceFlinger.cpp | 16 ++++++++++ services/surfaceflinger/SurfaceFlinger.h | 1 + 7 files changed, 80 insertions(+), 1 deletion(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 7f9668fc2c..81f692d374 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -331,6 +331,34 @@ public: return result; } + virtual status_t getDisplayViewport(const sp& display, Rect* outViewport) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to transact: %d", result); + return result; + } + result = reply.readInt32(); + if (result == NO_ERROR) { + result = reply.read(*outViewport); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to read: %d", result); + return result; + } + } + return result; + } + virtual int getActiveConfig(const sp& display) { Parcel data, reply; @@ -747,6 +775,26 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } + case GET_DISPLAY_VIEWPORT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + Rect outViewport; + sp display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to readStrongBinder: %d", result); + return result; + } + result = getDisplayViewport(display, &outViewport); + result = reply->writeInt32(result); + if (result == NO_ERROR) { + result = reply->write(outViewport); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to write: %d", result); + return result; + } + } + return NO_ERROR; + } case GET_ACTIVE_CONFIG: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 17cff546e0..6518596caf 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -842,6 +842,10 @@ status_t SurfaceComposerClient::getDisplayInfo(const sp& display, return NO_ERROR; } +status_t SurfaceComposerClient::getDisplayViewport(const sp& display, Rect* outViewport) { + return ComposerService::getComposerService()->getDisplayViewport(display, outViewport); +} + int SurfaceComposerClient::getActiveConfig(const sp& display) { return ComposerService::getComposerService()->getActiveConfig(display); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 98ec33888d..b9158f128c 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -157,6 +157,9 @@ public: virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats) = 0; + /* returns display viewport information of the given display */ + virtual status_t getDisplayViewport(const sp& display, Rect* outViewport) = 0; + /* indicates which of the configurations returned by getDisplayInfo is * currently active */ virtual int getActiveConfig(const sp& display) = 0; @@ -250,7 +253,8 @@ public: ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, GET_LAYER_DEBUG_INFO, - CREATE_SCOPED_CONNECTION + CREATE_SCOPED_CONNECTION, + GET_DISPLAY_VIEWPORT }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 4907866d0f..9bd1131ec0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -79,6 +79,9 @@ public: static status_t getDisplayInfo(const sp& display, DisplayInfo* info); + // Get the display viewport for the given display + static status_t getDisplayViewport(const sp& display, Rect* outViewport); + // Get the index of the current active configuration (relative to the list // returned by getDisplayInfo) static int getActiveConfig(const sp& display); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3542aba83f..f22e7026e9 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -581,6 +581,9 @@ public: Vector* /*configs*/) override { return NO_ERROR; } status_t getDisplayStats(const sp& /*display*/, DisplayStatInfo* /*stats*/) override { return NO_ERROR; } + status_t getDisplayViewport(const sp& /*display*/, Rect* /*outViewport*/) override { + return NO_ERROR; + } int getActiveConfig(const sp& /*display*/) override { return 0; } status_t setActiveConfig(const sp& /*display*/, int /*id*/) override { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 337f89da67..31152c4915 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -876,6 +876,21 @@ status_t SurfaceFlinger::getDisplayStats(const sp&, DisplayStatInfo* st return NO_ERROR; } +status_t SurfaceFlinger::getDisplayViewport(const sp& display, Rect* outViewport) { + if (outViewport == nullptr || display.get() == nullptr) { + return BAD_VALUE; + } + + sp device(getDisplayDevice(display)); + if (device == nullptr) { + return BAD_VALUE; + } + + *outViewport = device->getViewport(); + + return NO_ERROR; +} + int SurfaceFlinger::getActiveConfig(const sp& displayToken) { const auto display = getDisplayDevice(displayToken); if (!display) { @@ -4483,6 +4498,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_DISPLAY_COLOR_MODES: case GET_DISPLAY_CONFIGS: case GET_DISPLAY_STATS: + case GET_DISPLAY_VIEWPORT: case GET_SUPPORTED_FRAME_TIMESTAMPS: // Calling setTransactionState is safe, because you need to have been // granted a reference to Client* and Handle* to do anything with it. diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f5d8eb408b..273ce22d71 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -431,6 +431,7 @@ private: virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats); + virtual status_t getDisplayViewport(const sp& display, Rect* outViewport); virtual status_t getDisplayConfigs(const sp& displayToken, Vector* configs); virtual int getActiveConfig(const sp& displayToken); -- cgit v1.2.3-59-g8ed1b From 27de5df947ad88ea0a49e31680f80dc344c556bf Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 23 Aug 2018 17:04:51 -0700 Subject: Merge getDisplayViewport into DisplayInfo Bug: b/113041831 Test: build and adb shell screenrecord Change-Id: Id248d3ef6a6d90f51a5906e693d989b088e2bc99 --- libs/gui/ISurfaceComposer.cpp | 48 ---------------------------- libs/gui/SurfaceComposerClient.cpp | 4 --- libs/gui/include/gui/ISurfaceComposer.h | 6 +--- libs/gui/include/gui/SurfaceComposerClient.h | 3 -- libs/gui/tests/Surface_test.cpp | 3 -- libs/ui/include/ui/DisplayInfo.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 31 ++++++++---------- services/surfaceflinger/SurfaceFlinger.h | 1 - 8 files changed, 16 insertions(+), 82 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 81f692d374..7f9668fc2c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -331,34 +331,6 @@ public: return result; } - virtual status_t getDisplayViewport(const sp& display, Rect* outViewport) { - Parcel data, reply; - status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (result != NO_ERROR) { - ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result); - return result; - } - result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply); - if (result != NO_ERROR) { - ALOGE("getDisplayViewport failed to transact: %d", result); - return result; - } - result = reply.readInt32(); - if (result == NO_ERROR) { - result = reply.read(*outViewport); - if (result != NO_ERROR) { - ALOGE("getDisplayViewport failed to read: %d", result); - return result; - } - } - return result; - } - virtual int getActiveConfig(const sp& display) { Parcel data, reply; @@ -775,26 +747,6 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case GET_DISPLAY_VIEWPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - Rect outViewport; - sp display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getDisplayViewport failed to readStrongBinder: %d", result); - return result; - } - result = getDisplayViewport(display, &outViewport); - result = reply->writeInt32(result); - if (result == NO_ERROR) { - result = reply->write(outViewport); - if (result != NO_ERROR) { - ALOGE("getDisplayViewport failed to write: %d", result); - return result; - } - } - return NO_ERROR; - } case GET_ACTIVE_CONFIG: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6518596caf..17cff546e0 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -842,10 +842,6 @@ status_t SurfaceComposerClient::getDisplayInfo(const sp& display, return NO_ERROR; } -status_t SurfaceComposerClient::getDisplayViewport(const sp& display, Rect* outViewport) { - return ComposerService::getComposerService()->getDisplayViewport(display, outViewport); -} - int SurfaceComposerClient::getActiveConfig(const sp& display) { return ComposerService::getComposerService()->getActiveConfig(display); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index b9158f128c..98ec33888d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -157,9 +157,6 @@ public: virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats) = 0; - /* returns display viewport information of the given display */ - virtual status_t getDisplayViewport(const sp& display, Rect* outViewport) = 0; - /* indicates which of the configurations returned by getDisplayInfo is * currently active */ virtual int getActiveConfig(const sp& display) = 0; @@ -253,8 +250,7 @@ public: ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, GET_LAYER_DEBUG_INFO, - CREATE_SCOPED_CONNECTION, - GET_DISPLAY_VIEWPORT + CREATE_SCOPED_CONNECTION }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 9bd1131ec0..4907866d0f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -79,9 +79,6 @@ public: static status_t getDisplayInfo(const sp& display, DisplayInfo* info); - // Get the display viewport for the given display - static status_t getDisplayViewport(const sp& display, Rect* outViewport); - // Get the index of the current active configuration (relative to the list // returned by getDisplayInfo) static int getActiveConfig(const sp& display); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index f22e7026e9..3542aba83f 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -581,9 +581,6 @@ public: Vector* /*configs*/) override { return NO_ERROR; } status_t getDisplayStats(const sp& /*display*/, DisplayStatInfo* /*stats*/) override { return NO_ERROR; } - status_t getDisplayViewport(const sp& /*display*/, Rect* /*outViewport*/) override { - return NO_ERROR; - } int getActiveConfig(const sp& /*display*/) override { return 0; } status_t setActiveConfig(const sp& /*display*/, int /*id*/) override { diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h index 94caf6b9d3..8976d2d584 100644 --- a/libs/ui/include/ui/DisplayInfo.h +++ b/libs/ui/include/ui/DisplayInfo.h @@ -35,6 +35,8 @@ struct DisplayInfo { bool secure{false}; nsecs_t appVsyncOffset{0}; nsecs_t presentationDeadline{0}; + uint32_t viewportW{0}; + uint32_t viewportH{0}; }; /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a7792893ef..6162b16322 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -805,6 +805,12 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, float xdpi = hwConfig->getDpiX(); float ydpi = hwConfig->getDpiY(); + info.w = hwConfig->getWidth(); + info.h = hwConfig->getHeight(); + // Default display viewport to display width and height + info.viewportW = info.w; + info.viewportH = info.h; + if (type == DisplayDevice::DISPLAY_PRIMARY) { // The density of the device is provided by a build property float density = Density::getBuildDensity() / 160.0f; @@ -824,6 +830,13 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, // TODO: this needs to go away (currently needed only by webkit) const auto display = getDefaultDisplayDeviceLocked(); info.orientation = display ? display->getOrientation() : 0; + + // This is for screenrecord + const Rect viewport = display->getViewport(); + if (viewport.isValid()) { + info.viewportW = uint32_t(viewport.getWidth()); + info.viewportH = uint32_t(viewport.getHeight()); + } } else { // TODO: where should this value come from? static const int TV_DENSITY = 213; @@ -831,8 +844,6 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, info.orientation = 0; } - info.w = hwConfig->getWidth(); - info.h = hwConfig->getHeight(); info.xdpi = xdpi; info.ydpi = ydpi; info.fps = 1e9 / hwConfig->getVsyncPeriod(); @@ -879,21 +890,6 @@ status_t SurfaceFlinger::getDisplayStats(const sp&, DisplayStatInfo* st return NO_ERROR; } -status_t SurfaceFlinger::getDisplayViewport(const sp& display, Rect* outViewport) { - if (outViewport == nullptr || display.get() == nullptr) { - return BAD_VALUE; - } - - sp device(getDisplayDevice(display)); - if (device == nullptr) { - return BAD_VALUE; - } - - *outViewport = device->getViewport(); - - return NO_ERROR; -} - int SurfaceFlinger::getActiveConfig(const sp& displayToken) { const auto display = getDisplayDevice(displayToken); if (!display) { @@ -4544,7 +4540,6 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_DISPLAY_COLOR_MODES: case GET_DISPLAY_CONFIGS: case GET_DISPLAY_STATS: - case GET_DISPLAY_VIEWPORT: case GET_SUPPORTED_FRAME_TIMESTAMPS: // Calling setTransactionState is safe, because you need to have been // granted a reference to Client* and Handle* to do anything with it. diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ed9e212722..173ead8cd8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -435,7 +435,6 @@ private: virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats); - virtual status_t getDisplayViewport(const sp& display, Rect* outViewport); virtual status_t getDisplayConfigs(const sp& displayToken, Vector* configs); virtual int getActiveConfig(const sp& displayToken); -- cgit v1.2.3-59-g8ed1b From dcce0e2462c9bd0b6ac0db3f95c43cd2b9222eb2 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 23 Aug 2018 08:35:19 -0700 Subject: SF: Remove setFinalCrop impl 2/2 setFinalCrop functionality is reimplemented by creating a new bounds layer and applying a crop on this layer. see ag/4625718 Test: mmma frameworks/native/services/surfaceflinger/tests/ && \ mmma frameworks/native/libs/gui/tests/ && adb sync data && \ adb shell /data/nativetest64/libgui_test/libgui_test && \ adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \ adb shell /data/nativetest64/sffakehwc_test/sffakehwc_test && \ echo "ALL TESTS PASSED" Change-Id: I9be511c07a3351a2947afb2beed10ce2a462b635 --- cmds/surfacereplayer/proto/src/trace.proto | 7 +- cmds/surfacereplayer/replayer/Replayer.cpp | 13 -- cmds/surfacereplayer/replayer/Replayer.h | 2 - libs/gui/LayerDebugInfo.cpp | 5 +- libs/gui/LayerState.cpp | 6 - libs/gui/SurfaceComposerClient.cpp | 12 -- libs/gui/include/gui/LayerDebugInfo.h | 1 - libs/gui/include/gui/LayerState.h | 39 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 1 - services/surfaceflinger/BufferLayer.cpp | 11 -- services/surfaceflinger/BufferStateLayer.h | 2 - services/surfaceflinger/Layer.cpp | 69 +------ services/surfaceflinger/Layer.h | 7 - services/surfaceflinger/LayerRejecter.cpp | 5 - services/surfaceflinger/SurfaceFlinger.cpp | 4 - services/surfaceflinger/SurfaceInterceptor.cpp | 13 -- services/surfaceflinger/SurfaceInterceptor.h | 1 - .../surfaceflinger/layerproto/LayerProtoParser.cpp | 4 +- .../include/layerproto/LayerProtoParser.h | 1 - services/surfaceflinger/layerproto/layers.proto | 2 +- .../tests/SurfaceFlinger_test.filter | 2 +- .../tests/SurfaceInterceptor_test.cpp | 30 --- services/surfaceflinger/tests/Transaction_test.cpp | 216 --------------------- .../tests/fakehwc/SFFakeHwc_test.cpp | 156 --------------- 24 files changed, 24 insertions(+), 585 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 0bc08a91ab..68ddeb02d6 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -30,14 +30,13 @@ message Transaction { message SurfaceChange { required int32 id = 1; - + reserved 7; oneof SurfaceChange { PositionChange position = 2; SizeChange size = 3; AlphaChange alpha = 4; LayerChange layer = 5; CropChange crop = 6; - FinalCropChange final_crop = 7; MatrixChange matrix = 8; OverrideScalingModeChange override_scaling_mode = 9; TransparentRegionHintChange transparent_region_hint = 10; @@ -71,10 +70,6 @@ message CropChange { required Rectangle rectangle = 1; } -message FinalCropChange { - required Rectangle rectangle = 1; -} - message MatrixChange { required float dsdx = 1; required float dtdx = 2; diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index d9ff4ba59f..66025468ea 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -388,9 +388,6 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kMatrix: setMatrix(transaction, change.id(), change.matrix()); break; - case SurfaceChange::SurfaceChangeCase::kFinalCrop: - setFinalCrop(transaction, change.id(), change.final_crop()); - break; case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode: setOverrideScalingMode(transaction, change.id(), change.override_scaling_mode()); @@ -492,16 +489,6 @@ void Replayer::setCrop(SurfaceComposerClient::Transaction& t, t.setCrop_legacy(mLayers[id], r); } -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()); - t.setFinalCrop_legacy(mLayers[id], r); -} - 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(), diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 295403eace..68390d33ae 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -92,8 +92,6 @@ class Replayer { 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, diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp index d3dc16d30e..ccde9e08e1 100644 --- a/libs/gui/LayerDebugInfo.cpp +++ b/libs/gui/LayerDebugInfo.cpp @@ -42,7 +42,6 @@ status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const { RETURN_ON_ERROR(parcel->writeInt32(mWidth)); RETURN_ON_ERROR(parcel->writeInt32(mHeight)); RETURN_ON_ERROR(parcel->write(mCrop)); - RETURN_ON_ERROR(parcel->write(mFinalCrop)); RETURN_ON_ERROR(parcel->writeFloat(mColor.r)); RETURN_ON_ERROR(parcel->writeFloat(mColor.g)); RETURN_ON_ERROR(parcel->writeFloat(mColor.b)); @@ -81,7 +80,6 @@ status_t LayerDebugInfo::readFromParcel(const Parcel* parcel) { RETURN_ON_ERROR(parcel->readInt32(&mWidth)); RETURN_ON_ERROR(parcel->readInt32(&mHeight)); RETURN_ON_ERROR(parcel->read(mCrop)); - RETURN_ON_ERROR(parcel->read(mFinalCrop)); mColor.r = parcel->readFloat(); RETURN_ON_ERROR(parcel->errorCheck()); mColor.g = parcel->readFloat(); @@ -121,8 +119,7 @@ std::string to_string(const LayerDebugInfo& info) { info.mLayerStack, info.mZ, static_cast(info.mX), static_cast(info.mY), info.mWidth, info.mHeight); - result.appendFormat("crop=%s, finalCrop=%s, ", - to_string(info.mCrop).c_str(), to_string(info.mFinalCrop).c_str()); + result.appendFormat("crop=%s, ", to_string(info.mCrop).c_str()); 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()); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 05c24c5e1a..deb8ea8f7e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -38,7 +38,6 @@ status_t layer_state_t::write(Parcel& output) const *reinterpret_cast( output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; output.write(crop_legacy); - output.write(finalCrop_legacy); output.writeStrongBinder(barrierHandle_legacy); output.writeStrongBinder(reparentHandle); output.writeUint64(frameNumber_legacy); @@ -99,7 +98,6 @@ status_t layer_state_t::read(const Parcel& input) return BAD_VALUE; } input.read(crop_legacy); - input.read(finalCrop_legacy); barrierHandle_legacy = input.readStrongBinder(); reparentHandle = input.readStrongBinder(); frameNumber_legacy = input.readUint64(); @@ -248,10 +246,6 @@ void layer_state_t::merge(const layer_state_t& other) { barrierGbp_legacy = other.barrierGbp_legacy; frameNumber_legacy = other.frameNumber_legacy; } - if (other.what & eFinalCropChanged_legacy) { - what |= eFinalCropChanged_legacy; - finalCrop_legacy = other.finalCrop_legacy; - } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; overrideScalingMode = other.overrideScalingMode; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b8465e37a6..f913977544 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -353,18 +353,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop_ return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop_legacy( - const sp& sc, const Rect& crop) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eFinalCropChanged_legacy; - s->finalCrop_legacy = crop; - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, const sp& handle, diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h index 92bd8c5b28..66a7b4dc06 100644 --- a/libs/gui/include/gui/LayerDebugInfo.h +++ b/libs/gui/include/gui/LayerDebugInfo.h @@ -52,7 +52,6 @@ public: int32_t mWidth = -1; int32_t mHeight = -1; Rect mCrop = Rect::INVALID_RECT; - Rect mFinalCrop = Rect::INVALID_RECT; half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf); uint32_t mFlags = 0; PixelFormat mPixelFormat = PIXEL_FORMAT_NONE; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 098179864a..0859aff8fa 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -54,25 +54,24 @@ struct layer_state_t { eLayerStackChanged = 0x00000080, eCropChanged_legacy = 0x00000100, eDeferTransaction_legacy = 0x00000200, - eFinalCropChanged_legacy = 0x00000400, - eOverrideScalingModeChanged = 0x00000800, - eGeometryAppliesWithResize = 0x00001000, - eReparentChildren = 0x00002000, - eDetachChildren = 0x00004000, - eRelativeLayerChanged = 0x00008000, - eReparent = 0x00010000, - eColorChanged = 0x00020000, - eDestroySurface = 0x00040000, - eTransformChanged = 0x00100000, - eTransformToDisplayInverseChanged = 0x00200000, - eCropChanged = 0x00400000, - eBufferChanged = 0x00800000, - eAcquireFenceChanged = 0x01000000, - eDataspaceChanged = 0x02000000, - eHdrMetadataChanged = 0x04000000, - eSurfaceDamageRegionChanged = 0x08000000, - eApiChanged = 0x10000000, - eSidebandStreamChanged = 0x20000000, + eOverrideScalingModeChanged = 0x00000400, + eGeometryAppliesWithResize = 0x00000800, + eReparentChildren = 0x00001000, + eDetachChildren = 0x00002000, + eRelativeLayerChanged = 0x00004000, + eReparent = 0x00008000, + eColorChanged = 0x00010000, + eDestroySurface = 0x00020000, + eTransformChanged = 0x00040000, + eTransformToDisplayInverseChanged = 0x00080000, + eCropChanged = 0x00100000, + eBufferChanged = 0x00200000, + eAcquireFenceChanged = 0x00400000, + eDataspaceChanged = 0x00800000, + eHdrMetadataChanged = 0x01000000, + eSurfaceDamageRegionChanged = 0x02000000, + eApiChanged = 0x04000000, + eSidebandStreamChanged = 0x08000000, }; layer_state_t() @@ -88,7 +87,6 @@ struct layer_state_t { mask(0), reserved(0), crop_legacy(Rect::INVALID_RECT), - finalCrop_legacy(Rect::INVALID_RECT), frameNumber_legacy(0), overrideScalingMode(-1), transform(0), @@ -126,7 +124,6 @@ struct layer_state_t { uint8_t reserved; matrix22_t matrix; Rect crop_legacy; - Rect finalCrop_legacy; sp barrierHandle_legacy; sp reparentHandle; uint64_t frameNumber_legacy; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 9bd1131ec0..539e46c12d 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -204,7 +204,6 @@ public: Transaction& setMatrix(const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy); Transaction& setCrop_legacy(const sp& sc, const Rect& crop); - Transaction& setFinalCrop_legacy(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 diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 3e2fb2e408..0550b3527a 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -589,17 +589,6 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT ui::Transform t = getTransform(); Rect win = bounds; - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - win = t.transform(win); - if (!win.intersect(finalCrop, &win)) { - win.clear(); - } - win = t.inverse().transform(win); - if (!win.intersect(bounds, &win)) { - win.clear(); - } - } float left = float(win.left) / float(getActiveWidth(s)); float top = float(win.top) / float(getActiveHeight(s)); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 5cc8d567b9..ac3aad14b4 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -58,7 +58,6 @@ public: return s.transparentRegionHint; } Rect getCrop(const Layer::State& s) const; - Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; } bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; @@ -79,7 +78,6 @@ public: // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; - bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d2ab1b3d48..edd5cd1716 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -103,8 +103,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.flags = layerFlags; mCurrentState.active_legacy.transform.set(0, 0); mCurrentState.crop_legacy.makeInvalid(); - mCurrentState.finalCrop_legacy.makeInvalid(); - mCurrentState.requestedFinalCrop_legacy = mCurrentState.finalCrop_legacy; mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy; mCurrentState.z = 0; mCurrentState.color.a = 1.0f; @@ -298,11 +296,6 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { ui::Transform t = getTransform(); win = t.transform(win); - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - win.intersect(finalCrop, &win); - } - const sp& p = mDrawingParent.promote(); // Now we need to calculate the parent bounds, so we can clip ourselves to those. // When calculating the parent bounds for purposes of clipping, @@ -351,13 +344,9 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { ui::Transform t = s.active_legacy.transform; - if (p != nullptr || !s.finalCrop_legacy.isEmpty()) { + if (p != nullptr) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); - - if (!s.finalCrop_legacy.isEmpty()) { - floatWin = floatWin.intersect(s.finalCrop_legacy.toFloatRect()); - } floatWin = t.inverse().transform(floatWin); } @@ -388,12 +377,6 @@ Rect Layer::computeInitialCrop(const sp& display) const { if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - if (!activeCrop.intersect(finalCrop, &activeCrop)) { - activeCrop.clear(); - } - } const auto& p = mDrawingParent.promote(); if (p != nullptr) { @@ -554,12 +537,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // computeBounds returns a FloatRect to provide more accuracy during the // transformation. We then round upon constructing 'frame'. Rect frame{t.transform(computeBounds(activeTransparentRegion))}; - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - if (!frame.intersect(finalCrop, &frame)) { - frame.clear(); - } - } if (!frame.intersect(display->getViewport(), &frame)) { frame.clear(); } @@ -671,10 +648,6 @@ void Layer::updateCursorPosition(const sp& display) { Rect bounds = reduce(win, getActiveTransparentRegion(s)); Rect frame(getTransform().transform(bounds)); frame.intersect(display->getViewport(), &frame); - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - frame.intersect(finalCrop, &frame); - } auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); @@ -780,25 +753,9 @@ bool Layer::getFiltering() const { // local state // ---------------------------------------------------------------------------- -static void boundPoint(vec2* point, const Rect& crop) { - if (point->x < crop.left) { - point->x = crop.left; - } - if (point->x > crop.right) { - point->x = crop.right; - } - if (point->y < crop.top) { - point->y = crop.top; - } - if (point->y > crop.bottom) { - point->y = crop.bottom; - } -} - void Layer::computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh, bool useIdentityTransform) const { - const Layer::State& s(getDrawingState()); const ui::Transform renderAreaTransform(renderArea.getTransform()); const uint32_t height = renderArea.getHeight(); FloatRect win = computeBounds(); @@ -816,14 +773,6 @@ void Layer::computeGeometry(const RenderArea& renderArea, rt = layerTransform.transform(rt); } - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - boundPoint(<, finalCrop); - boundPoint(&lb, finalCrop); - boundPoint(&rb, finalCrop); - boundPoint(&rt, finalCrop); - } - renderengine::Mesh::VertexArray position(mesh.getPositionArray()); position[0] = renderAreaTransform.transform(lt); position[1] = renderAreaTransform.transform(lb); @@ -1292,20 +1241,6 @@ bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { return true; } -bool Layer::setFinalCrop_legacy(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop_legacy == crop) return false; - mCurrentState.sequence++; - mCurrentState.requestedFinalCrop_legacy = crop; - if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.finalCrop_legacy = crop; - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; - - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - bool Layer::setOverrideScalingMode(int32_t scalingMode) { if (scalingMode == mOverrideScalingMode) return false; mOverrideScalingMode = scalingMode; @@ -1417,7 +1352,6 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mWidth = ds.active_legacy.w; info.mHeight = ds.active_legacy.h; info.mCrop = ds.crop_legacy; - info.mFinalCrop = ds.finalCrop_legacy; info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); @@ -1955,7 +1889,6 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) size->set_h(state.active_legacy.h); LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop()); - LayerProtoHelper::writeToProto(state.finalCrop_legacy, layerInfo->mutable_final_crop()); layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 56261b9268..0a169efb66 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -129,10 +129,6 @@ public: Rect crop_legacy; Rect requestedCrop_legacy; - // finalCrop is expressed in display space coordinate. - Rect finalCrop_legacy; - Rect requestedFinalCrop_legacy; - // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber wp barrierLayer_legacy; @@ -225,8 +221,6 @@ public: virtual bool setPosition(float x, float y, bool immediate); // Buffer space virtual bool setCrop_legacy(const Rect& crop, bool immediate); - // Parent buffer space/display space - virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? @@ -351,7 +345,6 @@ public: return s.activeTransparentRegion_legacy; } virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } - virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; } protected: /* diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 136cdc03f7..72abea8b2d 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -90,11 +90,6 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) mCurrent.crop_legacy = mFront.requestedCrop_legacy; mRecomputeVisibleRegions = true; } - if (mFront.finalCrop_legacy != mFront.requestedFinalCrop_legacy) { - mFront.finalCrop_legacy = mFront.requestedFinalCrop_legacy; - mCurrent.finalCrop_legacy = mFront.requestedFinalCrop_legacy; - mRecomputeVisibleRegions = true; - } } ALOGD_IF(DEBUG_RESIZE, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 00e2bbdf39..3c8c92e2fa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3570,10 +3570,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFinalCropChanged_legacy) { - if (layer->setFinalCrop_legacy(s.finalCrop_legacy, !geometryAppliesWithResize)) - flags |= eTraversalNeeded; - } if (what & layer_state_t::eLayerStackChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); // We only allow setting layer stacks for top level layers, diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index f504c13a97..0b4c6fcb79 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -113,7 +113,6 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, layer->mCurrentState.barrierLayer_legacy.promote(), layer->mCurrentState.frameNumber_legacy); } - addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop_legacy); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } @@ -289,15 +288,6 @@ void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId setProtoRectLocked(protoRect, rect); } -void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId, - const Rect& rect) -{ - SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - FinalCropChange* finalCropChange(change->mutable_final_crop()); - Rectangle* protoRect(finalCropChange->mutable_rectangle()); - setProtoRectLocked(protoRect, rect); -} - void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber) { @@ -374,9 +364,6 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, } addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); } - if (state.what & layer_state_t::eFinalCropChanged_legacy) { - addFinalCropLocked(transaction, layerId, state.finalCrop_legacy); - } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 218a1d2d22..394b99b415 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -146,7 +146,6 @@ private: void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber); - void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode); void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index e1c0fd340d..a5bf9c16ca 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -101,7 +101,6 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layerProto.requested_position().y()}; layer->size = {layerProto.size().w(), layerProto.size().h()}; layer->crop = generateRect(layerProto.crop()); - layer->finalCrop = generateRect(layerProto.final_crop()); layer->isOpaque = layerProto.is_opaque(); layer->invalidate = layerProto.invalidate(); layer->dataspace = layerProto.dataspace(); @@ -299,8 +298,7 @@ std::string LayerProtoParser::Layer::to_string() const { z, static_cast(position.x), static_cast(position.y), size.x, size.y); - StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(), - finalCrop.to_string().c_str()); + StringAppendF(&result, "crop=%s, ", crop.to_string().c_str()); StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str()); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 360e5997d1..b1610cf9ce 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -92,7 +92,6 @@ public: float2 requestedPosition; int2 size; LayerProtoParser::Rect crop; - LayerProtoParser::Rect finalCrop; bool isOpaque; bool invalidate; std::string dataspace; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 7f882daa60..2a096345af 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -41,7 +41,7 @@ message LayerProto { // The layer's crop in it's own bounds. optional RectProto crop = 14; // The layer's crop in it's parent's bounds. - optional RectProto final_crop = 15; + optional RectProto final_crop = 15 [deprecated=true]; optional bool is_opaque = 16; optional bool invalidate = 17; optional string dataspace = 18; diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 1319e12493..34d0fd75f9 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize" + "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*" } } diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 8ac2c87b9e..740d2fa302 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -167,7 +167,6 @@ public: bool alphaUpdateFound(const SurfaceChange& change, bool foundAlpha); bool layerUpdateFound(const SurfaceChange& change, bool foundLayer); bool cropUpdateFound(const SurfaceChange& change, bool foundCrop); - bool finalCropUpdateFound(const SurfaceChange& change, bool foundFinalCrop); bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix); bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode); bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion); @@ -199,7 +198,6 @@ public: void alphaUpdate(Transaction&); void layerUpdate(Transaction&); void cropUpdate(Transaction&); - void finalCropUpdate(Transaction&); void matrixUpdate(Transaction&); void overrideScalingModeUpdate(Transaction&); void transparentRegionHintUpdate(Transaction&); @@ -323,10 +321,6 @@ void SurfaceInterceptorTest::cropUpdate(Transaction& t) { t.setCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } -void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) { - t.setFinalCrop_legacy(mBGSurfaceControl, CROP_UPDATE); -} - void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2); } @@ -377,7 +371,6 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::alphaUpdate); runInTransaction(&SurfaceInterceptorTest::layerUpdate); runInTransaction(&SurfaceInterceptorTest::cropUpdate); - runInTransaction(&SurfaceInterceptorTest::finalCropUpdate); runInTransaction(&SurfaceInterceptorTest::matrixUpdate); runInTransaction(&SurfaceInterceptorTest::overrideScalingModeUpdate); runInTransaction(&SurfaceInterceptorTest::transparentRegionHintUpdate); @@ -460,20 +453,6 @@ bool SurfaceInterceptorTest::cropUpdateFound(const SurfaceChange& change, bool f return foundCrop; } -bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change, - bool foundFinalCrop) { - bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left); - bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top); - bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right); - bool hasBottom(change.final_crop().rectangle().bottom() == CROP_UPDATE.bottom); - if (hasLeft && hasRight && hasTop && hasBottom && !foundFinalCrop) { - foundFinalCrop = true; - } else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) { - [] () { FAIL(); }(); - } - return foundFinalCrop; -} - bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) { bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2); bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2); @@ -593,9 +572,6 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kCrop: foundUpdate = cropUpdateFound(change, foundUpdate); break; - case SurfaceChange::SurfaceChangeCase::kFinalCrop: - foundUpdate = finalCropUpdateFound(change, foundUpdate); - break; case SurfaceChange::SurfaceChangeCase::kMatrix: foundUpdate = matrixUpdateFound(change, foundUpdate); break; @@ -636,7 +612,6 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayer)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kCrop)); - ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kFinalCrop)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kMatrix)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOverrideScalingMode)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint)); @@ -755,11 +730,6 @@ TEST_F(SurfaceInterceptorTest, InterceptCropUpdateWorks) { captureTest(&SurfaceInterceptorTest::cropUpdate, SurfaceChange::SurfaceChangeCase::kCrop); } -TEST_F(SurfaceInterceptorTest, InterceptFinalCropUpdateWorks) { - captureTest(&SurfaceInterceptorTest::finalCropUpdate, - SurfaceChange::SurfaceChangeCase::kFinalCrop); -} - TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) { captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix); } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 4ab4fec267..ed1529b37b 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1759,168 +1759,6 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) { } } -TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - const Rect crop(8, 8, 24, 24); - - // same as in SetCropBasic - Transaction().setFinalCrop_legacy(layer, crop).apply(); - auto shot = screenshot(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropEmpty - { - SCOPED_TRACE("empty rect"); - Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - { - SCOPED_TRACE("negative rect"); - Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } -} - -TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropOutOfBounds - Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // final crop is applied post-translation - Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); - auto shot = screenshot(); - shot->expectColor(Rect(16, 16, 24, 24), Color::RED); - shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // final crop is not affected by matrix - Transaction() - .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) - .apply(); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 24, 24), Color::RED); - shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropWithResize - Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 24, 24), Color::RED); - shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("resize applied"); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 16, 16), Color::RED); - shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); - } -} - -TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropWithNextResize - Transaction() - .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("waiting for next resize"); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); - { - SCOPED_TRACE("pending final crop modified"); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - // finally resize - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("new final crop applied"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - -TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropWithNextResizeScaleToWindow - Transaction() - .setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)) - .setSize(layer, 16, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("new final crop pending"); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 16, 16), Color::RED); - shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK); - } - - // XXX final crop is never latched without other geometry change (b/69315677) - Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - Transaction().setPosition(layer, 0, 0).apply(); - { - SCOPED_TRACE("new final crop applied"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( @@ -2346,7 +2184,6 @@ protected: t.setSize(mFGSurfaceControl, 64, 64); t.setPosition(mFGSurfaceControl, 64, 64); t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); }); EXPECT_INITIAL_STATE("After restoring initial state"); @@ -2375,43 +2212,6 @@ protected: } }; -// In this test we ensure that setGeometryAppliesWithResize actually demands -// a buffer of the new size, and not just any size. -TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { - EXPECT_INITIAL_STATE("before anything"); - // Normally the crop applies immediately even while a resize is pending. - asTransaction([&](Transaction& t) { - t.setSize(mFGSurfaceControl, 128, 128); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - }); - - EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); - - restoreInitialState(); - - // In order to prepare to submit a buffer at the wrong size, we acquire it prior to - // initiating the resize. - lockAndFillFGBuffer(); - - asTransaction([&](Transaction& t) { - t.setSize(mFGSurfaceControl, 128, 128); - t.setGeometryAppliesWithResize(mFGSurfaceControl); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - }); - - EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); - - // We now submit our old buffer, at the old size, and ensure it doesn't - // trigger geometry latching. - unlockFGBuffer(); - - EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)"); - - completeFGResize(); - - EXPECT_CROPPED_STATE("after the resize finishes"); -} - TEST_F(LayerUpdateTest, DeferredTransactionTest) { sp sc; { @@ -2588,22 +2388,6 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { } } -TEST_F(ChildLayerTest, ChildLayerFinalCropping) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); - }); - - { - ScreenCapture::captureScreen(&mCapture); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(4, 4); - mCapture->expectBGColor(5, 5); - } -} - TEST_F(ChildLayerTest, ChildLayerConstraints) { asTransaction([&](Transaction& t) { t.show(mChild); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 7fafab9302..356a880b6e 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -634,40 +634,6 @@ TEST_F(TransactionTest, LayerCrop) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); } -TEST_F(TransactionTest, LayerFinalCrop) { - // TODO: Add scaling to confirm that crop happens in display space? - { - TransactionScope ts(*sFakeComposer); - Rect cropRect(32, 32, 32 + 64, 32 + 64); - ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); - } - ASSERT_EQ(2, sFakeComposer->getFrameCount()); - - // In display space we are cropping with [32, 32, 96, 96] against display rect - // [64, 64, 128, 128]. Should yield display rect [64, 64, 96, 96] - auto referenceFrame = mBaseFrame; - referenceFrame[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 32.f, 32.f}; - referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 32, 64 + 32}; - - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - -TEST_F(TransactionTest, LayerFinalCropEmpty) { - // TODO: Add scaling to confirm that crop happens in display space? - { - TransactionScope ts(*sFakeComposer); - Rect cropRect(16, 16, 32, 32); - ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); - } - ASSERT_EQ(2, sFakeComposer->getFrameCount()); - - // In display space we are cropping with [16, 16, 32, 32] against display rect - // [64, 64, 128, 128]. The intersection is empty and only the background layer is composited. - std::vector referenceFrame(1); - referenceFrame[BG_LAYER] = mBaseFrame[BG_LAYER]; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - TEST_F(TransactionTest, LayerSetLayer) { { TransactionScope ts(*sFakeComposer); @@ -992,22 +958,6 @@ TEST_F(ChildLayerTest, Cropping) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); } -TEST_F(ChildLayerTest, FinalCropping) { - { - TransactionScope ts(*sFakeComposer); - ts.show(mChild); - ts.setPosition(mChild, 0, 0); - ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); - } - auto referenceFrame = mBaseFrame; - referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; - referenceFrame[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 5.f, 5.f}; - referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; - referenceFrame[CHILD_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 5.f, 5.f}; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - TEST_F(ChildLayerTest, Constraints) { { TransactionScope ts(*sFakeComposer); @@ -1354,7 +1304,6 @@ protected: ts.setSize(mFGSurfaceControl, 64, 64); ts.setPosition(mFGSurfaceControl, 64, 64); ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } }; @@ -1425,111 +1374,6 @@ TEST_F(LatchingTest, CropLatching) { EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); } -TEST_F(LatchingTest, FinalCropLatching) { - // Normally the crop applies immediately even while a resize is pending. - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - - auto referenceFrame1 = mBaseFrame; - referenceFrame1[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame1[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - EXPECT_TRUE(framesAreSame(referenceFrame1, sFakeComposer->getLatestFrame())); - - restoreInitialState(); - - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - - completeFGResize(); - - auto referenceFrame2 = mBaseFrame; - referenceFrame2[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame2[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - referenceFrame2[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); -} - -// In this test we ensure that setGeometryAppliesWithResize actually demands -// a buffer of the new size, and not just any size. -TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { - // Normally the crop applies immediately even while a resize is pending. - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - - auto referenceFrame1 = mBaseFrame; - referenceFrame1[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame1[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - EXPECT_TRUE(framesAreSame(referenceFrame1, sFakeComposer->getLatestFrame())); - - restoreInitialState(); - - // In order to prepare to submit a buffer at the wrong size, we acquire it prior to - // initiating the resize. - lockAndFillFGBuffer(); - - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - - // We now submit our old buffer, at the old size, and ensure it doesn't - // trigger geometry latching. - unlockFGBuffer(); - - auto referenceFrame2 = mBaseFrame; - referenceFrame2[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); - - completeFGResize(); - auto referenceFrame3 = referenceFrame2; - referenceFrame3[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame3[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - referenceFrame3[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame3, sFakeComposer->getLatestFrame())); -} - -TEST_F(LatchingTest, 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. - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - - { - TransactionScope ts(*sFakeComposer); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - - completeFGResize(); - - auto referenceFrame = mBaseFrame; - referenceFrame[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - } // namespace int main(int argc, char** argv) { -- cgit v1.2.3-59-g8ed1b From 0256f72d22cb4f8f73a86e3fbc916289b5feed43 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Fri, 31 Aug 2018 15:45:10 -0700 Subject: [SurfaceFlinger] Add getCompositionPreference APIs to SurfaceComposer. Previously we added APIs in ConfigStore to return the composition data space and pixel format that SurfaceFlinger would prefer for the device. This patch we plumb such information up to SurfaceComposer to prepare HWUI to use it to render. BUG: 113530681 Test: Build, flash, boot and verified the output in adb logcat. Change-Id: Ic96156e103af9f12febc98081179c2dc035a5139 --- libs/gui/ISurfaceComposer.cpp | 31 +++++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 5 ++++ libs/gui/include/gui/ISurfaceComposer.h | 6 ++++- libs/gui/include/gui/SurfaceComposerClient.h | 4 ++++ libs/gui/tests/Surface_test.cpp | 4 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 34 ++++++++++++++++++++++++---- services/surfaceflinger/SurfaceFlinger.h | 8 +++++++ 7 files changed, 86 insertions(+), 6 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 7f9668fc2c..08fbfffd03 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -558,6 +558,25 @@ public: outLayers->clear(); return reply.readParcelableVector(outLayers); } + + virtual status_t getCompositionPreference(ui::Dataspace* dataSpace, + ui::PixelFormat* pixelFormat) const { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + return error; + } + error = remote()->transact(BnSurfaceComposer::GET_COMPOSITION_PREFERENCE, data, &reply); + if (error != NO_ERROR) { + return error; + } + error = static_cast(reply.readInt32()); + if (error == NO_ERROR) { + *dataSpace = static_cast(reply.readInt32()); + *pixelFormat = static_cast(reply.readInt32()); + } + return error; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -881,6 +900,18 @@ status_t BnSurfaceComposer::onTransact( } return result; } + case GET_COMPOSITION_PREFERENCE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + ui::Dataspace dataSpace; + ui::PixelFormat pixelFormat; + status_t error = getCompositionPreference(&dataSpace, &pixelFormat); + reply->writeInt32(error); + if (error == NO_ERROR) { + reply->writeInt32(static_cast(dataSpace)); + reply->writeInt32(static_cast(pixelFormat)); + } + return NO_ERROR; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7168de4f3b..4caadd13bd 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -854,6 +854,11 @@ void SurfaceComposerClient::setDisplayPowerMode(const sp& token, ComposerService::getComposerService()->setPowerMode(token, mode); } +status_t SurfaceComposerClient::getCompositionPreference(ui::Dataspace* dataSpace, + ui::PixelFormat* pixelFormat) { + return ComposerService::getComposerService()->getCompositionPreference(dataSpace, pixelFormat); +} + status_t SurfaceComposerClient::clearAnimationFrameStats() { return ComposerService::getComposerService()->clearAnimationFrameStats(); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 98ec33888d..8015095a9e 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -214,6 +214,9 @@ public: * Requires the ACCESS_SURFACE_FLINGER permission. */ virtual status_t getLayerDebugInfo(std::vector* outLayers) const = 0; + + virtual status_t getCompositionPreference(ui::Dataspace* dataSpace, + ui::PixelFormat* pixelFormat) const = 0; }; // ---------------------------------------------------------------------------- @@ -250,7 +253,8 @@ public: ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, GET_LAYER_DEBUG_INFO, - CREATE_SCOPED_CONNECTION + CREATE_SCOPED_CONNECTION, + GET_COMPOSITION_PREFERENCE, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index d83ba84228..662acc9acf 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -101,6 +101,10 @@ public: /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); + // + static status_t getCompositionPreference(ui::Dataspace* dataSpace, + ui::PixelFormat* pixelFormat); + // ------------------------------------------------------------------------ // surface creation / destruction diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3542aba83f..243f27f813 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -622,6 +622,10 @@ public: status_t getLayerDebugInfo(std::vector* /*layers*/) const override { return NO_ERROR; } + status_t getCompositionPreference(ui::Dataspace* /*outDataSpace*/, + ui::PixelFormat* /*outPixelFormat*/) const override { + return NO_ERROR; + } protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d008f26bea..a5bd73a532 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -197,6 +197,8 @@ bool SurfaceFlinger::hasWideColorDisplay; int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault; bool SurfaceFlinger::useColorManagement; bool SurfaceFlinger::useContextPriority; +Dataspace SurfaceFlinger::compositionDataSpace = Dataspace::V0_SRGB; +ui::PixelFormat SurfaceFlinger::compositionPixelFormat = ui::PixelFormat::RGBA_8888; std::string getHwcServiceName() { char value[PROPERTY_VALUE_MAX] = {}; @@ -323,13 +325,24 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { hasWideColorDisplay = getBool(false); useColorManagement = - getBool(false); + getBool(false); + + auto surfaceFlingerConfigsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService(); + if (surfaceFlingerConfigsServiceV1_2) { + surfaceFlingerConfigsServiceV1_2->getCompositionPreference( + [&](Dataspace tmpDataSpace, ui::PixelFormat tmpPixelFormat) { + compositionDataSpace = tmpDataSpace; + compositionPixelFormat = tmpPixelFormat; + }); + } useContextPriority = getBool(true); V1_1::DisplayOrientation primaryDisplayOrientation = - getDisplayOrientation< V1_1::ISurfaceFlingerConfigs, &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>( + getDisplayOrientation( V1_1::DisplayOrientation::ORIENTATION_0); switch (primaryDisplayOrientation) { @@ -651,8 +664,11 @@ void SurfaceFlinger::init() { renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0); renderEngineFeature |= (useContextPriority ? renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0); - getBE().mRenderEngine = renderengine::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, - renderEngineFeature); + + // TODO(b/77156734): We need to stop casting and use HAL types when possible. + getBE().mRenderEngine = + renderengine::impl::RenderEngine::create(static_cast(compositionPixelFormat), + renderEngineFeature); LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine"); LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, @@ -1170,6 +1186,13 @@ status_t SurfaceFlinger::getLayerDebugInfo(std::vector* outLayer return NO_ERROR; } +status_t SurfaceFlinger::getCompositionPreference(Dataspace* outDataSpace, + ui::PixelFormat* outPixelFormat) const { + *outDataSpace = compositionDataSpace; + *outPixelFormat = compositionPixelFormat; + return NO_ERROR; +} + // ---------------------------------------------------------------------------- sp SurfaceFlinger::createDisplayEventConnection( @@ -4824,7 +4847,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // granted a reference to Client* and Handle* to do anything with it. case SET_TRANSACTION_STATE: // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h - case CREATE_SCOPED_CONNECTION: { + case CREATE_SCOPED_CONNECTION: + case GET_COMPOSITION_PREFERENCE: { return OK; } case CAPTURE_LAYERS: diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b20fe44688..72ede93dda 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -296,6 +296,12 @@ public: static bool useContextPriority; + // The data space and pixel format that SurfaceFlinger expects hardware composer + // to composite efficiently. Meaning under most scenarios, hardware composer + // will accept layers with the data space and pixel format. + static ui::Dataspace compositionDataSpace; + static ui::PixelFormat compositionPixelFormat; + static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } @@ -454,6 +460,8 @@ private: virtual status_t enableVSyncInjections(bool enable); virtual status_t injectVSync(nsecs_t when); virtual status_t getLayerDebugInfo(std::vector* outLayers) const; + status_t getCompositionPreference(ui::Dataspace* outDataSpace, + ui::PixelFormat* outPixelFormat) const override; /* ------------------------------------------------------------------------ -- cgit v1.2.3-59-g8ed1b From 0e3479f854cc5b5d89a70011f035de4839cab017 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 10 Sep 2018 16:49:30 -0700 Subject: Remove minLayer and maxLayer from screenshot code. When taking a full display screenshot, there's no longer a need for min and max layer. Instead, the entire display will be screenshotted. If only some layers should be screenshotted, then use the captureLayers method instead. This was already the case for real code, but required some clean up in Transaction_test Test: Transaction_test Change-Id: I774357b284ca9e026097f79fb7146e4931fa629a --- libs/gui/ISurfaceComposer.cpp | 9 +- libs/gui/SurfaceComposerClient.cpp | 7 +- libs/gui/include/gui/ISurfaceComposer.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 3 +- libs/gui/tests/Surface_test.cpp | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.h | 7 +- services/surfaceflinger/tests/Credentials_test.cpp | 6 +- services/surfaceflinger/tests/Transaction_test.cpp | 222 +++++++++++---------- .../tests/unittests/CompositionTest.cpp | 4 +- .../tests/unittests/TestableSurfaceFlinger.h | 7 +- 11 files changed, 143 insertions(+), 143 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 08fbfffd03..f99bc5307c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -104,16 +104,13 @@ public: 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) { + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); - data.writeInt32(minLayerZ); - data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); @@ -653,13 +650,11 @@ status_t BnSurfaceComposer::onTransact( data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); uint32_t reqHeight = data.readUint32(); - int32_t minLayerZ = data.readInt32(); - int32_t maxLayerZ = data.readInt32(); bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, + useIdentityTransform, static_cast(rotation)); reply->writeInt32(res); if (res == NO_ERROR) { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4caadd13bd..09ea0f601a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -876,13 +876,12 @@ 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, + uint32_t reqHeight, bool useIdentityTransform, uint32_t rotation, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, - maxLayerZ, useIdentityTransform, + status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, + useIdentityTransform, static_cast(rotation)); if (ret != NO_ERROR) { return ret; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 46103c4fb1..a55cfe04d9 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -193,8 +193,7 @@ public: */ 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; + bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; /** * Capture a subtree of the layer hierarchy, potentially ignoring the root node. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 662acc9acf..314b1182b4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -326,8 +326,7 @@ 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, + uint32_t reqHeight, bool useIdentityTransform, uint32_t rotation, sp* outBuffer); static status_t captureLayers(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 243f27f813..bc8089982c 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -135,7 +135,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { ISurfaceComposer::eDisplayIdMain)); sp outBuffer; ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), - 64, 64, 0, 0x7fffffff, false)); + 64, 64, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU)); @@ -166,7 +166,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), - 64, 64, 0, 0x7fffffff, false)); + 64, 64, false)); } TEST_F(SurfaceTest, ConcreteTypeIsSurface) { @@ -599,7 +599,6 @@ public: 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*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f17710ef0d..f218664af7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5199,8 +5199,8 @@ private: status_t SurfaceFlinger::captureScreen(const sp& displayToken, sp* outBuffer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, + uint32_t reqWidth, uint32_t reqHeight, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -5230,7 +5230,7 @@ status_t SurfaceFlinger::captureScreen(const sp& displayToken, DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, renderAreaRotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, - display, minLayerZ, maxLayerZ, std::placeholders::_1); + display, std::placeholders::_1); return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } @@ -5562,19 +5562,14 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& } void SurfaceFlinger::traverseLayersInDisplay(const sp& display, - 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. + // as we need to determine which layers belong to the requested display. for (const auto& layer : mDrawingState.layersSortedByZ) { if (!layer->belongsToDisplay(display->getLayerStack(), false)) { continue; } - const Layer::State& state(layer->getDrawingState()); // relative layers are traversed in Layer::traverseInZOrder - if (state.zOrderRelativeOf != nullptr || state.z < minLayerZ || state.z > maxLayerZ) { - continue; - } layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->belongsToDisplay(display->getLayerStack(), false)) { return; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 00ee2c4dac..9eb572c8f8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -439,8 +439,7 @@ private: ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); virtual status_t captureScreen(const sp& displayToken, sp* outBuffer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation); + bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats); @@ -599,8 +598,8 @@ private: TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, bool forSystem, int* outSyncFd); - void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, - int32_t maxLayerZ, const LayerVector::Visitor& visitor); + void traverseLayersInDisplay(const sp& display, + const LayerVector::Visitor& visitor); sp mStartPropertySetThread = nullptr; diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 8e23eb8e61..9e762f0eb1 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -23,8 +23,6 @@ using Transaction = SurfaceComposerClient::Transaction; namespace { const String8 DISPLAY_NAME("Credentials Display Test"); const String8 SURFACE_NAME("Test Surface Name"); -const int32_t MIN_LAYER_Z = 0; -const int32_t MAX_LAYER_Z = std::numeric_limits::max(); const uint32_t ROTATION = 0; const float FRAME_SCALE = 1.0f; } // namespace @@ -269,8 +267,8 @@ TEST_F(CredentialsTest, CaptureTest) { sp display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); std::function condition = [=]() { sp outBuffer; - return ScreenshotClient::capture(display, Rect(), 0 /*reqWidth*/, 0 /*reqHeight*/, - MIN_LAYER_Z, MAX_LAYER_Z, false, ROTATION, &outBuffer); + return ScreenshotClient::capture(display, Rect(), 0 /*reqWidth*/, 0 /*reqHeight*/, false, + ROTATION, &outBuffer); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ed1529b37b..3af98e5c9b 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -186,17 +186,15 @@ static void fillSurfaceRGBA8(const sp& sc, uint8_t r, uint8_t g, // individual pixel values for testing purposes. class ScreenCapture : public RefBase { public: - static void captureScreen(sp* sc, int32_t minLayerZ = 0, - int32_t maxLayerZ = std::numeric_limits::max()) { + static void captureScreen(std::unique_ptr* sc) { 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); + sf->captureScreen(display, &outBuffer, Rect(), 0, 0, false)); + *sc = std::make_unique(outBuffer); } static void captureLayers(std::unique_ptr* sc, sp& parentHandle, @@ -318,6 +316,12 @@ protected: ASSERT_NO_FATAL_FAILURE(SetUpDisplay()); } + virtual void TearDown() { + mBlackBgSurface = 0; + mClient->dispose(); + mClient = 0; + } + virtual sp createLayer(const char* name, uint32_t width, uint32_t height, uint32_t flags = 0) { auto layer = @@ -445,9 +449,9 @@ protected: Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); } - sp screenshot() { - sp screenshot; - ScreenCapture::captureScreen(&screenshot, mLayerZBase); + std::unique_ptr screenshot() { + std::unique_ptr screenshot; + ScreenCapture::captureScreen(&screenshot); return screenshot; } @@ -465,6 +469,7 @@ protected: void setSizeBasicHelper(uint32_t layerType); void setMatrixWithResizeHelper(uint32_t layerType); + sp mBlackBgSurface; private: void SetUpDisplay() { mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain); @@ -482,13 +487,26 @@ private: mBufferPostDelay = int32_t(1e6 / info.fps) * 3; mDisplayLayerStack = 0; + + mBlackBgSurface = mClient->createSurface(String8("BaseSurface"), mDisplayWidth, + mDisplayHeight, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor); + // set layer stack (b/68888219) Transaction t; t.setDisplayLayerStack(mDisplay, mDisplayLayerStack); + t.setLayerStack(mBlackBgSurface, mDisplayLayerStack); + t.setColor(mBlackBgSurface, half3{0, 0, 0}); + t.setLayer(mBlackBgSurface, mLayerZBase); t.apply(); } - void waitForLayerBuffers() { usleep(mBufferPostDelay); } + void waitForLayerBuffers() { + // Request an empty transaction to get applied synchronously to ensure the buffer is + // latched. + Transaction().apply(true); + usleep(mBufferPostDelay); + } int32_t mBufferPostDelay; }; @@ -793,6 +811,9 @@ TEST_P(LayerTypeTransactionTest, SetZBasic) { } TEST_P(LayerTypeTransactionTest, SetZNegative) { + sp parent = + LayerTransactionTest::createLayer("Parent", mDisplayWidth, mDisplayHeight, + ISurfaceComposerClient::eFXSurfaceContainer); sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); @@ -800,20 +821,22 @@ TEST_P(LayerTypeTransactionTest, SetZNegative) { ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); + Transaction() + .reparent(layerR, parent->getHandle()) + .reparent(layerG, parent->getHandle()) + .apply(); Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); { SCOPED_TRACE("layerR"); - sp screenshot; - ScreenCapture::captureScreen(&screenshot, -2, -1); - screenshot->expectColor(Rect(0, 0, 32, 32), Color::RED); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); } Transaction().setLayer(layerR, -3).apply(); { SCOPED_TRACE("layerG"); - sp screenshot; - ScreenCapture::captureScreen(&screenshot, -3, -1); - screenshot->expectColor(Rect(0, 0, 32, 32), Color::GREEN); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN); } } @@ -846,6 +869,9 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { } TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { + sp parent = + LayerTransactionTest::createLayer("Parent", mDisplayWidth, mDisplayHeight, + ISurfaceComposerClient::eFXSurfaceContainer); sp layerR; sp layerG; sp layerB; @@ -856,12 +882,17 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); + Transaction() + .reparent(layerB, parent->getHandle()) + .apply(); + // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); - sp screenshot; + std::unique_ptr screenshot; // only layerB is in this range - ScreenCapture::captureScreen(&screenshot, -2, -1); + sp parentHandle = parent->getHandle(); + ScreenCapture::captureLayers(&screenshot, parentHandle); screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); } @@ -1006,13 +1037,11 @@ TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { .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, - false)); + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, - false)); + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); } TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferQueue) { @@ -2038,8 +2067,8 @@ TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { - mComposerClient = new SurfaceComposerClient; - ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); sp display( SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); @@ -2050,24 +2079,22 @@ protected: ssize_t displayHeight = info.h; // Background surface - mBGSurfaceControl = - mComposerClient->createSurface(String8("BG Test Surface"), displayWidth, - displayHeight, PIXEL_FORMAT_RGBA_8888, 0); + mBGSurfaceControl = createLayer(String8("BG Test Surface"), displayWidth, + displayHeight, 0); ASSERT_TRUE(mBGSurfaceControl != nullptr); ASSERT_TRUE(mBGSurfaceControl->isValid()); fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195); // Foreground surface - mFGSurfaceControl = mComposerClient->createSurface(String8("FG Test Surface"), 64, 64, - PIXEL_FORMAT_RGBA_8888, 0); + mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0); + ASSERT_TRUE(mFGSurfaceControl != nullptr); ASSERT_TRUE(mFGSurfaceControl->isValid()); fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); // Synchronization surface - mSyncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1, - PIXEL_FORMAT_RGBA_8888, 0); + mSyncSurfaceControl = createLayer(String8("Sync Test Surface"), 1, 1, 0); ASSERT_TRUE(mSyncSurfaceControl != nullptr); ASSERT_TRUE(mSyncSurfaceControl->isValid()); @@ -2089,11 +2116,10 @@ protected: } virtual void TearDown() { - mComposerClient->dispose(); + LayerTransactionTest::TearDown(); mBGSurfaceControl = 0; mFGSurfaceControl = 0; mSyncSurfaceControl = 0; - mComposerClient = 0; } void waitForPostedBuffers() { @@ -2112,7 +2138,6 @@ protected: t.apply(true); } - sp mComposerClient; sp mBGSurfaceControl; sp mFGSurfaceControl; @@ -2122,10 +2147,10 @@ protected: }; TEST_F(LayerUpdateTest, RelativesAreNotDetached) { - sp sc; - sp relative = mComposerClient->createSurface(String8("relativeTestSurface"), 10, - 10, PIXEL_FORMAT_RGBA_8888, 0); + std::unique_ptr sc; + + sp relative = createLayer(String8("relativeTestSurface"), 10, 10, 0); fillSurfaceRGBA8(relative, 10, 10, 10); waitForPostedBuffers(); @@ -2188,7 +2213,7 @@ protected: EXPECT_INITIAL_STATE("After restoring initial state"); } - sp sc; + std::unique_ptr sc; }; class CropLatchingTest : public GeometryLatchingTest { @@ -2213,7 +2238,7 @@ protected: }; TEST_F(LayerUpdateTest, DeferredTransactionTest) { - sp sc; + std::unique_ptr sc; { SCOPED_TRACE("before anything"); ScreenCapture::captureScreen(&sc); @@ -2268,13 +2293,13 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { } TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { - sp sc; + std::unique_ptr sc; sp childNoBuffer = - mComposerClient->createSurface(String8("Bufferless child"), 10, 10, + mClient->createSurface(String8("Bufferless child"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); sp childBuffer = - mComposerClient->createSurface(String8("Buffered child"), 20, 20, + mClient->createSurface(String8("Buffered child"), 20, 20, PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); fillSurfaceRGBA8(childBuffer, 200, 200, 200); @@ -2296,7 +2321,7 @@ TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { } TEST_F(LayerUpdateTest, MergingTransactions) { - sp sc; + std::unique_ptr sc; { SCOPED_TRACE("before move"); ScreenCapture::captureScreen(&sc); @@ -2323,13 +2348,13 @@ class ChildLayerTest : public LayerUpdateTest { protected: void SetUp() override { LayerUpdateTest::SetUp(); - mChild = mComposerClient->createSurface(String8("Child surface"), 10, 10, + mChild = mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(mChild, 200, 200, 200); { SCOPED_TRACE("before anything"); - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectChildColor(64, 64); } } @@ -2339,7 +2364,7 @@ protected: } sp mChild; - sp mCapture; + std::unique_ptr mCapture; }; TEST_F(ChildLayerTest, ChildLayerPositioning) { @@ -2350,7 +2375,7 @@ TEST_F(ChildLayerTest, ChildLayerPositioning) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // But 10 pixels in we should see the child surface @@ -2362,7 +2387,7 @@ TEST_F(ChildLayerTest, ChildLayerPositioning) { asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground should now be at 0, 0 mCapture->expectFGColor(0, 0); // But 10 pixels in we should see the child surface @@ -2381,7 +2406,7 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(4, 4); mCapture->expectBGColor(5, 5); @@ -2396,7 +2421,7 @@ TEST_F(ChildLayerTest, ChildLayerConstraints) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectFGColor(0, 0); // Last pixel in foreground should now be the child. mCapture->expectChildColor(63, 63); @@ -2411,7 +2436,7 @@ TEST_F(ChildLayerTest, ChildLayerScaling) { // Find the boundary between the parent and child { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectChildColor(9, 9); mCapture->expectFGColor(10, 10); } @@ -2421,7 +2446,7 @@ TEST_F(ChildLayerTest, ChildLayerScaling) { // The boundary should be twice as far from the origin now. // The pixels from the last test should all be child now { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectChildColor(9, 9); mCapture->expectChildColor(10, 10); mCapture->expectChildColor(19, 19); @@ -2442,7 +2467,7 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Unblended child color mCapture->checkPixel(0, 0, 0, 254, 0); } @@ -2450,7 +2475,7 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { asTransaction([&](Transaction& t) { t.setAlpha(mChild, 0.5); }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Child and BG blended. mCapture->checkPixel(0, 0, 127, 127, 0); } @@ -2458,7 +2483,7 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.5); }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Child and BG blended. mCapture->checkPixel(0, 0, 95, 64, 95); } @@ -2472,7 +2497,7 @@ TEST_F(ChildLayerTest, ReparentChildren) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // But 10 pixels in we should see the child surface @@ -2486,7 +2511,7 @@ TEST_F(ChildLayerTest, ReparentChildren) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectFGColor(64, 64); // In reparenting we should have exposed the entire foreground surface. mCapture->expectFGColor(74, 74); @@ -2505,7 +2530,7 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // But 10 pixels in we should see the child surface @@ -2514,6 +2539,7 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { mCapture->expectFGColor(84, 84); } + asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); }); asTransaction([&](Transaction& t) { t.hide(mChild); }); @@ -2521,7 +2547,7 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { // Since the child has the same client as the parent, it will not get // detached and will be hidden. { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectFGColor(64, 64); mCapture->expectFGColor(74, 74); mCapture->expectFGColor(84, 84); @@ -2547,7 +2573,7 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // But 10 pixels in we should see the child surface @@ -2562,7 +2588,7 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { // Nothing should have changed. { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectFGColor(64, 64); mCapture->expectChildColor(74, 74); mCapture->expectFGColor(84, 84); @@ -2577,7 +2603,7 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // We've positioned the child in the top left. mCapture->expectChildColor(0, 0); // But it's only 10x10. @@ -2591,7 +2617,7 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // We've positioned the child in the top left. mCapture->expectChildColor(0, 0); mCapture->expectChildColor(10, 10); @@ -2610,7 +2636,7 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // We've positioned the child in the top left. mCapture->expectChildColor(0, 0); // But it's only 10x10. @@ -2629,7 +2655,7 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { { // The child should still be in the same place and not have any strange scaling as in // b/37673612. - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectChildColor(0, 0); mCapture->expectFGColor(10, 10); } @@ -2640,7 +2666,7 @@ TEST_F(ChildLayerTest, Bug36858924) { mChild.clear(); // Now recreate it as hidden - mChild = mComposerClient->createSurface(String8("Child surface"), 10, 10, + mChild = mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eHidden, mFGSurfaceControl.get()); @@ -2674,7 +2700,7 @@ TEST_F(ChildLayerTest, Reparent) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // But 10 pixels in we should see the child surface @@ -2686,7 +2712,7 @@ TEST_F(ChildLayerTest, Reparent) { asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectFGColor(64, 64); // In reparenting we should have exposed the entire foreground surface. mCapture->expectFGColor(74, 74); @@ -2705,7 +2731,7 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // But 10 pixels in we should see the child surface @@ -2715,7 +2741,7 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { } asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Nothing should have changed. mCapture->expectFGColor(64, 64); mCapture->expectChildColor(74, 74); @@ -2724,8 +2750,7 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { } TEST_F(ChildLayerTest, ReparentFromNoParent) { - sp newSurface = mComposerClient->createSurface(String8("New Surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0); + sp newSurface = createLayer(String8("New Surface"), 10, 10, 0); ASSERT_TRUE(newSurface != nullptr); ASSERT_TRUE(newSurface->isValid()); @@ -2739,7 +2764,7 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Top left of foreground must now be visible mCapture->expectFGColor(64, 64); // At 10, 10 we should see the new surface @@ -2749,7 +2774,7 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); }); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // 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); @@ -2760,12 +2785,12 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { TEST_F(ChildLayerTest, NestedChildren) { sp grandchild = - mComposerClient->createSurface(String8("Grandchild surface"), 10, 10, + mClient->createSurface(String8("Grandchild surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); fillSurfaceRGBA8(grandchild, 50, 50, 50); { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer // which begins at 64, 64 mCapture->checkPixel(64, 64, 50, 50, 50); @@ -2773,8 +2798,7 @@ TEST_F(ChildLayerTest, NestedChildren) { } TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { - sp relative = mComposerClient->createSurface(String8("Relative surface"), 128, - 128, PIXEL_FORMAT_RGBA_8888, 0); + sp relative = createLayer(String8("Relative surface"), 128, 128, 0); fillSurfaceRGBA8(relative, 255, 255, 255); Transaction t; @@ -2786,7 +2810,7 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { // We expect that the child should have been elevated above our // INT_MAX layer even though it's not a child of it. { - ScreenCapture::captureScreen(&mCapture); + mCapture = screenshot(); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); mCapture->checkPixel(10, 10, 255, 255, 255); @@ -2810,7 +2834,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { auto fgHandle = mFGSurfaceControl->getHandle(); sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); @@ -2826,7 +2850,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { auto fgHandle = mFGSurfaceControl->getHandle(); sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); @@ -2840,7 +2864,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { TEST_F(ScreenCaptureTest, CaptureTransparent) { sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); @@ -2860,10 +2884,9 @@ TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { auto fgHandle = mFGSurfaceControl->getHandle(); sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - sp relative = mComposerClient->createSurface(String8("Relative surface"), 10, - 10, PIXEL_FORMAT_RGBA_8888, 0); + sp relative = createLayer(String8("Relative surface"), 10, 10, 0); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); @@ -2884,10 +2907,10 @@ TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { auto fgHandle = mFGSurfaceControl->getHandle(); sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); sp relative = - mComposerClient->createSurface(String8("Relative surface"), 10, 10, + mClient->createSurface(String8("Relative surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); @@ -2918,7 +2941,7 @@ public: LayerUpdateTest::SetUp(); mChild = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(mChild, 200, 200, 200); @@ -2976,12 +2999,12 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { auto fgHandle = mFGSurfaceControl->getHandle(); sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->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, + mClient->createSurface(String8("Grandchild surface"), 5, 5, PIXEL_FORMAT_RGBA_8888, 0, child.get()); fillSurfaceRGBA8(grandchild, 50, 50, 50); @@ -3000,7 +3023,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { TEST_F(ScreenCaptureTest, CaptureChildOnly) { sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); auto childHandle = child->getHandle(); @@ -3015,13 +3038,13 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { sp child = - mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + mClient->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, + mClient->createSurface(String8("Grandchild surface"), 5, 5, PIXEL_FORMAT_RGBA_8888, 0, child.get()); fillSurfaceRGBA8(grandchild, 50, 50, 50); @@ -3040,10 +3063,9 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = createLayer(String8("Red surface"), 60, 60, 0); sp blueLayer = - mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); @@ -3074,10 +3096,9 @@ TEST_F(ScreenCaptureTest, CaptureCrop) { } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = createLayer(String8("Red surface"), 60, 60, 0); sp blueLayer = - mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + mClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); @@ -3110,13 +3131,12 @@ TEST_F(ScreenCaptureTest, CaptureSize) { } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = createLayer(String8("Red surface"), 60, 60, 0); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); auto redLayerHandle = redLayer->getHandle(); - mComposerClient->destroySurface(redLayerHandle); + mClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); sp outBuffer; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 5aa6e27553..d52f0d87c3 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -185,8 +185,6 @@ void CompositionTest::captureScreenComposition() { LayerCase::setupForScreenCapture(this); const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); - constexpr int32_t minLayerZ = -1; - constexpr int32_t maxLayerZ = 1000; constexpr bool useIdentityTransform = true; constexpr bool forSystem = true; @@ -194,7 +192,7 @@ void CompositionTest::captureScreenComposition() { DEFAULT_DISPLAY_HEIGHT, ui::Transform::ROT_0); auto traverseLayers = [this](const LayerVector::Visitor& visitor) { - return mFlinger.traverseLayersInDisplay(mDisplay, minLayerZ, maxLayerZ, visitor); + return mFlinger.traverseLayersInDisplay(mDisplay, visitor); }; // TODO: Eliminate expensive/real allocation if possible. diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 341734cd63..f367275c76 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -121,10 +121,9 @@ public: useIdentityTransform, forSystem, outSyncFd); } - auto traverseLayersInDisplay(const sp& display, int32_t minLayerZ, - int32_t maxLayerZ, const LayerVector::Visitor& visitor) { - return mFlinger->SurfaceFlinger::traverseLayersInDisplay(display, minLayerZ, maxLayerZ, - visitor); + auto traverseLayersInDisplay(const sp& display, + const LayerVector::Visitor& visitor) { + return mFlinger->SurfaceFlinger::traverseLayersInDisplay(display, visitor); } /* ------------------------------------------------------------------------ -- cgit v1.2.3-59-g8ed1b From d3788632cfc226386f7c7e30612ed2584b6ecb46 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 18 Sep 2018 16:01:31 -0700 Subject: [SurfaceFlinger] Implement per layer color transformation. Previously we introduced a new composer HAL API to set color transform for per layer and added the plumbing in SurfaceFlinger. This patch implements the functionality and alwasy mark those layers to fall back to GPU composition until composer 2.3 is implemented. BUG: 111562338 Test: Build, boot, flash, tested by setting a greyscale matrix on Settings Test: adb shell /data/nativetest/SurfaceFlinger_test/SurfaceFlinger_test Change-Id: If8d5ed52bf920d8cc962602196fb1b0b6e2955da --- libs/gui/LayerState.cpp | 9 ++++++ libs/gui/SurfaceComposerClient.cpp | 12 +++++++ libs/gui/include/gui/LayerState.h | 6 +++- libs/gui/include/gui/SurfaceComposerClient.h | 4 +++ services/surfaceflinger/BufferLayer.cpp | 1 + services/surfaceflinger/ColorLayer.cpp | 1 + services/surfaceflinger/Layer.cpp | 19 +++++++++++ services/surfaceflinger/Layer.h | 4 +++ services/surfaceflinger/LayerBE.cpp | 14 ++++++++ services/surfaceflinger/LayerBE.h | 1 + .../RenderEngine/gl/GLES20RenderEngine.cpp | 2 +- .../RenderEngine/gl/GLES20RenderEngine.h | 2 +- .../include/renderengine/RenderEngine.h | 5 +-- .../include/renderengine/private/Description.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 37 ++++++++++++++++++---- services/surfaceflinger/SurfaceFlinger.h | 1 - services/surfaceflinger/tests/Transaction_test.cpp | 28 ++++++++++++++++ .../tests/unittests/CompositionTest.cpp | 2 +- .../unittests/mock/RenderEngine/MockRenderEngine.h | 2 +- 19 files changed, 138 insertions(+), 14 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 5a8d8dbc81..2b0a46181b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -77,6 +77,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeBool(false); } + memcpy(output.writeInplace(16 * sizeof(float)), + colorTransform.asArray(), 16 * sizeof(float)); + return NO_ERROR; } @@ -130,6 +133,8 @@ status_t layer_state_t::read(const Parcel& input) sidebandStream = NativeHandle::create(input.readNativeHandle(), true); } + colorTransform = mat4(static_cast(input.readInplace(16 * sizeof(float)))); + return NO_ERROR; } @@ -314,6 +319,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eSidebandStreamChanged; sidebandStream = other.sidebandStream; } + if (other.what & eColorTransformChanged) { + what |= eColorTransformChanged; + colorTransform = other.colorTransform; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 09ea0f601a..1ac96094cc 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -602,6 +602,18 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroyS return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform( + const sp& sc, const mat3& matrix, const vec3& translation) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eColorTransformChanged; + s->colorTransform = mat4(matrix, translation); + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 9a9f633ed7..e06e2b14b9 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -72,6 +73,7 @@ struct layer_state_t { eSurfaceDamageRegionChanged = 0x02000000, eApiChanged = 0x04000000, eSidebandStreamChanged = 0x08000000, + eColorTransformChanged = 0x10000000, }; layer_state_t() @@ -94,7 +96,8 @@ struct layer_state_t { crop(Rect::INVALID_RECT), dataspace(ui::Dataspace::UNKNOWN), surfaceDamageRegion(), - api(-1) { + api(-1), + colorTransform(mat4()) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -150,6 +153,7 @@ struct layer_state_t { Region surfaceDamageRegion; int32_t api; sp sidebandStream; + mat4 colorTransform; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 314b1182b4..69a759fb4e 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -269,6 +269,10 @@ public: Transaction& destroySurface(const sp& sc); + // Set a color transform matrix on the given layer on the built-in display. + Transaction& setColorTransform(const sp& sc, const mat3& matrix, + const vec3& translation); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 642ed2fefc..1a73ff0391 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -258,6 +258,7 @@ void BufferLayer::setPerFrameData(const sp& display) { getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); + getBE().compositionInfo.hwc.colorTransform = getColorTransform(); setHwcLayerBuffer(display); } diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index b02c16c595..3a554c9e44 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -75,6 +75,7 @@ void ColorLayer::setPerFrameData(const sp& display) { // Clear out the transform, because it doesn't make sense absent a source buffer getBE().compositionInfo.hwc.transform = HWC2::Transform::None; + getBE().compositionInfo.hwc.colorTransform = getColorTransform(); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f9bc1e7007..8afd3b3df4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1546,6 +1546,25 @@ bool Layer::detachChildren() { return true; } +bool Layer::setColorTransform(const mat4& matrix) { + if (mCurrentState.colorTransform == matrix) { + return false; + } + ++mCurrentState.sequence; + mCurrentState.colorTransform = matrix; + setTransactionFlags(eTransactionNeeded); + return true; +} + +const mat4& Layer::getColorTransform() const { + return getDrawingState().colorTransform; +} + +bool Layer::hasColorTransform() const { + static const mat4 identityMatrix = mat4(); + return getDrawingState().colorTransform != identityMatrix; +} + bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 874b5513e3..4890fa603a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -181,6 +181,7 @@ public: int32_t api; sp sidebandStream; + mat4 colorTransform; }; explicit Layer(const LayerCreationArgs& args); @@ -255,6 +256,9 @@ public: virtual void setChildrenDrawingParent(const sp& layer); virtual bool reparent(const sp& newParentHandle); virtual bool detachChildren(); + virtual bool setColorTransform(const mat4& matrix); + virtual const mat4& getColorTransform() const; + virtual bool hasColorTransform() const; // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index ef017aa9d5..c9b793377a 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -112,6 +112,20 @@ void CompositionInfo::dumpHwc(std::string& result, const char* tag) const { hwc.surfaceDamage.dump(regionString, "surfaceDamage"); result += regionString.string(); } + + result += base::StringPrintf("\tcolor transform matrix:\n" + "\t\t[%f, %f, %f, %f,\n" + "\t\t %f, %f, %f, %f,\n" + "\t\t %f, %f, %f, %f,\n" + "\t\t %f, %f, %f, %f]\n", + hwc.colorTransform[0][0], hwc.colorTransform[1][0], + hwc.colorTransform[2][0], hwc.colorTransform[3][0], + hwc.colorTransform[0][1], hwc.colorTransform[1][1], + hwc.colorTransform[2][1], hwc.colorTransform[3][1], + hwc.colorTransform[0][2], hwc.colorTransform[1][2], + hwc.colorTransform[2][2], hwc.colorTransform[3][2], + hwc.colorTransform[0][3], hwc.colorTransform[1][3], + hwc.colorTransform[2][3], hwc.colorTransform[3][3]); } void CompositionInfo::dumpRe(std::string& result, const char* tag) const { diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 2722b01ea2..d63d16f59e 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -60,6 +60,7 @@ struct CompositionInfo { bool clearClientTarget = false; bool supportedPerFrameMetadata = false; HdrMetadata hdrMetadata; + mat4 colorTransform; } hwc; struct { bool blackoutLayer = false; diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp index 813c9e60ad..1b0a539f24 100644 --- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp @@ -743,7 +743,7 @@ void GLES20RenderEngine::setupLayerBlackedOut() { mState.textureEnabled = true; } -void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { +void GLES20RenderEngine::setColorTransform(const mat4& colorTransform) { mState.colorMatrix = colorTransform; } diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h index fa0141046f..4f03a904a9 100644 --- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h @@ -86,7 +86,7 @@ protected: void setupLayerTexturing(const Texture& texture) override; void setupLayerBlackedOut() override; void setupFillWithColor(float r, float g, float b, float a) override; - void setupColorTransform(const mat4& colorTransform) override; + void setColorTransform(const mat4& colorTransform) override; void disableTexturing() override; void disableBlending() override; diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h index 05668f8ce4..122271f9d6 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h @@ -115,7 +115,9 @@ public: virtual void setupLayerTexturing(const Texture& texture) = 0; virtual void setupLayerBlackedOut() = 0; virtual void setupFillWithColor(float r, float g, float b, float a) = 0; - virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; + + // Set a color transform matrix that is applied in linear space right before OETF. + virtual void setColorTransform(const mat4& /* colorTransform */) = 0; virtual void disableTexturing() = 0; virtual void disableBlending() = 0; @@ -163,7 +165,6 @@ public: bool useNativeFenceSync() const override; bool useWaitSync() const override; - void setupColorTransform(const mat4& /* colorTransform */) override {} protected: RenderEngine(uint32_t featureFlags); diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h index efab8ffb70..911bb7aacd 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h @@ -68,6 +68,8 @@ struct Description { // projection matrix mat4 projectionMatrix; + + // The color matrix will be applied in linear space right before OETF. mat4 colorMatrix; mat4 inputTransformMatrix; mat4 outputTransformMatrix; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9410cdb64c..c37b3b19b8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1604,6 +1604,11 @@ void SurfaceFlinger::calculateWorkingSet() { layer->forceClientComposition(displayId); } + // TODO(b/111562338) remove when composer 2.3 is shipped. + if (layer->hasColorTransform()) { + layer->forceClientComposition(displayId); + } + if (layer->getForceClientComposition(displayId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); layer->setCompositionType(displayId, HWC2::Composition::Client); @@ -2141,6 +2146,8 @@ void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionIn ALOGE_IF(error != HWC2::Error::None, "[SF] Failed to set surface damage: %s (%d)", to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setColorTransform(compositionInfo.hwc.colorTransform); } void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const @@ -3091,6 +3098,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId); ATRACE_INT("hasClientComposition", hasClientComposition); + mat4 colorMatrix; bool applyColorMatrix = false; bool needsEnhancedColorMatrix = false; @@ -3109,7 +3117,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { const bool skipClientColorTransform = getBE().mHwc->hasCapability( HWC2::Capability::SkipClientColorTransform); - mat4 colorMatrix; + // Compute the global color transform matrix. applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { colorMatrix = mDrawingState.colorMatrix; @@ -3125,8 +3133,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { colorMatrix *= mEnhancedSaturationMatrix; } - getRenderEngine().setupColorTransform(colorMatrix); - if (!display->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", display->getDisplayName().c_str()); @@ -3205,6 +3211,19 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { break; } case HWC2::Composition::Client: { + if (layer->hasColorTransform()) { + mat4 tmpMatrix; + if (applyColorMatrix) { + tmpMatrix = mDrawingState.colorMatrix; + } + tmpMatrix *= layer->getColorTransform(); + if (needsEnhancedColorMatrix) { + tmpMatrix *= mEnhancedSaturationMatrix; + } + getRenderEngine().setColorTransform(tmpMatrix); + } else { + getRenderEngine().setColorTransform(colorMatrix); + } layer->draw(renderArea, clip); break; } @@ -3217,9 +3236,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { firstLayer = false; } - if (applyColorMatrix || needsEnhancedColorMatrix) { - getRenderEngine().setupColorTransform(mat4()); - } + // Clear color transform matrix at the end of the frame. + getRenderEngine().setColorTransform(mat4()); // disable scissor at the end of the frame getBE().mRenderEngine->disableScissor(); @@ -3596,6 +3614,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setColor(s.color)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorTransformChanged) { + if (layer->setColorTransform(s.colorTransform)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eMatrixChanged) { // TODO: b/109894387 // @@ -5441,7 +5464,9 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, engine.clearWithColor(0, 0, 0, alpha); traverseLayers([&](Layer* layer) { + engine.setColorTransform(layer->getColorTransform()); layer->draw(renderArea, useIdentityTransform); + engine.setColorTransform(mat4()); }); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b77bf48361..3f3086b252 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -454,7 +454,6 @@ private: status_t getCompositionPreference(ui::Dataspace* outDataSpace, ui::PixelFormat* outPixelFormat) const override; - /* ------------------------------------------------------------------------ * DeathRecipient interface */ diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 3af98e5c9b..3166a8c752 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2064,6 +2064,34 @@ TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { Transaction().setSidebandStream(layer, nullptr).apply(); } +TEST_F(LayerTransactionTest, SetColorTransformBasic) { + sp colorLayer; + ASSERT_NO_FATAL_FAILURE( + colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); + + Transaction().setLayer(colorLayer, mLayerZBase + 1).apply(); + { + SCOPED_TRACE("default color"); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); + const Color expected = {90, 90, 90, 255}; + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + mat3 matrix; + matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11; + matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11; + matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11; + Transaction().setColor(colorLayer, color) + .setColorTransform(colorLayer, matrix, vec3()).apply(); + { + SCOPED_TRACE("new color"); + screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance); + } +} + class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 52e64d82ac..3caf1f6823 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -325,7 +325,7 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(ui::Dataspace::UNKNOWN)).Times(1); EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE)) .Times(1); - EXPECT_CALL(*test->mRenderEngine, setupColorTransform(_)).Times(2); + EXPECT_CALL(*test->mRenderEngine, setColorTransform(_)).Times(2); // These expectations retire on saturation as the code path these // expectations are for appears to make an extra call to them. // TODO: Investigate this extra call diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index c29452c0d2..6813cdaa7b 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -62,7 +62,7 @@ public: MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); MOCK_METHOD0(setupLayerBlackedOut, void()); MOCK_METHOD4(setupFillWithColor, void(float, float, float, float)); - MOCK_METHOD1(setupColorTransform, void(const mat4&)); + MOCK_METHOD1(setColorTransform, void(const mat4&)); MOCK_METHOD1(setSaturationMatrix, void(const mat4&)); MOCK_METHOD0(disableTexturing, void()); MOCK_METHOD0(disableBlending, void()); -- cgit v1.2.3-59-g8ed1b From 0e003c90398640fe653c534bfec84335a31c0d63 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 17 Sep 2018 11:09:51 -0700 Subject: [SurfaceFlinger] Accept data space and pixel format to take screenshot. Previously we always take screenshot in SRGB data space. However, the current color mode of the display can be in a different color mode, and so can HWUI render in a different color space. Thus we want to remove the assumption that screenshot is captured in SRGB color space, and give the ability to the upper stack to specify the color space and pixel format it wants. BUG: 111436479 BUG: 116112787 Test: Build, flash, boot and take screenshot, observe there's no color shift. Test: Take screenshot, verified the color profile is correct of the png. Change-Id: I83a0682839f39a99bff6b471a33060dd570be9b0 --- libs/gui/ISurfaceComposer.cpp | 27 ++++++++--- libs/gui/SurfaceComposerClient.cpp | 27 ++++++----- libs/gui/include/gui/ISurfaceComposer.h | 53 +++++++++++++++++++++- libs/gui/include/gui/SurfaceComposerClient.h | 16 ++++--- libs/gui/tests/Surface_test.cpp | 29 +++++++----- services/surfaceflinger/DisplayDevice.h | 7 +-- services/surfaceflinger/RenderArea.h | 7 +++ services/surfaceflinger/SurfaceFlinger.cpp | 29 +++++++----- services/surfaceflinger/SurfaceFlinger.h | 12 +++-- services/surfaceflinger/tests/Credentials_test.cpp | 10 ++-- .../tests/unittests/CompositionTest.cpp | 5 +- 11 files changed, 161 insertions(+), 61 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index f99bc5307c..cf9d4c5aba 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -103,11 +103,15 @@ public: } virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { + const ui::Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); + data.writeInt32(static_cast(reqDataspace)); + data.writeInt32(static_cast(reqPixelFormat)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -126,15 +130,19 @@ public: *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); + return result; } virtual status_t captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, + sp* outBuffer, const ui::Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale, bool childrenOnly) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); + data.writeInt32(static_cast(reqDataspace)); + data.writeInt32(static_cast(reqPixelFormat)); data.write(sourceCrop); data.writeFloat(frameScale); data.writeBool(childrenOnly); @@ -148,6 +156,7 @@ public: ALOGE("captureLayers failed to readInt32: %d", result); return result; } + *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); @@ -645,6 +654,8 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); + ui::Dataspace reqDataspace = static_cast(data.readInt32()); + ui::PixelFormat reqPixelFormat = static_cast(data.readInt32()); sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); @@ -653,8 +664,8 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, - useIdentityTransform, + status_t res = captureScreen(display, &outBuffer, reqDataspace, reqPixelFormat, + sourceCrop, reqWidth, reqHeight, useIdentityTransform, static_cast(rotation)); reply->writeInt32(res); if (res == NO_ERROR) { @@ -665,14 +676,16 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); + ui::Dataspace reqDataspace = static_cast(data.readInt32()); + ui::PixelFormat reqPixelFormat = static_cast(data.readInt32()); sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); bool childrenOnly = data.readBool(); - status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale, - childrenOnly); + status_t res = captureLayers(layerHandleBinder, &outBuffer, reqDataspace, + reqPixelFormat, 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 1ac96094cc..7498f365a0 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -887,13 +887,14 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, bool useIdentityTransform, uint32_t rotation, - sp* outBuffer) { +status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + uint32_t rotation, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, - useIdentityTransform, + status_t ret = s->captureScreen(display, outBuffer, reqDataSpace, reqPixelFormat, sourceCrop, + reqWidth, reqHeight, useIdentityTransform, static_cast(rotation)); if (ret != NO_ERROR) { return ret; @@ -901,21 +902,25 @@ status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, +status_t ScreenshotClient::captureLayers(const sp& layerHandle, + const ui::Dataspace reqDataSpace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, - false /* childrenOnly */); + status_t ret = s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat, + sourceCrop, frameScale, false /* childrenOnly */); return ret; } -status_t ScreenshotClient::captureChildLayers(const sp& layerHandle, Rect sourceCrop, +status_t ScreenshotClient::captureChildLayers(const sp& layerHandle, + const ui::Dataspace reqDataSpace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, - true /* childrenOnly */); + status_t ret = s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat, + sourceCrop, frameScale, true /* childrenOnly */); return ret; } // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index a55cfe04d9..781e06275d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -180,6 +180,36 @@ public: * The subregion can be optionally rotated. It will also be scaled to * match the size of the output buffer. * + * reqDataspace and reqPixelFormat specify the data space and pixel format + * of the buffer. The caller should pick the data space and pixel format + * that it can consume. + * + * At the moment, sourceCrop is ignored and is always set to the visible + * region (projected display viewport) of the screen. + * + * reqWidth and reqHeight specifies the size of the buffer. When either + * of them is 0, they are set to the size of the logical display viewport. + * + * When useIdentityTransform is true, layer transformations are disabled. + * + * rotation specifies the rotation of the source crop (and the pixels in + * it) around its center. + */ + virtual status_t captureScreen(const sp& display, sp* outBuffer, + const ui::Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; + /** + * Capture the specified screen. This requires READ_FRAME_BUFFER + * permission. This function will fail if there is a secure window on + * screen. + * + * This function can capture a subregion (the source crop) of the screen + * into an sRGB buffer with RGBA_8888 pixel format. + * The subregion can be optionally rotated. It will also be scaled to + * match the size of the output buffer. + * * At the moment, sourceCrop is ignored and is always set to the visible * region (projected display viewport) of the screen. * @@ -193,15 +223,34 @@ public: */ virtual status_t captureScreen(const sp& display, sp* outBuffer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; + bool useIdentityTransform, Rotation rotation = eRotateNone) { + return captureScreen(display, outBuffer, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, + sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation); + } /** * Capture a subtree of the layer hierarchy, potentially ignoring the root node. + * + * reqDataspace and reqPixelFormat specify the data space and pixel format + * of the buffer. The caller should pick the data space and pixel format + * that it can consume. */ virtual status_t captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, + sp* outBuffer, const ui::Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale = 1.0, bool childrenOnly = false) = 0; + /** + * Capture a subtree of the layer hierarchy into an sRGB buffer with RGBA_8888 pixel format, + * potentially ignoring the root node. + */ + status_t captureLayers(const sp& layerHandleBinder, sp* outBuffer, + const Rect& sourceCrop, float frameScale = 1.0, + bool childrenOnly = false) { + return captureLayers(layerHandleBinder, outBuffer, ui::Dataspace::V0_SRGB, + ui::PixelFormat::RGBA_8888, sourceCrop, frameScale, childrenOnly); + } + /* Clears the frame statistics for animations. * * Requires the ACCESS_SURFACE_FLINGER permission. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 69a759fb4e..1b4eda720a 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -329,12 +329,16 @@ 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, bool useIdentityTransform, uint32_t rotation, - sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float frameScale, - sp* outBuffer); - static status_t captureChildLayers(const sp& layerHandle, Rect sourceCrop, + static status_t capture(const sp& display, const ui::Dataspace reqDataSpace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + uint32_t rotation, sp* outBuffer); + static status_t captureLayers(const sp& layerHandle, const ui::Dataspace reqDataSpace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + float frameScale, sp* outBuffer); + static status_t captureChildLayers(const sp& layerHandle, + const ui::Dataspace reqDataSpace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, float frameScale, sp* outBuffer); }; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index bc8089982c..500df055c2 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -134,8 +134,9 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); sp outBuffer; - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), - 64, 64, false)); + ASSERT_EQ(NO_ERROR, + sf->captureScreen(display, &outBuffer, ui::Dataspace::V0_SRGB, + ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU)); @@ -165,8 +166,9 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), - 64, 64, false)); + ASSERT_EQ(NO_ERROR, + sf->captureScreen(display, &outBuffer, ui::Dataspace::V0_SRGB, + ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false)); } TEST_F(SurfaceTest, ConcreteTypeIsSurface) { @@ -596,14 +598,19 @@ public: } status_t setActiveColorMode(const sp& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } - status_t captureScreen(const sp& /*display*/, - sp* /*outBuffer*/, - Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, - bool /*useIdentityTransform*/, - Rotation /*rotation*/) override { return NO_ERROR; } + status_t captureScreen(const sp& /*display*/, sp* /*outBuffer*/, + const ui::Dataspace /*reqDataspace*/, + const ui::PixelFormat /*reqPixelFormat*/, Rect /*sourceCrop*/, + uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, + bool /*useIdentityTransform*/, Rotation /*rotation*/) override { + return NO_ERROR; + } virtual status_t captureLayers(const sp& /*parentHandle*/, - sp* /*outBuffer*/, const Rect& /*sourceCrop*/, - float /*frameScale*/, bool /*childrenOnly*/) override { + sp* /*outBuffer*/, + const ui::Dataspace /*reqDataspace*/, + const ui::PixelFormat /*reqPixelFormat*/, + const Rect& /*sourceCrop*/, float /*frameScale*/, + bool /*childrenOnly*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 38482c9dd5..918f7dec89 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -349,10 +349,11 @@ public: DisplayRenderArea(const sp device, ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(), - rotation) {} + device->getCompositionDataSpace(), rotation) {} DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, ui::Transform::orientation_flags rotation) - : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, + uint32_t reqHeight, ui::Dataspace reqDataSpace, + ui::Transform::orientation_flags rotation) + : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, getDisplayRotation(rotation, device->getInstallOrientation())), mDevice(device), mSourceCrop(sourceCrop) {} diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 3c11e73199..9bad6dee04 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -19,9 +20,11 @@ public: static float getCaptureFillValue(CaptureFill captureFill); RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill, + ui::Dataspace reqDataSpace, ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) : mReqWidth(reqWidth), mReqHeight(reqHeight), + mReqDataSpace(reqDataSpace), mCaptureFill(captureFill), mRotationFlags(rotation) {} @@ -66,6 +69,9 @@ public: int getReqWidth() const { return mReqWidth; }; int getReqHeight() const { return mReqHeight; }; + // Returns the composition data space of the render area. + ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } + // Returns the fill color of the physical render area. Regions not // covered by any rendered layer should be filled with this color. CaptureFill getCaptureFill() const { return mCaptureFill; }; @@ -73,6 +79,7 @@ public: private: const uint32_t mReqWidth; const uint32_t mReqHeight; + const ui::Dataspace mReqDataSpace; const CaptureFill mCaptureFill; const ui::Transform::orientation_flags mRotationFlags; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f0723e897b..fe42480fb1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5257,7 +5257,8 @@ private: }; status_t SurfaceFlinger::captureScreen(const sp& displayToken, - sp* outBuffer, Rect sourceCrop, + sp* outBuffer, const Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { @@ -5286,23 +5287,27 @@ status_t SurfaceFlinger::captureScreen(const sp& displayToken, } } - DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, renderAreaRotation); + DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace, + renderAreaRotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, display, std::placeholders::_1); - return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, + useIdentityTransform); } status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, + sp* outBuffer, const Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale, bool childrenOnly) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(SurfaceFlinger* flinger, const sp& layer, const Rect crop, - int32_t reqWidth, int32_t reqHeight, bool childrenOnly) - : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR), + int32_t reqWidth, int32_t reqHeight, Dataspace reqDataSpace, + bool childrenOnly) + : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR, reqDataSpace), mLayer(layer), mCrop(crop), mNeedsFiltering(false), @@ -5409,7 +5414,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, reqHeight = 1; } - LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly); + LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly); auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { @@ -5421,19 +5426,22 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, sp* outBuffer, + const ui::PixelFormat reqPixelFormat, bool useIdentityTransform) { ATRACE_CALL(); + // TODO(b/116112787) Make buffer usage a parameter. 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"); + static_cast(reqPixelFormat), 1, usage, + "screenshot"); // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -5509,8 +5517,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, const auto sourceCrop = renderArea.getSourceCrop(); const auto rotation = renderArea.getRotationFlags(); - // assume ColorMode::SRGB / RenderIntent::COLORIMETRIC - engine.setOutputDataSpace(Dataspace::SRGB); + engine.setOutputDataSpace(renderArea.getReqDataSpace()); engine.setDisplayMaxLuminance(DisplayDevice::sDefaultMaxLumiance); // make sure to clear all GL error flags diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f535c4ed13..1425818271 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -433,10 +433,14 @@ private: virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); virtual status_t captureScreen(const sp& displayToken, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + const ui::Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, - const Rect& sourceCrop, float frameScale, bool childrenOnly); + const ui::Dataspace reqDataspace, + const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, + float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& displayToken, Vector* configs); @@ -586,7 +590,7 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool useIdentityTransform); status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - sp* outBuffer, + sp* outBuffer, const ui::PixelFormat reqPixelFormat, bool useIdentityTransform); status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 9e762f0eb1..a73ec6c7ef 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -267,8 +267,9 @@ TEST_F(CredentialsTest, CaptureTest) { sp display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); std::function condition = [=]() { sp outBuffer; - return ScreenshotClient::capture(display, Rect(), 0 /*reqWidth*/, 0 /*reqHeight*/, false, - ROTATION, &outBuffer); + return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB, + ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/, + 0 /*reqHeight*/, false, ROTATION, &outBuffer); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } @@ -278,8 +279,9 @@ TEST_F(CredentialsTest, CaptureLayersTest) { sp outBuffer; std::function condition = [=]() { sp outBuffer; - return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(), Rect(), FRAME_SCALE, - &outBuffer); + return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(), + ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, + Rect(), FRAME_SCALE, &outBuffer); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 4e403b79ca..f4306794f3 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -189,7 +189,8 @@ void CompositionTest::captureScreenComposition() { constexpr bool forSystem = true; DisplayRenderArea renderArea(mDisplay, sourceCrop, DEFAULT_DISPLAY_WIDTH, - DEFAULT_DISPLAY_HEIGHT, ui::Transform::ROT_0); + DEFAULT_DISPLAY_HEIGHT, ui::Dataspace::V0_SRGB, + ui::Transform::ROT_0); auto traverseLayers = [this](const LayerVector::Visitor& visitor) { return mFlinger.traverseLayersInDisplay(mDisplay, visitor); @@ -287,7 +288,7 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, flush()).WillOnce(Return(ByMove(base::unique_fd()))); EXPECT_CALL(*test->mRenderEngine, finish()).WillOnce(Return(true)); - EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(ui::Dataspace::SRGB)).Times(1); + EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(_)).Times(1); EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE)) .Times(1); // This expectation retires on saturation as setViewportAndProjection is -- cgit v1.2.3-59-g8ed1b From c678097979379cdf59a91697a1fcfa020cda70b6 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Sun, 28 Oct 2018 15:24:08 -0700 Subject: [SurfaceFlinger] Expose WCG composition preference through ISurfaceComposer API. Previously we introduced an API to return default composition preference. However, wide color gamut composition preference is very likely to be different than the default composition preference. This patch also exposes this information back to upper stack, notable HWUI, to make sure upper stack has the flexibility to render into desired format for wide color gamut surfaces. BUG: 111436479 Test: Build, flash and boot, run some display validation. Change-Id: Ic05747591e62ca5f3c396704390555b7f545c31c --- libs/gui/ISurfaceComposer.cpp | 28 +++++++++++++++-------- libs/gui/SurfaceComposerClient.cpp | 9 +++++--- libs/gui/include/gui/ISurfaceComposer.h | 15 ++++++++++--- libs/gui/include/gui/SurfaceComposerClient.h | 12 +++++++--- libs/gui/tests/Surface_test.cpp | 6 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 33 ++++++++++++++++++---------- services/surfaceflinger/SurfaceFlinger.h | 15 +++++++++---- 7 files changed, 82 insertions(+), 36 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index cc0a307c65..e66c0e5dd6 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -565,8 +565,10 @@ public: return reply.readParcelableVector(outLayers); } - virtual status_t getCompositionPreference(ui::Dataspace* dataSpace, - ui::PixelFormat* pixelFormat) const { + virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace, + ui::PixelFormat* defaultPixelFormat, + ui::Dataspace* wideColorGamutDataspace, + ui::PixelFormat* wideColorGamutPixelFormat) const { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -578,8 +580,10 @@ public: } error = static_cast(reply.readInt32()); if (error == NO_ERROR) { - *dataSpace = static_cast(reply.readInt32()); - *pixelFormat = static_cast(reply.readInt32()); + *defaultDataspace = static_cast(reply.readInt32()); + *defaultPixelFormat = static_cast(reply.readInt32()); + *wideColorGamutDataspace = static_cast(reply.readInt32()); + *wideColorGamutPixelFormat = static_cast(reply.readInt32()); } return error; } @@ -925,13 +929,19 @@ status_t BnSurfaceComposer::onTransact( } case GET_COMPOSITION_PREFERENCE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - ui::Dataspace dataSpace; - ui::PixelFormat pixelFormat; - status_t error = getCompositionPreference(&dataSpace, &pixelFormat); + ui::Dataspace defaultDataspace; + ui::PixelFormat defaultPixelFormat; + ui::Dataspace wideColorGamutDataspace; + ui::PixelFormat wideColorGamutPixelFormat; + status_t error = + getCompositionPreference(&defaultDataspace, &defaultPixelFormat, + &wideColorGamutDataspace, &wideColorGamutPixelFormat); reply->writeInt32(error); if (error == NO_ERROR) { - reply->writeInt32(static_cast(dataSpace)); - reply->writeInt32(static_cast(pixelFormat)); + reply->writeInt32(static_cast(defaultDataspace)); + reply->writeInt32(static_cast(defaultPixelFormat)); + reply->writeInt32(static_cast(wideColorGamutDataspace)); + reply->writeInt32(static_cast(wideColorGamutDataspace)); } return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7498f365a0..e5a2454db3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -866,9 +866,12 @@ void SurfaceComposerClient::setDisplayPowerMode(const sp& token, ComposerService::getComposerService()->setPowerMode(token, mode); } -status_t SurfaceComposerClient::getCompositionPreference(ui::Dataspace* dataSpace, - ui::PixelFormat* pixelFormat) { - return ComposerService::getComposerService()->getCompositionPreference(dataSpace, pixelFormat); +status_t SurfaceComposerClient::getCompositionPreference( + ui::Dataspace* defaultDataspace, ui::PixelFormat* defaultPixelFormat, + ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat) { + return ComposerService::getComposerService() + ->getCompositionPreference(defaultDataspace, defaultPixelFormat, + wideColorGamutDataspace, wideColorGamutPixelFormat); } status_t SurfaceComposerClient::clearAnimationFrameStats() { diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 35cb3be7df..9316ae69bc 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -280,10 +280,19 @@ public: */ virtual status_t getLayerDebugInfo(std::vector* outLayers) const = 0; - virtual status_t getCompositionPreference(ui::Dataspace* dataSpace, - ui::PixelFormat* pixelFormat) const = 0; - virtual bool isColorManagementUsed() const = 0; + + /* Gets the composition preference of the default data space and default pixel format, + * as well as the wide color gamut data space and wide color gamut pixel format. + * If the wide color gamut data space is V0_SRGB, then it implies that the platform + * has no wide color gamut support. + * + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace, + ui::PixelFormat* defaultPixelFormat, + ui::Dataspace* wideColorGamutDataspace, + ui::PixelFormat* wideColorGamutPixelFormat) const = 0; }; // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 1b4eda720a..8ccee05ba4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -101,9 +101,15 @@ public: /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); - // - static status_t getCompositionPreference(ui::Dataspace* dataSpace, - ui::PixelFormat* pixelFormat); + /* Returns the composition preference of the default data space and default pixel format, + * as well as the wide color gamut data space and wide color gamut pixel format. + * If the wide color gamut data space is V0_SRGB, then it implies that the platform + * has no wide color gamut support. + */ + static status_t getCompositionPreference(ui::Dataspace* defaultDataspace, + ui::PixelFormat* defaultPixelFormat, + ui::Dataspace* wideColorGamutDataspace, + ui::PixelFormat* wideColorGamutPixelFormat); // ------------------------------------------------------------------------ // surface creation / destruction diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 25f762bbe3..a3e9249ac2 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -628,8 +628,10 @@ public: status_t getLayerDebugInfo(std::vector* /*layers*/) const override { return NO_ERROR; } - status_t getCompositionPreference(ui::Dataspace* /*outDataSpace*/, - ui::PixelFormat* /*outPixelFormat*/) const override { + status_t getCompositionPreference( + ui::Dataspace* /*outDefaultDataspace*/, ui::PixelFormat* /*outDefaultPixelFormat*/, + ui::Dataspace* /*outWideColorGamutDataspace*/, + ui::PixelFormat* /*outWideColorGamutPixelFormat*/) const override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fc8ca54797..5c31ada5ef 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -196,8 +196,10 @@ bool SurfaceFlinger::hasWideColorDisplay; int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault; bool SurfaceFlinger::useColorManagement; bool SurfaceFlinger::useContextPriority; -Dataspace SurfaceFlinger::compositionDataSpace = Dataspace::V0_SRGB; -ui::PixelFormat SurfaceFlinger::compositionPixelFormat = ui::PixelFormat::RGBA_8888; +Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB; +ui::PixelFormat SurfaceFlinger::defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888; +Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB; +ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; std::string getHwcServiceName() { char value[PROPERTY_VALUE_MAX] = {}; @@ -303,10 +305,13 @@ SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory) auto surfaceFlingerConfigsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService(); if (surfaceFlingerConfigsServiceV1_2) { surfaceFlingerConfigsServiceV1_2->getCompositionPreference( - [&](Dataspace tmpDataSpace, ui::PixelFormat tmpPixelFormat) { - compositionDataSpace = tmpDataSpace; - compositionPixelFormat = tmpPixelFormat; - }); + [&](auto tmpDefaultDataspace, auto tmpDefaultPixelFormat, + auto tmpWideColorGamutDataspace, auto tmpWideColorGamutPixelFormat) { + defaultCompositionDataspace = tmpDefaultDataspace; + defaultCompositionPixelFormat = tmpDefaultPixelFormat; + wideColorGamutCompositionDataspace = tmpWideColorGamutDataspace; + wideColorGamutCompositionPixelFormat = tmpWideColorGamutPixelFormat; + }); } useContextPriority = getBool(compositionPixelFormat), - renderEngineFeature); + renderengine::RenderEngine::create(static_cast(defaultCompositionPixelFormat), + renderEngineFeature); LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine"); LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, @@ -1157,10 +1162,14 @@ status_t SurfaceFlinger::getLayerDebugInfo(std::vector* outLayer return NO_ERROR; } -status_t SurfaceFlinger::getCompositionPreference(Dataspace* outDataSpace, - ui::PixelFormat* outPixelFormat) const { - *outDataSpace = compositionDataSpace; - *outPixelFormat = compositionPixelFormat; +status_t SurfaceFlinger::getCompositionPreference( + Dataspace* outDataspace, ui::PixelFormat* outPixelFormat, + Dataspace* outWideColorGamutDataspace, + ui::PixelFormat* outWideColorGamutPixelFormat) const { + *outDataspace = defaultCompositionDataspace; + *outPixelFormat = defaultCompositionPixelFormat; + *outWideColorGamutDataspace = wideColorGamutCompositionDataspace; + *outWideColorGamutPixelFormat = wideColorGamutCompositionPixelFormat; return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 73c9d952d9..d60765cc1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -294,8 +294,14 @@ public: // The data space and pixel format that SurfaceFlinger expects hardware composer // to composite efficiently. Meaning under most scenarios, hardware composer // will accept layers with the data space and pixel format. - static ui::Dataspace compositionDataSpace; - static ui::PixelFormat compositionPixelFormat; + static ui::Dataspace defaultCompositionDataspace; + static ui::PixelFormat defaultCompositionPixelFormat; + + // The data space and pixel format that SurfaceFlinger expects hardware composer + // to composite efficiently for wide color gamut surfaces. Meaning under most scenarios, + // hardware composer will accept layers with the data space and pixel format. + static ui::Dataspace wideColorGamutCompositionDataspace; + static ui::PixelFormat wideColorGamutCompositionPixelFormat; static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; @@ -460,9 +466,10 @@ private: virtual status_t enableVSyncInjections(bool enable); virtual status_t injectVSync(nsecs_t when); virtual status_t getLayerDebugInfo(std::vector* outLayers) const; - status_t getCompositionPreference(ui::Dataspace* outDataSpace, - ui::PixelFormat* outPixelFormat) const override; virtual bool isColorManagementUsed() const; + status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat, + ui::Dataspace* outWideColorGamutDataspace, + ui::PixelFormat* outWideColorGamutPixelFormat) const override; /* ------------------------------------------------------------------------ * DeathRecipient interface -- cgit v1.2.3-59-g8ed1b From 7a9b6ff7ce374ecf49990ee2496130c75a37f7fd Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 21 Aug 2018 17:26:20 -0700 Subject: blast: Create ITransactionCompletedListener ITransactionCompletedListener will be used to send a binder callback from SurfaceFlinger to SurfaceComposerClient. Test: Transaction_test Bug: 80477568 Change-Id: I1e6c18642109dc782990219d140cc38cf412fa0b --- libs/gui/Android.bp | 1 + libs/gui/ITransactionCompletedListener.cpp | 66 ++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 26 +++++++++ .../include/gui/ITransactionCompletedListener.h | 42 ++++++++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 22 +++++++- 5 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 libs/gui/ITransactionCompletedListener.cpp create mode 100644 libs/gui/include/gui/ITransactionCompletedListener.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 98264ac35f..7677c3a919 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -107,6 +107,7 @@ cc_library_shared { "IProducerListener.cpp", "ISurfaceComposer.cpp", "ISurfaceComposerClient.cpp", + "ITransactionCompletedListener.cpp", "LayerDebugInfo.cpp", "LayerState.cpp", "OccupancyTracker.cpp", diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp new file mode 100644 index 0000000000..38ff59d746 --- /dev/null +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#define LOG_TAG "ITransactionCompletedListener" +//#define LOG_NDEBUG 0 + +#include + +namespace android { + +namespace { // Anonymous + +enum class Tag : uint32_t { + ON_TRANSACTION_COMPLETED = IBinder::FIRST_CALL_TRANSACTION, + LAST = ON_TRANSACTION_COMPLETED, +}; + +} // Anonymous namespace + +class BpTransactionCompletedListener : public SafeBpInterface { +public: + explicit BpTransactionCompletedListener(const sp& impl) + : SafeBpInterface(impl, "BpTransactionCompletedListener") { + } + + ~BpTransactionCompletedListener() override; + + void onTransactionCompleted() override { + callRemoteAsync( + Tag::ON_TRANSACTION_COMPLETED); + } +}; + +// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see +// clang warning -Wweak-vtables) +BpTransactionCompletedListener::~BpTransactionCompletedListener() = default; + +IMPLEMENT_META_INTERFACE(TransactionCompletedListener, "android.gui.ITransactionComposerListener"); + +status_t BnTransactionCompletedListener::onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags) { + if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast(Tag::LAST)) { + return BBinder::onTransact(code, data, reply, flags); + } + auto tag = static_cast(code); + switch (tag) { + case Tag::ON_TRANSACTION_COMPLETED: + return callLocalAsync(data, reply, + &ITransactionCompletedListener::onTransactionCompleted); + } +} + +}; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e5a2454db3..84df7a9a3d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -25,7 +25,9 @@ #include #include +#include #include +#include #include @@ -98,6 +100,30 @@ void ComposerService::composerServiceDied() // --------------------------------------------------------------------------- +// TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs +// to be able to return a sp<> to its instance to pass to SurfaceFlinger. +// ANDROID_SINGLETON_STATIC_INSTANCE only allows a reference to an instance. + +sp TransactionCompletedListener::getInstance() { + static sp sInstance = new TransactionCompletedListener; + return sInstance; +} + +void TransactionCompletedListener::startListening() { + std::lock_guard lock(mMutex); + if (mListening) { + return; + } + ProcessState::self()->startThreadPool(); + mListening = true; +} + +void TransactionCompletedListener::onTransactionCompleted() { + return; +} + +// --------------------------------------------------------------------------- + SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : mForceSynchronous(other.mForceSynchronous), mTransactionNestCount(other.mTransactionNestCount), diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h new file mode 100644 index 0000000000..cdc6a7e187 --- /dev/null +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -0,0 +1,42 @@ +/* + * 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 + +#include + +namespace android { + +class ITransactionCompletedListener : public IInterface { +public: + DECLARE_META_INTERFACE(TransactionCompletedListener) + + virtual void onTransactionCompleted() = 0; +}; + +class BnTransactionCompletedListener : public SafeBnInterface { +public: + BnTransactionCompletedListener() + : SafeBnInterface("BnTransactionCompletedListener") {} + + status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags = 0) override; +}; + +} // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 8ccee05ba4..8dcb8c9f33 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -33,9 +33,10 @@ #include #include +#include +#include #include #include -#include namespace android { @@ -49,6 +50,24 @@ class Region; // --------------------------------------------------------------------------- +class TransactionCompletedListener : public BnTransactionCompletedListener { + TransactionCompletedListener() = default; + + std::mutex mMutex; + + bool mListening GUARDED_BY(mMutex) = false; + +public: + static sp getInstance(); + + void startListening(); + + // Overrides BnTransactionCompletedListener's onTransactionCompleted + void onTransactionCompleted() override; +}; + +// --------------------------------------------------------------------------- + class SurfaceComposerClient : public RefBase { friend class Composer; @@ -349,6 +368,7 @@ public: }; // --------------------------------------------------------------------------- + }; // namespace android #endif // ANDROID_GUI_SURFACE_COMPOSER_CLIENT_H -- cgit v1.2.3-59-g8ed1b From c837b5ecc406f6bf6e5424d48435b56decbd903e Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 12 Oct 2018 10:04:44 -0700 Subject: blast: Send transaction listener from SCC to SF Send the TransactionCompletedListeners to SurfaceFlinger via transactions. The listener will be used to send callbacks after a transaction has completed. Test: Transaction_test Bug: 80477568 Change-Id: I51d3877f2803a192f95db4dd211f48aca9651c30 --- libs/gui/ISurfaceComposer.cpp | 2 +- libs/gui/LayerState.cpp | 19 +++ libs/gui/SurfaceComposerClient.cpp | 131 ++++++++++++++++++++- .../include/gui/ITransactionCompletedListener.h | 18 +++ libs/gui/include/gui/LayerState.h | 4 + libs/gui/include/gui/SurfaceComposerClient.h | 41 ++++++- 6 files changed, 210 insertions(+), 5 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index accf72c390..69e5379047 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -634,10 +634,10 @@ status_t BnSurfaceComposer::onTransact( if (count > data.dataSize()) { return BAD_VALUE; } - ComposerState s; Vector state; state.setCapacity(count); for (size_t i = 0; i < count; i++) { + ComposerState s; if (s.read(data) == BAD_VALUE) { return BAD_VALUE; } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2b0a46181b..7b71b39ce0 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -80,6 +80,13 @@ status_t layer_state_t::write(Parcel& output) const memcpy(output.writeInplace(16 * sizeof(float)), colorTransform.asArray(), 16 * sizeof(float)); + if (output.writeVectorSize(listenerCallbacks) == NO_ERROR) { + for (const auto& [listener, callbackIds] : listenerCallbacks) { + output.writeStrongBinder(IInterface::asBinder(listener)); + output.writeInt64Vector(callbackIds); + } + } + return NO_ERROR; } @@ -135,6 +142,14 @@ status_t layer_state_t::read(const Parcel& input) colorTransform = mat4(static_cast(input.readInplace(16 * sizeof(float)))); + int32_t listenersSize = input.readInt32(); + for (int32_t i = 0; i < listenersSize; i++) { + auto listener = interface_cast(input.readStrongBinder()); + std::vector callbackIds; + input.readInt64Vector(&callbackIds); + listenerCallbacks.emplace_back(listener, callbackIds); + } + return NO_ERROR; } @@ -323,6 +338,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eColorTransformChanged; colorTransform = other.colorTransform; } + if (other.what & eListenerCallbacksChanged) { + what |= eListenerCallbacksChanged; + listenerCallbacks = other.listenerCallbacks; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 84df7a9a3d..88c574286b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -104,13 +104,23 @@ void ComposerService::composerServiceDied() // to be able to return a sp<> to its instance to pass to SurfaceFlinger. // ANDROID_SINGLETON_STATIC_INSTANCE only allows a reference to an instance. +// 0 is an invalid callback id +TransactionCompletedListener::TransactionCompletedListener() : mCallbackIdCounter(1) {} + +CallbackId TransactionCompletedListener::getNextIdLocked() { + return mCallbackIdCounter++; +} + sp TransactionCompletedListener::getInstance() { static sp sInstance = new TransactionCompletedListener; return sInstance; } -void TransactionCompletedListener::startListening() { - std::lock_guard lock(mMutex); +sp TransactionCompletedListener::getIInstance() { + return static_cast>(getInstance()); +} + +void TransactionCompletedListener::startListeningLocked() { if (mListening) { return; } @@ -118,6 +128,16 @@ void TransactionCompletedListener::startListening() { mListening = true; } +CallbackId TransactionCompletedListener::addCallback( + const TransactionCompletedCallbackWithContext& callback) { + std::lock_guard lock(mMutex); + startListeningLocked(); + + CallbackId callbackId = getNextIdLocked(); + mCallbacks.emplace(callbackId, callback); + return callbackId; +} + void TransactionCompletedListener::onTransactionCompleted() { return; } @@ -153,6 +173,17 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr } other.mDisplayStates.clear(); + for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) { + auto& [callbackIds, surfaceControls] = callbackInfo; + mListenerCallbacks[listener].callbackIds.insert(std::make_move_iterator( + callbackIds.begin()), + std::make_move_iterator(callbackIds.end())); + mListenerCallbacks[listener] + .surfaceControls.insert(std::make_move_iterator(surfaceControls.begin()), + std::make_move_iterator(surfaceControls.end())); + } + other.mListenerCallbacks.clear(); + return *this; } @@ -163,6 +194,26 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { sp sf(ComposerService::getComposerService()); + // For every listener with registered callbacks + for (const auto& [listener, callbackInfo] : mListenerCallbacks) { + auto& [callbackIds, surfaceControls] = callbackInfo; + if (callbackIds.empty()) { + continue; + } + + // If the listener has any SurfaceControls set on this Transaction update the surface state + for (const auto& surfaceControl : surfaceControls) { + layer_state_t* s = getLayerState(surfaceControl); + if (!s) { + ALOGE("failed to get layer state"); + continue; + } + s->what |= layer_state_t::eListenerCallbacksChanged; + s->listenerCallbacks.emplace_back(listener, std::move(callbackIds)); + } + } + mListenerCallbacks.clear(); + Vector composerStates; Vector displayStates; uint32_t flags = 0; @@ -232,6 +283,11 @@ layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { + mListenerCallbacks[TransactionCompletedListener::getIInstance()].surfaceControls.insert(sc); +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( const sp& sc, float x, float y) { layer_state_t* s = getLayerState(sc); @@ -242,6 +298,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosit s->what |= layer_state_t::ePositionChanged; s->x = x; s->y = y; + + registerSurfaceControlForCallback(sc); return *this; } @@ -266,6 +324,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( s->w = w; s->h = h; + registerSurfaceControlForCallback(sc); return *this; } @@ -278,6 +337,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer } s->what |= layer_state_t::eLayerChanged; s->z = z; + + registerSurfaceControlForCallback(sc); return *this; } @@ -290,6 +351,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelat s->what |= layer_state_t::eRelativeLayerChanged; s->relativeLayerHandle = relativeTo; s->z = z; + + registerSurfaceControlForCallback(sc); return *this; } @@ -309,6 +372,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags s->flags &= ~mask; s->flags |= (flags & mask); s->mask |= mask; + + registerSurfaceControlForCallback(sc); return *this; } @@ -322,6 +387,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrans } s->what |= layer_state_t::eTransparentRegionChanged; s->transparentRegion = transparentRegion; + + registerSurfaceControlForCallback(sc); return *this; } @@ -334,6 +401,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha } s->what |= layer_state_t::eAlphaChanged; s->alpha = alpha; + + registerSurfaceControlForCallback(sc); return *this; } @@ -346,6 +415,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer } s->what |= layer_state_t::eLayerStackChanged; s->layerStack = layerStack; + + registerSurfaceControlForCallback(sc); return *this; } @@ -364,6 +435,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatri matrix.dsdy = dsdy; matrix.dtdy = dtdy; s->matrix = matrix; + + registerSurfaceControlForCallback(sc); return *this; } @@ -376,6 +449,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop_ } s->what |= layer_state_t::eCropChanged_legacy; s->crop_legacy = crop; + + registerSurfaceControlForCallback(sc); return *this; } @@ -391,6 +466,8 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const spwhat |= layer_state_t::eDeferTransaction_legacy; s->barrierHandle_legacy = handle; s->frameNumber_legacy = frameNumber; + + registerSurfaceControlForCallback(sc); return *this; } @@ -406,6 +483,8 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const spwhat |= layer_state_t::eDeferTransaction_legacy; s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); s->frameNumber_legacy = frameNumber; + + registerSurfaceControlForCallback(sc); return *this; } @@ -419,6 +498,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent } s->what |= layer_state_t::eReparentChildren; s->reparentHandle = newParentHandle; + + registerSurfaceControlForCallback(sc); return *this; } @@ -432,6 +513,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent } s->what |= layer_state_t::eReparent; s->parentHandleForChild = newParentHandle; + + registerSurfaceControlForCallback(sc); return *this; } @@ -445,6 +528,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor } s->what |= layer_state_t::eColorChanged; s->color = color; + + registerSurfaceControlForCallback(sc); return *this; } @@ -457,6 +542,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrans } s->what |= layer_state_t::eTransformChanged; s->transform = transform; + + registerSurfaceControlForCallback(sc); return *this; } @@ -470,6 +557,8 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const spwhat |= layer_state_t::eTransformToDisplayInverseChanged; s->transformToDisplayInverse = transformToDisplayInverse; + + registerSurfaceControlForCallback(sc); return *this; } @@ -482,6 +571,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( } s->what |= layer_state_t::eCropChanged; s->crop = crop; + + registerSurfaceControlForCallback(sc); return *this; } @@ -494,6 +585,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe } s->what |= layer_state_t::eBufferChanged; s->buffer = buffer; + + registerSurfaceControlForCallback(sc); return *this; } @@ -506,6 +599,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcqui } s->what |= layer_state_t::eAcquireFenceChanged; s->acquireFence = fence; + + registerSurfaceControlForCallback(sc); return *this; } @@ -518,6 +613,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDatas } s->what |= layer_state_t::eDataspaceChanged; s->dataspace = dataspace; + + registerSurfaceControlForCallback(sc); return *this; } @@ -530,6 +627,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setHdrMe } s->what |= layer_state_t::eHdrMetadataChanged; s->hdrMetadata = hdrMetadata; + + registerSurfaceControlForCallback(sc); return *this; } @@ -542,6 +641,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSurfa } s->what |= layer_state_t::eSurfaceDamageRegionChanged; s->surfaceDamageRegion = surfaceDamageRegion; + + registerSurfaceControlForCallback(sc); return *this; } @@ -554,6 +655,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApi( } s->what |= layer_state_t::eApiChanged; s->api = api; + + registerSurfaceControlForCallback(sc); return *this; } @@ -566,6 +669,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb } s->what |= layer_state_t::eSidebandStreamChanged; s->sidebandStream = sidebandStream; + + registerSurfaceControlForCallback(sc); + return *this; +} + +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::addTransactionCompletedCallback( + TransactionCompletedCallback callback, void* callbackContext) { + auto listener = TransactionCompletedListener::getInstance(); + + auto callbackWithContext = std::bind(callback, callbackContext); + + CallbackId callbackId = listener->addCallback(callbackWithContext); + + mListenerCallbacks[TransactionCompletedListener::getIInstance()].callbackIds.emplace( + callbackId); return *this; } @@ -576,6 +695,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachCh mStatus = BAD_INDEX; } s->what |= layer_state_t::eDetachChildren; + + registerSurfaceControlForCallback(sc); return *this; } @@ -603,6 +724,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverr s->what |= layer_state_t::eOverrideScalingModeChanged; s->overrideScalingMode = overrideScalingMode; + + registerSurfaceControlForCallback(sc); return *this; } @@ -614,6 +737,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome return *this; } s->what |= layer_state_t::eGeometryAppliesWithResize; + + registerSurfaceControlForCallback(sc); return *this; } @@ -637,6 +762,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor } s->what |= layer_state_t::eColorTransformChanged; s->colorTransform = mat4(matrix, translation); + + registerSurfaceControlForCallback(sc); return *this; } diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index cdc6a7e187..0a61cd1c9b 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -20,6 +20,7 @@ #include #include +#include namespace android { @@ -39,4 +40,21 @@ public: uint32_t flags = 0) override; }; +using CallbackId = int64_t; + +class ListenerCallbacks { +public: + ListenerCallbacks(const sp& listener, + const std::unordered_set& callbacks) + : transactionCompletedListener(listener), + callbackIds(callbacks.begin(), callbacks.end()) {} + + ListenerCallbacks(const sp& listener, + const std::vector& ids) + : transactionCompletedListener(listener), callbackIds(ids) {} + + sp transactionCompletedListener; + std::vector callbackIds; +}; + } // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e06e2b14b9..ddbac7bf47 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -74,6 +75,7 @@ struct layer_state_t { eApiChanged = 0x04000000, eSidebandStreamChanged = 0x08000000, eColorTransformChanged = 0x10000000, + eListenerCallbacksChanged = 0x20000000, }; layer_state_t() @@ -154,6 +156,8 @@ struct layer_state_t { int32_t api; sp sidebandStream; mat4 colorTransform; + + std::vector listenerCallbacks; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 8dcb8c9f33..2ed4f8f3e4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include @@ -50,17 +52,29 @@ class Region; // --------------------------------------------------------------------------- +using TransactionCompletedCallback = std::function; +using TransactionCompletedCallbackWithContext = std::function; + class TransactionCompletedListener : public BnTransactionCompletedListener { - TransactionCompletedListener() = default; + TransactionCompletedListener(); + + CallbackId getNextIdLocked() REQUIRES(mMutex); std::mutex mMutex; bool mListening GUARDED_BY(mMutex) = false; + CallbackId mCallbackIdCounter GUARDED_BY(mMutex) = 1; + + std::map mCallbacks GUARDED_BY(mMutex); + public: static sp getInstance(); + static sp getIInstance(); - void startListening(); + void startListeningLocked() REQUIRES(mMutex); + + CallbackId addCallback(const TransactionCompletedCallbackWithContext& callback); // Overrides BnTransactionCompletedListener's onTransactionCompleted void onTransactionCompleted() override; @@ -177,9 +191,27 @@ public: } }; + struct TCLHash { + std::size_t operator()(const sp& tcl) const { + return std::hash{}((tcl) ? IInterface::asBinder(tcl).get() : nullptr); + } + }; + + struct CallbackInfo { + // All the callbacks that have been requested for a TransactionCompletedListener in the + // Transaction + std::unordered_set callbackIds; + // All the SurfaceControls that have been modified in this TransactionCompletedListener's + // process that require a callback if there is one or more callbackIds set. + std::unordered_set, SCHash> surfaceControls; + }; + class Transaction { std::unordered_map, ComposerState, SCHash> mComposerStates; SortedVector mDisplayStates; + std::unordered_map, CallbackInfo, TCLHash> + mListenerCallbacks; + uint32_t mForceSynchronous = 0; uint32_t mTransactionNestCount = 0; bool mAnimation = false; @@ -190,6 +222,8 @@ public: layer_state_t* getLayerState(const sp& sc); DisplayState& getDisplayState(const sp& token); + void registerSurfaceControlForCallback(const sp& sc); + public: Transaction() = default; virtual ~Transaction() = default; @@ -269,6 +303,9 @@ public: Transaction& setSidebandStream(const sp& sc, const sp& sidebandStream); + Transaction& addTransactionCompletedCallback(TransactionCompletedCallback callback, + void* callbackContext); + // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. // The child SurfaceControls will not throw exceptions or return errors, -- cgit v1.2.3-59-g8ed1b From e2ffb426c3c48bbc93bc2cfc28b33b6f6e0ddfa2 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 12 Oct 2018 11:33:52 -0700 Subject: blast: Send transaction callback Send transaction callback to client via the TransactionCompletedListener. Test: Transaction_test Bug: 80477568 Change-Id: Iac98780b1357b9cc54b93cc3c848013b28fab441 --- libs/gui/ITransactionCompletedListener.cpp | 75 ++++++++- libs/gui/SurfaceComposerClient.cpp | 29 +++- .../include/gui/ITransactionCompletedListener.h | 56 ++++++- libs/gui/include/gui/SurfaceComposerClient.h | 15 +- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferStateLayer.cpp | 37 +++++ services/surfaceflinger/BufferStateLayer.h | 2 + services/surfaceflinger/Layer.cpp | 1 + services/surfaceflinger/Layer.h | 9 ++ services/surfaceflinger/SurfaceFlinger.cpp | 21 ++- services/surfaceflinger/SurfaceFlinger.h | 7 + .../surfaceflinger/TransactionCompletedThread.cpp | 168 +++++++++++++++++++++ .../surfaceflinger/TransactionCompletedThread.h | 102 +++++++++++++ 13 files changed, 503 insertions(+), 20 deletions(-) create mode 100644 services/surfaceflinger/TransactionCompletedThread.cpp create mode 100644 services/surfaceflinger/TransactionCompletedThread.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 38ff59d746..3ecd13c28c 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -30,6 +30,74 @@ enum class Tag : uint32_t { } // Anonymous namespace +status_t SurfaceStats::writeToParcel(Parcel* output) const { + return output->writeStrongBinder(surfaceControl); +} + +status_t SurfaceStats::readFromParcel(const Parcel* input) { + return input->readStrongBinder(&surfaceControl); +} + +status_t TransactionStats::writeToParcel(Parcel* output) const { + return output->writeParcelableVector(surfaceStats); +} + +status_t TransactionStats::readFromParcel(const Parcel* input) { + return input->readParcelableVector(&surfaceStats); +} + +status_t ListenerStats::writeToParcel(Parcel* output) const { + status_t err = output->writeInt32(static_cast(transactionStats.size())); + if (err != NO_ERROR) { + return err; + } + + for (const auto& [callbackIds, stats] : transactionStats) { + err = output->writeParcelable(stats); + if (err != NO_ERROR) { + return err; + } + err = output->writeInt64Vector(callbackIds); + if (err != NO_ERROR) { + return err; + } + } + return NO_ERROR; +} + +status_t ListenerStats::readFromParcel(const Parcel* input) { + int32_t transactionStats_size = input->readInt32(); + + for (int i = 0; i < transactionStats_size; i++) { + TransactionStats stats; + std::vector callbackIds; + + status_t err = input->readParcelable(&stats); + if (err != NO_ERROR) { + return err; + } + err = input->readInt64Vector(&callbackIds); + if (err != NO_ERROR) { + return err; + } + + transactionStats.emplace(callbackIds, stats); + } + return NO_ERROR; +} + +ListenerStats ListenerStats::createEmpty(const sp& listener, + const std::unordered_set& callbackIds) { + ListenerStats listenerStats; + listenerStats.listener = listener; + TransactionStats transactionStats; + listenerStats.transactionStats.emplace(std::piecewise_construct, + std::forward_as_tuple(callbackIds.begin(), + callbackIds.end()), + std::forward_as_tuple(transactionStats)); + return listenerStats; +} + class BpTransactionCompletedListener : public SafeBpInterface { public: explicit BpTransactionCompletedListener(const sp& impl) @@ -38,9 +106,10 @@ public: ~BpTransactionCompletedListener() override; - void onTransactionCompleted() override { - callRemoteAsync( - Tag::ON_TRANSACTION_COMPLETED); + void onTransactionCompleted(ListenerStats stats) override { + callRemoteAsync(Tag::ON_TRANSACTION_COMPLETED, + stats); } }; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 88c574286b..e10bda485b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -128,8 +128,7 @@ void TransactionCompletedListener::startListeningLocked() { mListening = true; } -CallbackId TransactionCompletedListener::addCallback( - const TransactionCompletedCallbackWithContext& callback) { +CallbackId TransactionCompletedListener::addCallback(const TransactionCompletedCallback& callback) { std::lock_guard lock(mMutex); startListeningLocked(); @@ -138,8 +137,20 @@ CallbackId TransactionCompletedListener::addCallback( return callbackId; } -void TransactionCompletedListener::onTransactionCompleted() { - return; +void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { + std::lock_guard lock(mMutex); + + for (const auto& [callbackIds, transactionStats] : listenerStats.transactionStats) { + for (auto callbackId : callbackIds) { + const auto& callback = mCallbacks[callbackId]; + if (!callback) { + ALOGE("cannot call null callback function, skipping"); + continue; + } + callback(transactionStats); + mCallbacks.erase(callbackId); + } + } } // --------------------------------------------------------------------------- @@ -201,6 +212,12 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { continue; } + // If the listener does not have any SurfaceControls set on this Transaction, send the + // callback now + if (surfaceControls.empty()) { + listener->onTransactionCompleted(ListenerStats::createEmpty(listener, callbackIds)); + } + // If the listener has any SurfaceControls set on this Transaction update the surface state for (const auto& surfaceControl : surfaceControls) { layer_state_t* s = getLayerState(surfaceControl); @@ -676,10 +693,10 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addTransactionCompletedCallback( - TransactionCompletedCallback callback, void* callbackContext) { + TransactionCompletedCallbackTakesContext callback, void* callbackContext) { auto listener = TransactionCompletedListener::getInstance(); - auto callbackWithContext = std::bind(callback, callbackContext); + auto callbackWithContext = std::bind(callback, callbackContext, std::placeholders::_1); CallbackId callbackId = listener->addCallback(callbackWithContext); diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 0a61cd1c9b..3c4c393172 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -17,18 +17,70 @@ #pragma once #include +#include +#include #include +#include + #include +#include #include namespace android { +class ITransactionCompletedListener; + +using CallbackId = int64_t; + +struct CallbackIdsHash { + // CallbackId vectors have several properties that let us get away with this simple hash. + // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is + // empty we can still hash 0. + // 2) CallbackId vectors for the same listener either are identical or contain none of the + // same members. It is sufficient to just check the first CallbackId in the vectors. If + // they match, they are the same. If they do not match, they are not the same. + std::size_t operator()(const std::vector callbackIds) const { + return std::hash{}((callbackIds.size() == 0) ? 0 : callbackIds.front()); + } +}; + +class SurfaceStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + SurfaceStats() = default; + explicit SurfaceStats(const sp& sc) : surfaceControl(sc) {} + + sp surfaceControl; +}; + +class TransactionStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + std::vector surfaceStats; +}; + +class ListenerStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + static ListenerStats createEmpty(const sp& listener, + const std::unordered_set& callbackIds); + + sp listener; + std::unordered_map, TransactionStats, CallbackIdsHash> transactionStats; +}; + class ITransactionCompletedListener : public IInterface { public: DECLARE_META_INTERFACE(TransactionCompletedListener) - virtual void onTransactionCompleted() = 0; + virtual void onTransactionCompleted(ListenerStats stats) = 0; }; class BnTransactionCompletedListener : public SafeBnInterface { @@ -40,8 +92,6 @@ public: uint32_t flags = 0) override; }; -using CallbackId = int64_t; - class ListenerCallbacks { public: ListenerCallbacks(const sp& listener, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2ed4f8f3e4..1cafb77af1 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,8 +52,9 @@ class Region; // --------------------------------------------------------------------------- -using TransactionCompletedCallback = std::function; -using TransactionCompletedCallbackWithContext = std::function; +using TransactionCompletedCallbackTakesContext = + std::function; +using TransactionCompletedCallback = std::function; class TransactionCompletedListener : public BnTransactionCompletedListener { TransactionCompletedListener(); @@ -66,7 +67,7 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { CallbackId mCallbackIdCounter GUARDED_BY(mMutex) = 1; - std::map mCallbacks GUARDED_BY(mMutex); + std::map mCallbacks GUARDED_BY(mMutex); public: static sp getInstance(); @@ -74,10 +75,10 @@ public: void startListeningLocked() REQUIRES(mMutex); - CallbackId addCallback(const TransactionCompletedCallbackWithContext& callback); + CallbackId addCallback(const TransactionCompletedCallback& callback); // Overrides BnTransactionCompletedListener's onTransactionCompleted - void onTransactionCompleted() override; + void onTransactionCompleted(ListenerStats stats) override; }; // --------------------------------------------------------------------------- @@ -303,8 +304,8 @@ public: Transaction& setSidebandStream(const sp& sc, const sp& sidebandStream); - Transaction& addTransactionCompletedCallback(TransactionCompletedCallback callback, - void* callbackContext); + Transaction& addTransactionCompletedCallback( + TransactionCompletedCallbackTakesContext callback, void* callbackContext); // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 16003a258c..0e75d7fe4c 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -153,6 +153,7 @@ filegroup { "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", "TimeStats/TimeStats.cpp", + "TransactionCompletedThread.cpp", ], } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 0e14d8c9d8..adc91a73e0 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -64,6 +64,12 @@ bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return hasFrameUpdate(); } +bool BufferStateLayer::willPresentCurrentTransaction() const { + // Returns true if the most recent Transaction applied to CurrentState will be presented. + return getSidebandStreamChanged() || getAutoRefresh() || + (mCurrentState.modified && mCurrentState.buffer != nullptr); +} + bool BufferStateLayer::getTransformToDisplayInverse() const { return mCurrentState.transformToDisplayInverse; } @@ -183,6 +189,34 @@ bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) return true; } +bool BufferStateLayer::setTransactionCompletedListeners( + const std::vector>& handles) { + // If there is no handle, we will not send a callback + if (handles.empty()) { + return false; + } + + const bool willPresent = willPresentCurrentTransaction(); + + for (const auto& handle : handles) { + // If this layer will be presented in this frame + if (willPresent) { + // Notify the transaction completed thread that there is a pending latched callback + // handle + mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle); + + // Store so latched time and release fence can be set + mCurrentState.callbackHandles.push_back(handle); + + } else { // If this layer will NOT need to be relatched and presented this frame + // Notify the transaction completed thread this handle is done + mFlinger->getTransactionCompletedThread().addUnlatchedCallbackHandle(handle); + } + } + + return willPresent; +} + bool BufferStateLayer::setSize(uint32_t w, uint32_t h) { if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false; mCurrentState.active.w = w; @@ -404,6 +438,9 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return BAD_VALUE; } + mFlinger->getTransactionCompletedThread().addLatchedCallbackHandles( + getDrawingState().callbackHandles); + // Handle sync fences if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) { // TODO(alecmouri): Fail somewhere upstream if the fence is invalid. diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cf4d0f004b..fcea96dae6 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -69,6 +69,7 @@ public: bool setSurfaceDamageRegion(const Region& surfaceDamage) override; bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; + bool setTransactionCompletedListeners(const std::vector>& handles) override; bool setSize(uint32_t w, uint32_t h) override; bool setPosition(float x, float y, bool immediate) override; @@ -125,6 +126,7 @@ private: // ----------------------------------------------------------------------- private: void onFirstRef() override; + bool willPresentCurrentTransaction() const; static const std::array IDENTITY_MATRIX; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f29dfc0f1b..c1f0587b3c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1049,6 +1049,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // Commit the transaction commitTransaction(c); + mCurrentState.callbackHandles = {}; return flags; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 12671ff51d..9235b645a6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -47,6 +47,7 @@ #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "TimeStats/TimeStats.h" +#include "TransactionCompletedThread.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" @@ -183,6 +184,10 @@ public: sp sidebandStream; mat4 colorTransform; bool hasColorTransform; + + // The deque of callback handles for this frame. The back of the deque contains the most + // recent callback handle. + std::deque> callbackHandles; }; explicit Layer(const LayerCreationArgs& args); @@ -272,6 +277,10 @@ public: virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; virtual bool setApi(int32_t /*api*/) { return false; }; virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; + virtual bool setTransactionCompletedListeners( + const std::vector>& /*handles*/) { + return false; + }; ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dec08fd629..643b1ce336 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1942,6 +1942,8 @@ void SurfaceFlinger::postComposition() ATRACE_INT("TexturePoolSize", mTexturePool.size()); } } + + mTransactionCompletedThread.sendCallbacks(); } void SurfaceFlinger::rebuildLayerStacks() { @@ -3295,9 +3297,15 @@ void SurfaceFlinger::setTransactionState( transactionFlags |= setDisplayStateLocked(display); } + uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - transactionFlags |= setClientStateLocked(state); + clientStateFlags |= setClientStateLocked(state); + } + // If the state doesn't require a traversal and there are callbacks, send them now + if (!(clientStateFlags & eTraversalNeeded)) { + mTransactionCompletedThread.sendCallbacks(); } + transactionFlags |= clientStateFlags; // 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 @@ -3606,6 +3614,17 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (what & layer_state_t::eSidebandStreamChanged) { if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; } + + std::vector> callbackHandles; + if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) { + mTransactionCompletedThread.run(); + for (const auto& [listener, callbackIds] : s.listenerCallbacks) { + callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); + } + } + if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; + // Do not put anything that updates layer state or modifies flags after + // setTransactionCompletedListener return flags; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51168a6724..18e1ca18b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -62,6 +62,7 @@ #include "SurfaceFlingerFactory.h" #include "SurfaceInterceptor.h" #include "SurfaceTracing.h" +#include "TransactionCompletedThread.h" #include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" @@ -367,6 +368,10 @@ public: inline void onLayerCreated() { mNumLayers++; } inline void onLayerDestroyed() { mNumLayers--; } + TransactionCompletedThread& getTransactionCompletedThread() { + return mTransactionCompletedThread; + } + private: friend class Client; friend class DisplayEventConnection; @@ -886,6 +891,8 @@ private: bool mUseHwcVirtualDisplays = false; std::atomic mFrameMissedCount{0}; + TransactionCompletedThread mTransactionCompletedThread; + // Restrict layers to use two buffers in their bufferqueues. bool mLayerTripleBufferingDisabled = false; diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp new file mode 100644 index 0000000000..e83422e23b --- /dev/null +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -0,0 +1,168 @@ +/* + * 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. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "TransactionCompletedThread" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "TransactionCompletedThread.h" + +#include + +#include +#include +#include + +namespace android { + +TransactionCompletedThread::~TransactionCompletedThread() { + { + std::lock_guard lock(mMutex); + mKeepRunning = false; + mConditionVariable.notify_all(); + } + + mThread.join(); + + { + std::lock_guard lock(mMutex); + for (const auto& [listener, listenerStats] : mListenerStats) { + listener->unlinkToDeath(mDeathRecipient); + } + } +} + +void TransactionCompletedThread::run() { + std::lock_guard lock(mMutex); + if (mRunning) { + return; + } + mDeathRecipient = new ThreadDeathRecipient(); + mRunning = true; + mThread = std::thread(&TransactionCompletedThread::threadMain, this); +} + +void TransactionCompletedThread::registerPendingLatchedCallbackHandle( + const sp& handle) { + std::lock_guard lock(mMutex); + + sp listener = IInterface::asBinder(handle->listener); + const auto& callbackIds = handle->callbackIds; + + mPendingTransactions[listener][callbackIds]++; +} + +void TransactionCompletedThread::addLatchedCallbackHandles( + const std::deque>& handles) { + std::lock_guard lock(mMutex); + + for (const auto& handle : handles) { + auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener)); + auto& pendingCallbacks = listener->second; + auto pendingCallback = pendingCallbacks.find(handle->callbackIds); + + if (pendingCallback != pendingCallbacks.end()) { + auto& pendingCount = pendingCallback->second; + + // Decrease the pending count for this listener + if (--pendingCount == 0) { + pendingCallbacks.erase(pendingCallback); + } + } else { + ALOGW("there are more latched callbacks than there were registered callbacks"); + } + + addCallbackHandle(handle); + } +} + +void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp& handle) { + std::lock_guard lock(mMutex); + addCallbackHandle(handle); +} + +void TransactionCompletedThread::addCallbackHandle(const sp& handle) { + const sp listener = IInterface::asBinder(handle->listener); + + // If we don't already have a reference to this listener, linkToDeath so we get a notification + // if it dies. + if (mListenerStats.count(listener) == 0) { + status_t error = listener->linkToDeath(mDeathRecipient); + if (error != NO_ERROR) { + ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error); + return; + } + } + + auto& listenerStats = mListenerStats[listener]; + listenerStats.listener = handle->listener; + + auto& transactionStats = listenerStats.transactionStats[handle->callbackIds]; + transactionStats.surfaceStats.emplace_back(handle->surfaceControl); +} + +void TransactionCompletedThread::sendCallbacks() { + std::lock_guard lock(mMutex); + if (mRunning) { + mConditionVariable.notify_all(); + } +} + +void TransactionCompletedThread::threadMain() { + std::lock_guard lock(mMutex); + + while (mKeepRunning) { + mConditionVariable.wait(mMutex); + + // For each listener + auto it = mListenerStats.begin(); + while (it != mListenerStats.end()) { + auto& [listener, listenerStats] = *it; + + // For each transaction + bool sendCallback = true; + for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) { + // If we are still waiting on the callback handles for this transaction, skip it + if (mPendingTransactions[listener].count(callbackIds) != 0) { + sendCallback = false; + break; + } + } + // If the listener has no pending transactions and all latched transactions have been + // presented + if (sendCallback) { + // If the listener is still alive + if (listener->isBinderAlive()) { + // Send callback + listenerStats.listener->onTransactionCompleted(listenerStats); + listener->unlinkToDeath(mDeathRecipient); + } + it = mListenerStats.erase(it); + } else { + it++; + } + } + } +} + +// ----------------------------------------------------------------------- + +CallbackHandle::CallbackHandle(const sp& transactionListener, + const std::vector& ids, const sp& sc) + : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {} + +} // namespace android diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h new file mode 100644 index 0000000000..39cf7e877c --- /dev/null +++ b/services/surfaceflinger/TransactionCompletedThread.h @@ -0,0 +1,102 @@ +/* + * 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 +#include +#include +#include + +#include + +#include +#include + +namespace android { + +class CallbackHandle : public RefBase { +public: + CallbackHandle(const sp& transactionListener, + const std::vector& ids, const sp& sc); + + sp listener; + std::vector callbackIds; + sp surfaceControl; +}; + +class TransactionCompletedThread { +public: + ~TransactionCompletedThread(); + + void run(); + + // Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle + // that needs to be latched and presented this frame. This function should be called once the + // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send + // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and + // presented. + void registerPendingLatchedCallbackHandle(const sp& handle); + // Notifies the TransactionCompletedThread that a pending CallbackHandle has been latched. + void addLatchedCallbackHandles(const std::deque>& handles); + + // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and + // presented this frame. + void addUnlatchedCallbackHandle(const sp& handle); + + void sendCallbacks(); + +private: + void threadMain(); + + void addCallbackHandle(const sp& handle) REQUIRES(mMutex); + + class ThreadDeathRecipient : public IBinder::DeathRecipient { + public: + // This function is a no-op. isBinderAlive needs a linked DeathRecipient to work. + // Death recipients needs a binderDied function. + // + // (isBinderAlive checks if BpBinder's mAlive is 0. mAlive is only set to 0 in sendObituary. + // sendObituary is only called if linkToDeath was called with a DeathRecipient.) + void binderDied(const wp& /*who*/) override {} + }; + sp mDeathRecipient; + + struct IBinderHash { + std::size_t operator()(const sp& strongPointer) const { + return std::hash{}(strongPointer.get()); + } + }; + + std::thread mThread; + + std::mutex mMutex; + std::condition_variable_any mConditionVariable; + + std::unordered_map< + sp, + std::unordered_map, uint32_t /*count*/, CallbackIdsHash>, + IBinderHash> + mPendingTransactions GUARDED_BY(mMutex); + std::unordered_map, ListenerStats, IBinderHash> mListenerStats + GUARDED_BY(mMutex); + + bool mRunning GUARDED_BY(mMutex) = false; + bool mKeepRunning GUARDED_BY(mMutex) = true; +}; + +} // namespace android -- cgit v1.2.3-59-g8ed1b From 2c358bf8206d591a4707d33fd2ca45f0dc5360f7 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 8 Aug 2018 15:58:15 -0700 Subject: Add setInputWindowInfo to SurfaceComposerClient::Transaction In preparation for passing input through SurfaceFlinger to the InputDispatcher. Bug: 80101428 Bug: 113136004 Bug: 111440400 Change-Id: I5f67fbb9894136bfb16c718ffe1cc23a02f3414d --- include/input/Input.h | 2 ++ include/input/InputTransport.h | 2 ++ libs/gui/Android.bp | 4 +++- libs/gui/LayerState.cpp | 15 +++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 19 +++++++++++++++++++ libs/gui/include/gui/LayerState.h | 9 +++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 4 ++++ 7 files changed, 54 insertions(+), 1 deletion(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/include/input/Input.h b/include/input/Input.h index 819a89f37c..d35354b0f6 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -17,6 +17,8 @@ #ifndef _LIBINPUT_INPUT_H #define _LIBINPUT_INPUT_H +#pragma GCC system_header + /** * Native input event structures. */ diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 4782c9b237..4c91427a77 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -17,6 +17,8 @@ #ifndef _LIBINPUT_INPUT_TRANSPORT_H #define _LIBINPUT_INPUT_TRANSPORT_H +#pragma GCC system_header + /** * Native input transport. * diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 7677c3a919..127fcd618b 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -135,6 +135,7 @@ cc_library_shared { "libutils", "libnativewindow", "liblog", + "libinput", "libhidlbase", "libhidltransport", "android.hidl.token@1.0-utils", @@ -146,7 +147,7 @@ cc_library_shared { // bufferhub is not used when building libgui for vendors target: { vendor: { - cflags: ["-DNO_BUFFERHUB"], + cflags: ["-DNO_BUFFERHUB", "-DNO_INPUT"], exclude_srcs: [ "BufferHubConsumer.cpp", "BufferHubProducer.cpp", @@ -155,6 +156,7 @@ cc_library_shared { "libbufferhub", "libbufferhubqueue", "libpdx_default_transport", + "libinput" ], }, }, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 7b71b39ce0..9f30060467 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -50,6 +50,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.r); output.writeFloat(color.g); output.writeFloat(color.b); +#ifndef NO_INPUT + inputInfo.write(output); +#endif output.write(transparentRegion); output.writeUint32(transform); output.writeBool(transformToDisplayInverse); @@ -120,6 +123,11 @@ status_t layer_state_t::read(const Parcel& input) color.r = input.readFloat(); color.g = input.readFloat(); color.b = input.readFloat(); + +#ifndef NO_INPUT + inputInfo = InputWindowInfo::read(input); +#endif + input.read(transparentRegion); transform = input.readUint32(); transformToDisplayInverse = input.readBool(); @@ -343,6 +351,13 @@ void layer_state_t::merge(const layer_state_t& other) { listenerCallbacks = other.listenerCallbacks; } +#ifndef NO_INPUT + if (other.what & eInputInfoChanged) { + what |= eInputInfoChanged; + inputInfo = other.inputInfo; + } +#endif + if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%X what=0x%X", diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e10bda485b..87c6f27c57 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -42,6 +42,10 @@ #include #include +#ifndef NO_INPUT +#include & display, + bool enable, uint8_t componentMask, + uint64_t maxFrames) { + return ComposerService::getComposerService()->setDisplayContentSamplingEnabled(display, enable, + componentMask, + maxFrames); +} + // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3b6c6e44b1..41369c855a 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -300,6 +300,14 @@ public: ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, uint8_t* outComponentMask) const = 0; + + /* Turns on the color sampling engine on the display. + * + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, + uint8_t componentMask, + uint64_t maxFrames) const = 0; }; // ---------------------------------------------------------------------------- @@ -340,6 +348,7 @@ public: GET_COMPOSITION_PREFERENCE, GET_COLOR_MANAGEMENT, GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, + SET_DISPLAY_CONTENT_SAMPLING_ENABLED, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 7d0551289e..ba943a0f8e 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -386,6 +386,8 @@ public: ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, uint8_t* outComponentMask); + static status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, + uint8_t componentMask, uint64_t maxFrames); private: virtual void onFirstRef(); diff --git a/libs/gui/tests/DisplayedContentSampling_test.cpp b/libs/gui/tests/DisplayedContentSampling_test.cpp index f2c0e0ca7f..f9d5dd632b 100644 --- a/libs/gui/tests/DisplayedContentSampling_test.cpp +++ b/libs/gui/tests/DisplayedContentSampling_test.cpp @@ -36,7 +36,12 @@ protected: ASSERT_TRUE(mDisplayToken); } - bool shouldSkipTest(status_t status) { + bool shouldSkipTest() { + ui::PixelFormat format; + ui::Dataspace dataspace; + status_t status = + mComposerClient->getDisplayedContentSamplingAttributes(mDisplayToken, &format, + &dataspace, &componentMask); if (status == PERMISSION_DENIED) { SUCCEED() << "permissions denial, skipping test"; return true; @@ -50,19 +55,53 @@ protected: sp mComposerClient; sp mDisplayToken; + uint8_t componentMask = 0; }; TEST_F(DisplayedContentSamplingTest, GetDisplayedContentSamplingAttributesAreSane) { + // tradefed infrastructure does not support use of GTEST_SKIP + if (shouldSkipTest()) return; + ui::PixelFormat format; ui::Dataspace dataspace; - uint8_t componentMask = 0; status_t status = mComposerClient->getDisplayedContentSamplingAttributes(mDisplayToken, &format, &dataspace, &componentMask); - if (shouldSkipTest(status)) { - return; - } EXPECT_EQ(OK, status); EXPECT_LE(componentMask, INVALID_MASK); } + +TEST_F(DisplayedContentSamplingTest, EnableWithInvalidMaskReturnsBadValue) { + if (shouldSkipTest()) return; + + status_t status = + mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, true, INVALID_MASK, 0); + EXPECT_EQ(BAD_VALUE, status); +} + +TEST_F(DisplayedContentSamplingTest, EnableAndDisableSucceed) { + if (shouldSkipTest()) return; + + status_t status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, true, + componentMask, 10); + EXPECT_EQ(OK, status); + + status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, false, componentMask, + 0); + EXPECT_EQ(OK, status); +} + +TEST_F(DisplayedContentSamplingTest, SelectivelyDisableComponentOk) { + if (shouldSkipTest()) return; + + status_t status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, true, + componentMask, 0); + EXPECT_EQ(OK, status); + + // Clear the lowest bit. + componentMask &= (componentMask - 1); + status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, false, componentMask, + 0); + EXPECT_EQ(OK, status); +} } // namespace android diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3950bb6258..cb1756f15b 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -647,6 +647,11 @@ public: uint8_t* /*outComponentMask*/) const override { return NO_ERROR; } + status_t setDisplayContentSamplingEnabled(const sp& /*display*/, bool /*enable*/, + uint8_t /*componentMask*/, + uint64_t /*maxFrames*/) const override { + return NO_ERROR; + } virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 5b641a23aa..3b7ed155ba 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -1067,6 +1067,18 @@ Error Composer::getDisplayCapabilities(Display display, return error; } +Error Composer::setDisplayContentSamplingEnabled(Display display, bool enabled, + uint8_t componentMask, uint64_t maxFrames) { + if (!mClient_2_3) { + return Error::UNSUPPORTED; + } + + auto enable = enabled ? V2_3::IComposerClient::DisplayedContentSampling::ENABLE + : V2_3::IComposerClient::DisplayedContentSampling::DISABLE; + return mClient_2_3->setDisplayedContentSamplingEnabled(display, enable, componentMask, + maxFrames); +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 61af34892b..0db12a16cf 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -192,6 +192,8 @@ public: virtual Error getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat, Dataspace* outDataspace, uint8_t* outComponentMask) = 0; + virtual Error setDisplayContentSamplingEnabled(Display display, bool enabled, + uint8_t componentMask, uint64_t maxFrames) = 0; virtual Error getDisplayCapabilities(Display display, std::vector* outCapabilities) = 0; }; @@ -396,6 +398,8 @@ public: Error getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat, Dataspace* outDataspace, uint8_t* outComponentMask) override; + Error setDisplayContentSamplingEnabled(Display display, bool enabled, uint8_t componentMask, + uint64_t maxFrames) override; Error getDisplayCapabilities(Display display, std::vector* outCapabilities) override; diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 2df2d3b5b9..733a5dae43 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -555,6 +555,13 @@ Error Display::getDisplayedContentSamplingAttributes(PixelFormat* outFormat, return static_cast(intError); } +Error Display::setDisplayContentSamplingEnabled(bool enabled, uint8_t componentMask, + uint64_t maxFrames) const { + auto intError = + mComposer.setDisplayContentSamplingEnabled(mId, enabled, componentMask, maxFrames); + return static_cast(intError); +} + Error Display::getReleaseFences( std::unordered_map>* outFences) const { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 8c0f50c068..2d65051dff 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -240,6 +240,9 @@ public: [[clang::warn_unused_result]] Error getDisplayedContentSamplingAttributes( android::ui::PixelFormat* outFormat, android::ui::Dataspace* outDataspace, uint8_t* outComponentMask) const; + [[clang::warn_unused_result]] Error setDisplayContentSamplingEnabled(bool enabled, + uint8_t componentMask, + uint64_t maxFrames) const; [[clang::warn_unused_result]] Error getReleaseFences( std::unordered_map>* outFences) const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index a752a7da4b..b27344d48e 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -756,6 +756,20 @@ status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId, return NO_ERROR; } +status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled, + uint8_t componentMask, uint64_t maxFrames) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = + mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled, + componentMask, + maxFrames); + + if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + if (error == HWC2::Error::BadParameter) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + bool HWComposer::isUsingVrComposer() const { return getComposer()->isUsingVrComposer(); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 0375f7489d..3f1328e90e 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -131,6 +131,8 @@ public: status_t getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, uint8_t* outComponentMask); + status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled, + uint8_t componentMask, uint64_t maxFrames); // Events handling --------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5b3c47713e..75363bf874 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1121,8 +1121,7 @@ status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp if (!outFormat || !outDataspace || !outComponentMask) { return BAD_VALUE; } - Mutex::Autolock _l(mStateLock); - const auto display = getDisplayDeviceLocked(displayToken); + const auto display = getDisplayDevice(displayToken); if (!display || !display->getId()) { ALOGE("getDisplayedContentSamplingAttributes: Bad display token: %p", display.get()); return BAD_VALUE; @@ -1131,6 +1130,19 @@ status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp outDataspace, outComponentMask); } +status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp& displayToken, + bool enable, uint8_t componentMask, + uint64_t maxFrames) const { + const auto display = getDisplayDevice(displayToken); + if (!display || !display->getId()) { + ALOGE("setDisplayContentSamplingEnabled: Bad display token: %p", display.get()); + return BAD_VALUE; + } + + return getHwComposer().setDisplayContentSamplingEnabled(*display->getId(), enable, + componentMask, maxFrames); +} + status_t SurfaceFlinger::enableVSyncInjections(bool enable) { postMessageSync(new LambdaMessage([&] { Mutex::Autolock _l(mStateLock); @@ -4776,7 +4788,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case SET_ACTIVE_COLOR_MODE: case INJECT_VSYNC: case SET_POWER_MODE: - case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: { + case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: + case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: { if (!callingThreadHasUnscopedSurfaceFlingerAccess()) { IPCThreadState* ipc = IPCThreadState::self(); ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index eff5fca95f..1dd6e23291 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -483,6 +483,9 @@ private: virtual status_t getDisplayedContentSamplingAttributes( const sp& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, uint8_t* outComponentMask) const override; + virtual status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, + uint8_t componentMask, + uint64_t maxFrames) const override; /* ------------------------------------------------------------------------ * DeathRecipient interface diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 5a46c26653..68fd8b4907 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -115,6 +115,7 @@ public: MOCK_METHOD3(setLayerColorTransform, Error(Display, Layer, const float*)); MOCK_METHOD4(getDisplayedContentSamplingAttributes, Error(Display, PixelFormat*, Dataspace*, uint8_t*)); + MOCK_METHOD4(setDisplayContentSamplingEnabled, Error(Display, bool, uint8_t, uint64_t)); MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector*)); }; -- cgit v1.2.3-59-g8ed1b From 861616dff990d85dbf5624c59868c94e4ac00d9a Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Mon, 22 Oct 2018 12:52:23 -0700 Subject: blast: use frame instead of size and position BufferStateLayers will have a source crop rect and destination frame rect. The crop is the portion of the buffer that should be displayed. The frame is where that portion of the buffer should be displayed. The portion of the cropped buffer is scaled to fit the frame. Shader provided by romainguy@google.com. Test: Transaction_test Bug: 80477568 Change-Id: Ied3f3af2211132f79098aeb986292ee705a62219 --- libs/gui/LayerState.cpp | 6 + libs/gui/SurfaceComposerClient.cpp | 14 + libs/gui/include/gui/LayerState.h | 3 + libs/gui/include/gui/SurfaceComposerClient.h | 1 + services/surfaceflinger/BufferStateLayer.cpp | 89 +-- services/surfaceflinger/BufferStateLayer.h | 19 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/tests/Transaction_test.cpp | 728 ++++++++++++--------- 10 files changed, 508 insertions(+), 360 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 4f6341533d..35ce6e393a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -59,6 +59,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint32(transform); output.writeBool(transformToDisplayInverse); output.write(crop); + output.write(frame); if (buffer) { output.writeBool(true); output.write(*buffer); @@ -135,6 +136,7 @@ status_t layer_state_t::read(const Parcel& input) transform = input.readUint32(); transformToDisplayInverse = input.readBool(); input.read(crop); + input.read(frame); buffer = new GraphicBuffer(); if (input.readBool()) { input.read(*buffer); @@ -322,6 +324,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } + if (other.what & eFrameChanged) { + what |= eFrameChanged; + frame = other.frame; + } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9dfccc799e..a51af2c927 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -609,6 +609,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame( + const sp& sc, const Rect& frame) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameChanged; + s->frame = frame; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp& sc, const sp& buffer) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 5d27a75565..02c6be25c7 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -83,6 +83,7 @@ struct layer_state_t { eListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, + eFrameChanged = 0x1'00000000, }; layer_state_t() @@ -104,6 +105,7 @@ struct layer_state_t { transform(0), transformToDisplayInverse(false), crop(Rect::INVALID_RECT), + frame(Rect::INVALID_RECT), dataspace(ui::Dataspace::UNKNOWN), surfaceDamageRegion(), api(-1), @@ -157,6 +159,7 @@ struct layer_state_t { uint32_t transform; bool transformToDisplayInverse; Rect crop; + Rect frame; sp buffer; sp acquireFence; ui::Dataspace dataspace; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 7d0551289e..5a4715b489 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -295,6 +295,7 @@ public: Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); Transaction& setCrop(const sp& sc, const Rect& crop); + Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer); Transaction& setAcquireFence(const sp& sc, const sp& fence); Transaction& setDataspace(const sp& sc, ui::Dataspace dataspace); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5ffd8ad95e..1c21968065 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -95,10 +95,9 @@ bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { return stateUpdateAvailable; } -Rect BufferStateLayer::getCrop(const Layer::State& s) const { - return (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) - ? GLConsumer::scaleDownCrop(s.crop, s.active.w, s.active.h) - : s.crop; +// Crop that applies to the window +Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { + return Rect::INVALID_RECT; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -128,6 +127,30 @@ bool BufferStateLayer::setCrop(const Rect& crop) { return true; } +bool BufferStateLayer::setFrame(const Rect& frame) { + int x = frame.left; + int y = frame.top; + int w = frame.getWidth(); + int h = frame.getHeight(); + + if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y && + mCurrentState.active.w == w && mCurrentState.active.h == h) { + return false; + } + + if (!frame.isValid()) { + x = y = w = h = 0; + } + mCurrentState.active.transform.set(x, y); + mCurrentState.active.w = w; + mCurrentState.active.h = h; + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool BufferStateLayer::setBuffer(const sp& buffer) { if (mCurrentState.buffer) { mReleasePreviousBuffer = true; @@ -237,27 +260,6 @@ bool BufferStateLayer::setTransactionCompletedListeners( return willPresent; } -bool BufferStateLayer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false; - mCurrentState.active.w = w; - mCurrentState.active.h = h; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - -bool BufferStateLayer::setPosition(float x, float y, bool /*immediate*/) { - if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y) - return false; - - mCurrentState.active.transform.set(x, y); - - mCurrentState.sequence++; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { mCurrentState.transparentRegionHint = transparent; mCurrentState.modified = true; @@ -265,21 +267,26 @@ bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { return true; } -bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, - bool allowNonRectPreservingTransforms) { - ui::Transform t; - t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); +Rect BufferStateLayer::getBufferSize(const State& s) const { + // for buffer state layers we use the display frame size as the buffer size. + if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) { + return Rect(getActiveWidth(s), getActiveHeight(s)); + } - if (!allowNonRectPreservingTransforms && !t.preserveRects()) { - ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored"); - return false; + // if the display frame is not defined, use the parent bounds as the buffer size. + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + Rect parentBounds = Rect(p->computeBounds(Region())); + if (!parentBounds.isEmpty()) { + return parentBounds; + } } - mCurrentState.sequence++; - mCurrentState.active.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; + // if there is no parent layer, use the buffer's bounds as the buffer size + if (s.buffer) { + return s.buffer->getBounds(); + } + return Rect::INVALID_RECT; } // ----------------------------------------------------------------------- @@ -315,8 +322,14 @@ ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { return getDrawingState().dataspace; } +// Crop that applies to the buffer Rect BufferStateLayer::getDrawingCrop() const { - return Rect::INVALID_RECT; + const State& s(getDrawingState()); + + if (s.crop.isEmpty() && s.buffer) { + return s.buffer->getBounds(); + } + return s.crop; } uint32_t BufferStateLayer::getDrawingScalingMode() const { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 315d5af748..3f891d3fd6 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -62,6 +62,7 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; + bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; @@ -71,18 +72,22 @@ public: bool setSidebandStream(const sp& sidebandStream) override; bool setTransactionCompletedListeners(const std::vector>& handles) override; - bool setSize(uint32_t w, uint32_t h) override; - bool setPosition(float x, float y, bool immediate) override; - bool setTransparentRegionHint(const Region& transparent) override; - bool setMatrix(const layer_state_t::matrix22_t& matrix, - bool allowNonRectPreservingTransforms) override; - // Override to ignore legacy layer state properties that are not used by BufferStateLayer - bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } + bool setPosition(float /*x*/, float /*y*/, bool /*immediate*/) override { return false; } + bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/) override { + return false; + } + bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; } + bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, uint64_t /*frameNumber*/) override {} + + Rect getBufferSize(const State& s) const override; // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c9c0a5ce5e..2a2f20b912 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -91,8 +91,8 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.requested_legacy = mCurrentState.active_legacy; mCurrentState.appId = 0; mCurrentState.type = 0; - mCurrentState.active.w = 0; - mCurrentState.active.h = 0; + mCurrentState.active.w = UINT32_MAX; + mCurrentState.active.h = UINT32_MAX; mCurrentState.active.transform.set(0, 0); mCurrentState.transform = 0; mCurrentState.transformToDisplayInverse = false; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 687fc0a712..55a56285e2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -297,6 +297,7 @@ public: virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; virtual bool setCrop(const Rect& /*crop*/) { return false; }; + virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 39d54a2f85..60da038081 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3663,6 +3663,9 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eFrameChanged) { + if (layer->setFrame(s.frame)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eBufferChanged) { if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index e414991620..3dedf24a17 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -395,7 +395,7 @@ protected: BufferUsage::COMPOSER_OVERLAY, "test"); fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); - Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); + Transaction().setBuffer(layer, buffer).apply(); } void fillLayerColor(uint32_t mLayerType, const sp& layer, const Color& color, @@ -483,13 +483,14 @@ protected: uint32_t mDisplayWidth; uint32_t mDisplayHeight; uint32_t mDisplayLayerStack; + Rect mDisplayRect = Rect::INVALID_RECT; // leave room for ~256 layers const int32_t mLayerZBase = std::numeric_limits::max() - 256; - void setPositionWithResizeHelper(uint32_t layerType); - void setSizeBasicHelper(uint32_t layerType); - void setMatrixWithResizeHelper(uint32_t layerType); + void setRelativeZBasicHelper(uint32_t layerType); + void setRelativeZGroupHelper(uint32_t layerType); + void setAlphaBasicHelper(uint32_t layerType); sp mBlackBgSurface; bool mColorManagementUsed; @@ -504,6 +505,8 @@ private: SurfaceComposerClient::getDisplayInfo(mDisplay, &info); mDisplayWidth = info.w; mDisplayHeight = info.h; + mDisplayRect = + Rect(static_cast(mDisplayWidth), static_cast(mDisplayHeight)); // After a new buffer is queued, SurfaceFlinger is notified and will // latch the new buffer on next vsync. Let's heuristically wait for 3 @@ -574,31 +577,33 @@ INSTANTIATE_TEST_CASE_P( ::testing::Values(static_cast(ISurfaceComposerClient::eFXSurfaceBufferQueue), static_cast(ISurfaceComposerClient::eFXSurfaceBufferState))); -TEST_P(LayerTypeTransactionTest, SetPositionBasic) { +TEST_F(LayerTransactionTest, SetPositionBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("default position"); + const Rect rect(0, 0, 32, 32); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } Transaction().setPosition(layer, 5, 10).apply(); { SCOPED_TRACE("new position"); + const Rect rect(5, 10, 37, 42); auto shot = screenshot(); - shot->expectColor(Rect(5, 10, 37, 42), Color::RED); - shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } } -TEST_P(LayerTypeTransactionTest, SetPositionRounding) { +TEST_F(LayerTransactionTest, SetPositionRounding_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // GLES requires only 4 bits of subpixel precision during rasterization // XXX GLES composition does not match HWC composition due to precision @@ -617,28 +622,28 @@ TEST_P(LayerTypeTransactionTest, SetPositionRounding) { } } -TEST_P(LayerTypeTransactionTest, SetPositionOutOfBounds) { +TEST_F(LayerTransactionTest, SetPositionOutOfBounds_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); Transaction().setPosition(layer, -32, -32).apply(); { SCOPED_TRACE("negative coordinates"); - screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + screenshot()->expectColor(mDisplayRect, Color::BLACK); } Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply(); { SCOPED_TRACE("positive coordinates"); - screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + screenshot()->expectColor(mDisplayRect, Color::BLACK); } } -TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) { +TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // partially out of bounds Transaction().setPosition(layer, -30, -30).apply(); @@ -656,10 +661,10 @@ TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) { } } -void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) { +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setPosition is applied immediately by default, with or without resize // pending @@ -667,39 +672,18 @@ void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) { { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - Rect rect; - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - rect = {5, 10, 37, 42}; - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - rect = {5, 10, 69, 74}; - break; - default: - ASSERT_FALSE(true) << "Unsupported layer type"; - } - + const Rect rect(5, 10, 37, 42); shot->expectColor(rect, Color::RED); shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) { - ASSERT_NO_FATAL_FAILURE( - setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); -} - -TEST_F(LayerTransactionTest, SetPositionWithResize_BufferState) { - ASSERT_NO_FATAL_FAILURE( - setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); -} - TEST_F(LayerTransactionTest, SetPositionWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -756,55 +740,38 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) } } -void LayerTransactionTest::setSizeBasicHelper(uint32_t layerType) { +TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); Transaction().setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - Rect rect; - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - rect = {0, 0, 32, 32}; - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - rect = {0, 0, 64, 64}; - break; - default: - ASSERT_FALSE(true) << "Unsupported layer type"; - } + const Rect rect(0, 0, 32, 32); shot->expectColor(rect, Color::RED); shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + const Rect rect(0, 0, 64, 64); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } } -TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) { - setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue); -} - -TEST_F(LayerTransactionTest, SetSizeBasic_BufferState) { - setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState); -} - TEST_P(LayerTypeTransactionTest, SetSizeInvalid) { // cannot test robustness against invalid sizes (zero or really huge) } -TEST_P(LayerTypeTransactionTest, SetSizeWithScaleToWindow) { +TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -866,18 +833,31 @@ TEST_P(LayerTypeTransactionTest, SetZNegative) { } } -TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { +void LayerTransactionTest::setRelativeZBasicHelper(uint32_t layerType) { sp layerR; sp layerG; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - - Transaction() - .setPosition(layerG, 16, 16) - .setRelativeLayer(layerG, layerR->getHandle(), 1) - .apply(); + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32)); + + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + Transaction() + .setPosition(layerG, 16, 16) + .setRelativeLayer(layerG, layerR->getHandle(), 1) + .apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(16, 16, 48, 48)) + .setRelativeLayer(layerG, layerR->getHandle(), 1) + .apply(); + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } { SCOPED_TRACE("layerG above"); auto shot = screenshot(); @@ -894,6 +874,14 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { } } +TEST_F(LayerTransactionTest, SetRelativeZBasic_BufferQueue) { + ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetRelativeZBasic_BufferState) { + ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { sp parent = LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, @@ -919,28 +907,44 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { std::unique_ptr screenshot; // only layerB is in this range sp parentHandle = parent->getHandle(); - ScreenCapture::captureLayers(&screenshot, parentHandle); + ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32)); screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); } -TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) { +void LayerTransactionTest::setRelativeZGroupHelper(uint32_t layerType) { sp layerR; sp layerG; sp layerB; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerB, Color::BLUE, 32, 32)); // layerR = 0, layerG = layerR + 3, layerB = 2 - Transaction() - .setPosition(layerG, 8, 8) - .setRelativeLayer(layerG, layerR->getHandle(), 3) - .setPosition(layerB, 16, 16) - .setLayer(layerB, mLayerZBase + 2) - .apply(); + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + Transaction() + .setPosition(layerG, 8, 8) + .setRelativeLayer(layerG, layerR->getHandle(), 3) + .setPosition(layerB, 16, 16) + .setLayer(layerB, mLayerZBase + 2) + .apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(8, 8, 40, 40)) + .setRelativeLayer(layerG, layerR->getHandle(), 3) + .setFrame(layerB, Rect(16, 16, 48, 48)) + .setLayer(layerB, mLayerZBase + 2) + .apply(); + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + { SCOPED_TRACE("(layerR < layerG) < layerB"); auto shot = screenshot(); @@ -990,6 +994,14 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) { } } +TEST_F(LayerTransactionTest, SetRelativeZGroup_BufferQueue) { + ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetRelativeZGroup_BufferState) { + ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) { sp layerR; sp layerG; @@ -1017,7 +1029,7 @@ TEST_P(LayerTypeTransactionTest, SetFlagsHidden) { Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply(); { SCOPED_TRACE("layer hidden"); - screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + screenshot()->expectColor(mDisplayRect, Color::BLACK); } Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply(); @@ -1129,7 +1141,7 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) { Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) - .setSize(layer, 32, 32) + .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -1153,7 +1165,7 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED)); ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT)); - Transaction().setBuffer(layer, buffer).setSize(layer, 32, 32).apply(); + Transaction().setBuffer(layer, buffer).apply(); { SCOPED_TRACE("bottom transparent"); auto shot = screenshot(); @@ -1162,7 +1174,7 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) { } } -TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds_BufferQueue) { sp layerTransparent; sp layerR; ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); @@ -1170,30 +1182,64 @@ TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) { // check that transparent region hint is bound by the layer size Transaction() - .setTransparentRegionHint(layerTransparent, - Region(Rect(0, 0, mDisplayWidth, mDisplayHeight))) + .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE( + fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layerR, Color::RED, 32, 32)); screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED); } -TEST_P(LayerTypeTransactionTest, SetAlphaBasic) { - sp layer1; - sp layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}, 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}, 32, 32)); +TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds_BufferState) { + sp layerTransparent; + sp layerR; + ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); + ASSERT_NO_FATAL_FAILURE( + layerR = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + // check that transparent region hint is bound by the layer size Transaction() - .setAlpha(layer1, 0.25f) - .setAlpha(layer2, 0.75f) - .setPosition(layer2, 16, 0) - .setLayer(layer2, mLayerZBase + 1) + .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) + .setFrame(layerR, Rect(16, 16, 48, 48)) + .setLayer(layerR, mLayerZBase + 1) .apply(); + ASSERT_NO_FATAL_FAILURE( + fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32)); + screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED); +} + +void LayerTransactionTest::setAlphaBasicHelper(uint32_t layerType) { + sp layer1; + sp layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer1, {64, 0, 0, 255}, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer2, {0, 64, 0, 255}, 32, 32)); + + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + Transaction() + .setAlpha(layer1, 0.25f) + .setAlpha(layer2, 0.75f) + .setPosition(layer2, 16, 0) + .setLayer(layer2, mLayerZBase + 1) + .apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + Transaction() + .setAlpha(layer1, 0.25f) + .setAlpha(layer2, 0.75f) + .setFrame(layer1, Rect(0, 0, 32, 32)) + .setFrame(layer2, Rect(16, 0, 48, 32)) + .setLayer(layer2, mLayerZBase + 1) + .apply(); + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } { auto shot = screenshot(); uint8_t r = 16; // 64 * 0.25f @@ -1206,6 +1252,14 @@ TEST_P(LayerTypeTransactionTest, SetAlphaBasic) { } } +TEST_F(LayerTransactionTest, SetAlphaBasic_BufferQueue) { + ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetAlphaBasic_BufferState) { + ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + TEST_P(LayerTypeTransactionTest, SetAlphaClamped) { const Color color = {64, 0, 0, 255}; sp layer; @@ -1361,7 +1415,7 @@ TEST_P(LayerTypeTransactionTest, SetLayerStackBasic) { Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply(); { SCOPED_TRACE("non-existing layer stack"); - screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + screenshot()->expectColor(mDisplayRect, Color::BLACK); } Transaction().setLayerStack(layer, mDisplayLayerStack).apply(); @@ -1371,11 +1425,11 @@ TEST_P(LayerTypeTransactionTest, SetLayerStackBasic) { } } -TEST_P(LayerTypeTransactionTest, SetMatrixBasic) { +TEST_F(LayerTransactionTest, SetMatrixBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply(); { @@ -1413,11 +1467,57 @@ TEST_P(LayerTypeTransactionTest, SetMatrixBasic) { } } -TEST_P(LayerTypeTransactionTest, SetMatrixRot45) { +TEST_F(LayerTransactionTest, SetMatrixBasic_BufferState) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction() + .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) + .setFrame(layer, Rect(0, 0, 32, 32)) + .apply(); + { + SCOPED_TRACE("IDENTITY"); + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, + Color::WHITE); + } + + Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); + { + SCOPED_TRACE("FLIP_H"); + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, + Color::WHITE); + } + + Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); + { + SCOPED_TRACE("FLIP_V"); + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, + Color::WHITE); + } + + Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); + { + SCOPED_TRACE("ROT_90"); + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, + Color::WHITE); + } + + Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); + { + SCOPED_TRACE("SCALE"); + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, + Color::WHITE); + } +} + +TEST_F(LayerTransactionTest, SetMatrixRot45_BufferQueue) { + sp layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); const float rot = M_SQRT1_2; // 45 degrees const float trans = M_SQRT2 * 16.0f; @@ -1436,52 +1536,33 @@ TEST_P(LayerTypeTransactionTest, SetMatrixRot45) { shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE); } -void LayerTransactionTest::setMatrixWithResizeHelper(uint32_t layerType) { +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setMatrix is applied after any pending resize, unlike setPosition Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - Rect rect; - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - rect = {0, 0, 32, 32}; - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - rect = {0, 0, 128, 128}; - break; - default: - ASSERT_FALSE(true) << "Unsupported layer type"; - } + const Rect rect(0, 0, 32, 32); shot->expectColor(rect, Color::RED); shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); - screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); + const Rect rect(0, 0, 128, 128); + screenshot()->expectColor(rect, Color::RED); } } -TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) { - ASSERT_NO_FATAL_FAILURE( - setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); -} - -TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferState) { - ASSERT_NO_FATAL_FAILURE( - setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); -} - -TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) { +TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -1492,11 +1573,11 @@ TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } -TEST_P(LayerTypeTransactionTest, SetOverrideScalingModeBasic) { +TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); // XXX SCALE_CROP is not respected; calling setSize and // setOverrideScalingMode in separate transactions does not work @@ -1546,8 +1627,8 @@ TEST_F(LayerTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = screenshot(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_F(LayerTransactionTest, SetCropEmpty_BufferQueue) { @@ -1598,18 +1679,22 @@ TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferQueue) { shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) { - sp layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply(); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - +// TODO (marissaw): change Layer to make crop to be in bounds instead of passing a bad crop to hwc +// TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) { +// sp layer; +// ASSERT_NO_FATAL_FAILURE( +// layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); +// ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); +// +// Transaction() +// .setCrop(layer, Rect(-128, -64, 128, 64)) +// .setFrame(layer, Rect(0, 0, 32, 32)) +// .apply(); +// auto shot = screenshot(); +// shot->expectColor(Rect(0, 0, 32, 32), Color::RED); +// shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +//} +// TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -1629,12 +1714,12 @@ TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - const Point position(32, 32); + const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply(); + Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); auto shot = screenshot(); - shot->expectColor(crop + position, Color::RED); - shot->expectBorder(crop + position, Color::BLACK); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); } TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) { @@ -1642,7 +1727,7 @@ TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - // crop is affected by matrix + // crop_legacy is affected by matrix Transaction() .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) .setCrop_legacy(layer, Rect(8, 8, 24, 24)) @@ -1652,22 +1737,6 @@ TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) { shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithScale_BufferState) { - sp layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - // crop is affected by matrix - Transaction() - .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setCrop(layer, Rect(8, 8, 24, 24)) - .apply(); - auto shot = screenshot(); - shot->expectColor(Rect(16, 16, 48, 48), Color::RED); - shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); -} - TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -1691,30 +1760,6 @@ TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) { } } -TEST_F(LayerTransactionTest, SetCropWithResize_BufferState) { - sp layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - // setCrop_legacy is applied immediately by default, with or without resize pending - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("new buffer pending"); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 16, 16), Color::RED); - shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("new buffer"); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 16, 16), Color::RED); - shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); - } -} - TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -1752,41 +1797,6 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferState) { - sp layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - // request setCrop_legacy to be applied with the next resize - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); - { - SCOPED_TRACE("set crop 1"); - screenshot()->expectColor(Rect(8, 8, 24, 24), Color::RED); - } - - Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); - { - SCOPED_TRACE("set crop 2"); - screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); - } - - Transaction().setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize"); - screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); - } - - // finally resize - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("new buffer"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -1818,37 +1828,122 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) { +TEST_F(LayerTransactionTest, SetFrameBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect frame(8, 8, 24, 24); + + Transaction().setFrame(layer, frame).apply(); + auto shot = screenshot(); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetFrameEmpty_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - // all properties are applied immediate so setGeometryAppliesWithResize has no effect - Transaction() - .setCrop(layer, Rect(4, 4, 12, 12)) - .setSize(layer, 16, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); { - SCOPED_TRACE("new crop pending"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + SCOPED_TRACE("empty rect"); + Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } - Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); - Transaction().setPosition(layer, 0, 0).apply(); { - SCOPED_TRACE("new crop applied"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + SCOPED_TRACE("negative rect"); + Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } } +TEST_F(LayerTransactionTest, SetFrameDefaultParentless_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); + + // A parentless layer will default to a frame with the same size as the buffer + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 10, 10), Color::RED); + shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetFrameDefaultBSParent_BufferState) { + sp parent, child; + ASSERT_NO_FATAL_FAILURE( + parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); + + ASSERT_NO_FATAL_FAILURE( + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); + + Transaction().reparent(child, parent->getHandle()).apply(); + + // A layer will default to the frame of its parent + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetFrameDefaultBQParent_BufferState) { + sp parent, child; + ASSERT_NO_FATAL_FAILURE(parent = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); + + ASSERT_NO_FATAL_FAILURE( + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); + + Transaction().reparent(child, parent->getHandle()).apply(); + + // A layer will default to the frame of its parent + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetFrameUpdate_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + std::this_thread::sleep_for(500ms); + + Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(16, 16, 48, 48), Color::RED); + shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetFrameOutsideBounds_BufferState) { + sp parent, child; + ASSERT_NO_FATAL_FAILURE( + parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE( + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + Transaction().reparent(child, parent->getHandle()).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); + Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 16), Color::RED); + shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( @@ -1905,6 +2000,7 @@ TEST_F(LayerTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = screenshot(); @@ -1913,6 +2009,7 @@ TEST_F(LayerTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = screenshot(); @@ -1949,7 +2046,10 @@ TEST_F(LayerTransactionTest, SetTransformRotate90_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90).apply(); + Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) + .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) + .apply(); screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE, Color::GREEN, true /* filtered */); @@ -1963,7 +2063,10 @@ TEST_F(LayerTransactionTest, SetTransformFlipH_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H).apply(); + Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) + .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) + .apply(); screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE, Color::BLUE, true /* filtered */); @@ -1977,7 +2080,10 @@ TEST_F(LayerTransactionTest, SetTransformFlipV_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V).apply(); + Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) + .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) + .apply(); screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED, Color::GREEN, true /* filtered */); @@ -2012,7 +2118,6 @@ TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) { Transaction() .setBuffer(layer, buffer) .setAcquireFence(layer, fence) - .setSize(layer, 32, 32) .apply(); auto shot = screenshot(); @@ -2035,7 +2140,6 @@ TEST_F(LayerTransactionTest, SetDataspaceBasic_BufferState) { Transaction() .setBuffer(layer, buffer) .setDataspace(layer, ui::Dataspace::UNKNOWN) - .setSize(layer, 32, 32) .apply(); auto shot = screenshot(); @@ -2060,7 +2164,6 @@ TEST_F(LayerTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction() .setBuffer(layer, buffer) .setHdrMetadata(layer, hdrMetadata) - .setSize(layer, 32, 32) .apply(); auto shot = screenshot(); @@ -2085,7 +2188,6 @@ TEST_F(LayerTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { Transaction() .setBuffer(layer, buffer) .setSurfaceDamageRegion(layer, region) - .setSize(layer, 32, 32) .apply(); auto shot = screenshot(); @@ -2108,7 +2210,6 @@ TEST_F(LayerTransactionTest, SetApiBasic_BufferState) { Transaction() .setBuffer(layer, buffer) .setApi(layer, NATIVE_WINDOW_API_CPU) - .setSize(layer, 32, 32) .apply(); auto shot = screenshot(); @@ -2348,36 +2449,33 @@ public: }; class LayerCallbackTest : public LayerTransactionTest { -protected: +public: virtual sp createBufferStateLayer() { - return createLayer(mClient, "test", mWidth, mHeight, - ISurfaceComposerClient::eFXSurfaceBufferState); + return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState); } - virtual void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper, - const sp& layer = nullptr) { + static void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper, + const sp& layer = nullptr) { if (layer) { sp buffer = - new GraphicBuffer(mWidth, mHeight, PIXEL_FORMAT_RGBA_8888, 1, + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE, "test"); - fillGraphicBufferColor(buffer, Rect(0, 0, mWidth, mHeight), Color::RED); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); sp fence = new Fence(-1); - transaction.setBuffer(layer, buffer) - .setAcquireFence(layer, fence) - .setSize(layer, mWidth, mHeight); + transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence); } transaction.addTransactionCompletedCallback(callbackHelper->function, callbackHelper->getContext()); } - void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult, - bool finalState = false) { + static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult, + bool finalState = false) { TransactionStats transactionStats; ASSERT_NO_FATAL_FAILURE(helper.getTransactionStats(&transactionStats)); EXPECT_NO_FATAL_FAILURE(expectedResult.verifyTransactionStats(transactionStats)); @@ -2387,9 +2485,9 @@ protected: } } - void waitForCallbacks(CallbackHelper& helper, - const std::vector& expectedResults, - bool finalState = false) { + static void waitForCallbacks(CallbackHelper& helper, + const std::vector& expectedResults, + bool finalState = false) { for (const auto& expectedResult : expectedResults) { waitForCallback(helper, expectedResult); } @@ -2397,9 +2495,6 @@ protected: ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState()); } } - - uint32_t mWidth = 32; - uint32_t mHeight = 32; }; TEST_F(LayerCallbackTest, Basic) { @@ -2425,7 +2520,7 @@ TEST_F(LayerCallbackTest, NoBuffer) { CallbackHelper callback; fillTransaction(transaction, &callback); - transaction.setPosition(layer, mWidth, mHeight).apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer); @@ -2451,7 +2546,7 @@ TEST_F(LayerCallbackTest, OffScreen) { CallbackHelper callback; fillTransaction(transaction, &callback, layer); - transaction.setPosition(layer, -100, -100).apply(); + transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -2468,7 +2563,8 @@ TEST_F(LayerCallbackTest, Merge) { fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2, layer2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -2521,7 +2617,8 @@ TEST_F(LayerCallbackTest, Merge_SingleBuffer) { fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -2537,9 +2634,9 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; sp layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction transaction1, transaction2; @@ -2547,7 +2644,8 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2, layer2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -2612,7 +2710,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { fillTransaction(transaction, &callback); } - transaction.setPosition(layer, mWidth, mHeight).apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -2634,7 +2732,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2, layer2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -2655,9 +2754,9 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; sp layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction transaction1, transaction2; @@ -2666,7 +2765,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2, layer2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -2687,9 +2787,9 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; sp layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction transaction1, transaction2; @@ -2699,7 +2799,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2, layer2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -2725,9 +2826,9 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; sp layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight, + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction transaction1, transaction2; @@ -2737,7 +2838,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC fillTransaction(transaction1, &callback1, layer1); fillTransaction(transaction2, &callback2, layer2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -2749,7 +2851,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC fillTransaction(transaction1, &callback1); fillTransaction(transaction2, &callback2); - transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply(); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); @@ -2813,7 +2915,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { CallbackHelper callback; fillTransaction(transaction, &callback, layer); - transaction.setPosition(layer, mWidth, mHeight).apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -2827,7 +2929,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { fillTransaction(transaction, &callback); - transaction.setPosition(layer, mWidth, mHeight).apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(200ms); } @@ -4128,7 +4230,7 @@ TEST_F(ScreenCaptureTest, CaptureCrop) { // 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); + const Rect crop = Rect(0, 0, 30, 30); ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. -- cgit v1.2.3-59-g8ed1b From 1d4249acec3ee6a936f2400177a3316b60388057 Mon Sep 17 00:00:00 2001 From: Kevin DuBois Date: Wed, 29 Aug 2018 10:45:14 -0700 Subject: [SurfaceFlinger] add getDisplayedContentSample i/f Add interface to ISurfaceComposer that can query the graphics.composer for statistics on the displayed pixel content. Bug: 116028618 Test: Boot Test: ran test client, see data collected Change-Id: Ide9b81b80c3399e7d648c7b611514e0d699120de --- libs/gui/ISurfaceComposer.cpp | 77 ++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 6 ++ libs/gui/include/gui/ISurfaceComposer.h | 12 +++- libs/gui/include/gui/SurfaceComposerClient.h | 4 ++ libs/gui/tests/DisplayedContentSampling_test.cpp | 15 +++++ libs/gui/tests/Surface_test.cpp | 5 ++ libs/ui/include/ui/DisplayedFrameStats.h | 41 ++++++++++++ libs/ui/include_vndk/ui/DisplayedFrameStats.h | 1 + .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 25 +++++++ .../surfaceflinger/DisplayHardware/ComposerHal.h | 5 ++ services/surfaceflinger/DisplayHardware/HWC2.cpp | 6 ++ services/surfaceflinger/DisplayHardware/HWC2.h | 3 + .../surfaceflinger/DisplayHardware/HWComposer.cpp | 10 +++ .../surfaceflinger/DisplayHardware/HWComposer.h | 3 + services/surfaceflinger/SurfaceFlinger.cpp | 16 ++++- services/surfaceflinger/SurfaceFlinger.h | 3 + .../unittests/mock/DisplayHardware/MockComposer.h | 2 + 17 files changed, 232 insertions(+), 2 deletions(-) create mode 100644 libs/ui/include/ui/DisplayedFrameStats.h create mode 120000 libs/ui/include_vndk/ui/DisplayedFrameStats.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 7d2615166f..f1fefcc14b 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -651,6 +651,49 @@ public: &reply); return result; } + + virtual status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, + uint64_t timestamp, + DisplayedFrameStats* outStats) const { + if (!outStats) return BAD_VALUE; + + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + data.writeUint64(maxFrames); + data.writeUint64(timestamp); + + status_t result = + remote()->transact(BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE, data, &reply); + + if (result != NO_ERROR) { + return result; + } + + result = reply.readUint64(&outStats->numFrames); + if (result != NO_ERROR) { + return result; + } + + result = reply.readInt64Vector( + reinterpret_cast*>(&outStats->component_0_sample)); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt64Vector( + reinterpret_cast*>(&outStats->component_1_sample)); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt64Vector( + reinterpret_cast*>(&outStats->component_2_sample)); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt64Vector( + reinterpret_cast*>(&outStats->component_3_sample)); + return result; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -1055,6 +1098,40 @@ status_t BnSurfaceComposer::onTransact( return setDisplayContentSamplingEnabled(display, enable, static_cast(componentMask), maxFrames); } + case GET_DISPLAYED_CONTENT_SAMPLE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + + sp display = data.readStrongBinder(); + uint64_t maxFrames = 0; + uint64_t timestamp = 0; + + status_t result = data.readUint64(&maxFrames); + if (result != NO_ERROR) { + ALOGE("getDisplayedContentSample failure in reading max frames: %d", result); + return result; + } + + result = data.readUint64(×tamp); + if (result != NO_ERROR) { + ALOGE("getDisplayedContentSample failure in reading timestamp: %d", result); + return result; + } + + DisplayedFrameStats stats; + result = getDisplayedContentSample(display, maxFrames, timestamp, &stats); + if (result == NO_ERROR) { + reply->writeUint64(stats.numFrames); + reply->writeInt64Vector( + *reinterpret_cast*>(&stats.component_0_sample)); + reply->writeInt64Vector( + *reinterpret_cast*>(&stats.component_1_sample)); + reply->writeInt64Vector( + *reinterpret_cast*>(&stats.component_2_sample)); + reply->writeInt64Vector( + *reinterpret_cast*>(&stats.component_3_sample)); + } + return result; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 405d2287be..070b253a80 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1106,6 +1106,12 @@ status_t SurfaceComposerClient::setDisplayContentSamplingEnabled(const sp& display, + uint64_t maxFrames, uint64_t timestamp, + DisplayedFrameStats* outStats) { + return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames, + timestamp, outStats); +} // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 41369c855a..3052c0b312 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -27,10 +27,11 @@ #include +#include #include -#include #include #include +#include #include @@ -308,6 +309,14 @@ public: virtual status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, uint8_t componentMask, uint64_t maxFrames) const = 0; + + /* Returns statistics on the color profile of the last frame displayed for a given display + * + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, + uint64_t timestamp, + DisplayedFrameStats* outStats) const = 0; }; // ---------------------------------------------------------------------------- @@ -349,6 +358,7 @@ public: GET_COLOR_MANAGEMENT, GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, SET_DISPLAY_CONTENT_SAMPLING_ENABLED, + GET_DISPLAYED_CONTENT_SAMPLE, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index ba943a0f8e..2b107aa520 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -389,6 +390,9 @@ public: static status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, uint8_t componentMask, uint64_t maxFrames); + static status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, + uint64_t timestamp, DisplayedFrameStats* outStats); + private: virtual void onFirstRef(); diff --git a/libs/gui/tests/DisplayedContentSampling_test.cpp b/libs/gui/tests/DisplayedContentSampling_test.cpp index f9d5dd632b..5443812bff 100644 --- a/libs/gui/tests/DisplayedContentSampling_test.cpp +++ b/libs/gui/tests/DisplayedContentSampling_test.cpp @@ -104,4 +104,19 @@ TEST_F(DisplayedContentSamplingTest, SelectivelyDisableComponentOk) { 0); EXPECT_EQ(OK, status); } + +TEST_F(DisplayedContentSamplingTest, SampleCollectionCoherentWithSupportMask) { + if (shouldSkipTest()) return; + + DisplayedFrameStats stats; + status_t status = mComposerClient->getDisplayedContentSample(mDisplayToken, 0, 0, &stats); + EXPECT_EQ(OK, status); + if (stats.numFrames <= 0) return; + + if (componentMask & (0x1 << 0)) EXPECT_NE(0, stats.component_0_sample.size()); + if (componentMask & (0x1 << 1)) EXPECT_NE(0, stats.component_1_sample.size()); + if (componentMask & (0x1 << 2)) EXPECT_NE(0, stats.component_2_sample.size()); + if (componentMask & (0x1 << 3)) EXPECT_NE(0, stats.component_3_sample.size()); +} + } // namespace android diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index cb1756f15b..d37b81096b 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -652,6 +652,11 @@ public: uint64_t /*maxFrames*/) const override { return NO_ERROR; } + status_t getDisplayedContentSample(const sp& /*display*/, uint64_t /*maxFrames*/, + uint64_t /*timestamp*/, + DisplayedFrameStats* /*outStats*/) const override { + return NO_ERROR; + } virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; } diff --git a/libs/ui/include/ui/DisplayedFrameStats.h b/libs/ui/include/ui/DisplayedFrameStats.h new file mode 100644 index 0000000000..7a70ea1f06 --- /dev/null +++ b/libs/ui/include/ui/DisplayedFrameStats.h @@ -0,0 +1,41 @@ +/* + * 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 + +namespace android { + +struct DisplayedFrameStats { + /* The number of frames represented by this sample. */ + uint64_t numFrames = 0; + /* A histogram counting how many times a pixel of a given value was displayed onscreen for + * FORMAT_COMPONENT_0. The buckets of the histogram are evenly weighted, the number of buckets + * is device specific. eg, for RGBA_8888, if sampleComponent0 is {10, 6, 4, 1} this means that + * 10 red pixels were displayed onscreen in range 0x00->0x3F, 6 red pixels + * were displayed onscreen in range 0x40->0x7F, etc. + */ + std::vector component_0_sample = {}; + /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_1. */ + std::vector component_1_sample = {}; + /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_2. */ + std::vector component_2_sample = {}; + /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_3. */ + std::vector component_3_sample = {}; +}; + +} // namespace android diff --git a/libs/ui/include_vndk/ui/DisplayedFrameStats.h b/libs/ui/include_vndk/ui/DisplayedFrameStats.h new file mode 120000 index 0000000000..6014e1954a --- /dev/null +++ b/libs/ui/include_vndk/ui/DisplayedFrameStats.h @@ -0,0 +1 @@ +../../include/ui/DisplayedFrameStats.h \ No newline at end of file diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 3b7ed155ba..d6237cbdfc 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -1079,6 +1079,31 @@ Error Composer::setDisplayContentSamplingEnabled(Display display, bool enabled, maxFrames); } +Error Composer::getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp, + DisplayedFrameStats* outStats) { + if (!outStats) { + return Error::BAD_PARAMETER; + } + if (!mClient_2_3) { + return Error::UNSUPPORTED; + } + Error error = kDefaultError; + mClient_2_3->getDisplayedContentSample(display, maxFrames, timestamp, + [&](const auto tmpError, auto tmpNumFrames, + const auto& tmpSamples0, const auto& tmpSamples1, + const auto& tmpSamples2, const auto& tmpSamples3) { + error = tmpError; + if (error == Error::NONE) { + outStats->numFrames = tmpNumFrames; + outStats->component_0_sample = tmpSamples0; + outStats->component_1_sample = tmpSamples1; + outStats->component_2_sample = tmpSamples2; + outStats->component_3_sample = tmpSamples3; + } + }); + return error; +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 0db12a16cf..38ee7ad545 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -194,6 +195,8 @@ public: uint8_t* outComponentMask) = 0; virtual Error setDisplayContentSamplingEnabled(Display display, bool enabled, uint8_t componentMask, uint64_t maxFrames) = 0; + virtual Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp, + DisplayedFrameStats* outStats) = 0; virtual Error getDisplayCapabilities(Display display, std::vector* outCapabilities) = 0; }; @@ -400,6 +403,8 @@ public: uint8_t* outComponentMask) override; Error setDisplayContentSamplingEnabled(Display display, bool enabled, uint8_t componentMask, uint64_t maxFrames) override; + Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp, + DisplayedFrameStats* outStats) override; Error getDisplayCapabilities(Display display, std::vector* outCapabilities) override; diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 733a5dae43..d2aa4ad031 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -562,6 +562,12 @@ Error Display::setDisplayContentSamplingEnabled(bool enabled, uint8_t componentM return static_cast(intError); } +Error Display::getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp, + android::DisplayedFrameStats* outStats) const { + auto intError = mComposer.getDisplayedContentSample(mId, maxFrames, timestamp, outStats); + return static_cast(intError); +} + Error Display::getReleaseFences( std::unordered_map>* outFences) const { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 2d65051dff..f5cb97e061 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -40,6 +40,7 @@ #include "PowerAdvisor.h" namespace android { + struct DisplayedFrameStats; class Fence; class FloatRect; class GraphicBuffer; @@ -243,6 +244,8 @@ public: [[clang::warn_unused_result]] Error setDisplayContentSamplingEnabled(bool enabled, uint8_t componentMask, uint64_t maxFrames) const; + [[clang::warn_unused_result]] Error getDisplayedContentSample( + uint64_t maxFrames, uint64_t timestamp, android::DisplayedFrameStats* outStats) const; [[clang::warn_unused_result]] Error getReleaseFences( std::unordered_map>* outFences) const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index b27344d48e..dc6faad414 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -770,6 +770,16 @@ status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool return NO_ERROR; } +status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, + uint64_t timestamp, DisplayedFrameStats* outStats) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = + mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp, + outStats); + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + bool HWComposer::isUsingVrComposer() const { return getComposer()->isUsingVrComposer(); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 3f1328e90e..4d0694ec2e 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -36,6 +36,7 @@ namespace android { +struct DisplayedFrameStats; class GraphicBuffer; class String8; class TestableSurfaceFlinger; @@ -133,6 +134,8 @@ public: uint8_t* outComponentMask); status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled, uint8_t componentMask, uint64_t maxFrames); + status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp, + DisplayedFrameStats* outStats); // Events handling --------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0bda020a8a..90eccd2fed 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1145,6 +1145,19 @@ status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp& dis componentMask, maxFrames); } +status_t SurfaceFlinger::getDisplayedContentSample(const sp& displayToken, + uint64_t maxFrames, uint64_t timestamp, + DisplayedFrameStats* outStats) const { + const auto display = getDisplayDevice(displayToken); + if (!display || !display->getId()) { + ALOGE("getDisplayContentSample: Bad display token: %p", displayToken.get()); + return BAD_VALUE; + } + + return getHwComposer().getDisplayedContentSample(*display->getId(), maxFrames, timestamp, + outStats); +} + status_t SurfaceFlinger::enableVSyncInjections(bool enable) { postMessageSync(new LambdaMessage([&] { Mutex::Autolock _l(mStateLock); @@ -4791,7 +4804,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case INJECT_VSYNC: case SET_POWER_MODE: case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: - case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: { + case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: + case GET_DISPLAYED_CONTENT_SAMPLE: { if (!callingThreadHasUnscopedSurfaceFlingerAccess()) { IPCThreadState* ipc = IPCThreadState::self(); ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index fe2f1c2658..ba92a8f4db 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -486,6 +486,9 @@ private: virtual status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, uint8_t componentMask, uint64_t maxFrames) const override; + virtual status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, + uint64_t timestamp, + DisplayedFrameStats* outStats) const override; /* ------------------------------------------------------------------------ * DeathRecipient interface diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 68fd8b4907..dfdda099b3 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -116,6 +116,8 @@ public: MOCK_METHOD4(getDisplayedContentSamplingAttributes, Error(Display, PixelFormat*, Dataspace*, uint8_t*)); MOCK_METHOD4(setDisplayContentSamplingEnabled, Error(Display, bool, uint8_t, uint64_t)); + MOCK_METHOD4(getDisplayedContentSample, + Error(Display, uint64_t, uint64_t, DisplayedFrameStats*)); MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector*)); }; -- cgit v1.2.3-59-g8ed1b From 713b63f3e6f397cd688c982ee5c2bb5e26fa9446 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Wed, 17 Oct 2018 15:42:43 -0700 Subject: blast: Queue transactions by applying client Do not update SurfaceFlinger until all the fences in a transaction have signaled. While waiting on the fences, place the transaction in a queue with other transactions that were applied by the same SurfaceComposerClient. Test: Transaction_test Bug: 80477568 Change-Id: I6b866bfa955d5eafef28016a0c5de7c3862f1837 --- libs/gui/ISurfaceComposer.cpp | 12 +- libs/gui/SurfaceComposerClient.cpp | 4 +- libs/gui/include/gui/ISurfaceComposer.h | 3 +- libs/gui/tests/Surface_test.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 75 +++- services/surfaceflinger/SurfaceFlinger.h | 24 +- services/surfaceflinger/tests/Android.bp | 1 + services/surfaceflinger/tests/BufferGenerator.cpp | 381 +++++++++++++++++++++ services/surfaceflinger/tests/BufferGenerator.h | 58 ++++ .../surfaceflinger/tests/BufferGeneratorShader.h | 355 +++++++++++++++++++ services/surfaceflinger/tests/Transaction_test.cpp | 323 ++++++++++++----- 11 files changed, 1136 insertions(+), 104 deletions(-) create mode 100644 services/surfaceflinger/tests/BufferGenerator.cpp create mode 100644 services/surfaceflinger/tests/BufferGenerator.h create mode 100644 services/surfaceflinger/tests/BufferGeneratorShader.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 2d6be26903..799151ae87 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -73,11 +73,9 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual void setTransactionState( - const Vector& state, - const Vector& displays, - uint32_t flags) - { + virtual void setTransactionState(const Vector& state, + const Vector& displays, uint32_t flags, + const sp& applyToken) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -92,6 +90,7 @@ public: } data.writeUint32(flags); + data.writeStrongBinder(applyToken); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -750,7 +749,8 @@ status_t BnSurfaceComposer::onTransact( } uint32_t stateFlags = data.readUint32(); - setTransactionState(state, displays, stateFlags); + sp applyToken = data.readStrongBinder(); + setTransactionState(state, displays, stateFlags, applyToken); return NO_ERROR; } case BOOT_FINISHED: { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 95862199eb..5b004e2805 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -264,7 +264,9 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { mAnimation = false; mEarlyWakeup = false; - sf->setTransactionState(composerStates, displayStates, flags); + sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + + sf->setTransactionState(composerStates, displayStates, flags, applyToken); mStatus = NO_ERROR; return NO_ERROR; } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3052c0b312..8cb40e78ad 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -124,7 +124,8 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual void setTransactionState(const Vector& state, - const Vector& displays, uint32_t flags) = 0; + const Vector& displays, uint32_t flags, + const sp& applyToken) = 0; /* signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 67afbd6a52..c56304fdd4 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -558,8 +558,8 @@ public: void destroyDisplay(const sp& /*display */) override {} sp getBuiltInDisplay(int32_t /*id*/) override { return nullptr; } void setTransactionState(const Vector& /*state*/, - const Vector& /*displays*/, uint32_t /*flags*/) - override {} + const Vector& /*displays*/, uint32_t /*flags*/, + const sp& /*applyToken*/) override {} void bootFinished() override {} bool authenticateSurfaceTexture( const sp& /*surface*/) const override { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4a93be6fb4..02cd9d9f61 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1568,11 +1568,23 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { bool SurfaceFlinger::handleMessageTransaction() { uint32_t transactionFlags = peekTransactionFlags(); + + // Apply any ready transactions in the queues if there are still transactions that have not been + // applied, wake up during the next vsync period and check again + bool transactionNeeded = false; + if (!flushTransactionQueues()) { + transactionNeeded = true; + } + if (transactionFlags) { handleTransaction(transactionFlags); - return true; } - return false; + + if (transactionNeeded) { + setTransactionFlags(eTransactionNeeded); + } + + return transactionFlags; } void SurfaceFlinger::handleMessageRefresh() { @@ -3314,6 +3326,26 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, return old; } +bool SurfaceFlinger::flushTransactionQueues() { + Mutex::Autolock _l(mStateLock); + auto it = mTransactionQueues.begin(); + while (it != mTransactionQueues.end()) { + auto& [applyToken, transactionQueue] = *it; + + while (!transactionQueue.empty()) { + const auto& [states, displays, flags] = transactionQueue.front(); + if (composerStateContainsUnsignaledFences(states)) { + break; + } + applyTransactionState(states, displays, flags); + transactionQueue.pop(); + } + + it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1); + } + return mTransactionQueues.empty(); +} + bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& states) { for (const ComposerState& state : states) { // Here we need to check that the interface we're given is indeed @@ -3336,19 +3368,44 @@ bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& return false; } -void SurfaceFlinger::setTransactionState( - const Vector& states, - const Vector& displays, - uint32_t flags) -{ +bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector& states) { + for (const ComposerState& state : states) { + const layer_state_t& s = state.state; + if (!(s.what & layer_state_t::eAcquireFenceChanged)) { + continue; + } + if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) { + return true; + } + } + return false; +} + +void SurfaceFlinger::setTransactionState(const Vector& states, + const Vector& displays, uint32_t flags, + const sp& applyToken) { ATRACE_CALL(); Mutex::Autolock _l(mStateLock); - uint32_t transactionFlags = 0; if (containsAnyInvalidClientState(states)) { return; } + // If its TransactionQueue already has a pending TransactionState or if it is pending + if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() || + composerStateContainsUnsignaledFences(states)) { + mTransactionQueues[applyToken].emplace(states, displays, flags); + setTransactionFlags(eTransactionNeeded); + return; + } + + applyTransactionState(states, displays, flags); +} + +void SurfaceFlinger::applyTransactionState(const Vector& states, + const Vector& displays, uint32_t flags) { + uint32_t transactionFlags = 0; + if (flags & eAnimation) { // For window updates that are part of an animation we must wait for // previous animation "frames" to be handled. @@ -3938,7 +3995,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0); + setTransactionState(state, displays, 0, nullptr); const auto display = getDisplayDevice(displayToken); if (!display) return; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b1bfb3a08d..822bb18f99 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -442,7 +442,8 @@ private: virtual void destroyDisplay(const sp& displayToken); virtual sp getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector& state, - const Vector& displays, uint32_t flags); + const Vector& displays, uint32_t flags, + const sp& applyToken); virtual void bootFinished(); virtual bool authenticateSurfaceTexture( const sp& bufferProducer) const; @@ -553,6 +554,10 @@ private: /* ------------------------------------------------------------------------ * Transactions */ + void applyTransactionState(const Vector& state, + const Vector& displays, uint32_t flags) + REQUIRES(mStateLock); + bool flushTransactionQueues(); uint32_t getTransactionFlags(uint32_t flags); uint32_t peekTransactionFlags(); // Can only be called from the main thread or with mStateLock held @@ -561,6 +566,7 @@ private: void latchAndReleaseBuffer(const sp& layer); void commitTransaction(); bool containsAnyInvalidClientState(const Vector& states); + bool composerStateContainsUnsignaledFences(const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); void setDestroyStateLocked(const ComposerState& composerState); @@ -965,6 +971,22 @@ private: uint32_t mTexturePoolSize = 0; std::vector mTexturePool; + struct IBinderHash { + std::size_t operator()(const sp& strongPointer) const { + return std::hash{}(strongPointer.get()); + } + }; + struct TransactionState { + TransactionState(const Vector& composerStates, + const Vector& displayStates, uint32_t transactionFlags) + : states(composerStates), displays(displayStates), flags(transactionFlags) {} + + Vector states; + Vector displays; + uint32_t flags; + }; + std::unordered_map, std::queue, IBinderHash> mTransactionQueues; + /* ------------------------------------------------------------------------ * Feature prototyping */ diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 604aa7df56..f121a952d8 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -17,6 +17,7 @@ cc_test { defaults: ["surfaceflinger_defaults"], test_suites: ["device-tests"], srcs: [ + "BufferGenerator.cpp", "Credentials_test.cpp", "Stress_test.cpp", "SurfaceInterceptor_test.cpp", diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp new file mode 100644 index 0000000000..8ddda60cd2 --- /dev/null +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -0,0 +1,381 @@ +/* + * 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. + */ + +#include +#include + +#include +#include +#include +#include + +#include "BufferGenerator.h" +#include "BufferGeneratorShader.h" + +namespace android { + +/* Used to receive the surfaces and fences from egl. The egl buffers are thrown + * away. The fences are sent to the requester via a callback */ +class SurfaceManager { +public: + /* Returns a fence from egl */ + using BufferCallback = std::function& buffer, int32_t fence)>; + + /* Listens for a new frame, detaches the buffer and returns the fence + * through saved callback. */ + class BufferListener : public ConsumerBase::FrameAvailableListener { + public: + BufferListener(sp consumer, BufferCallback callback) + : mConsumer(consumer), mCallback(callback) {} + + void onFrameAvailable(const BufferItem& /*item*/) { + BufferItem item; + + if (mConsumer->acquireBuffer(&item, 0)) return; + if (mConsumer->detachBuffer(item.mSlot)) return; + + mCallback(item.mGraphicBuffer, item.mFence->dup()); + } + + private: + sp mConsumer; + BufferCallback mCallback; + }; + + /* Creates a buffer listener that waits on a new frame from the buffer + * queue. */ + void initialize(uint32_t width, uint32_t height, android_pixel_format_t format, + BufferCallback callback) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + consumer->setDefaultBufferSize(width, height); + consumer->setDefaultBufferFormat(format); + + mBufferItemConsumer = new BufferItemConsumer(consumer, 0); + + mListener = new BufferListener(consumer, callback); + mBufferItemConsumer->setFrameAvailableListener(mListener); + + mSurface = new Surface(producer, true); + } + + /* Used by Egl manager. The surface is never displayed. */ + sp getSurface() const { return mSurface; } + +private: + sp mBufferItemConsumer; + sp mListener; + /* Used by Egl manager. The surface is never displayed */ + sp mSurface; +}; + +/* Used to generate valid fences. It is not possible to create a dummy sync + * fence for testing. Egl can generate buffers along with a valid fence. + * The buffer cannot be guaranteed to be the same format across all devices so + * a CPU filled buffer is used instead. The Egl fence is used along with the + * CPU filled buffer. */ +class EglManager { +public: + EglManager() + : mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT) {} + + ~EglManager() { cleanup(); } + + int initialize(sp surface) { + mSurface = surface; + + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL_NO_DISPLAY) return false; + + EGLint major; + EGLint minor; + if (!eglInitialize(mEglDisplay, &major, &minor)) { + ALOGW("Could not initialize EGL"); + return false; + } + + /* We're going to use a 1x1 pbuffer surface later on + * The configuration distance doesn't really matter for what we're + * trying to do */ + EGLint configAttrs[] = {EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 0, + EGL_DEPTH_SIZE, + 24, + EGL_STENCIL_SIZE, + 0, + EGL_NONE}; + + EGLConfig configs[1]; + EGLint configCnt; + if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1, &configCnt)) { + ALOGW("Could not select EGL configuration"); + eglReleaseThread(); + eglTerminate(mEglDisplay); + return false; + } + + if (configCnt <= 0) { + ALOGW("Could not find EGL configuration"); + eglReleaseThread(); + eglTerminate(mEglDisplay); + return false; + } + + /* These objects are initialized below but the default "null" values are + * used to cleanup properly at any point in the initialization sequence */ + EGLint attrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; + mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT, attrs); + if (mEglContext == EGL_NO_CONTEXT) { + ALOGW("Could not create EGL context"); + cleanup(); + return false; + } + + EGLint majorVersion; + if (!eglQueryContext(mEglDisplay, mEglContext, EGL_CONTEXT_CLIENT_VERSION, &majorVersion)) { + ALOGW("Could not query EGL version"); + cleanup(); + return false; + } + + if (majorVersion != 3) { + ALOGW("Unsupported EGL version"); + cleanup(); + return false; + } + + EGLint surfaceAttrs[] = {EGL_NONE}; + mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0], mSurface.get(), surfaceAttrs); + if (mEglSurface == EGL_NO_SURFACE) { + ALOGW("Could not create EGL surface"); + cleanup(); + return false; + } + + if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + ALOGW("Could not change current EGL context"); + cleanup(); + return false; + } + + return true; + } + + void makeCurrent() const { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); } + + void present() const { eglSwapBuffers(mEglDisplay, mEglSurface); } + +private: + void cleanup() { + if (mEglDisplay == EGL_NO_DISPLAY) return; + if (mEglSurface != EGL_NO_SURFACE) eglDestroySurface(mEglDisplay, mEglSurface); + if (mEglContext != EGL_NO_CONTEXT) eglDestroyContext(mEglDisplay, mEglContext); + + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglReleaseThread(); + eglTerminate(mEglDisplay); + } + + sp mSurface; + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLContext mEglContext; +}; + +class Program { +public: + ~Program() { + if (mInitialized) { + glDetachShader(mProgram, mVertexShader); + glDetachShader(mProgram, mFragmentShader); + + glDeleteShader(mVertexShader); + glDeleteShader(mFragmentShader); + + glDeleteProgram(mProgram); + } + } + + bool initialize(const char* vertex, const char* fragment) { + mVertexShader = buildShader(vertex, GL_VERTEX_SHADER); + if (!mVertexShader) { + return false; + } + + mFragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); + if (!mFragmentShader) { + return false; + } + + mProgram = glCreateProgram(); + glAttachShader(mProgram, mVertexShader); + glAttachShader(mProgram, mFragmentShader); + + glLinkProgram(mProgram); + + GLint status; + glGetProgramiv(mProgram, GL_LINK_STATUS, &status); + if (status != GL_TRUE) { + GLint length = 0; + glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length); + if (length > 1) { + GLchar log[length]; + glGetProgramInfoLog(mProgram, length, nullptr, &log[0]); + ALOGE("%s", log); + } + ALOGE("Error while linking shaders"); + return false; + } + mInitialized = true; + return true; + } + + void use() const { glUseProgram(mProgram); } + + void bindVec4(GLint location, vec4 v) const { glUniform4f(location, v.x, v.y, v.z, v.w); } + + void bindVec3(GLint location, const vec3* v, uint32_t count) const { + glUniform3fv(location, count, &(v->x)); + } + + void bindFloat(GLint location, float v) { glUniform1f(location, v); } + +private: + GLuint buildShader(const char* source, GLenum type) const { + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &source, nullptr); + glCompileShader(shader); + + GLint status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + ALOGE("Error while compiling shader of type 0x%x:\n===\n%s\n===", type, source); + // Some drivers return wrong values for GL_INFO_LOG_LENGTH + // use a fixed size instead + GLchar log[512]; + glGetShaderInfoLog(shader, sizeof(log), nullptr, &log[0]); + ALOGE("Shader info log: %s", log); + return 0; + } + + return shader; + } + + GLuint mProgram = 0; + GLuint mVertexShader = 0; + GLuint mFragmentShader = 0; + bool mInitialized = false; +}; + +BufferGenerator::BufferGenerator() + : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { + const float width = 1000.0; + const float height = 1000.0; + + auto setBufferWithContext = + std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); + mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); + + if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; + + mEglManager->makeCurrent(); + + if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; + mProgram->use(); + mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); + mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &TRIANGLE[0]); + + mInitialized = true; +} + +BufferGenerator::~BufferGenerator() { + mEglManager->makeCurrent(); +} + +status_t BufferGenerator::get(sp* outBuffer, sp* outFence) { + // mMutex is used to protect get() from getting called by multiple threads at the same time + static std::mutex mMutex; + std::lock_guard lock(mMutex); + + if (!mInitialized) { + if (outBuffer) { + *outBuffer = nullptr; + } + if (*outFence) { + *outFence = nullptr; + } + return -EINVAL; + } + + // Generate a buffer and fence. They will be returned through the setBuffer callback + mEglManager->makeCurrent(); + + glClear(GL_COLOR_BUFFER_BIT); + + const std::chrono::duration time = std::chrono::steady_clock::now() - mEpoch; + mProgram->bindFloat(1, time.count()); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + mPending = true; + mEglManager->present(); + + // Wait for the setBuffer callback + if (!mConditionVariable.wait_for(mMutex, std::chrono::seconds(2), + [this] { return !mPending; })) { + ALOGE("failed to set buffer and fence"); + return -ETIME; + } + + // Return buffer and fence + if (outBuffer) { + *outBuffer = mGraphicBuffer; + } + if (outFence) { + *outFence = new Fence(mFence); + } else { + close(mFence); + } + mGraphicBuffer = nullptr; + mFence = -1; + + return NO_ERROR; +} + +// static +void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, + void* bufferGenerator) { + BufferGenerator* generator = static_cast(bufferGenerator); + generator->mGraphicBuffer = buffer; + generator->mFence = fence; + generator->mPending = false; + generator->mConditionVariable.notify_all(); +} + +} // namespace android diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h new file mode 100644 index 0000000000..a3ffe86572 --- /dev/null +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -0,0 +1,58 @@ +/* + * 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 + +#include + +namespace android { + +class SurfaceManager; +class EglManager; +class Program; + +class BufferGenerator { +public: + BufferGenerator(); + ~BufferGenerator(); + + /* Get a new fence */ + status_t get(sp* outBuffer, sp* outFence); + + /* Static callback that sets the fence on a particular instance */ + static void setBuffer(const sp& buffer, int32_t fence, void* fenceGenerator); + +private: + bool mInitialized = false; + + std::unique_ptr mSurfaceManager; + std::unique_ptr mEglManager; + std::unique_ptr mProgram; + + std::condition_variable_any mConditionVariable; + + sp mGraphicBuffer; + int32_t mFence = -1; + bool mPending = false; + + using Epoch = std::chrono::time_point; + Epoch mEpoch = std::chrono::steady_clock::now(); +}; + +} // namespace android diff --git a/services/surfaceflinger/tests/BufferGeneratorShader.h b/services/surfaceflinger/tests/BufferGeneratorShader.h new file mode 100644 index 0000000000..564cda3ccc --- /dev/null +++ b/services/surfaceflinger/tests/BufferGeneratorShader.h @@ -0,0 +1,355 @@ +/* + * 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 +#include +#include + +static const char* VERTEX_SHADER = R"SHADER__(#version 300 es +precision highp float; + +layout(location = 0) in vec4 mesh_position; + +void main() { + gl_Position = mesh_position; +} +)SHADER__"; + +static const char* FRAGMENT_SHADER = R"SHADER__(#version 300 es +precision highp float; + +layout(location = 0) uniform vec4 resolution; +layout(location = 1) uniform float time; +layout(location = 2) uniform vec3[4] SPHERICAL_HARMONICS; + +layout(location = 0) out vec4 fragColor; + +#define saturate(x) clamp(x, 0.0, 1.0) +#define PI 3.14159265359 + +//------------------------------------------------------------------------------ +// Distance field functions +//------------------------------------------------------------------------------ + +float sdPlane(in vec3 p) { + return p.y; +} + +float sdSphere(in vec3 p, float s) { + return length(p) - s; +} + +float sdTorus(in vec3 p, in vec2 t) { + return length(vec2(length(p.xz) - t.x, p.y)) - t.y; +} + +vec2 opUnion(vec2 d1, vec2 d2) { + return d1.x < d2.x ? d1 : d2; +} + +vec2 scene(in vec3 position) { + vec2 scene = opUnion( + vec2(sdPlane(position), 1.0), + vec2(sdSphere(position - vec3(0.0, 0.4, 0.0), 0.4), 12.0) + ); + return scene; +} + +//------------------------------------------------------------------------------ +// Ray casting +//------------------------------------------------------------------------------ + +float shadow(in vec3 origin, in vec3 direction, in float tmin, in float tmax) { + float hit = 1.0; + + for (float t = tmin; t < tmax; ) { + float h = scene(origin + direction * t).x; + if (h < 0.001) return 0.0; + t += h; + hit = min(hit, 10.0 * h / t); + } + + return clamp(hit, 0.0, 1.0); +} + +vec2 traceRay(in vec3 origin, in vec3 direction) { + float tmin = 0.02; + float tmax = 20.0; + + float material = -1.0; + float t = tmin; + + for ( ; t < tmax; ) { + vec2 hit = scene(origin + direction * t); + if (hit.x < 0.002 || t > tmax) break; + t += hit.x; + material = hit.y; + } + + if (t > tmax) { + material = -1.0; + } + + return vec2(t, material); +} + +vec3 normal(in vec3 position) { + vec3 epsilon = vec3(0.001, 0.0, 0.0); + vec3 n = vec3( + scene(position + epsilon.xyy).x - scene(position - epsilon.xyy).x, + scene(position + epsilon.yxy).x - scene(position - epsilon.yxy).x, + scene(position + epsilon.yyx).x - scene(position - epsilon.yyx).x); + return normalize(n); +} + +//------------------------------------------------------------------------------ +// BRDF +//------------------------------------------------------------------------------ + +float pow5(float x) { + float x2 = x * x; + return x2 * x2 * x; +} + +float D_GGX(float linearRoughness, float NoH, const vec3 h) { + // Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces" + float oneMinusNoHSquared = 1.0 - NoH * NoH; + float a = NoH * linearRoughness; + float k = linearRoughness / (oneMinusNoHSquared + a * a); + float d = k * k * (1.0 / PI); + return d; +} + +float V_SmithGGXCorrelated(float linearRoughness, float NoV, float NoL) { + // Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs" + float a2 = linearRoughness * linearRoughness; + float GGXV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2); + float GGXL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2); + return 0.5 / (GGXV + GGXL); +} + +vec3 F_Schlick(const vec3 f0, float VoH) { + // Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering" + return f0 + (vec3(1.0) - f0) * pow5(1.0 - VoH); +} + +float F_Schlick(float f0, float f90, float VoH) { + return f0 + (f90 - f0) * pow5(1.0 - VoH); +} + +float Fd_Burley(float linearRoughness, float NoV, float NoL, float LoH) { + // Burley 2012, "Physically-Based Shading at Disney" + float f90 = 0.5 + 2.0 * linearRoughness * LoH * LoH; + float lightScatter = F_Schlick(1.0, f90, NoL); + float viewScatter = F_Schlick(1.0, f90, NoV); + return lightScatter * viewScatter * (1.0 / PI); +} + +float Fd_Lambert() { + return 1.0 / PI; +} + +//------------------------------------------------------------------------------ +// Indirect lighting +//------------------------------------------------------------------------------ + +vec3 Irradiance_SphericalHarmonics(const vec3 n) { + return max( + SPHERICAL_HARMONICS[0] + + SPHERICAL_HARMONICS[1] * (n.y) + + SPHERICAL_HARMONICS[2] * (n.z) + + SPHERICAL_HARMONICS[3] * (n.x) + , 0.0); +} + +vec2 PrefilteredDFG_Karis(float roughness, float NoV) { + // Karis 2014, "Physically Based Material on Mobile" + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4( 1.0, 0.0425, 1.040, -0.040); + + vec4 r = roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; + + return vec2(-1.04, 1.04) * a004 + r.zw; +} + +//------------------------------------------------------------------------------ +// Tone mapping and transfer functions +//------------------------------------------------------------------------------ + +vec3 Tonemap_ACES(const vec3 x) { + // Narkowicz 2015, "ACES Filmic Tone Mapping Curve" + const float a = 2.51; + const float b = 0.03; + const float c = 2.43; + const float d = 0.59; + const float e = 0.14; + return (x * (a * x + b)) / (x * (c * x + d) + e); +} + +vec3 OECF_sRGBFast(const vec3 linear) { + return pow(linear, vec3(1.0 / 2.2)); +} + +//------------------------------------------------------------------------------ +// Rendering +//------------------------------------------------------------------------------ + +vec3 render(in vec3 origin, in vec3 direction, out float distance) { + // Sky gradient + vec3 color = vec3(0.65, 0.85, 1.0) + direction.y * 0.72; + + // (distance, material) + vec2 hit = traceRay(origin, direction); + distance = hit.x; + float material = hit.y; + + // We've hit something in the scene + if (material > 0.0) { + vec3 position = origin + distance * direction; + + vec3 v = normalize(-direction); + vec3 n = normal(position); + vec3 l = normalize(vec3(0.6, 0.7, -0.7)); + vec3 h = normalize(v + l); + vec3 r = normalize(reflect(direction, n)); + + float NoV = abs(dot(n, v)) + 1e-5; + float NoL = saturate(dot(n, l)); + float NoH = saturate(dot(n, h)); + float LoH = saturate(dot(l, h)); + + vec3 baseColor = vec3(0.0); + float roughness = 0.0; + float metallic = 0.0; + + float intensity = 2.0; + float indirectIntensity = 0.64; + + if (material < 4.0) { + // Checkerboard floor + float f = mod(floor(6.0 * position.z) + floor(6.0 * position.x), 2.0); + baseColor = 0.4 + f * vec3(0.6); + roughness = 0.1; + } else if (material < 16.0) { + // Metallic objects + baseColor = vec3(0.3, 0.0, 0.0); + roughness = 0.2; + } + + float linearRoughness = roughness * roughness; + vec3 diffuseColor = (1.0 - metallic) * baseColor.rgb; + vec3 f0 = 0.04 * (1.0 - metallic) + baseColor.rgb * metallic; + + float attenuation = shadow(position, l, 0.02, 2.5); + + // specular BRDF + float D = D_GGX(linearRoughness, NoH, h); + float V = V_SmithGGXCorrelated(linearRoughness, NoV, NoL); + vec3 F = F_Schlick(f0, LoH); + vec3 Fr = (D * V) * F; + + // diffuse BRDF + vec3 Fd = diffuseColor * Fd_Burley(linearRoughness, NoV, NoL, LoH); + + color = Fd + Fr; + color *= (intensity * attenuation * NoL) * vec3(0.98, 0.92, 0.89); + + // diffuse indirect + vec3 indirectDiffuse = Irradiance_SphericalHarmonics(n) * Fd_Lambert(); + + vec2 indirectHit = traceRay(position, r); + vec3 indirectSpecular = vec3(0.65, 0.85, 1.0) + r.y * 0.72; + if (indirectHit.y > 0.0) { + if (indirectHit.y < 4.0) { + vec3 indirectPosition = position + indirectHit.x * r; + // Checkerboard floor + float f = mod(floor(6.0 * indirectPosition.z) + floor(6.0 * indirectPosition.x), 2.0); + indirectSpecular = 0.4 + f * vec3(0.6); + } else if (indirectHit.y < 16.0) { + // Metallic objects + indirectSpecular = vec3(0.3, 0.0, 0.0); + } + } + + // indirect contribution + vec2 dfg = PrefilteredDFG_Karis(roughness, NoV); + vec3 specularColor = f0 * dfg.x + dfg.y; + vec3 ibl = diffuseColor * indirectDiffuse + indirectSpecular * specularColor; + + color += ibl * indirectIntensity; + } + + return color; +} + +//------------------------------------------------------------------------------ +// Setup and execution +//------------------------------------------------------------------------------ + +mat3 setCamera(in vec3 origin, in vec3 target, float rotation) { + vec3 forward = normalize(target - origin); + vec3 orientation = vec3(sin(rotation), cos(rotation), 0.0); + vec3 left = normalize(cross(forward, orientation)); + vec3 up = normalize(cross(left, forward)); + return mat3(left, up, forward); +} + +void main() { + // Normalized coordinates + vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; + // Aspect ratio + p.x *= resolution.x / resolution.y; + + // Camera position and "look at" + vec3 origin = vec3(0.0, 1.0, 0.0); + vec3 target = vec3(0.0); + + origin.x += 2.0 * cos(time * 0.2); + origin.z += 2.0 * sin(time * 0.2); + + mat3 toWorld = setCamera(origin, target, 0.0); + vec3 direction = toWorld * normalize(vec3(p.xy, 2.0)); + + // Render scene + float distance; + vec3 color = render(origin, direction, distance); + + // Tone mapping + color = Tonemap_ACES(color); + + // Exponential distance fog + color = mix(color, 0.8 * vec3(0.7, 0.8, 1.0), 1.0 - exp2(-0.011 * distance * distance)); + + // Gamma compression + color = OECF_sRGBFast(color); + + fragColor = vec4(color, 1.0); +} +)SHADER__"; + +static const android::vec3 SPHERICAL_HARMONICS[4] = + {{0.754554516862612, 0.748542953903366, 0.790921515418539}, + {-0.083856548007422, 0.092533500963210, 0.322764661032516}, + {0.308152705331738, 0.366796330467391, 0.466698181299906}, + {-0.188884931542396, -0.277402551592231, -0.377844212327557}}; + +static const android::vec4 TRIANGLE[3] = {{-1.0f, -1.0f, 1.0f, 1.0f}, + {3.0f, -1.0f, 1.0f, 1.0f}, + {-1.0f, 3.0f, 1.0f, 1.0f}}; diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 037d32faff..d118ad6402 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -28,7 +28,6 @@ #include #include - #include #include #include @@ -41,6 +40,8 @@ #include #include +#include "BufferGenerator.h" + namespace android { namespace { @@ -478,6 +479,11 @@ protected: return screenshot; } + static status_t getBuffer(sp* outBuffer, sp* outFence) { + static BufferGenerator bufferGenerator; + return bufferGenerator.get(outBuffer, outFence); + } + sp mClient; sp mDisplay; @@ -2163,6 +2169,36 @@ TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) { } TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) { + sp layer; + Transaction transaction; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + sp fence; + if (getBuffer(nullptr, &fence) != NO_ERROR) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); + + status_t status = fence->wait(1000); + ASSERT_NE(static_cast(Fence::Status::Unsignaled), status); + std::this_thread::sleep_for(200ms); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetFenceNull_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); @@ -2514,7 +2550,7 @@ public: } void addSurface(ExpectedResult::Transaction transactionResult, const sp& layer, - ExpectedResult::Buffer bufferResult = NOT_ACQUIRED, + ExpectedResult::Buffer bufferResult = ACQUIRED, ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) { mTransactionResult = transactionResult; mExpectedSurfaceResults.emplace(std::piecewise_construct, @@ -2524,7 +2560,7 @@ public: void addSurfaces(ExpectedResult::Transaction transactionResult, const std::vector>& layers, - ExpectedResult::Buffer bufferResult = NOT_ACQUIRED, + ExpectedResult::Buffer bufferResult = ACQUIRED, ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) { for (const auto& layer : layers) { addSurface(transactionResult, layer, bufferResult, previousBufferResult); @@ -2631,24 +2667,22 @@ public: return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState); } - static void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper, - const sp& layer = nullptr) { + static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper, + const sp& layer = nullptr) { if (layer) { - sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY | - BufferUsage::GPU_TEXTURE, - "test"); - fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - sp fence = new Fence(-1); + sp buffer; + sp fence; + int err = getBuffer(&buffer, &fence); + if (err != NO_ERROR) { + return err; + } transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence); } transaction.addTransactionCompletedCallback(callbackHelper->function, callbackHelper->getContext()); + return NO_ERROR; } static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult, @@ -2680,7 +2714,11 @@ TEST_F(LayerCallbackTest, Basic) { Transaction transaction; CallbackHelper callback; - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.apply(); @@ -2695,19 +2733,28 @@ TEST_F(LayerCallbackTest, NoBuffer) { Transaction transaction; CallbackHelper callback; - fillTransaction(transaction, &callback); + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer); + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } TEST_F(LayerCallbackTest, NoStateChange) { Transaction transaction; CallbackHelper callback; - fillTransaction(transaction, &callback); + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.apply(); @@ -2721,7 +2768,11 @@ TEST_F(LayerCallbackTest, OffScreen) { Transaction transaction; CallbackHelper callback; - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); @@ -2737,8 +2788,16 @@ TEST_F(LayerCallbackTest, Merge) { Transaction transaction1, transaction2; CallbackHelper callback1, callback2; - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2, layer2); + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); @@ -2756,8 +2815,16 @@ TEST_F(LayerCallbackTest, Merge_SameCallback) { Transaction transaction1, transaction2; CallbackHelper callback; - fillTransaction(transaction1, &callback, layer1); - fillTransaction(transaction2, &callback, layer2); + int err = fillTransaction(transaction1, &callback, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction2.merge(std::move(transaction1)).apply(); @@ -2773,8 +2840,16 @@ TEST_F(LayerCallbackTest, Merge_SameLayer) { Transaction transaction1, transaction2; CallbackHelper callback1, callback2; - fillTransaction(transaction1, &callback1, layer); - fillTransaction(transaction2, &callback2, layer); + int err = fillTransaction(transaction1, &callback1, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction2.merge(std::move(transaction1)).apply(); @@ -2784,25 +2859,6 @@ TEST_F(LayerCallbackTest, Merge_SameLayer) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); } -TEST_F(LayerCallbackTest, Merge_SingleBuffer) { - sp layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); - ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2); - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - TEST_F(LayerCallbackTest, Merge_DifferentClients) { sp client1(new SurfaceComposerClient), client2(new SurfaceComposerClient); @@ -2818,8 +2874,16 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { Transaction transaction1, transaction2; CallbackHelper callback1, callback2; - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2, layer2); + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); @@ -2837,13 +2901,17 @@ TEST_F(LayerCallbackTest, MultipleTransactions) { Transaction transaction; CallbackHelper callback; for (size_t i = 0; i < 10; i++) { - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::Buffer::ACQUIRED, (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED : ExpectedResult::PreviousBuffer::RELEASED); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); @@ -2861,10 +2929,18 @@ TEST_F(LayerCallbackTest, MultipleTransactions_NoStateChange) { ExpectedResult expected; if (i == 0) { - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); } else { - fillTransaction(transaction, &callback); + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } } transaction.apply(); @@ -2882,9 +2958,17 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { CallbackHelper callback; for (size_t i = 0; i < 10; i++) { if (i == 0) { - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } } else { - fillTransaction(transaction, &callback); + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } } transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); @@ -2892,7 +2976,9 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED : ExpectedResult::Transaction::NOT_PRESENTED, - layer); + layer, + (i == 0) ? ExpectedResult::Buffer::ACQUIRED + : ExpectedResult::Buffer::NOT_ACQUIRED); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0)); } ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); @@ -2906,15 +2992,23 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { Transaction transaction1, transaction2; CallbackHelper callback1, callback2; for (size_t i = 0; i < 10; i++) { - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2, layer2); + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, - ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::Buffer::ACQUIRED, (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED : ExpectedResult::PreviousBuffer::RELEASED); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected)); @@ -2939,15 +3033,23 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { Transaction transaction1, transaction2; CallbackHelper callback1, callback2; for (size_t i = 0; i < 10; i++) { - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2, layer2); + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, - ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::Buffer::ACQUIRED, (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED : ExpectedResult::PreviousBuffer::RELEASED); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected)); @@ -2973,8 +3075,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha CallbackHelper callback1, callback2; // Normal call to set up test - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2, layer2); + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); @@ -2986,8 +3096,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha expected.reset(); // Test - fillTransaction(transaction1, &callback1); - fillTransaction(transaction2, &callback2); + err = fillTransaction(transaction1, &callback1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction2.merge(std::move(transaction1)).apply(); @@ -3012,8 +3130,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC CallbackHelper callback1, callback2; // Normal call to set up test - fillTransaction(transaction1, &callback1, layer1); - fillTransaction(transaction2, &callback2, layer2); + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); @@ -3025,12 +3151,21 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC expected.reset(); // Test - fillTransaction(transaction1, &callback1); - fillTransaction(transaction2, &callback2); + err = fillTransaction(transaction1, &callback1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2); + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, + ExpectedResult::Buffer::NOT_ACQUIRED); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); } @@ -3047,13 +3182,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame) { for (auto& expected : expectedResults) { expected.reset(); expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::NOT_ACQUIRED, previousBufferResult); + ExpectedResult::Buffer::ACQUIRED, previousBufferResult); previousBufferResult = ExpectedResult::PreviousBuffer::RELEASED; - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.apply(); - std::this_thread::sleep_for(200ms); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } @@ -3062,23 +3200,33 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_NoStateChange) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + // Normal call to set up test Transaction transaction; CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); + + // Test std::vector expectedResults(50); - bool first = true; for (auto& expected : expectedResults) { expected.reset(); - if (first) { - fillTransaction(transaction, &callback, layer); - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - first = false; - } else { - fillTransaction(transaction, &callback); + err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; } transaction.apply(); - std::this_thread::sleep_for(200ms); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } @@ -3090,7 +3238,11 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { // Normal call to set up test Transaction transaction; CallbackHelper callback; - fillTransaction(transaction, &callback, layer); + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); @@ -3102,13 +3254,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { std::vector expectedResults(50); for (auto& expected : expectedResults) { expected.reset(); - expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer); + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); - fillTransaction(transaction, &callback); + err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - std::this_thread::sleep_for(200ms); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } -- cgit v1.2.3-59-g8ed1b From 273171bd098028d12ee8d1209bb72a090bb66f2e Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 26 Dec 2018 11:46:30 -0800 Subject: Fix drag and drop (1/3) Added ability to send different InputWindowCommands to SurfaceFlinger. Also added transferTouchFocus function from client so it can be translated to an InputWindowCommand and passed to SF. Bug: 120463595 Test: Builds, no uses of new function Change-Id: I17deaf4a96d5a5bf6b14795d66419acffdb10882 --- libs/gui/ISurfaceComposer.cpp | 8 +++++-- libs/gui/LayerState.cpp | 32 ++++++++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 17 +++++++++++++-- libs/gui/include/gui/ISurfaceComposer.h | 4 +++- libs/gui/include/gui/LayerState.h | 14 ++++++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 2 ++ libs/gui/tests/Surface_test.cpp | 3 ++- services/surfaceflinger/SurfaceFlinger.cpp | 24 ++++++++++++++++----- services/surfaceflinger/SurfaceFlinger.h | 10 ++++++--- 9 files changed, 100 insertions(+), 14 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 799151ae87..2f6ef79af9 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -75,7 +75,8 @@ public: virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, - const sp& applyToken) { + const sp& applyToken, + const InputWindowCommands& commands) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -91,6 +92,7 @@ public: data.writeUint32(flags); data.writeStrongBinder(applyToken); + commands.write(data); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -750,7 +752,9 @@ status_t BnSurfaceComposer::onTransact( uint32_t stateFlags = data.readUint32(); sp applyToken = data.readStrongBinder(); - setTransactionState(state, displays, stateFlags, applyToken); + InputWindowCommands inputWindowCommands; + inputWindowCommands.read(data); + setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands); return NO_ERROR; } case BOOT_FINISHED: { diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 35ce6e393a..e5170ab73b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -379,4 +379,36 @@ void layer_state_t::merge(const layer_state_t& other) { } } +// ------------------------------- InputWindowCommands ---------------------------------------- + +void InputWindowCommands::merge(const InputWindowCommands& other) { + transferTouchFocusCommands + .insert(transferTouchFocusCommands.end(), + std::make_move_iterator(other.transferTouchFocusCommands.begin()), + std::make_move_iterator(other.transferTouchFocusCommands.end())); +} + +void InputWindowCommands::clear() { + transferTouchFocusCommands.clear(); +} + +void InputWindowCommands::write(Parcel& output) const { + output.writeUint32(static_cast(transferTouchFocusCommands.size())); + for (const auto& transferTouchFocusCommand : transferTouchFocusCommands) { + output.writeStrongBinder(transferTouchFocusCommand.fromToken); + output.writeStrongBinder(transferTouchFocusCommand.toToken); + } +} + +void InputWindowCommands::read(const Parcel& input) { + size_t count = input.readUint32(); + transferTouchFocusCommands.clear(); + for (size_t i = 0; i < count; i++) { + TransferTouchFocusCommand transferTouchFocusCommand; + transferTouchFocusCommand.fromToken = input.readStrongBinder(); + transferTouchFocusCommand.toToken = input.readStrongBinder(); + transferTouchFocusCommands.emplace_back(transferTouchFocusCommand); + } +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5b004e2805..e043762653 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -166,6 +166,7 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : mEarlyWakeup(other.mEarlyWakeup) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; + mInputWindowCommands = other.mInputWindowCommands; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { @@ -199,6 +200,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr } other.mListenerCallbacks.clear(); + mInputWindowCommands.merge(other.mInputWindowCommands); + return *this; } @@ -265,8 +268,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { mEarlyWakeup = false; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - - sf->setTransactionState(composerStates, displayStates, flags, applyToken); + sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands); + mInputWindowCommands.clear(); mStatus = NO_ERROR; return NO_ERROR; } @@ -804,6 +807,16 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput s->what |= layer_state_t::eInputInfoChanged; return *this; } + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transferTouchFocus( + const sp& fromToken, const sp& toToken) { + InputWindowCommands::TransferTouchFocusCommand transferTouchFocusCommand; + transferTouchFocusCommand.fromToken = fromToken; + transferTouchFocusCommand.toToken = toToken; + mInputWindowCommands.transferTouchFocusCommands.emplace_back(transferTouchFocusCommand); + return *this; +} + #endif SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 8cb40e78ad..e0ff410873 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -42,6 +42,7 @@ struct ComposerState; struct DisplayState; struct DisplayInfo; struct DisplayStatInfo; +struct InputWindowCommands; class LayerDebugInfo; class HdrCapabilities; class IDisplayEventConnection; @@ -125,7 +126,8 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, - const sp& applyToken) = 0; + const sp& applyToken, + const InputWindowCommands& inputWindowCommands) = 0; /* signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 02c6be25c7..e7564f5ed4 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -228,6 +228,20 @@ struct DisplayState { status_t read(const Parcel& input); }; +struct InputWindowCommands { + struct TransferTouchFocusCommand { + sp fromToken; + sp toToken; + }; + + std::vector transferTouchFocusCommands; + + void merge(const InputWindowCommands& other); + void clear(); + void write(Parcel& output) const; + void 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; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 8e3ba78108..9765cdd714 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -219,6 +219,7 @@ public: bool mAnimation = false; bool mEarlyWakeup = false; + InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; layer_state_t* getLayerState(const sp& sc); @@ -335,6 +336,7 @@ public: #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp& sc, const InputWindowInfo& info); + Transaction& transferTouchFocus(const sp& fromToken, const sp& toToken); #endif Transaction& destroySurface(const sp& sc); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index c56304fdd4..13fac7fa04 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -559,7 +559,8 @@ public: sp getBuiltInDisplay(int32_t /*id*/) override { return nullptr; } void setTransactionState(const Vector& /*state*/, const Vector& /*displays*/, uint32_t /*flags*/, - const sp& /*applyToken*/) override {} + const sp& /*applyToken*/, + const InputWindowCommands& /*inputWindowCommands*/) override {} void bootFinished() override {} bool authenticateSurfaceTexture( const sp& /*surface*/) const override { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 02cd9d9f61..4d685590cb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3337,7 +3337,7 @@ bool SurfaceFlinger::flushTransactionQueues() { if (composerStateContainsUnsignaledFences(states)) { break; } - applyTransactionState(states, displays, flags); + applyTransactionState(states, displays, flags, mInputWindowCommands); transactionQueue.pop(); } @@ -3383,7 +3383,8 @@ bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector& states, const Vector& displays, uint32_t flags, - const sp& applyToken) { + const sp& applyToken, + const InputWindowCommands& inputWindowCommands) { ATRACE_CALL(); Mutex::Autolock _l(mStateLock); @@ -3399,11 +3400,12 @@ void SurfaceFlinger::setTransactionState(const Vector& states, return; } - applyTransactionState(states, displays, flags); + applyTransactionState(states, displays, flags, inputWindowCommands); } void SurfaceFlinger::applyTransactionState(const Vector& states, - const Vector& displays, uint32_t flags) { + const Vector& displays, uint32_t flags, + const InputWindowCommands& inputWindowCommands) { uint32_t transactionFlags = 0; if (flags & eAnimation) { @@ -3444,6 +3446,8 @@ void SurfaceFlinger::applyTransactionState(const Vector& states, setDestroyStateLocked(state); } + transactionFlags |= addInputWindowCommands(inputWindowCommands); + // If a synchronous transaction is explicitly requested without any changes, force a transaction // anyway. This can be used as a flush mechanism for previous async transactions. // Empty animation transaction can be used to simulate back-pressure, so also force a @@ -3781,6 +3785,16 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { } } +uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) { + uint32_t flags = 0; + if (!inputWindowCommands.transferTouchFocusCommands.empty()) { + flags |= eTraversalNeeded; + } + + mInputWindowCommands.merge(inputWindowCommands); + return flags; +} + status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, @@ -3995,7 +4009,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0, nullptr); + setTransactionState(state, displays, 0, nullptr, mInputWindowCommands); const auto display = getDisplayDevice(displayToken); if (!display) return; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 822bb18f99..c37f159f7b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -443,7 +443,8 @@ private: virtual sp getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, - const sp& applyToken); + const sp& applyToken, + const InputWindowCommands& inputWindowCommands); virtual void bootFinished(); virtual bool authenticateSurfaceTexture( const sp& bufferProducer) const; @@ -555,8 +556,8 @@ private: * Transactions */ void applyTransactionState(const Vector& state, - const Vector& displays, uint32_t flags) - REQUIRES(mStateLock); + const Vector& displays, uint32_t flags, + const InputWindowCommands& inputWindowCommands) REQUIRES(mStateLock); bool flushTransactionQueues(); uint32_t getTransactionFlags(uint32_t flags); uint32_t peekTransactionFlags(); @@ -570,6 +571,7 @@ private: uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); void setDestroyStateLocked(const ComposerState& composerState); + uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands); /* ------------------------------------------------------------------------ * Layer management @@ -1020,6 +1022,8 @@ private: sp mSfConnectionHandle; sp mInputFlinger; + + InputWindowCommands mInputWindowCommands; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From b89ea9d9533864bc6f73a24a4d33d3edba6d1365 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 10 Dec 2018 13:01:14 -0800 Subject: SurfaceFlinger: Removed createScopedConnection. Scoped connections existed to constrain clients to only making surfaces with parents. However now that we support off-screen parents this is no longer required and we can use normal connections everywhere. We take however care that only priviledged clients can place layers in the current state. Test: Manual Bug: 62536731 Bug: 111373437 Bug: 111297488 Change-Id: I0a034767e92becec63071d7b1e3e71b95d505b77 --- libs/gui/ISurfaceComposer.cpp | 18 ------- libs/gui/SurfaceComposerClient.cpp | 9 +--- libs/gui/SurfaceControl.cpp | 7 +++ libs/gui/include/gui/ISurfaceComposer.h | 16 +----- libs/gui/include/gui/SurfaceComposerClient.h | 2 - libs/gui/include/gui/SurfaceControl.h | 2 + libs/gui/tests/Surface_test.cpp | 4 -- services/surfaceflinger/Client.cpp | 63 +--------------------- services/surfaceflinger/Client.h | 9 ---- services/surfaceflinger/Layer.cpp | 12 ----- services/surfaceflinger/SurfaceFlinger.cpp | 31 ++++------- services/surfaceflinger/SurfaceFlinger.h | 4 +- services/surfaceflinger/tests/Credentials_test.cpp | 20 +------ 13 files changed, 27 insertions(+), 170 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 2f6ef79af9..a481e81131 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -63,16 +63,6 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual sp createScopedConnection( - const sp& parent) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(IInterface::asBinder(parent)); - remote()->transact(BnSurfaceComposer::CREATE_SCOPED_CONNECTION, data, &reply); - return interface_cast(reply.readStrongBinder()); - } - virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, @@ -711,14 +701,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeStrongBinder(b); return NO_ERROR; } - case CREATE_SCOPED_CONNECTION: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp bufferProducer = - interface_cast(data.readStrongBinder()); - sp b = IInterface::asBinder(createScopedConnection(bufferProducer)); - reply->writeStrongBinder(b); - return NO_ERROR; - } case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e043762653..824e43fb07 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -910,11 +910,6 @@ SurfaceComposerClient::SurfaceComposerClient() { } -SurfaceComposerClient::SurfaceComposerClient(const sp& root) - : mStatus(NO_INIT), mParent(root) -{ -} - SurfaceComposerClient::SurfaceComposerClient(const sp& client) : mStatus(NO_ERROR), mClient(client) { @@ -923,10 +918,8 @@ SurfaceComposerClient::SurfaceComposerClient(const sp& c void SurfaceComposerClient::onFirstRef() { sp sf(ComposerService::getComposerService()); if (sf != nullptr && mStatus == NO_INIT) { - auto rootProducer = mParent.promote(); sp conn; - conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) : - sf->createConnection(); + conn = sf->createConnection(); if (conn != nullptr) { mClient = conn; mStatus = NO_ERROR; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 3a6dfdada5..b6ef286fd4 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -54,6 +54,13 @@ SurfaceControl::SurfaceControl( { } +SurfaceControl::SurfaceControl(const sp& other) { + mClient = other->mClient; + mHandle = other->mHandle; + mGraphicBufferProducer = other->mGraphicBufferProducer; + mOwned = false; +} + SurfaceControl::~SurfaceControl() { destroy(); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e0ff410873..1534fca790 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -87,22 +87,11 @@ public: eVsyncSourceSurfaceFlinger = 1 }; - /* create connection with surface flinger, requires - * ACCESS_SURFACE_FLINGER permission + /* + * Create a connection with SurfaceFlinger. */ virtual sp createConnection() = 0; - /** create a scoped connection with surface flinger. - * Surfaces produced with this connection will act - * as children of the passed in GBP. That is to say - * SurfaceFlinger will draw them relative and confined to - * drawing of buffers from the layer associated with parent. - * As this is graphically equivalent in reach to just drawing - * pixels into the parent buffers, it requires no special permission. - */ - virtual sp createScopedConnection( - const sp& parent) = 0; - /* return an IDisplayEventConnection */ virtual sp createDisplayEventConnection( VsyncSource vsyncSource = eVsyncSourceApp) = 0; @@ -356,7 +345,6 @@ public: ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, GET_LAYER_DEBUG_INFO, - CREATE_SCOPED_CONNECTION, GET_COMPOSITION_PREFERENCE, GET_COLOR_MANAGEMENT, GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 9765cdd714..4a8e01bec1 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -90,7 +90,6 @@ class SurfaceComposerClient : public RefBase public: SurfaceComposerClient(); SurfaceComposerClient(const sp& client); - SurfaceComposerClient(const sp& parent); virtual ~SurfaceComposerClient(); // Always make sure we could initialize @@ -402,7 +401,6 @@ private: mutable Mutex mLock; status_t mStatus; sp mClient; - wp mParent; }; // --------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index ccb30fa8e7..9bba76674d 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -75,6 +75,8 @@ public: status_t getLayerFrameStats(FrameStats* outStats) const; sp getClient() const; + + explicit SurfaceControl(const sp& other); private: // can't be copied diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 13fac7fa04..afc30d17b0 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -545,10 +545,6 @@ public: } sp createConnection() override { return nullptr; } - sp createScopedConnection( - const sp& /* parent */) override { - return nullptr; - } sp createDisplayEventConnection(ISurfaceComposer::VsyncSource) override { return nullptr; diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 0b59147c5a..ee4ec506f7 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -35,13 +35,7 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER" // --------------------------------------------------------------------------- Client::Client(const sp& flinger) - : Client(flinger, nullptr) -{ -} - -Client::Client(const sp& flinger, const sp& parentLayer) - : mFlinger(flinger), - mParentLayer(parentLayer) + : mFlinger(flinger) { } @@ -65,25 +59,6 @@ Client::~Client() } } -void Client::updateParent(const sp& parentLayer) { - Mutex::Autolock _l(mLock); - - // If we didn't ever have a parent, then we must instead be - // relying on permissions and we never need a parent. - if (mParentLayer != nullptr) { - mParentLayer = parentLayer; - } -} - -sp Client::getParentLayer(bool* outParentDied) const { - Mutex::Autolock _l(mLock); - sp parent = mParentLayer.promote(); - if (outParentDied != nullptr) { - *outParentDied = (mParentLayer != nullptr && parent == nullptr); - } - return parent; -} - status_t Client::initCheck() const { return NO_ERROR; } @@ -119,32 +94,6 @@ sp Client::getLayerUser(const sp& handle) const } -status_t Client::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - // these must be checked - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int uid = ipc->getCallingUid(); - const int self_pid = getpid(); - // If we are called from another non root process without the GRAPHICS, SYSTEM, or ROOT - // uid we require the sAccessSurfaceFlinger permission. - // We grant an exception in the case that the Client has a "parent layer", as its - // effects will be scoped to that layer. - if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != AID_SYSTEM && uid != 0) - && (getParentLayer() == nullptr)) { - // we're called from a different process, do the real check - if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger)) - { - ALOGE("Permission Denial: " - "can't openGlobalTransaction pid=%d, uid<=%d", pid, uid); - return PERMISSION_DENIED; - } - } - return BnSurfaceComposerClient::onTransact(code, data, reply, flags); -} - - status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, @@ -160,16 +109,8 @@ status_t Client::createSurface( return NAME_NOT_FOUND; } } - if (parent == nullptr) { - bool parentDied; - parent = getParentLayer(&parentDied); - // If we had a parent, but it died, we've lost all - // our capabilities. - if (parentDied) { - return NAME_NOT_FOUND; - } - } + // We rely on createLayer to check permissions. return mFlinger->createLayer(name, this, w, h, format, flags, windowType, ownerUid, handle, gbp, &parent); } diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 49437ed7fd..4a74739a10 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -39,7 +39,6 @@ class Client : public BnSurfaceComposerClient { public: explicit Client(const sp& flinger); - Client(const sp& flinger, const sp& parentLayer); ~Client(); status_t initCheck() const; @@ -51,8 +50,6 @@ public: sp getLayerUser(const sp& handle) const; - void updateParent(const sp& parentLayer); - private: // ISurfaceComposerClient interface virtual status_t createSurface( @@ -68,17 +65,11 @@ private: virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - - sp getParentLayer(bool* outParentDied = nullptr) const; - // constant sp mFlinger; // protected by mLock DefaultKeyedVector< wp, wp > mLayers; - wp mParentLayer; // thread-safe mutable Mutex mLock; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f4b3cddc63..2d3fd8ecbb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1666,11 +1666,6 @@ bool Layer::reparentChildren(const sp& newParentHandle) { } for (const sp& child : mCurrentChildren) { newParent->addChild(child); - - sp client(child->mClientRef.promote()); - if (client != nullptr) { - client->updateParent(newParent); - } } mCurrentChildren.clear(); @@ -1705,13 +1700,6 @@ bool Layer::reparent(const sp& newParentHandle) { addToCurrentState(); } - sp client(mClientRef.promote()); - sp newParentClient(newParent->mClientRef.promote()); - - if (client != newParentClient) { - client->updateParent(newParent); - } - Mutex::Autolock lock(mStateMutex); if (mLayerDetached) { mLayerDetached = false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4d685590cb..13997bea21 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -458,19 +458,6 @@ sp SurfaceFlinger::createConnection() { return initClient(new Client(this)); } -sp SurfaceFlinger::createScopedConnection( - const sp& gbp) { - if (authenticateSurfaceTexture(gbp) == false) { - return nullptr; - } - const auto& layer = (static_cast(gbp.get()))->getLayer(); - if (layer == nullptr) { - return nullptr; - } - - return initClient(new Client(this, layer)); -} - sp SurfaceFlinger::createDisplay(const String8& displayName, bool secure) { @@ -3243,7 +3230,8 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, const sp& handle, const sp& gbc, const sp& lbc, - const sp& parent) + const sp& parent, + bool addToCurrentState) { // add this layer to the current state list { @@ -3253,13 +3241,12 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, MAX_LAYERS); return NO_MEMORY; } - if (parent == nullptr) { + if (parent == nullptr && addToCurrentState) { mCurrentState.layersSortedByZ.add(lbc); - } else { - if (parent->isRemovedFromCurrentState()) { + } else if (parent == nullptr || parent->isRemovedFromCurrentState()) { ALOGE("addClientLayer called with a removed parent"); lbc->onRemovedFromCurrentState(); - } + } else { parent->addChild(lbc); } @@ -3864,7 +3851,9 @@ status_t SurfaceFlinger::createLayer( layer->setInfo(windowType, ownerUid); - result = addClientLayer(client, *handle, *gbp, layer, *parent); + bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess(); + result = addClientLayer(client, *handle, *gbp, layer, *parent, + addToCurrentState); if (result != NO_ERROR) { return result; } @@ -4828,7 +4817,6 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // access to SF. case BOOT_FINISHED: case CLEAR_ANIMATION_FRAME_STATS: - case CREATE_CONNECTION: case CREATE_DISPLAY: case DESTROY_DISPLAY: case ENABLE_VSYNC_INJECTIONS: @@ -4875,8 +4863,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // Calling setTransactionState is safe, because you need to have been // granted a reference to Client* and Handle* to do anything with it. case SET_TRANSACTION_STATE: - // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h - case CREATE_SCOPED_CONNECTION: + case CREATE_CONNECTION: case GET_COLOR_MANAGEMENT: case GET_COMPOSITION_PREFERENCE: { return OK; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c37f159f7b..bfc87a02eb 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -437,7 +437,6 @@ private: * ISurfaceComposer interface */ virtual sp createConnection(); - virtual sp createScopedConnection(const sp& gbp); virtual sp createDisplay(const String8& displayName, bool secure); virtual void destroyDisplay(const sp& displayToken); virtual sp getBuiltInDisplay(int32_t id); @@ -620,7 +619,8 @@ private: const sp& handle, const sp& gbc, const sp& lbc, - const sp& parent); + const sp& parent, + bool addToCurrentState); /* ------------------------------------------------------------------------ * Boot animation, on/off animations and screen capture diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index a73ec6c7ef..8560f5ed3e 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -162,10 +162,10 @@ TEST_F(CredentialsTest, ClientInitTest) { setSystemUID(); ASSERT_NO_FATAL_FAILURE(initClient()); - // No one else can init the client. + // Anyone else can init the client. setBinUID(); mComposerClient = new SurfaceComposerClient; - ASSERT_EQ(NO_INIT, mComposerClient->initCheck()); + ASSERT_NO_FATAL_FAILURE(initClient()); } TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) { @@ -222,22 +222,6 @@ TEST_F(CredentialsTest, SetActiveColorModeTest) { ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } -TEST_F(CredentialsTest, CreateSurfaceTest) { - sp display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); - DisplayInfo info; - SurfaceComposerClient::getDisplayInfo(display, &info); - const ssize_t displayWidth = info.w; - const ssize_t displayHeight = info.h; - - std::function condition = [=]() { - mBGSurfaceControl = - mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight, - PIXEL_FORMAT_RGBA_8888, 0); - return mBGSurfaceControl != nullptr && mBGSurfaceControl->isValid(); - }; - ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false)); -} - TEST_F(CredentialsTest, CreateDisplayTest) { std::function condition = [=]() { sp testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true); -- cgit v1.2.3-59-g8ed1b From 6fb1a7e9627df030667304d88a3292f91e790ea9 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 11 Dec 2018 12:07:25 -0800 Subject: SurfaceFlinger: Remove removeLayer We remove explicit layer destruction and replace it with reparent->null, completing the transition to a reference counted model. Test: Manual Bug: 62536731 Bug: 111373437 Bug: 111297488 Change-Id: I8ac7c5c5125e1c8daf84b42db00e1dd93a544bb5 --- cmds/surfacereplayer/replayer/Replayer.cpp | 41 ------------ cmds/surfacereplayer/replayer/Replayer.h | 3 - libs/gui/ISurfaceComposerClient.cpp | 8 --- libs/gui/SurfaceComposerClient.cpp | 34 +++++----- libs/gui/SurfaceControl.cpp | 10 ++- libs/gui/include/gui/ISurfaceComposerClient.h | 5 -- libs/gui/include/gui/SurfaceComposerClient.h | 11 ++-- services/surfaceflinger/Client.cpp | 24 ------- services/surfaceflinger/Client.h | 5 +- services/surfaceflinger/Layer.cpp | 49 +++++++++----- services/surfaceflinger/SurfaceFlinger.cpp | 77 ++++------------------ services/surfaceflinger/SurfaceFlinger.h | 12 +--- services/surfaceflinger/tests/Stress_test.cpp | 2 +- .../tests/SurfaceInterceptor_test.cpp | 12 ---- services/surfaceflinger/tests/Transaction_test.cpp | 8 +-- 15 files changed, 82 insertions(+), 219 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 384f21ff17..34886a99e9 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -286,10 +286,6 @@ status_t Replayer::dispatchEvent(int index) { std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event) .detach(); } break; - case increment.kSurfaceDeletion: { - std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event) - .detach(); - } break; case increment.kBufferUpdate: { std::lock_guard lock1(mLayerLock); std::lock_guard lock2(mBufferQueueSchedulerLock); @@ -628,47 +624,10 @@ status_t Replayer::createSurfaceControl( return NO_ERROR; } -status_t Replayer::deleteSurfaceControl( - const SurfaceDeletion& delete_, const std::shared_ptr& event) { - ALOGV("Deleting %d Surface Control", delete_.id()); - event->readyToExecute(); - - std::lock_guard lock1(mPendingLayersLock); - - mLayersPendingRemoval.push_back(delete_.id()); - - const auto& iterator = mBufferQueueSchedulers.find(delete_.id()); - if (iterator != mBufferQueueSchedulers.end()) { - (*iterator).second->stopScheduling(); - } - - std::lock_guard lock2(mLayerLock); - if (mLayers[delete_.id()] != nullptr) { - mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle()); - } - - return NO_ERROR; -} - -void Replayer::doDeleteSurfaceControls() { - std::lock_guard lock1(mPendingLayersLock); - std::lock_guard lock2(mLayerLock); - if (!mLayersPendingRemoval.empty()) { - for (int id : mLayersPendingRemoval) { - mLayers.erase(id); - mColors.erase(id); - mBufferQueueSchedulers.erase(id); - } - mLayersPendingRemoval.clear(); - } -} - status_t Replayer::injectVSyncEvent( const VSyncEvent& vSyncEvent, const std::shared_ptr& event) { ALOGV("Injecting VSync Event"); - doDeleteSurfaceControls(); - event->readyToExecute(); SurfaceComposerClient::injectVSync(vSyncEvent.when()); diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 120dd9babd..ad807ee950 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -70,8 +70,6 @@ class Replayer { status_t doTransaction(const Transaction& transaction, const std::shared_ptr& event); status_t createSurfaceControl(const SurfaceCreation& create, const std::shared_ptr& event); - status_t deleteSurfaceControl(const SurfaceDeletion& delete_, - const std::shared_ptr& event); status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr& event); void createDisplay(const DisplayCreation& create, const std::shared_ptr& event); void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr& event); @@ -120,7 +118,6 @@ class Replayer { void setDisplayProjection(SurfaceComposerClient::Transaction& t, display_id id, const ProjectionChange& pc); - void doDeleteSurfaceControls(); void waitUntilTimestamp(int64_t timestamp); void waitUntilDeferredTransactionLayerExists( const DeferredTransactionChange& dtc, std::unique_lock& lock); diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index a6890eeb19..369f523ea4 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -31,7 +31,6 @@ namespace { // Anonymous enum class Tag : uint32_t { CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, - DESTROY_SURFACE, CLEAR_LAYER_FRAME_STATS, GET_LAYER_FRAME_STATS, LAST = GET_LAYER_FRAME_STATS, @@ -57,11 +56,6 @@ public: handle, gbp); } - status_t destroySurface(const sp& handle) override { - return callRemote(Tag::DESTROY_SURFACE, - handle); - } - status_t clearLayerFrameStats(const sp& handle) const override { return callRemote(Tag::CLEAR_LAYER_FRAME_STATS, @@ -92,8 +86,6 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, switch (tag) { case Tag::CREATE_SURFACE: return callLocal(data, reply, &ISurfaceComposerClient::createSurface); - case Tag::DESTROY_SURFACE: - return callLocal(data, reply, &ISurfaceComposerClient::destroySurface); case Tag::CLEAR_LAYER_FRAME_STATS: return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats); case Tag::GET_LAYER_FRAME_STATS: diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 824e43fb07..6c39d6f1b8 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -205,6 +205,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr return *this; } +void SurfaceComposerClient::doDropReferenceTransaction(const sp& handle, + const sp& client) { + sp sf(ComposerService::getComposerService()); + Vector composerStates; + Vector displayStates; + + ComposerState s; + s.client = client; + s.state.surface = handle; + s.state.what |= layer_state_t::eReparent; + s.state.parentHandleForChild = nullptr; + + composerStates.add(s); + sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}); +} + status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mStatus != NO_ERROR) { return mStatus; @@ -819,17 +835,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transfer #endif -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( - const sp& sc) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eDestroySurface; - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform( const sp& sc, const mat3& matrix, const vec3& translation) { layer_state_t* s = getLayerState(sc); @@ -1004,13 +1009,6 @@ status_t SurfaceComposerClient::createSurfaceChecked( return err; } -status_t SurfaceComposerClient::destroySurface(const sp& sid) { - if (mStatus != NO_ERROR) - return mStatus; - status_t err = mClient->destroySurface(sid); - return err; -} - status_t SurfaceComposerClient::clearLayerFrameStats(const sp& token) const { if (mStatus != NO_ERROR) { return mStatus; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index b6ef286fd4..8e500a4f9b 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -63,7 +63,13 @@ SurfaceControl::SurfaceControl(const sp& other) { SurfaceControl::~SurfaceControl() { - destroy(); + if (mClient != nullptr && mHandle != nullptr && mOwned) { + SurfaceComposerClient::doDropReferenceTransaction(mHandle, mClient->getClient()); + } + mClient.clear(); + mHandle.clear(); + mGraphicBufferProducer.clear(); + IPCThreadState::self()->flushCommands(); } void SurfaceControl::destroy() @@ -71,7 +77,7 @@ void SurfaceControl::destroy() // 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); + SurfaceComposerClient::Transaction().reparent(this, nullptr).apply(); } // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 82b01b8cf0..56ca197ff9 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -55,11 +55,6 @@ public: int32_t ownerUid, sp* handle, sp* gbp) = 0; - /* - * Requires ACCESS_SURFACE_FLINGER permission - */ - virtual status_t destroySurface(const sp& handle) = 0; - /* * Requires ACCESS_SURFACE_FLINGER permission */ diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 4a8e01bec1..e0cbb705c7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -145,6 +145,13 @@ public: ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat); + /** + * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it + * to null), but without needing an sp to avoid infinite ressurection. + */ + static void doDropReferenceTransaction(const sp& handle, + const sp& client); + // ------------------------------------------------------------------------ // surface creation / destruction @@ -338,8 +345,6 @@ public: Transaction& transferTouchFocus(const sp& fromToken, const sp& toToken); #endif - Transaction& destroySurface(const sp& sc); - // Set a color transform matrix on the given layer on the built-in display. Transaction& setColorTransform(const sp& sc, const mat3& matrix, const vec3& translation); @@ -368,8 +373,6 @@ public: void setEarlyWakeup(); }; - 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(); diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index ee4ec506f7..4f6fb1cca6 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -39,26 +39,6 @@ Client::Client(const sp& flinger) { } -Client::~Client() -{ - // We need to post a message to remove our remaining layers rather than - // do so directly by acquiring the SurfaceFlinger lock. If we were to - // attempt to directly call the lock it becomes effectively impossible - // to use sp while holding the SF lock as descoping it could - // then trigger a dead-lock. - - const size_t count = mLayers.size(); - for (size_t i=0 ; i l = mLayers.valueAt(i).promote(); - if (l == nullptr) { - continue; - } - mFlinger->postMessageAsync(new LambdaMessage([flinger = mFlinger, l]() { - flinger->removeLayer(l); - })); - } -} - status_t Client::initCheck() const { return NO_ERROR; } @@ -115,10 +95,6 @@ status_t Client::createSurface( ownerUid, handle, gbp, &parent); } -status_t Client::destroySurface(const sp& handle) { - return mFlinger->onLayerRemoved(this, handle); -} - status_t Client::clearLayerFrameStats(const sp& handle) const { sp layer = getLayerUser(handle); if (layer == nullptr) { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 4a74739a10..d0051dee1a 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -39,13 +39,12 @@ class Client : public BnSurfaceComposerClient { public: explicit Client(const sp& flinger); - ~Client(); + ~Client() = default; status_t initCheck() const; // protected by SurfaceFlinger::mStateLock void attachLayer(const sp& handle, const sp& layer); - void detachLayer(const Layer* layer); sp getLayerUser(const sp& handle) const; @@ -59,8 +58,6 @@ private: sp* handle, sp* gbp); - virtual status_t destroySurface(const sp& handle); - virtual status_t clearLayerFrameStats(const sp& handle) const; virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b1827c191c..3f2d10a45b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -179,6 +179,8 @@ void Layer::onRemovedFromCurrentState() { for (const auto& child : mCurrentChildren) { child->onRemovedFromCurrentState(); } + + mFlinger->markLayerPendingRemovalLocked(this); } void Layer::addToCurrentState() { @@ -1571,6 +1573,7 @@ void Layer::addChild(const sp& layer) { ssize_t Layer::removeChild(const sp& layer) { layer->setParent(nullptr); + return mCurrentChildren.remove(layer); } @@ -1605,14 +1608,14 @@ void Layer::setChildrenDrawingParent(const sp& newParent) { } bool Layer::reparent(const sp& newParentHandle) { - if (newParentHandle == nullptr) { - return false; - } - - auto handle = static_cast(newParentHandle.get()); - sp newParent = handle->owner.promote(); - if (newParent == nullptr) { - ALOGE("Unable to promote Layer handle"); + bool callSetTransactionFlags = false; + + // While layers are detached, we allow most operations + // and simply halt performing the actual transaction. However + // for reparent != null we would enter the mRemovedFromCurrentState + // state, regardless of whether doTransaction was called, and + // so we need to prevent the update here. + if (mLayerDetached && newParentHandle == nullptr) { return false; } @@ -1620,17 +1623,31 @@ bool Layer::reparent(const sp& newParentHandle) { if (parent != nullptr) { parent->removeChild(this); } - newParent->addChild(this); - if (!newParent->isRemovedFromCurrentState()) { - addToCurrentState(); - } + if (newParentHandle != nullptr) { + auto handle = static_cast(newParentHandle.get()); + sp newParent = handle->owner.promote(); + if (newParent == nullptr) { + ALOGE("Unable to promote Layer handle"); + return false; + } - if (mLayerDetached) { - mLayerDetached = false; - setTransactionFlags(eTransactionNeeded); + newParent->addChild(this); + if (!newParent->isRemovedFromCurrentState()) { + addToCurrentState(); + } else { + onRemovedFromCurrentState(); + } + + if (mLayerDetached) { + mLayerDetached = false; + callSetTransactionFlags = true; + } + } else { + onRemovedFromCurrentState(); } - if (attachChildren()) { + + if (callSetTransactionFlags || attachChildren()) { setTransactionFlags(eTransactionNeeded); } return true; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fd25abf1a5..3648be49ec 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2799,10 +2799,8 @@ void SurfaceFlinger::commitTransaction() // showing at its last configured state until we eventually // abandon the buffer queue. if (l->isRemovedFromCurrentState()) { - l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) { - child->destroyHwcLayersForAllDisplays(); - latchAndReleaseBuffer(child); - }); + l->destroyHwcLayersForAllDisplays(); + latchAndReleaseBuffer(l); } } mLayersPendingRemoval.clear(); @@ -3276,30 +3274,6 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(const sp& layer) { - Mutex::Autolock _l(mStateLock); - return removeLayerLocked(mStateLock, layer); -} - -status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp& layer) { - if (layer->isLayerDetached()) { - return NO_ERROR; - } - - const auto& p = layer->getParent(); - ssize_t index; - if (p != nullptr) { - index = p->removeChild(layer); - } else { - index = mCurrentState.layersSortedByZ.remove(layer); - } - - layer->onRemovedFromCurrentState(); - - markLayerPendingRemovalLocked(lock, layer); - return NO_ERROR; -} - uint32_t SurfaceFlinger::peekTransactionFlags() { return mTransactionFlags; } @@ -3434,14 +3408,6 @@ void SurfaceFlinger::applyTransactionState(const Vector& states, } transactionFlags |= clientStateFlags; - // 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); - } - transactionFlags |= addInputWindowCommands(inputWindowCommands); // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -3767,20 +3733,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState 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 (state.what & layer_state_t::eDestroySurface) { - removeLayerLocked(mStateLock, layer); - } -} - uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) { uint32_t flags = 0; if (!inputWindowCommands.transferTouchFocusCommands.empty()) { @@ -3960,21 +3912,7 @@ status_t SurfaceFlinger::createContainerLayer(const sp& client, } -status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& handle) -{ - // called by a client when it wants to remove a Layer - status_t err = NO_ERROR; - sp l(client->getLayerUser(handle)); - if (l != nullptr) { - mInterceptor->saveSurfaceDeletion(l); - err = removeLayer(l); - ALOGE_IF(err<0 && err != NAME_NOT_FOUND, - "error removing layer=%p (%s)", l.get(), strerror(-err)); - } - return err; -} - -void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp& layer) { +void SurfaceFlinger::markLayerPendingRemovalLocked(const sp& layer) { mLayersPendingRemoval.add(layer); mLayersRemoved = true; setTransactionFlags(eTransactionNeeded); @@ -3983,7 +3921,14 @@ void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp void SurfaceFlinger::onHandleDestroyed(sp& layer) { Mutex::Autolock lock(mStateLock); - markLayerPendingRemovalLocked(mStateLock, layer); + // If a layer has a parent, we allow it to out-live it's handle + // with the idea that the parent holds a reference and will eventually + // be cleaned up. However no one cleans up the top-level so we do so + // here. + if (layer->getParent() == nullptr) { + mCurrentState.layersSortedByZ.remove(layer); + } + markLayerPendingRemovalLocked(layer); layer.clear(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bfc87a02eb..b8bfcf1f9e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -569,7 +569,6 @@ private: bool composerStateContainsUnsignaledFences(const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); - void setDestroyStateLocked(const ComposerState& composerState); uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands); /* ------------------------------------------------------------------------ @@ -599,20 +598,11 @@ private: String8 getUniqueLayerName(const String8& name); - // called in response to the window-manager calling - // ISurfaceComposerClient::destroySurface() - status_t onLayerRemoved(const sp& client, const sp& handle); - - void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp& layer); - // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all // resources associated to this layer. void onHandleDestroyed(sp& layer); - - // remove a layer from SurfaceFlinger immediately - status_t removeLayer(const sp& layer); - status_t removeLayerLocked(const Mutex&, const sp& layer); + void markLayerPendingRemovalLocked(const sp& layer); // add a layer to SurfaceFlinger status_t addClientLayer(const sp& client, diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index 3e1be8e288..89c26f4a98 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -34,7 +34,7 @@ TEST(SurfaceFlingerStress, create_and_destroy) { auto surf = client->createSurface(String8("t"), 100, 100, PIXEL_FORMAT_RGBA_8888, 0); ASSERT_TRUE(surf != nullptr); - client->destroySurface(surf->getHandle()); + surf->clear(); } }; diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index e506757867..8ec3e154e3 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -806,18 +806,6 @@ TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) { Increment::IncrementCase::kSurfaceCreation); } -TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) { - enableInterceptor(); - sp layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME), - SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0); - mComposerClient->destroySurface(layerToDelete->getHandle()); - disableInterceptor(); - - Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceDeletion)); -} - TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) { captureTest(&SurfaceInterceptorTest::displayCreation, Increment::IncrementCase::kDisplayCreation); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index d118ad6402..991ea36a3c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1023,7 +1023,7 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) { .setRelativeLayer(layerG, layerR->getHandle(), 1) .apply(); - mClient->destroySurface(layerG->getHandle()); + layerG->clear(); // layerG should have been removed screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } @@ -4030,9 +4030,9 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); }); { mCapture = screenshot(); - // Nothing should have changed. + // The surface should now be offscreen. mCapture->expectFGColor(64, 64); - mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(74, 74); mCapture->expectFGColor(84, 84); } } @@ -4610,7 +4610,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); auto redLayerHandle = redLayer->getHandle(); - mClient->destroySurface(redLayerHandle); + redLayer->clear(); SurfaceComposerClient::Transaction().apply(true); sp outBuffer; -- cgit v1.2.3-59-g8ed1b From 35187b32107eff2ded94adf29c19192524537ee1 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 8 Jan 2019 10:08:52 -0800 Subject: blast: [FIXED] create SurfaceControl from Surface parent Create a child SurfaceControl from a parent Surface. This is done by sending the parent IGBP to SurfaceFlinger who gets the parent Layer information. This is change is necessary for public SurfaceControl because createScopedConnection is deprecated. [Previous version used Layer::mStateMutex which was removed hours before this patch went in. Presubmit did not catch the conflict so the patch was immediately reverted. This version does not have that conflict.] Test: atest CtsViewTestCases:android.view.cts.ASurfaceControlTest Bug: 80477568 Change-Id: Ibbfb2851ff71c21cce1761cab434b85735e35515 --- libs/gui/ISurfaceComposerClient.cpp | 15 +++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 24 ++++++++++++++++++++++++ libs/gui/include/gui/ISurfaceComposerClient.h | 10 ++++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 24 ++++++++++++++++++------ services/surfaceflinger/Client.cpp | 20 ++++++++++++++++++++ services/surfaceflinger/Client.h | 6 ++++++ 6 files changed, 93 insertions(+), 6 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 369f523ea4..928ef95aa8 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -31,6 +31,7 @@ namespace { // Anonymous enum class Tag : uint32_t { CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, + CREATE_WITH_SURFACE_PARENT, CLEAR_LAYER_FRAME_STATS, GET_LAYER_FRAME_STATS, LAST = GET_LAYER_FRAME_STATS, @@ -56,6 +57,18 @@ public: handle, gbp); } + status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height, + PixelFormat format, uint32_t flags, + const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, + sp* gbp) override { + return callRemote(Tag::CREATE_WITH_SURFACE_PARENT, + name, width, height, format, + flags, parent, windowType, + ownerUid, handle, gbp); + } + status_t clearLayerFrameStats(const sp& handle) const override { return callRemote(Tag::CLEAR_LAYER_FRAME_STATS, @@ -86,6 +99,8 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, switch (tag) { case Tag::CREATE_SURFACE: return callLocal(data, reply, &ISurfaceComposerClient::createSurface); + case Tag::CREATE_WITH_SURFACE_PARENT: + return callLocal(data, reply, &ISurfaceComposerClient::createWithSurfaceParent); case Tag::CLEAR_LAYER_FRAME_STATS: return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats); case Tag::GET_LAYER_FRAME_STATS: diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6c39d6f1b8..8b9e4d7fee 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -977,6 +977,29 @@ sp SurfaceComposerClient::createSurface( return s; } +sp SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w, + uint32_t h, PixelFormat format, + uint32_t flags, Surface* parent, + int32_t windowType, + int32_t ownerUid) { + sp sur; + status_t err = mStatus; + + if (mStatus == NO_ERROR) { + sp handle; + sp parentGbp = parent->getIGraphicBufferProducer(); + sp gbp; + + err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType, + ownerUid, &handle, &gbp); + ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err)); + if (err == NO_ERROR) { + return new SurfaceControl(this, handle, gbp, true /* owned */); + } + } + return nullptr; +} + status_t SurfaceComposerClient::createSurfaceChecked( const String8& name, uint32_t w, @@ -1132,6 +1155,7 @@ status_t SurfaceComposerClient::getDisplayedContentSample(const sp& dis return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames, timestamp, outStats); } + // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 56ca197ff9..f443df8533 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -55,6 +55,16 @@ public: int32_t ownerUid, sp* handle, sp* gbp) = 0; + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ + virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + const sp& parent, + int32_t windowType, int32_t ownerUid, + sp* handle, + sp* gbp) = 0; + /* * Requires ACCESS_SURFACE_FLINGER permission */ diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e0cbb705c7..f16f7814e2 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -168,15 +168,27 @@ public: ); 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 + 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 + uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - int32_t ownerUid = -1 // UID of the task + int32_t ownerUid = -1 // UID of the task + ); + + //! Create a surface + sp createWithSurfaceParent( + const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + uint32_t flags = 0, // usage flags + Surface* parent = nullptr, // parent + 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 4f6fb1cca6..0e447d87f2 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -95,6 +95,26 @@ status_t Client::createSurface( ownerUid, handle, gbp, &parent); } +status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + const sp& parent, + int32_t windowType, int32_t ownerUid, sp* handle, + sp* gbp) { + if (mFlinger->authenticateSurfaceTexture(parent) == false) { + return BAD_VALUE; + } + + const auto& layer = (static_cast(parent.get()))->getLayer(); + if (layer == nullptr) { + return BAD_VALUE; + } + + sp parentHandle = layer->getHandle(); + + return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle, + gbp); +} + status_t Client::clearLayerFrameStats(const sp& handle) const { sp layer = getLayerUser(handle); if (layer == nullptr) { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index d0051dee1a..0f5ee4c85c 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -58,6 +58,12 @@ private: sp* handle, sp* gbp); + virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + const sp& parent, + int32_t windowType, int32_t ownerUid, + sp* handle, sp* gbp); + virtual status_t clearLayerFrameStats(const sp& handle) const; virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const; -- cgit v1.2.3-59-g8ed1b From 08d1051cc81c46b234f9b009fd009e8a1ddfc6f4 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 16 Jan 2019 13:27:35 -0800 Subject: [SurfaceComposerClient] Add API to query protected content support. To facilitate display color service to know the capability of protected content in GPU composition, add an API to allow SurfaceControl to query back from composer. BUG: 117436546 Test: Build. flash and boot. Verify by checking returned value. Change-Id: Ic99783c21a3bd130e90b5b71823d7761c22e4715 --- libs/gui/SurfaceComposerClient.cpp | 6 ++++++ libs/gui/include/gui/SurfaceComposerClient.h | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8b9e4d7fee..e3ee511750 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1118,6 +1118,12 @@ status_t SurfaceComposerClient::getCompositionPreference( wideColorGamutDataspace, wideColorGamutPixelFormat); } +bool SurfaceComposerClient::getProtectedContentSupport() { + bool supported = false; + ComposerService::getComposerService()->getProtectedContentSupport(&supported); + return supported; +} + status_t SurfaceComposerClient::clearAnimationFrameStats() { return ComposerService::getComposerService()->clearAnimationFrameStats(); } diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index f16f7814e2..9a4f7a02ba 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -145,6 +145,12 @@ public: ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat); + /* + * Gets whether SurfaceFlinger can support protected content in GPU composition. + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + static bool getProtectedContentSupport(); + /** * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it * to null), but without needing an sp to avoid infinite ressurection. -- cgit v1.2.3-59-g8ed1b From 17b4e4570fed99881a94730b9ad67b590aa426b9 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Wed, 26 Dec 2018 16:32:34 -0800 Subject: blast: add desired present time Add the option to set a desiredPresentTime for a transaction. This lets the framework know approximately when the transaction should be presented. Test: Transaction_test Bug: 80477568 Change-Id: Ic25617fb93f2c249b3b3c7a8f90f72ec358938f0 --- libs/gui/ISurfaceComposer.cpp | 9 +- libs/gui/SurfaceComposerClient.cpp | 22 ++- libs/gui/include/gui/ISurfaceComposer.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 13 ++ libs/gui/tests/Surface_test.cpp | 4 +- services/surfaceflinger/Scheduler/DispSync.cpp | 3 + services/surfaceflinger/SurfaceFlinger.cpp | 28 ++-- services/surfaceflinger/SurfaceFlinger.h | 15 ++- services/surfaceflinger/tests/Transaction_test.cpp | 150 +++++++++++++++++++++ 9 files changed, 223 insertions(+), 24 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 7357ba99f4..c3a4737e0e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -66,7 +66,8 @@ public: virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& commands) { + const InputWindowCommands& commands, + int64_t desiredPresentTime) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -83,6 +84,7 @@ public: data.writeUint32(flags); data.writeStrongBinder(applyToken); commands.write(data); + data.writeInt64(desiredPresentTime); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -748,7 +750,10 @@ status_t BnSurfaceComposer::onTransact( sp applyToken = data.readStrongBinder(); InputWindowCommands inputWindowCommands; inputWindowCommands.read(data); - setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands); + + int64_t desiredPresentTime = data.readInt64(); + setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands, + desiredPresentTime); return NO_ERROR; } case BOOT_FINISHED: { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8b9e4d7fee..32a368ebab 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -159,11 +159,12 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener // --------------------------------------------------------------------------- -SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : - mForceSynchronous(other.mForceSynchronous), - mTransactionNestCount(other.mTransactionNestCount), - mAnimation(other.mAnimation), - mEarlyWakeup(other.mEarlyWakeup) { +SurfaceComposerClient::Transaction::Transaction(const Transaction& other) + : mForceSynchronous(other.mForceSynchronous), + mTransactionNestCount(other.mTransactionNestCount), + mAnimation(other.mAnimation), + mEarlyWakeup(other.mEarlyWakeup), + mDesiredPresentTime(other.mDesiredPresentTime) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; mInputWindowCommands = other.mInputWindowCommands; @@ -218,7 +219,7 @@ void SurfaceComposerClient::doDropReferenceTransaction(const sp& handle s.state.parentHandleForChild = nullptr; composerStates.add(s); - sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}); + sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1); } status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { @@ -284,7 +285,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { mEarlyWakeup = false; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands); + sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands, + mDesiredPresentTime); mInputWindowCommands.clear(); mStatus = NO_ERROR; return NO_ERROR; @@ -742,6 +744,12 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime( + nsecs_t desiredPresentTime) { + mDesiredPresentTime = desiredPresentTime; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addTransactionCompletedCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext) { diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 9812e1ca6f..25a4185dec 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -116,7 +116,8 @@ public: virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& inputWindowCommands) = 0; + const InputWindowCommands& inputWindowCommands, + int64_t desiredPresentTime) = 0; /* signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index f16f7814e2..2f02328c99 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -237,6 +237,18 @@ public: bool mAnimation = false; bool mEarlyWakeup = false; + // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction + // to be presented. When it is not possible to present at exactly that time, it will be + // presented after the time has passed. + // + // Desired present times that are more than 1 second in the future may be ignored. + // When a desired present time has already passed, the transaction will be presented as soon + // as possible. + // + // Transactions from the same process are presented in the same order that they are applied. + // The desired present time does not affect this ordering. + int64_t mDesiredPresentTime = -1; + InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; @@ -325,6 +337,7 @@ public: Transaction& setApi(const sp& sc, int32_t api); Transaction& setSidebandStream(const sp& sc, const sp& sidebandStream); + Transaction& setDesiredPresentTime(nsecs_t desiredPresentTime); Transaction& addTransactionCompletedCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 2d773f240f..1d2950af19 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -556,7 +556,9 @@ public: void setTransactionState(const Vector& /*state*/, const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, - const InputWindowCommands& /*inputWindowCommands*/) override {} + const InputWindowCommands& /*inputWindowCommands*/, + int64_t /*desiredPresentTime*/) override {} + void bootFinished() override {} bool authenticateSurfaceTexture( const sp& /*surface*/) const override { diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp index b74b9010d2..9b2a6fc096 100644 --- a/services/surfaceflinger/Scheduler/DispSync.cpp +++ b/services/surfaceflinger/Scheduler/DispSync.cpp @@ -657,6 +657,9 @@ nsecs_t DispSync::computeNextRefresh(int periodOffset) const { Mutex::Autolock lock(mMutex); nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); nsecs_t phase = mReferenceTime + mPhase; + if (mPeriod == 0) { + return 0; + } return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dc02666559..c0059d5e2e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3498,8 +3498,8 @@ bool SurfaceFlinger::flushTransactionQueues() { auto& [applyToken, transactionQueue] = *it; while (!transactionQueue.empty()) { - const auto& [states, displays, flags] = transactionQueue.front(); - if (composerStateContainsUnsignaledFences(states)) { + const auto& [states, displays, flags, desiredPresentTime] = transactionQueue.front(); + if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) { break; } applyTransactionState(states, displays, flags, mInputWindowCommands); @@ -3533,23 +3533,33 @@ bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& return false; } -bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector& states) { +bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, + const Vector& states) { + const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime(); + // Do not present if the desiredPresentTime has not passed unless it is more than one second + // in the future. We ignore timestamps more than 1 second in the future for stability reasons. + if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime && + desiredPresentTime < expectedPresentTime + s2ns(1)) { + return false; + } + for (const ComposerState& state : states) { const layer_state_t& s = state.state; if (!(s.what & layer_state_t::eAcquireFenceChanged)) { continue; } if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) { - return true; + return false; } } - return false; + return true; } void SurfaceFlinger::setTransactionState(const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& inputWindowCommands) { + const InputWindowCommands& inputWindowCommands, + int64_t desiredPresentTime) { ATRACE_CALL(); Mutex::Autolock _l(mStateLock); @@ -3559,8 +3569,8 @@ void SurfaceFlinger::setTransactionState(const Vector& states, // If its TransactionQueue already has a pending TransactionState or if it is pending if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() || - composerStateContainsUnsignaledFences(states)) { - mTransactionQueues[applyToken].emplace(states, displays, flags); + !transactionIsReadyToBeApplied(desiredPresentTime, states)) { + mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime); setTransactionFlags(eTransactionNeeded); return; } @@ -4147,7 +4157,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0, nullptr, mInputWindowCommands); + setTransactionState(state, displays, 0, nullptr, mInputWindowCommands, -1); const auto display = getDisplayDevice(displayToken); if (!display) return; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c92874bab4..e5b3570fe3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -412,7 +412,8 @@ private: void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& inputWindowCommands) override; + const InputWindowCommands& inputWindowCommands, + int64_t desiredPresentTime) override; void bootFinished() override; bool authenticateSurfaceTexture( const sp& bufferProducer) const override; @@ -537,7 +538,8 @@ private: void latchAndReleaseBuffer(const sp& layer); void commitTransaction(); bool containsAnyInvalidClientState(const Vector& states); - bool composerStateContainsUnsignaledFences(const Vector& states); + bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, + const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands); @@ -982,12 +984,17 @@ private: }; struct TransactionState { TransactionState(const Vector& composerStates, - const Vector& displayStates, uint32_t transactionFlags) - : states(composerStates), displays(displayStates), flags(transactionFlags) {} + const Vector& displayStates, uint32_t transactionFlags, + int64_t desiredPresentTime) + : states(composerStates), + displays(displayStates), + flags(transactionFlags), + time(desiredPresentTime) {} Vector states; Vector displays; uint32_t flags; + int64_t time; }; std::unordered_map, std::queue, IBinderHash> mTransactionQueues; diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 9339761837..0ad2711fc9 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2568,11 +2568,23 @@ public: } } + void addExpectedPresentTime(nsecs_t expectedPresentTime) { + mExpectedPresentTime = expectedPresentTime; + } + void verifyTransactionStats(const TransactionStats& transactionStats) const { const auto& [latchTime, presentFence, surfaceStats] = transactionStats; if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) { ASSERT_GE(latchTime, 0) << "bad latch time"; ASSERT_NE(presentFence, nullptr); + if (mExpectedPresentTime >= 0) { + ASSERT_EQ(presentFence->wait(3000), NO_ERROR); + ASSERT_GE(presentFence->getSignalTime(), mExpectedPresentTime - nsecs_t(5 * 1e6)); + // if the panel is running at 30 hz, at the worst case, our expected time just + // misses vsync and we have to wait another 33.3ms + ASSERT_LE(presentFence->getSignalTime(), + mExpectedPresentTime + nsecs_t(66.666666 * 1e6)); + } } else { ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented"; ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched"; @@ -2623,6 +2635,7 @@ private: } }; ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED; + nsecs_t mExpectedPresentTime = -1; std::unordered_map, ExpectedSurfaceResult, IBinderHash> mExpectedSurfaceResults; }; @@ -3272,6 +3285,143 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } +TEST_F(LayerCallbackTest, DesiredPresentTime) { + sp layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the future + nsecs_t time = systemTime() + (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected.addExpectedPresentTime(time); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) { + sp layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback1; + int err = fillTransaction(transaction, &callback1, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the future + nsecs_t time = systemTime() + (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected1; + expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected1.addExpectedPresentTime(time); + + CallbackHelper callback2; + err = fillTransaction(transaction, &callback2, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 33ms after the first frame + time += (33.3 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected2; + expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::ACQUIRED, + ExpectedResult::PreviousBuffer::RELEASED); + expected2.addExpectedPresentTime(time); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) { + sp layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback1; + int err = fillTransaction(transaction, &callback1, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the future + nsecs_t time = systemTime() + (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected1; + expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected1.addExpectedPresentTime(time); + + CallbackHelper callback2; + err = fillTransaction(transaction, &callback2, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 33ms before the previous frame + time -= (33.3 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected2; + expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::ACQUIRED, + ExpectedResult::PreviousBuffer::RELEASED); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime_Past) { + sp layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the past + nsecs_t time = systemTime() - (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected.addExpectedPresentTime(systemTime()); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { -- cgit v1.2.3-59-g8ed1b From ebc2c059e73d3278e07c461b3f4e844a47019c3d Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Wed, 16 Jan 2019 19:16:55 -0800 Subject: blast: cache buffers Cache incoming buffers so they don't have to be imported by mapper everytime they are set. Amended by Change-Id: I3040f6d8886ca9b130115784c199edfdd9c85c7e Test: Transaction_test Bug: 80477568 Change-Id: Icd167c5e5bd59d7331b829667b1139919393d98b --- libs/gui/ISurfaceComposer.cpp | 78 ++++++++++++ libs/gui/LayerState.cpp | 10 ++ libs/gui/SurfaceComposerClient.cpp | 35 ++++++ libs/gui/include/gui/ISurfaceComposer.h | 7 ++ libs/gui/include/gui/LayerState.h | 7 ++ libs/gui/include/gui/SurfaceComposerClient.h | 7 ++ libs/gui/tests/Surface_test.cpp | 6 + services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferStateLayerCache.cpp | 99 +++++++++++++++ services/surfaceflinger/BufferStateLayerCache.h | 55 +++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 23 +++- services/surfaceflinger/SurfaceFlinger.h | 6 + services/surfaceflinger/tests/Transaction_test.cpp | 137 +++++++++++++++++++++ 13 files changed, 470 insertions(+), 1 deletion(-) create mode 100644 services/surfaceflinger/BufferStateLayerCache.cpp create mode 100644 services/surfaceflinger/BufferStateLayerCache.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c3a4737e0e..ad2dc14858 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -695,6 +695,42 @@ public: } return err; } + + virtual status_t cacheBuffer(const sp& token, const sp& buffer, + int32_t* outBufferId) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + + data.writeStrongBinder(token); + if (buffer) { + data.writeBool(true); + data.write(*buffer); + } else { + data.writeBool(false); + } + + status_t result = remote()->transact(BnSurfaceComposer::CACHE_BUFFER, data, &reply); + if (result != NO_ERROR) { + return result; + } + + int32_t id = -1; + result = reply.readInt32(&id); + if (result == NO_ERROR) { + *outBufferId = id; + } + return result; + } + + virtual status_t uncacheBuffer(const sp& token, int32_t bufferId) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + + data.writeStrongBinder(token); + data.writeInt32(bufferId); + + return remote()->transact(BnSurfaceComposer::UNCACHE_BUFFER, data, &reply); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -1136,6 +1172,48 @@ status_t BnSurfaceComposer::onTransact( } return error; } + case CACHE_BUFFER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp token; + status_t result = data.readStrongBinder(&token); + if (result != NO_ERROR) { + ALOGE("cache buffer failure in reading token: %d", result); + return result; + } + + sp buffer = new GraphicBuffer(); + if (data.readBool()) { + result = data.read(*buffer); + if (result != NO_ERROR) { + ALOGE("cache buffer failure in reading buffer: %d", result); + return result; + } + } + int32_t bufferId = -1; + status_t error = cacheBuffer(token, buffer, &bufferId); + if (error == NO_ERROR) { + reply->writeInt32(bufferId); + } + return error; + } + case UNCACHE_BUFFER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp token; + status_t result = data.readStrongBinder(&token); + if (result != NO_ERROR) { + ALOGE("uncache buffer failure in reading token: %d", result); + return result; + } + + int32_t bufferId = -1; + result = data.readInt32(&bufferId); + if (result != NO_ERROR) { + ALOGE("uncache buffer failure in reading buffer id: %d", result); + return result; + } + + return uncacheBuffer(token, bufferId); + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e5170ab73b..40b55fa28b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -94,6 +94,9 @@ status_t layer_state_t::write(Parcel& output) const } } + output.writeStrongBinder(cachedBuffer.token); + output.writeInt32(cachedBuffer.bufferId); + return NO_ERROR; } @@ -164,6 +167,9 @@ status_t layer_state_t::read(const Parcel& input) listenerCallbacks.emplace_back(listener, callbackIds); } + cachedBuffer.token = input.readStrongBinder(); + cachedBuffer.bufferId = input.readInt32(); + return NO_ERROR; } @@ -372,6 +378,10 @@ void layer_state_t::merge(const layer_state_t& other) { } #endif + if (other.what & eCachedBufferChanged) { + what |= eCachedBufferChanged; + cachedBuffer = other.cachedBuffer; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 32a368ebab..35659e96a9 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -660,6 +660,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCachedBuffer( + const sp& sc, int32_t bufferId) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eCachedBufferChanged; + s->cachedBuffer.token = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + s->cachedBuffer.bufferId = bufferId; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence( const sp& sc, const sp& fence) { layer_state_t* s = getLayerState(sc); @@ -1057,6 +1072,26 @@ status_t SurfaceComposerClient::getLayerFrameStats(const sp& token, // ---------------------------------------------------------------------------- +status_t SurfaceComposerClient::cacheBuffer(const sp& buffer, int32_t* outBufferId) { + sp sf(ComposerService::getComposerService()); + if (buffer == nullptr || outBufferId == nullptr) { + return BAD_VALUE; + } + return sf->cacheBuffer(IInterface::asBinder(TransactionCompletedListener::getIInstance()), + buffer, outBufferId); +} + +status_t SurfaceComposerClient::uncacheBuffer(int32_t bufferId) { + sp sf(ComposerService::getComposerService()); + if (bufferId < 0) { + return BAD_VALUE; + } + return sf->uncacheBuffer(IInterface::asBinder(TransactionCompletedListener::getIInstance()), + bufferId); +} + +// ---------------------------------------------------------------------------- + status_t SurfaceComposerClient::enableVSyncInjections(bool enable) { sp sf(ComposerService::getComposerService()); return sf->enableVSyncInjections(enable); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 25a4185dec..418d5fbf35 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -316,6 +316,11 @@ public: * Requires the ACCESS_SURFACE_FLINGER permission. */ virtual status_t getProtectedContentSupport(bool* outSupported) const = 0; + + virtual status_t cacheBuffer(const sp& token, const sp& buffer, + int32_t* outBufferId) = 0; + + virtual status_t uncacheBuffer(const sp& token, int32_t bufferId) = 0; }; // ---------------------------------------------------------------------------- @@ -358,6 +363,8 @@ public: SET_DISPLAY_CONTENT_SAMPLING_ENABLED, GET_DISPLAYED_CONTENT_SAMPLE, GET_PROTECTED_CONTENT_SUPPORT, + CACHE_BUFFER, + UNCACHE_BUFFER, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e7564f5ed4..af314208de 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -84,6 +84,7 @@ struct layer_state_t { eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, eFrameChanged = 0x1'00000000, + eCachedBufferChanged = 0x2'00000000, }; layer_state_t() @@ -125,6 +126,10 @@ struct layer_state_t { float dtdy{0}; float dsdy{0}; }; + struct cached_buffer_t { + sp token = nullptr; + int32_t bufferId = -1; + }; sp surface; uint64_t what; float x; @@ -173,6 +178,8 @@ struct layer_state_t { #ifndef NO_INPUT InputWindowInfo inputInfo; #endif + + cached_buffer_t cachedBuffer; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2f02328c99..78515d0d6c 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -152,6 +152,12 @@ public: static void doDropReferenceTransaction(const sp& handle, const sp& client); + // Caches a buffer with the ISurfaceComposer so the buffer does not need to be resent across + // processes + static status_t cacheBuffer(const sp& buffer, int32_t* outBufferId); + // Uncaches a buffer set by cacheBuffer + static status_t uncacheBuffer(int32_t bufferId); + // ------------------------------------------------------------------------ // surface creation / destruction @@ -329,6 +335,7 @@ public: Transaction& setCrop(const sp& sc, const Rect& crop); Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer); + Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); Transaction& setAcquireFence(const sp& sc, const sp& fence); Transaction& setDataspace(const sp& sc, ui::Dataspace dataspace); Transaction& setHdrMetadata(const sp& sc, const HdrMetadata& hdrMetadata); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 1d2950af19..259ef9f212 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -660,6 +660,12 @@ public: status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; } status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; } + status_t cacheBuffer(const sp& /*token*/, const sp& /*buffer*/, + int32_t* /*outBufferId*/) { + return NO_ERROR; + } + status_t uncacheBuffer(const sp& /*token*/, int32_t /*bufferId*/) { return NO_ERROR; } + protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 5b3bbca49f..033ed668c0 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -114,6 +114,7 @@ filegroup { "BufferLayerConsumer.cpp", "BufferQueueLayer.cpp", "BufferStateLayer.cpp", + "BufferStateLayerCache.cpp", "Client.cpp", "ColorLayer.cpp", "ContainerLayer.cpp", diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp new file mode 100644 index 0000000000..c82ad7bc49 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayerCache.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2019 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 "BufferStateLayerCache" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BufferStateLayerCache.h" + +#define MAX_CACHE_SIZE 64 + +namespace android { + +int32_t BufferStateLayerCache::add(const sp& processToken, + const sp& buffer) { + std::lock_guard lock(mMutex); + + auto& processCache = getProccessCache(processToken); + + int32_t slot = findSlot(processCache); + if (slot < 0) { + return slot; + } + + processCache[slot] = buffer; + + return slot; +} + +void BufferStateLayerCache::release(const sp& processToken, int32_t id) { + if (id < 0) { + ALOGE("invalid buffer id"); + return; + } + + std::lock_guard lock(mMutex); + auto& processCache = getProccessCache(processToken); + + if (id >= processCache.size()) { + ALOGE("invalid buffer id"); + return; + } + processCache[id] = nullptr; +} + +sp BufferStateLayerCache::get(const sp& processToken, int32_t id) { + if (id < 0) { + ALOGE("invalid buffer id"); + return nullptr; + } + + std::lock_guard lock(mMutex); + auto& processCache = getProccessCache(processToken); + + if (id >= processCache.size()) { + ALOGE("invalid buffer id"); + return nullptr; + } + return processCache[id]; +} + +std::vector>& BufferStateLayerCache::getProccessCache( + const sp& processToken) { + return mBuffers[processToken]; +} + +int32_t BufferStateLayerCache::findSlot(std::vector>& processCache) { + int32_t slot = 0; + + for (const sp buffer : processCache) { + if (!buffer) { + return slot; + } + slot++; + } + + if (processCache.size() < MAX_CACHE_SIZE) { + processCache.push_back(nullptr); + return slot; + } + + return -1; +} + +}; // namespace android diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h new file mode 100644 index 0000000000..623f0c65fd --- /dev/null +++ b/services/surfaceflinger/BufferStateLayerCache.h @@ -0,0 +1,55 @@ +/* + * Copyright 2019 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 +#include +#include + +#include +#include +#include + +namespace android { + +class BufferStateLayerCache { +public: + int32_t add(const sp& processToken, const sp& buffer); + void release(const sp& processToken, int32_t id); + + sp get(const sp& processToken, int32_t id); + +private: + std::mutex mMutex; + + std::vector>& getProccessCache(const sp& processToken) + REQUIRES(mMutex); + + int32_t findSlot(std::vector>& proccessCache) REQUIRES(mMutex); + + struct IBinderHash { + std::size_t operator()(const sp& strongPointer) const { + return std::hash{}(strongPointer.get()); + } + }; + + std::unordered_map /*caching process*/, std::vector>, IBinderHash> + mBuffers GUARDED_BY(mMutex); +}; + +}; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c0059d5e2e..26406250c3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1160,6 +1160,20 @@ status_t SurfaceFlinger::getProtectedContentSupport(bool* outSupported) const { return NO_ERROR; } +status_t SurfaceFlinger::cacheBuffer(const sp& token, const sp& buffer, + int32_t* outBufferId) { + if (!outBufferId) { + return BAD_VALUE; + } + *outBufferId = mBufferStateLayerCache.add(token, buffer); + return NO_ERROR; +} + +status_t SurfaceFlinger::uncacheBuffer(const sp& token, int32_t bufferId) { + mBufferStateLayerCache.release(token, bufferId); + return NO_ERROR; +} + status_t SurfaceFlinger::enableVSyncInjections(bool enable) { postMessageSync(new LambdaMessage([&] { Mutex::Autolock _l(mStateLock); @@ -3932,6 +3946,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); } } + if (what & layer_state_t::eCachedBufferChanged) { + sp buffer = + mBufferStateLayerCache.get(s.cachedBuffer.token, s.cachedBuffer.bufferId); + if (layer->setBuffer(buffer)) flags |= eTraversalNeeded; + } if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; // Do not put anything that updates layer state or modifies flags after // setTransactionCompletedListener @@ -5025,7 +5044,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CREATE_CONNECTION: case GET_COLOR_MANAGEMENT: case GET_COMPOSITION_PREFERENCE: - case GET_PROTECTED_CONTENT_SUPPORT: { + case GET_PROTECTED_CONTENT_SUPPORT: + case CACHE_BUFFER: + case UNCACHE_BUFFER: { return OK; } case CAPTURE_LAYERS: diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e5b3570fe3..1e6db068e3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -48,6 +48,7 @@ #include #include "Barrier.h" +#include "BufferStateLayerCache.h" #include "DisplayDevice.h" #include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" @@ -459,6 +460,9 @@ private: uint64_t timestamp, DisplayedFrameStats* outStats) const override; status_t getProtectedContentSupport(bool* outSupported) const override; + status_t cacheBuffer(const sp& token, const sp& buffer, + int32_t* outBufferId) override; + status_t uncacheBuffer(const sp& token, int32_t bufferId) override; /* ------------------------------------------------------------------------ * DeathRecipient interface @@ -1034,6 +1038,8 @@ private: sp mInputFlinger; InputWindowCommands mInputWindowCommands; + + BufferStateLayerCache mBufferStateLayerCache; }; }; // namespace android diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 0ad2711fc9..216532a814 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2323,6 +2323,143 @@ TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { Transaction().setSidebandStream(layer, nullptr).apply(); } +TEST_F(LayerTransactionTest, CacheBuffer_BufferState) { + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + int32_t bufferId = -1; + ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId)); + ASSERT_GE(bufferId, 0); + + ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId)); +} + +TEST_F(LayerTransactionTest, CacheBuffers_BufferState) { + std::vector bufferIds; + int32_t bufferCount = 20; + + for (int i = 0; i < bufferCount; i++) { + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + int32_t bufferId = -1; + ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId)); + if (bufferId < 0) { + EXPECT_GE(bufferId, 0); + break; + } + bufferIds.push_back(bufferId); + } + + for (int32_t bufferId : bufferIds) { + ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId)); + } +} + +TEST_F(LayerTransactionTest, CacheBufferInvalid_BufferState) { + sp buffer = nullptr; + + int32_t bufferId = -1; + ASSERT_NE(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId)); + ASSERT_LT(bufferId, 0); +} + +TEST_F(LayerTransactionTest, UncacheBufferTwice_BufferState) { + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + int32_t bufferId = -1; + ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId)); + ASSERT_GE(bufferId, 0); + + ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId)); + mClient->uncacheBuffer(bufferId); +} + +TEST_F(LayerTransactionTest, UncacheBufferInvalidId_BufferState) { + mClient->uncacheBuffer(-1); + mClient->uncacheBuffer(0); + mClient->uncacheBuffer(1); + mClient->uncacheBuffer(5); + mClient->uncacheBuffer(1000); +} + +TEST_F(LayerTransactionTest, SetCachedBuffer_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + int32_t bufferId = -1; + ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId)); + ASSERT_GE(bufferId, 0); + + Transaction().setCachedBuffer(layer, bufferId).apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + + ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId)); +} + +TEST_F(LayerTransactionTest, SetCachedBufferDelayed_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp cachedBuffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + int32_t bufferId = -1; + ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(cachedBuffer, &bufferId)); + ASSERT_GE(bufferId, 0); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::BLUE); + Transaction().setBuffer(layer, buffer).apply(); + { + SCOPED_TRACE("Uncached buffer"); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + fillGraphicBufferColor(cachedBuffer, Rect(0, 0, 32, 32), Color::RED); + Transaction().setCachedBuffer(layer, bufferId).apply(); + { + SCOPED_TRACE("Cached buffer"); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId)); +} + class ColorTransformHelper { public: static void DegammaColorSingle(half& s) { -- cgit v1.2.3-59-g8ed1b From 80d94ad74170212d21222a1d81e2e203e304f615 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 18 Jan 2019 16:04:36 -0800 Subject: ASurfaceControl: add more support to NDK (2/2) Adds several new functions and updates existing functions. - release fences - desired present time - alpha - hdr metadata Test: atest CtsViewTestCases:android.view.cts.ASurfaceControlTest Bug: 80477568 Change-Id: I6f6c4c6e295530cdb9e86b308483818062149cc1 --- include/android/surface_control.h | 157 +++++++++++++++++++-- libs/gui/SurfaceComposerClient.cpp | 73 ++++++++-- libs/gui/include/gui/SurfaceComposerClient.h | 87 ++++++++---- libs/nativewindow/include/android/hdr_metadata.h | 65 +++++++++ services/surfaceflinger/tests/Transaction_test.cpp | 64 +++++---- 5 files changed, 371 insertions(+), 75 deletions(-) create mode 100644 libs/nativewindow/include/android/hdr_metadata.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/include/android/surface_control.h b/include/android/surface_control.h index 13b630ba57..430f81be56 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -29,6 +29,7 @@ #include #include +#include #include __BEGIN_DECLS @@ -60,10 +61,11 @@ ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* deb __INTRODUCED_IN(29); /** - * Destroys the |surface_control| object. After releasing the ASurfaceControl the caller no longer - * has ownership of the AsurfaceControl. + * Releases the |surface_control| object. After releasing the ASurfaceControl the caller no longer + * has ownership of the AsurfaceControl. The surface and it's children may remain on display as long + * as their parent remains on display. */ -void ASurfaceControl_destroy(ASurfaceControl* surface_control) __INTRODUCED_IN(29); +void ASurfaceControl_release(ASurfaceControl* surface_control) __INTRODUCED_IN(29); struct ASurfaceTransaction; @@ -93,6 +95,13 @@ void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_I */ void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29); +/** + * An opaque handle returned during a callback that can be used to query general stats and stats for + * surfaces which were either removed or for which buffers were updated after this transaction was + * applied. + */ +typedef struct ASurfaceTransactionStats ASurfaceTransactionStats; + /** * Since the transactions are applied asynchronously, the * ASurfaceTransaction_OnComplete callback can be used to be notified when a frame @@ -100,18 +109,81 @@ void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN * * |context| is the optional context provided by the client that is passed into * the callback. - * |present_fence| is the sync fence that signals when the transaction has been presented. - * The recipient of the callback takes ownership of the present_fence and is responsible for closing - * it. * - * It is safe to assume that once the present fence singals, that reads for all buffers, - * submitted in previous transactions, which are not in the surface tree after a transaction is - * applied, are finished and the buffers may be reused. + * |stats| is an opaque handle that can be passed to ASurfaceTransactionStats functions to query + * information about the transaction. The handle is only valid during the the callback. * * THREADING * The transaction completed callback can be invoked on any thread. */ -typedef void (*ASurfaceTransaction_OnComplete)(void* context, int32_t present_fence); +typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactionStats* stats) + __INTRODUCED_IN(29); + +/** + * Returns the timestamp of when the frame was latched by the framework. Once a frame is + * latched by the framework, it is presented at the following hardware vsync. + */ +int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_transaction_stats) + __INTRODUCED_IN(29); + +/** + * Returns a sync fence that signals when the transaction has been presented. + * The recipient of the callback takes ownership of the fence and is responsible for closing + * it. + */ +int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats) + __INTRODUCED_IN(29); + +/** + * |outASurfaceControls| returns an array of ASurfaceControl pointers that were updated during the + * transaction. Stats for the surfaces can be queried through ASurfaceTransactionStats functions. + * When the client is done using the array, it must release it by calling + * ASurfaceTransactionStats_releaseASurfaceControls. + * + * |outASurfaceControlsSize| returns the size of the ASurfaceControls array. + */ +void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* surface_transaction_stats, + ASurfaceControl*** outASurfaceControls, + size_t* outASurfaceControlsSize) + __INTRODUCED_IN(29); +/** + * Releases the array of ASurfaceControls that were returned by + * ASurfaceTransactionStats_getASurfaceControls. + */ +void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_controls) + __INTRODUCED_IN(29); + +/** + * Returns the timestamp of when the CURRENT buffer was acquired. A buffer is considered + * acquired when its acquire_fence_fd has signaled. A buffer cannot be latched or presented until + * it is acquired. If no acquire_fence_fd was provided, this timestamp will be set to -1. + */ +int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surface_transaction_stats, + ASurfaceControl* surface_control) + __INTRODUCED_IN(29); + +/** + * The returns the fence used to signal the release of the PREVIOUS buffer set on + * this surface. If this fence is valid (>=0), the PREVIOUS buffer has not yet been released and the + * fence will signal when the PREVIOUS buffer has been released. If the fence is -1 , the PREVIOUS + * buffer is already released. The recipient of the callback takes ownership of the + * previousReleaseFenceFd and is responsible for closing it. + * + * Each time a buffer is set through ASurfaceTransaction_setBuffer()/_setCachedBuffer() on a + * transaction which is applied, the framework takes a ref on this buffer. The framework treats the + * addition of a buffer to a particular surface as a unique ref. When a transaction updates or + * removes a buffer from a surface, or removes the surface itself from the tree, this ref is + * guaranteed to be released in the OnComplete callback for this transaction. The + * ASurfaceControlStats provided in the callback for this surface may contain an optional fence + * which must be signaled before the ref is assumed to be released. + * + * The client must ensure that all pending refs on a buffer are released before attempting to reuse + * this buffer, otherwise synchronization errors may occur. + */ +int ASurfaceTransactionStats_getPreviousReleaseFenceFd( + ASurfaceTransactionStats* surface_transaction_stats, + ASurfaceControl* surface_control) + __INTRODUCED_IN(29); /** * Sets the callback that will be invoked when the updates from this transaction @@ -121,6 +193,16 @@ typedef void (*ASurfaceTransaction_OnComplete)(void* context, int32_t present_fe void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context, ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29); +/** + * Reparents the |surface_control| from its old parent to the |new_parent| surface control. + * Any children of the* reparented |surface_control| will remain children of the |surface_control|. + * + * The |new_parent| can be null. Surface controls with a null parent do not appear on the display. + */ +void ASurfaceTransaction_reparent(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, ASurfaceControl* new_parent) + __INTRODUCED_IN(29); + /* Parameter for ASurfaceTransaction_setVisibility */ enum { ASURFACE_TRANSACTION_VISIBILITY_HIDE = 0, @@ -148,15 +230,15 @@ void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction, /** * Updates the AHardwareBuffer displayed for |surface_control|. If not -1, the - * fence_fd should be a file descriptor that is signaled when all pending work + * acquire_fence_fd should be a file descriptor that is signaled when all pending work * for the buffer is complete and the buffer can be safely read. * - * The frameworks takes ownership of the |fence_fd| passed and is responsible + * The frameworks takes ownership of the |acquire_fence_fd| passed and is responsible * for closing it. */ void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, AHardwareBuffer* buffer, - int fence_fd = -1) __INTRODUCED_IN(29); + int acquire_fence_fd = -1) __INTRODUCED_IN(29); /** * |source| the sub-rect within the buffer's content to be rendered inside the surface's area @@ -189,8 +271,9 @@ enum { * opaque or visual errors can occur. */ void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction, - ASurfaceControl* surface_control, int8_t transparency) - __INTRODUCED_IN(29); + ASurfaceControl* surface_control, + int8_t transparency) + __INTRODUCED_IN(29); /** * Updates the region for the content on this surface updated in this @@ -200,6 +283,50 @@ void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, const ARect rects[], uint32_t count) __INTRODUCED_IN(29); +/** + * Specifies a desiredPresentTime for the transaction. The framework will try to present + * the transaction at or after the time specified. + * + * Transactions will not be presented until all of their acquire fences have signaled even if the + * app requests an earlier present time. + * + * If an earlier transaction has a desired present time of x, and a later transaction has a desired + * present time that is before x, the later transaction will not preempt the earlier transaction. + */ +void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction, + int64_t desiredPresentTime) __INTRODUCED_IN(29); + +/** + * Sets the alpha for the buffer. It uses a premultiplied blending. + * + * The |alpha| must be between 0.0 and 1.0. + */ +void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, float alpha) + __INTRODUCED_IN(29); + +/* + * SMPTE ST 2086 "Mastering Display Color Volume" static metadata + * + * When |metadata| is set to null, the framework does not use any smpte2086 metadata when rendering + * the surface's buffer. + */ +void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, + struct AHdrMetadata_smpte2086* metadata) + __INTRODUCED_IN(29); + +/* + * Sets the CTA 861.3 "HDR Static Metadata Extension" static metadata on a surface. + * + * When |metadata| is set to null, the framework does not use any cta861.3 metadata when rendering + * the surface's buffer. + */ +void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, + struct AHdrMetadata_cta861_3* metadata) + __INTRODUCED_IN(29); + #endif // __ANDROID_API__ >= 29 __END_DECLS diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 35659e96a9..1ed8a0d343 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -132,26 +132,76 @@ void TransactionCompletedListener::startListeningLocked() { mListening = true; } -CallbackId TransactionCompletedListener::addCallback(const TransactionCompletedCallback& callback) { +CallbackId TransactionCompletedListener::addCallbackFunction( + const TransactionCompletedCallback& callbackFunction, + const std::unordered_set, SurfaceComposerClient::SCHash>& + surfaceControls) { std::lock_guard lock(mMutex); startListeningLocked(); CallbackId callbackId = getNextIdLocked(); - mCallbacks.emplace(callbackId, callback); + mCallbacks[callbackId].callbackFunction = callbackFunction; + + auto& callbackSurfaceControls = mCallbacks[callbackId].surfaceControls; + + for (const auto& surfaceControl : surfaceControls) { + callbackSurfaceControls[surfaceControl->getHandle()] = surfaceControl; + } + return callbackId; } +void TransactionCompletedListener::addSurfaceControlToCallbacks( + const sp& surfaceControl, + const std::unordered_set& callbackIds) { + std::lock_guard lock(mMutex); + + for (auto callbackId : callbackIds) { + mCallbacks[callbackId].surfaceControls.emplace(std::piecewise_construct, + std::forward_as_tuple( + surfaceControl->getHandle()), + std::forward_as_tuple(surfaceControl)); + } +} + void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::lock_guard lock(mMutex); + /* This listener knows all the sp to sp for all its registered + * callbackIds, except for when Transactions are merged together. This probably cannot be + * solved before this point because the Transactions could be merged together and applied in a + * different process. + * + * Fortunately, we get all the callbacks for this listener for the same frame together at the + * same time. This means if any Transactions were merged together, we will get their callbacks + * at the same time. We can combine all the sp to sp maps for all the + * callbackIds to generate one super map that contains all the sp to sp + * that could possibly exist for the callbacks. + */ + std::unordered_map, sp, IBinderHash> surfaceControls; for (const auto& [callbackIds, transactionStats] : listenerStats.transactionStats) { for (auto callbackId : callbackIds) { - const auto& callback = mCallbacks[callbackId]; - if (!callback) { + auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId]; + surfaceControls.insert(callbackSurfaceControls.begin(), callbackSurfaceControls.end()); + } + } + + for (const auto& [callbackIds, transactionStats] : listenerStats.transactionStats) { + for (auto callbackId : callbackIds) { + auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId]; + if (!callbackFunction) { ALOGE("cannot call null callback function, skipping"); continue; } - callback(transactionStats); + std::vector surfaceControlStats; + for (const auto& surfaceStats : transactionStats.surfaceStats) { + surfaceControlStats.emplace_back(surfaceControls[surfaceStats.surfaceControl], + surfaceStats.acquireTime, + surfaceStats.previousReleaseFence); + } + + callbackFunction(transactionStats.latchTime, transactionStats.presentFence, + surfaceControlStats); mCallbacks.erase(callbackId); } } @@ -329,7 +379,11 @@ layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { - mListenerCallbacks[TransactionCompletedListener::getIInstance()].surfaceControls.insert(sc); + auto& callbackInfo = mListenerCallbacks[TransactionCompletedListener::getIInstance()]; + callbackInfo.surfaceControls.insert(sc); + + TransactionCompletedListener::getInstance() + ->addSurfaceControlToCallbacks(sc, callbackInfo.callbackIds); } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( @@ -770,9 +824,12 @@ SurfaceComposerClient::Transaction::addTransactionCompletedCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext) { auto listener = TransactionCompletedListener::getInstance(); - auto callbackWithContext = std::bind(callback, callbackContext, std::placeholders::_1); + auto callbackWithContext = std::bind(callback, callbackContext, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3); + const auto& surfaceControls = + mListenerCallbacks[TransactionCompletedListener::getIInstance()].surfaceControls; - CallbackId callbackId = listener->addCallback(callbackWithContext); + CallbackId callbackId = listener->addCallbackFunction(callbackWithContext, surfaceControls); mListenerCallbacks[TransactionCompletedListener::getIInstance()].callbackIds.emplace( callbackId); diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 78515d0d6c..29b467f062 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -53,35 +53,24 @@ class Region; // --------------------------------------------------------------------------- -using TransactionCompletedCallbackTakesContext = - std::function; -using TransactionCompletedCallback = std::function; - -class TransactionCompletedListener : public BnTransactionCompletedListener { - TransactionCompletedListener(); - - CallbackId getNextIdLocked() REQUIRES(mMutex); - - std::mutex mMutex; - - bool mListening GUARDED_BY(mMutex) = false; - - CallbackId mCallbackIdCounter GUARDED_BY(mMutex) = 1; - - std::map mCallbacks GUARDED_BY(mMutex); - -public: - static sp getInstance(); - static sp getIInstance(); - - void startListeningLocked() REQUIRES(mMutex); - - CallbackId addCallback(const TransactionCompletedCallback& callback); - - // Overrides BnTransactionCompletedListener's onTransactionCompleted - void onTransactionCompleted(ListenerStats stats) override; +struct SurfaceControlStats { + SurfaceControlStats(const sp& sc, nsecs_t time, + const sp& prevReleaseFence) + : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence) {} + + sp surfaceControl; + nsecs_t acquireTime = -1; + sp previousReleaseFence; }; +using TransactionCompletedCallbackTakesContext = + std::function& /*presentFence*/, + const std::vector& /*stats*/)>; +using TransactionCompletedCallback = + std::function& /*presentFence*/, + const std::vector& /*stats*/)>; + // --------------------------------------------------------------------------- class SurfaceComposerClient : public RefBase @@ -459,6 +448,50 @@ public: // --------------------------------------------------------------------------- +class TransactionCompletedListener : public BnTransactionCompletedListener { + TransactionCompletedListener(); + + CallbackId getNextIdLocked() REQUIRES(mMutex); + + std::mutex mMutex; + + bool mListening GUARDED_BY(mMutex) = false; + + CallbackId mCallbackIdCounter GUARDED_BY(mMutex) = 1; + + struct IBinderHash { + std::size_t operator()(const sp& iBinder) const { + return std::hash{}(iBinder.get()); + } + }; + + struct CallbackTranslation { + TransactionCompletedCallback callbackFunction; + std::unordered_map, sp, IBinderHash> surfaceControls; + }; + + std::unordered_map mCallbacks GUARDED_BY(mMutex); + +public: + static sp getInstance(); + static sp getIInstance(); + + void startListeningLocked() REQUIRES(mMutex); + + CallbackId addCallbackFunction( + const TransactionCompletedCallback& callbackFunction, + const std::unordered_set, SurfaceComposerClient::SCHash>& + surfaceControls); + + void addSurfaceControlToCallbacks(const sp& surfaceControl, + const std::unordered_set& callbackIds); + + // Overrides BnTransactionCompletedListener's onTransactionCompleted + void onTransactionCompleted(ListenerStats stats) override; +}; + +// --------------------------------------------------------------------------- + }; // namespace android #endif // ANDROID_GUI_SURFACE_COMPOSER_CLIENT_H diff --git a/libs/nativewindow/include/android/hdr_metadata.h b/libs/nativewindow/include/android/hdr_metadata.h new file mode 100644 index 0000000000..7e1313b993 --- /dev/null +++ b/libs/nativewindow/include/android/hdr_metadata.h @@ -0,0 +1,65 @@ +/* + * Copyright 2019 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. + */ + +/** + * @file hdr_metadata.h + */ + +#ifndef ANDROID_HDR_METADATA_H +#define ANDROID_HDR_METADATA_H + +#include + +#include + +__BEGIN_DECLS + +/** + * These structures are used to define the display's capabilities for HDR content. + * They can be used to better tone map content to user's display. + */ + +/** + * Color is defined in CIE XYZ coordinates. + */ +struct AColor_xy { + float x; + float y; +}; + +/** + * SMPTE ST 2086 "Mastering Display Color Volume" static metadata + */ +struct AHdrMetadata_smpte2086 { + struct AColor_xy displayPrimaryRed; + struct AColor_xy displayPrimaryGreen; + struct AColor_xy displayPrimaryBlue; + struct AColor_xy whitePoint; + float maxLuminance; + float minLuminance; +}; + +/** + * CTA 861.3 "HDR Static Metadata Extension" static metadata + */ +struct AHdrMetadata_cta861_3 { + float maxContentLightLevel; + float maxFrameAverageLightLevel; +}; + +__END_DECLS + +#endif // ANDROID_HDR_METADATA_H diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 216532a814..b95c0ec135 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2664,6 +2664,17 @@ TEST_F(LayerTransactionTest, SetColorTransformOnChildAndParent) { } } +struct CallbackData { + CallbackData() = default; + CallbackData(nsecs_t time, const sp& fence, + const std::vector& stats) + : latchTime(time), presentFence(fence), surfaceControlStats(stats) {} + + nsecs_t latchTime; + sp presentFence; + std::vector surfaceControlStats; +}; + class ExpectedResult { public: enum Transaction { @@ -2691,8 +2702,7 @@ public: ExpectedResult::Buffer bufferResult = ACQUIRED, ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) { mTransactionResult = transactionResult; - mExpectedSurfaceResults.emplace(std::piecewise_construct, - std::forward_as_tuple(layer->getHandle()), + mExpectedSurfaceResults.emplace(std::piecewise_construct, std::forward_as_tuple(layer), std::forward_as_tuple(bufferResult, previousBufferResult)); } @@ -2709,8 +2719,8 @@ public: mExpectedPresentTime = expectedPresentTime; } - void verifyTransactionStats(const TransactionStats& transactionStats) const { - const auto& [latchTime, presentFence, surfaceStats] = transactionStats; + void verifyCallbackData(const CallbackData& callbackData) const { + const auto& [latchTime, presentFence, surfaceControlStats] = callbackData; if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) { ASSERT_GE(latchTime, 0) << "bad latch time"; ASSERT_NE(presentFence, nullptr); @@ -2727,14 +2737,16 @@ public: ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched"; } - ASSERT_EQ(surfaceStats.size(), mExpectedSurfaceResults.size()) + ASSERT_EQ(surfaceControlStats.size(), mExpectedSurfaceResults.size()) << "wrong number of surfaces"; - for (const auto& stats : surfaceStats) { + for (const auto& stats : surfaceControlStats) { + ASSERT_NE(stats.surfaceControl, nullptr) << "returned null surface control"; + const auto& expectedSurfaceResult = mExpectedSurfaceResults.find(stats.surfaceControl); ASSERT_NE(expectedSurfaceResult, mExpectedSurfaceResults.end()) << "unexpected surface control"; - expectedSurfaceResult->second.verifySurfaceStats(stats, latchTime); + expectedSurfaceResult->second.verifySurfaceControlStats(stats, latchTime); } } @@ -2745,8 +2757,9 @@ private: ExpectedResult::PreviousBuffer previousBufferResult) : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {} - void verifySurfaceStats(const SurfaceStats& surfaceStats, nsecs_t latchTime) const { - const auto& [surfaceControl, acquireTime, previousReleaseFence] = surfaceStats; + void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, + nsecs_t latchTime) const { + const auto& [surfaceControl, acquireTime, previousReleaseFence] = surfaceControlStats; ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; @@ -2766,39 +2779,40 @@ private: ExpectedResult::PreviousBuffer mPreviousBufferResult; }; - struct IBinderHash { - std::size_t operator()(const sp& strongPointer) const { - return std::hash{}(strongPointer.get()); + struct SCHash { + std::size_t operator()(const sp& sc) const { + return std::hash{}(sc->getHandle().get()); } }; ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED; nsecs_t mExpectedPresentTime = -1; - std::unordered_map, ExpectedSurfaceResult, IBinderHash> mExpectedSurfaceResults; + std::unordered_map, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults; }; class CallbackHelper { public: - static void function(void* callbackContext, const TransactionStats& transactionStats) { + static void function(void* callbackContext, nsecs_t latchTime, const sp& presentFence, + const std::vector& stats) { if (!callbackContext) { ALOGE("failed to get callback context"); } CallbackHelper* helper = static_cast(callbackContext); std::lock_guard lock(helper->mMutex); - helper->mTransactionStatsQueue.push(transactionStats); + helper->mCallbackDataQueue.emplace(latchTime, presentFence, stats); helper->mConditionVariable.notify_all(); } - void getTransactionStats(TransactionStats* outStats) { + void getCallbackData(CallbackData* outData) { std::unique_lock lock(mMutex); - if (mTransactionStatsQueue.empty()) { + if (mCallbackDataQueue.empty()) { ASSERT_NE(mConditionVariable.wait_for(lock, std::chrono::seconds(3)), std::cv_status::timeout) << "did not receive callback"; } - *outStats = std::move(mTransactionStatsQueue.front()); - mTransactionStatsQueue.pop(); + *outData = std::move(mCallbackDataQueue.front()); + mCallbackDataQueue.pop(); } void verifyFinalState() { @@ -2806,15 +2820,15 @@ public: std::this_thread::sleep_for(500ms); std::lock_guard lock(mMutex); - EXPECT_EQ(mTransactionStatsQueue.size(), 0) << "extra callbacks received"; - mTransactionStatsQueue = {}; + EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received"; + mCallbackDataQueue = {}; } void* getContext() { return static_cast(this); } std::mutex mMutex; std::condition_variable mConditionVariable; - std::queue mTransactionStatsQueue; + std::queue mCallbackDataQueue; }; class LayerCallbackTest : public LayerTransactionTest { @@ -2843,9 +2857,9 @@ public: static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult, bool finalState = false) { - TransactionStats transactionStats; - ASSERT_NO_FATAL_FAILURE(helper.getTransactionStats(&transactionStats)); - EXPECT_NO_FATAL_FAILURE(expectedResult.verifyTransactionStats(transactionStats)); + CallbackData callbackData; + ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData)); + EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData)); if (finalState) { ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState()); -- cgit v1.2.3-59-g8ed1b From fb4d58be9df0bc8e90dcc9c6f32678cbdf8460b8 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 15 Jan 2019 09:21:27 -0800 Subject: Preparation for SurfaceControl publication through SDK We add a setGeometry wrapper for parity with the NDK API. Also we add a singleton SCC to avoid exposing that in the API. Bug: 111297488 Test: Builds Change-Id: Ibedaff8b34b09feb0ceaeb6c0b4c6105b15e281c --- libs/gui/SurfaceComposerClient.cpp | 69 ++++++++++++++++++++++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 5 ++ 2 files changed, 74 insertions(+) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7869a5b01e..422267c0f7 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -102,6 +102,27 @@ void ComposerService::composerServiceDied() mDeathObserver = nullptr; } +class DefaultComposerClient: public Singleton { + Mutex mLock; + sp mClient; + friend class Singleton; +public: + static sp getComposerClient() { + DefaultComposerClient& dc = DefaultComposerClient::getInstance(); + Mutex::Autolock _l(dc.mLock); + if (dc.mClient == nullptr) { + dc.mClient = new SurfaceComposerClient; + } + return dc.mClient; + } +}; +ANDROID_SINGLETON_STATIC_INSTANCE(DefaultComposerClient); + + +sp SurfaceComposerClient::getDefault() { + return DefaultComposerClient::getComposerClient(); +} + // --------------------------------------------------------------------------- // TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs @@ -929,6 +950,54 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometry( + const sp& sc, const Rect& source, const Rect& dst, int transform) { + setCrop_legacy(sc, source); + + int x = dst.left; + int y = dst.top; + float xScale = dst.getWidth() / static_cast(source.getWidth()); + float yScale = dst.getHeight() / static_cast(source.getHeight()); + float matrix[4] = {1, 0, 0, 1}; + + switch (transform) { + case NATIVE_WINDOW_TRANSFORM_FLIP_H: + matrix[0] = -xScale; matrix[1] = 0; + matrix[2] = 0; matrix[3] = yScale; + x += source.getWidth(); + break; + case NATIVE_WINDOW_TRANSFORM_FLIP_V: + matrix[0] = xScale; matrix[1] = 0; + matrix[2] = 0; matrix[3] = -yScale; + y += source.getHeight(); + break; + case NATIVE_WINDOW_TRANSFORM_ROT_90: + matrix[0] = 0; matrix[1] = -yScale; + matrix[2] = xScale; matrix[3] = 0; + x += source.getHeight(); + break; + case NATIVE_WINDOW_TRANSFORM_ROT_180: + matrix[0] = -xScale; matrix[1] = 0; + matrix[2] = 0; matrix[3] = -yScale; + x += source.getWidth(); + y += source.getHeight(); + break; + case NATIVE_WINDOW_TRANSFORM_ROT_270: + matrix[0] = 0; matrix[1] = yScale; + matrix[2] = -xScale; matrix[3] = 0; + y += source.getWidth(); + break; + default: + matrix[0] = xScale; matrix[1] = 0; + matrix[2] = 0; matrix[3] = yScale; + break; + } + setMatrix(sc, matrix[0], matrix[1], matrix[2], matrix[3]); + setPosition(sc, x, y); + + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b9686c323b..36f872e23f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -156,6 +156,8 @@ public: // ------------------------------------------------------------------------ // surface creation / destruction + static sp getDefault(); + //! Create a surface sp createSurface( const String8& name,// name of the surface @@ -376,6 +378,9 @@ public: Transaction& setColorTransform(const sp& sc, const mat3& matrix, const vec3& translation); + Transaction& setGeometry(const sp& sc, + const Rect& source, const Rect& dst, int transform); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); -- cgit v1.2.3-59-g8ed1b From ed54efa6e3d6b1403d07e0b68e0e741ec4d26cc4 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Fri, 11 Jan 2019 20:03:14 -0800 Subject: Add Color Layer to ASurfaceControl Bug:122326454 Test: atest CtsViewTestCases:android.view.cts.ASurfaceControlTests Change-Id: Ib05ad70d838c79aa6f2e309217b93906c950b6fa --- include/android/surface_control.h | 11 ++++++++++ libs/gui/LayerState.cpp | 14 +++++++++++++ libs/gui/SurfaceComposerClient.cpp | 30 ++++++++++++++++++++++++++++ libs/gui/include/gui/LayerState.h | 9 ++++++++- libs/gui/include/gui/SurfaceComposerClient.h | 6 ++++++ services/surfaceflinger/Layer.cpp | 1 + services/surfaceflinger/Layer.h | 4 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++++ 8 files changed, 80 insertions(+), 1 deletion(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/include/android/surface_control.h b/include/android/surface_control.h index 430f81be56..05731871d9 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -240,6 +240,17 @@ void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, AHardwareBuffer* buffer, int acquire_fence_fd = -1) __INTRODUCED_IN(29); +/** + * Updates the color for |surface_control|. This will make the background color for the + * ASurfaceControl visible in transparent regions of the surface. Colors |r|, |g|, + * and |b| must be within the range that is valid for |dataspace|. |dataspace| and |alpha| + * will be the dataspace and alpha set for the background color layer. + */ +void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, float r, float g, float b, + float alpha, ADataSpace dataspace) + __INTRODUCED_IN(29); + /** * |source| the sub-rect within the buffer's content to be rendered inside the surface's area * The surface's source rect is clipped by the bounds of its current buffer. The source rect's width diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 40b55fa28b..ab929731f3 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -97,6 +97,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(cachedBuffer.token); output.writeInt32(cachedBuffer.bufferId); + output.writeFloat(colorAlpha); + output.writeUint32(static_cast(colorDataspace)); + return NO_ERROR; } @@ -170,6 +173,9 @@ status_t layer_state_t::read(const Parcel& input) cachedBuffer.token = input.readStrongBinder(); cachedBuffer.bufferId = input.readInt32(); + colorAlpha = input.readFloat(); + colorDataspace = static_cast(input.readUint32()); + return NO_ERROR; } @@ -382,6 +388,14 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCachedBufferChanged; cachedBuffer = other.cachedBuffer; } + if (other.what & eColorAlphaChanged) { + what |= eColorAlphaChanged; + colorAlpha = other.colorAlpha; + } + if (other.what & eColorDataspaceChanged) { + what |= eColorDataspaceChanged; + colorDataspace = other.colorDataspace; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7869a5b01e..7cc0ee54b3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -643,6 +643,36 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorAlpha( + const sp& sc, float alpha) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eColorAlphaChanged; + s->colorAlpha = alpha; + + registerSurfaceControlForCallback(sc); + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorDataspace( + const sp& sc, ui::Dataspace dataspace) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eColorDataspaceChanged; + s->colorDataspace = dataspace; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransform( const sp& sc, uint32_t transform) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index af314208de..c1750cfb54 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -85,6 +85,8 @@ struct layer_state_t { eCornerRadiusChanged = 0x80000000, eFrameChanged = 0x1'00000000, eCachedBufferChanged = 0x2'00000000, + eColorAlphaChanged = 0x3'00000000, + eColorDataspaceChanged = 0x4'00000000, }; layer_state_t() @@ -110,7 +112,9 @@ struct layer_state_t { dataspace(ui::Dataspace::UNKNOWN), surfaceDamageRegion(), api(-1), - colorTransform(mat4()) { + colorTransform(mat4()), + colorAlpha(0), + colorDataspace(ui::Dataspace::UNKNOWN) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -180,6 +184,9 @@ struct layer_state_t { #endif cached_buffer_t cachedBuffer; + + float colorAlpha; + ui::Dataspace colorDataspace; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b9686c323b..2563351975 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -324,6 +324,12 @@ public: Transaction& setColor(const sp& sc, const half3& color); + // Sets the alpha of the background color layer if it exists. + Transaction& setColorAlpha(const sp& sc, float alpha); + + // Sets the dataspace of the background color layer if it exists. + Transaction& setColorDataspace(const sp& sc, ui::Dataspace dataspace); + Transaction& setTransform(const sp& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index aa9bc15f21..ef77590761 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -109,6 +109,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.cornerRadius = 0.0f; mCurrentState.api = -1; mCurrentState.hasColorTransform = false; + mCurrentState.colorDataspace = ui::Dataspace::UNKNOWN; // drawing state & current state are identical mDrawingState = mCurrentState; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 95a8630148..0f83464357 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -202,6 +202,8 @@ public: mat4 colorTransform; bool hasColorTransform; + ui::Dataspace colorDataspace; // The dataspace of the background color layer + // The deque of callback handles for this frame. The back of the deque contains the most // recent callback handle. std::deque> callbackHandles; @@ -308,6 +310,8 @@ public: const std::vector>& /*handles*/) { return false; }; + virtual bool setColorAlpha(float /*alpha*/) { return false; }; + virtual bool setColorDataspace(ui::Dataspace /*dataspace*/) { return false; }; ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3f6298f86b..709b1efb45 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3828,6 +3828,12 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setColor(s.color)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorAlphaChanged) { + if (layer->setColorAlpha(s.colorAlpha)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eColorDataspaceChanged) { + if (layer->setColorDataspace(s.colorDataspace)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eColorTransformChanged) { if (layer->setColorTransform(s.colorTransform)) { flags |= eTraversalNeeded; -- cgit v1.2.3-59-g8ed1b From 1f6d6d5db93ef4c3bbaeb5241eede30635fa5ff1 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Thu, 6 Dec 2018 10:47:26 -0800 Subject: Add metadata store to surfaces This adds a key/value metadata storage mechanism to surfaces that allows the windowmanager to pass information to the surfaceflinger frontend. This then moves the existing metadata (window type and ownerUID) into this metadata structure. Bug: 122925737 Test: Phone boots and surfaces fling. Some unittests Change-Id: I72c574737b7f75be2311a341812b15d385f507ed --- libs/gui/Android.bp | 1 + libs/gui/ISurfaceComposerClient.cpp | 16 +-- libs/gui/LayerMetadata.cpp | 114 +++++++++++++++++++++ libs/gui/LayerState.cpp | 6 ++ libs/gui/SurfaceComposerClient.cpp | 58 ++++++----- libs/gui/include/gui/ISurfaceComposerClient.h | 10 +- libs/gui/include/gui/LayerMetadata.h | 49 +++++++++ libs/gui/include/gui/LayerState.h | 4 + libs/gui/include/gui/SurfaceComposerClient.h | 52 +++++----- services/surfaceflinger/Client.cpp | 21 ++-- services/surfaceflinger/Client.h | 14 ++- services/surfaceflinger/Layer.cpp | 30 +++--- services/surfaceflinger/Layer.h | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 25 +++-- services/surfaceflinger/SurfaceFlinger.h | 8 +- services/surfaceflinger/layerproto/Android.bp | 2 +- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 17 ++- .../include/layerproto/LayerProtoParser.h | 4 +- services/surfaceflinger/layerproto/layers.proto | 6 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/LayerMetadataTest.cpp | 86 ++++++++++++++++ 21 files changed, 401 insertions(+), 128 deletions(-) create mode 100644 libs/gui/LayerMetadata.cpp create mode 100644 libs/gui/include/gui/LayerMetadata.h create mode 100644 services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 3521e89ae6..b148015c14 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -108,6 +108,7 @@ cc_library_shared { "ISurfaceComposerClient.cpp", "ITransactionCompletedListener.cpp", "LayerDebugInfo.cpp", + "LayerMetadata.cpp", "LayerState.cpp", "OccupancyTracker.cpp", "StreamSplitter.cpp", diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 928ef95aa8..129558bd15 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -47,26 +47,26 @@ public: ~BpSurfaceComposerClient() override; status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, - uint32_t flags, const sp& parent, int32_t windowType, - int32_t ownerUid, sp* handle, - sp* gbp) override { + uint32_t flags, const sp& parent, LayerMetadata metadata, + sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, format, flags, parent, - windowType, ownerUid, + std::move(metadata), handle, gbp); } status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, - const sp& parent, int32_t windowType, - int32_t ownerUid, sp* handle, + const sp& parent, + LayerMetadata metadata, sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_WITH_SURFACE_PARENT, name, width, height, format, - flags, parent, windowType, - ownerUid, handle, gbp); + flags, parent, + std::move(metadata), handle, + gbp); } status_t clearLayerFrameStats(const sp& handle) const override { diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp new file mode 100644 index 0000000000..c8a2b0754b --- /dev/null +++ b/libs/gui/LayerMetadata.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2019 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. + */ + +#include +#include +#include + +using android::base::StringPrintf; + +namespace android { + +LayerMetadata::LayerMetadata() = default; + +LayerMetadata::LayerMetadata(std::unordered_map> map) + : mMap(std::move(map)) {} + +LayerMetadata::LayerMetadata(const LayerMetadata& other) = default; + +LayerMetadata::LayerMetadata(LayerMetadata&& other) = default; + +void LayerMetadata::merge(const LayerMetadata& other) { + for (const auto& entry : other.mMap) { + mMap[entry.first] = entry.second; + } +} + +status_t LayerMetadata::writeToParcel(Parcel* parcel) const { + parcel->writeInt32(static_cast(mMap.size())); + status_t status = OK; + for (const auto& entry : mMap) { + status = parcel->writeUint32(entry.first); + if (status != OK) { + break; + } + status = parcel->writeByteVector(entry.second); + if (status != OK) { + break; + } + } + return status; +} + +status_t LayerMetadata::readFromParcel(const Parcel* parcel) { + int size = parcel->readInt32(); + status_t status = OK; + mMap.clear(); + for (int i = 0; i < size; ++i) { + uint32_t key = parcel->readUint32(); + status = parcel->readByteVector(&mMap[key]); + if (status != OK) { + break; + } + } + return status; +} + +LayerMetadata& LayerMetadata::operator=(const LayerMetadata& other) { + mMap = other.mMap; + return *this; +} + +LayerMetadata& LayerMetadata::operator=(LayerMetadata&& other) { + mMap = std::move(other.mMap); + return *this; +} + +bool LayerMetadata::has(uint32_t key) const { + return mMap.count(key); +} + +int32_t LayerMetadata::getInt32(uint32_t key, int32_t fallback) const { + if (!has(key)) return fallback; + const std::vector& data = mMap.at(key); + if (data.size() < sizeof(uint32_t)) return fallback; + Parcel p; + p.setData(data.data(), data.size()); + return p.readInt32(); +} + +void LayerMetadata::setInt32(uint32_t key, int32_t value) { + std::vector& data = mMap[key]; + Parcel p; + p.writeInt32(value); + data.resize(p.dataSize()); + memcpy(data.data(), p.data(), p.dataSize()); +} + +std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const { + if (!has(key)) return std::string(); + switch (key) { + case METADATA_OWNER_UID: + return StringPrintf("ownerUID%s%d", separator, getInt32(key, 0)); + case METADATA_WINDOW_TYPE: + return StringPrintf("windowType%s%d", separator, getInt32(key, 0)); + default: + return StringPrintf("%d%s%dbytes", key, separator, + static_cast(mMap.at(key).size())); + } +} + +} // namespace android diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index ab929731f3..6091d3f08a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -96,6 +96,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(cachedBuffer.token); output.writeInt32(cachedBuffer.bufferId); + output.writeParcelable(metadata); output.writeFloat(colorAlpha); output.writeUint32(static_cast(colorDataspace)); @@ -172,6 +173,7 @@ status_t layer_state_t::read(const Parcel& input) cachedBuffer.token = input.readStrongBinder(); cachedBuffer.bufferId = input.readInt32(); + input.readParcelable(&metadata); colorAlpha = input.readFloat(); colorDataspace = static_cast(input.readUint32()); @@ -396,6 +398,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eColorDataspaceChanged; colorDataspace = other.colorDataspace; } + if (other.what & eMetadataChanged) { + what |= eMetadataChanged; + metadata.merge(other.metadata); + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6c1c52e1bd..67d936100e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -539,6 +539,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMetadata( + const sp& sc, uint32_t key, std::vector data) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eMetadataChanged; + s->metadata.mMap[key] = std::move(data); + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix( const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy) { @@ -1141,26 +1155,19 @@ void SurfaceComposerClient::dispose() { mStatus = NO_INIT; } -sp SurfaceComposerClient::createSurface( - const String8& name, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags, - SurfaceControl* parent, - int32_t windowType, - int32_t ownerUid) -{ +sp SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + SurfaceControl* parent, + LayerMetadata metadata) { sp s; - createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid); + createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata)); return s; } sp SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, Surface* parent, - int32_t windowType, - int32_t ownerUid) { + LayerMetadata metadata) { sp sur; status_t err = mStatus; @@ -1169,8 +1176,8 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& sp parentGbp = parent->getIGraphicBufferProducer(); sp gbp; - err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType, - ownerUid, &handle, &gbp); + err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, + std::move(metadata), &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err)); if (err == NO_ERROR) { return new SurfaceControl(this, handle, gbp, true /* owned */); @@ -1179,17 +1186,11 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& return nullptr; } -status_t SurfaceComposerClient::createSurfaceChecked( - const String8& name, - uint32_t w, - uint32_t h, - PixelFormat format, - sp* outSurface, - uint32_t flags, - SurfaceControl* parent, - int32_t windowType, - int32_t ownerUid) -{ +status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, + sp* outSurface, uint32_t flags, + SurfaceControl* parent, + LayerMetadata metadata) { sp sur; status_t err = mStatus; @@ -1201,8 +1202,9 @@ status_t SurfaceComposerClient::createSurfaceChecked( if (parent != nullptr) { parentHandle = parent->getHandle(); } - err = mClient->createSurface(name, w, h, format, flags, parentHandle, - windowType, ownerUid, &handle, &gbp); + + err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), + &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */); diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index f443df8533..32ac9e8928 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -18,8 +18,11 @@ #include #include +#include #include +#include + namespace android { class FrameStats; @@ -51,8 +54,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, int32_t windowType, - int32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, + LayerMetadata metadata, sp* handle, sp* gbp) = 0; /* @@ -61,8 +64,7 @@ public: virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, - int32_t windowType, int32_t ownerUid, - sp* handle, + LayerMetadata metadata, sp* handle, sp* gbp) = 0; /* diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h new file mode 100644 index 0000000000..50121817d5 --- /dev/null +++ b/libs/gui/include/gui/LayerMetadata.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 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 { + +enum { METADATA_OWNER_UID = 1, METADATA_WINDOW_TYPE = 2 }; + +struct LayerMetadata : public Parcelable { + std::unordered_map> mMap; + + LayerMetadata(); + LayerMetadata(const LayerMetadata& other); + LayerMetadata(LayerMetadata&& other); + explicit LayerMetadata(std::unordered_map> map); + LayerMetadata& operator=(const LayerMetadata& other); + LayerMetadata& operator=(LayerMetadata&& other); + + void merge(const LayerMetadata& other); + + status_t writeToParcel(Parcel* parcel) const override; + status_t readFromParcel(const Parcel* parcel) override; + + bool has(uint32_t key) const; + int32_t getInt32(uint32_t key, int32_t fallback) const; + void setInt32(uint32_t key, int32_t value); + + std::string itemToString(uint32_t key, const char* separator) const; +}; + +} // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 9063e7fbb4..afd843f09e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -30,6 +30,7 @@ #include