diff options
30 files changed, 1696 insertions, 251 deletions
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index d089bf6bc3..e8b038b6c5 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -68,6 +68,7 @@ cc_library_shared { "PixelFormat.cpp", "Rect.cpp", "Region.cpp", + "Size.cpp", "Transform.cpp", "UiConfig.cpp", ], diff --git a/libs/ui/Size.cpp b/libs/ui/Size.cpp new file mode 100644 index 0000000000..d2996d164d --- /dev/null +++ b/libs/ui/Size.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#include <ui/Size.h> + +namespace android::ui { + +const Size Size::INVALID{-1, -1}; +const Size Size::EMPTY{0, 0}; + +} // namespace android::ui diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h index e9da087347..17688057a9 100644 --- a/libs/ui/include/ui/Rect.h +++ b/libs/ui/include/ui/Rect.h @@ -24,6 +24,7 @@ #include <ui/FloatRect.h> #include <ui/Point.h> +#include <ui/Size.h> #include <android/rect.h> @@ -78,6 +79,13 @@ public: bottom = static_cast<int32_t>(floatRect.bottom + 0.5f); } + inline explicit Rect(const ui::Size& size) { + left = 0; + top = 0; + right = size.width; + bottom = size.height; + } + void makeInvalid(); inline void clear() { @@ -106,6 +114,8 @@ public: return bottom - top; } + ui::Size getSize() const { return ui::Size(getWidth(), getHeight()); } + __attribute__((no_sanitize("signed-integer-overflow"))) inline Rect getBounds() const { return Rect(right - left, bottom - top); diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h new file mode 100644 index 0000000000..c39d8af1d6 --- /dev/null +++ b/libs/ui/include/ui/Size.h @@ -0,0 +1,158 @@ +/* + * 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 <algorithm> +#include <cstdint> +#include <limits> +#include <type_traits> +#include <utility> + +namespace android { +namespace ui { + +// Forward declare a few things. +struct Size; +bool operator==(const Size& lhs, const Size& rhs); + +/** + * A simple value type representing a two-dimensional size + */ +struct Size { + int32_t width; + int32_t height; + + // Special values + static const Size INVALID; + static const Size EMPTY; + + // ------------------------------------------------------------------------ + // Construction + // ------------------------------------------------------------------------ + + Size() : Size(INVALID) {} + template <typename T> + Size(T&& w, T&& h) + : width(Size::clamp<int32_t, T>(std::forward<T>(w))), + height(Size::clamp<int32_t, T>(std::forward<T>(h))) {} + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + int32_t getWidth() const { return width; } + int32_t getHeight() const { return height; } + + template <typename T> + void setWidth(T&& v) { + width = Size::clamp<int32_t, T>(std::forward<T>(v)); + } + template <typename T> + void setHeight(T&& v) { + height = Size::clamp<int32_t, T>(std::forward<T>(v)); + } + + // ------------------------------------------------------------------------ + // Assignment + // ------------------------------------------------------------------------ + + void set(const Size& size) { *this = size; } + template <typename T> + void set(T&& w, T&& h) { + set(Size(std::forward<T>(w), std::forward<T>(h))); + } + + // Sets the value to INVALID + void makeInvalid() { set(INVALID); } + + // Sets the value to EMPTY + void clear() { set(EMPTY); } + + // ------------------------------------------------------------------------ + // Semantic checks + // ------------------------------------------------------------------------ + + // Valid means non-negative width and height + bool isValid() const { return width >= 0 && height >= 0; } + + // Empty means zero width and height + bool isEmpty() const { return *this == EMPTY; } + + // ------------------------------------------------------------------------ + // Clamp Helpers + // ------------------------------------------------------------------------ + + // Note: We use only features available in C++11 here for compatibility with + // external targets which include this file directly or indirectly and which + // themselves use C++11. + + // C++11 compatible replacement for std::remove_cv_reference_t [C++20] + template <typename T> + using remove_cv_reference_t = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + + // Takes a value of type FromType, and ensures it can be represented as a value of type ToType, + // clamping the input value to the output range if necessary. + template <typename ToType, typename FromType> + static Size::remove_cv_reference_t<ToType> clamp( + typename std::enable_if< + std::numeric_limits<Size::remove_cv_reference_t<ToType>>::is_bounded && + std::numeric_limits<Size::remove_cv_reference_t<FromType>>::is_bounded, + FromType&&>::type v) { + static constexpr auto toHighest = std::numeric_limits<remove_cv_reference_t<ToType>>::max(); + static constexpr auto toLowest = + std::numeric_limits<remove_cv_reference_t<ToType>>::lowest(); + static constexpr auto fromHighest = + std::numeric_limits<remove_cv_reference_t<FromType>>::max(); + static constexpr auto fromLowest = + std::numeric_limits<remove_cv_reference_t<FromType>>::lowest(); + + // A clamp is needed if the range of FromType is not a subset of the range of ToType + static constexpr bool isClampNeeded = (toLowest > fromLowest) || (toHighest < fromHighest); + + // If a clamp is not needed, the conversion is just a trivial cast. + if (!isClampNeeded) { + return static_cast<ToType>(v); + } + + // Otherwise we leverage implicit conversion to safely compare values of + // different types, to ensure we return a value clamped to the range of + // ToType. + return v < toLowest ? toLowest : (v > toHighest ? toHighest : static_cast<ToType>(v)); + } +}; + +// ------------------------------------------------------------------------ +// Comparisons +// ------------------------------------------------------------------------ + +inline bool operator==(const Size& lhs, const Size& rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height; +} + +inline bool operator!=(const Size& lhs, const Size& rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator<(const Size& lhs, const Size& rhs) { + // Orders by increasing width, then height. + if (lhs.width != rhs.width) return lhs.width < rhs.width; + return lhs.height < rhs.height; +} + +} // namespace ui +} // namespace android diff --git a/libs/ui/include_vndk/ui/Size.h b/libs/ui/include_vndk/ui/Size.h new file mode 120000 index 0000000000..fd2b21b727 --- /dev/null +++ b/libs/ui/include_vndk/ui/Size.h @@ -0,0 +1 @@ +../../include/ui/Size.h
\ No newline at end of file diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 665469e015..373fa4f221 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -71,3 +71,10 @@ cc_test { ], cflags: ["-Wall", "-Werror"], } + +cc_test { + name: "Size_test", + shared_libs: ["libui"], + srcs: ["Size_test.cpp"], + cflags: ["-Wall", "-Werror"], +} diff --git a/libs/ui/tests/Size_test.cpp b/libs/ui/tests/Size_test.cpp new file mode 100644 index 0000000000..69e1ac8b27 --- /dev/null +++ b/libs/ui/tests/Size_test.cpp @@ -0,0 +1,184 @@ +/* + * 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_TAG "SizeTest" + +#include <cmath> +#include <cstdlib> + +#include <ui/Size.h> + +#include <gtest/gtest.h> + +namespace android { +namespace ui { + +TEST(SizeTest, BasicConstructionAndEqualityComparison) { + Size s(123, 456); + + EXPECT_EQ(123, s.width); + EXPECT_EQ(123, s.getWidth()); + + EXPECT_EQ(456, s.height); + EXPECT_EQ(456, s.getHeight()); + + EXPECT_EQ(Size(123, 456), s); + EXPECT_NE(Size(456, 123), s); +} + +TEST(SizeTest, BasicLessThanComparison) { + EXPECT_TRUE(Size(0, 1) < Size(2, 3)); + EXPECT_FALSE(Size(2, 3) < Size(0, 1)); + + EXPECT_TRUE(Size(0, 3) < Size(2, 1)); + EXPECT_FALSE(Size(2, 1) < Size(0, 3)); + + EXPECT_TRUE(Size(0, 1) < Size(0, 3)); + EXPECT_FALSE(Size(0, 3) < Size(0, 1)); + + EXPECT_FALSE(Size(1, 1) < Size(1, 1)); +} + +TEST(SizeTest, ValidAndEmpty) { + { + Size s; + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + Size s(-1, -1); + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + Size s(1, -1000); + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + Size s(-1000, 1); + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + Size s(-1000, -1000); + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + const auto& s = Size::INVALID; + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + Size s(123, 456); + s.makeInvalid(); + EXPECT_FALSE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } + + { + Size s(0, 0); + EXPECT_TRUE(s.isValid()); + EXPECT_TRUE(s.isEmpty()); + } + + { + const auto& s = Size::EMPTY; + EXPECT_TRUE(s.isValid()); + EXPECT_TRUE(s.isEmpty()); + } + + { + Size s(123, 456); + s.clear(); + EXPECT_TRUE(s.isValid()); + EXPECT_TRUE(s.isEmpty()); + } + + { + Size s(123, 456); + EXPECT_TRUE(s.isValid()); + EXPECT_FALSE(s.isEmpty()); + } +} + +TEST(SizeTest, Set) { + { + Size s; + s.setWidth(0); + EXPECT_EQ(Size(0, -1), s); + } + + { + Size s; + s.setHeight(0); + EXPECT_EQ(Size(-1, 0), s); + } + + { + Size s; + s.set(123, 456); + EXPECT_EQ(Size(123, 456), s); + } +} + +template <typename T, typename U> +void ClampTest(T input, U expected) { + // The constructor, set(), setWidth() and setHeight() all allow arbitrary + // conversions from other numeric types, and implement clamping if necessary. + + EXPECT_EQ(Size(expected, expected), Size(input, input)); + + { + Size s; + s.set(input, input); + EXPECT_EQ(Size(expected, expected), s); + } + + { + Size s; + s.setWidth(input); + EXPECT_EQ(expected, s.width); + } + + { + Size s; + s.setHeight(input); + EXPECT_EQ(expected, s.height); + } +} + +TEST(SizeTest, Int8RangeIsNotClamped) { + ClampTest(std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::max()); + ClampTest(int8_t(0), int8_t(0)); + ClampTest(std::numeric_limits<int8_t>::lowest(), std::numeric_limits<int8_t>::lowest()); +} + +TEST(SizeTest, FloatRangeIsClamped) { + ClampTest(std::numeric_limits<float>::max(), std::numeric_limits<int32_t>::max()); + ClampTest(float(0), int32_t(0)); + ClampTest(std::numeric_limits<float>::lowest(), std::numeric_limits<int32_t>::lowest()); +} + +} // namespace ui +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 64db6efe1f..6ec0e60e98 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -16,6 +16,8 @@ cc_defaults { "libgui", "liblayers_proto", "liblog", + "libnativewindow", + "libsync", "libtimestats_proto", "libui", "libutils", @@ -40,6 +42,7 @@ cc_library { "src/DumpHelpers.cpp", "src/Output.cpp", "src/OutputCompositionState.cpp", + "src/RenderSurface.cpp", ], local_include_dirs: ["include"], export_include_dirs: ["include"], @@ -53,6 +56,7 @@ cc_library { "mock/Display.cpp", "mock/DisplaySurface.cpp", "mock/Output.cpp", + "mock/RenderSurface.cpp", ], static_libs: [ "libgtest", @@ -72,6 +76,7 @@ cc_test { "tests/DisplayTest.cpp", "tests/OutputTest.cpp", "tests/MockHWComposer.cpp", + "tests/RenderSurfaceTest.cpp", ], static_libs: [ "libcompositionengine", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h index 979fdad988..9ba667166a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h @@ -25,6 +25,8 @@ namespace android::compositionengine { +struct RenderSurfaceCreationArgs; + /** * A display is a composition target which may be backed by a hardware composer * display device @@ -43,6 +45,8 @@ public: // Releases the use of the HWC display, if any virtual void disconnect() = 0; + virtual void createRenderSurface(RenderSurfaceCreationArgs&&) = 0; + protected: ~Display() = default; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 731189f8ca..7814bcb486 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -26,6 +26,8 @@ namespace android::compositionengine { +class RenderSurface; + namespace impl { struct OutputCompositionState; } // namespace impl @@ -47,7 +49,7 @@ public: virtual void setProjection(const ui::Transform&, int32_t orientation, const Rect& frame, const Rect& viewport, const Rect& scissor, bool needsFiltering) = 0; // Sets the bounds to use - virtual void setBounds(const Rect&) = 0; + virtual void setBounds(const ui::Size&) = 0; // Sets the layer stack filter for this output. If singleLayerStack is true, // this output displays just the single layer stack specified by @@ -70,6 +72,9 @@ public: // Sets a debug name for the output virtual void setName(const std::string&) = 0; + // Gets the current render surface for the output + virtual RenderSurface* getRenderSurface() const = 0; + using OutputCompositionState = compositionengine::impl::OutputCompositionState; // Gets the raw composition state data for the output @@ -92,6 +97,8 @@ public: protected: ~Output() = default; + + virtual void setRenderSurface(std::unique_ptr<RenderSurface> surface) = 0; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h new file mode 100644 index 0000000000..dd01b05c04 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -0,0 +1,104 @@ +/* + * 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 <cstdint> +#include <vector> + +#include <ui/Fence.h> +#include <ui/GraphicTypes.h> +#include <ui/Size.h> +#include <utils/Errors.h> +#include <utils/StrongPointer.h> + +namespace android { + +class GraphicBuffer; + +struct CompositionInfo; + +namespace compositionengine { + +/** + * Encapsulates everything for composing to a render surface with RenderEngine + */ +class RenderSurface { +public: + virtual ~RenderSurface(); + + // Returns true if the render surface is valid. This is meant to be checked + // post-construction and prior to use, as not everything is set up by the + // constructor. + virtual bool isValid() const = 0; + + // Performs one-time initialization of the render surface. This is meant + // to be called after the validation check. + virtual void initialize() = 0; + + // Returns the bounds of the surface + virtual const ui::Size& getSize() const = 0; + + // Gets the latest fence to pass to the HWC to signal that the surface + // buffer is done rendering + virtual const sp<Fence>& getClientTargetAcquireFence() const = 0; + + // Sets the size of the surface + virtual void setDisplaySize(const ui::Size&) = 0; + + // Sets the dataspace used for rendering the surface + virtual void setBufferDataspace(ui::Dataspace) = 0; + + // Configures the protected rendering on the surface + virtual void setProtected(bool useProtected) = 0; + + // Called to signal that rendering has started. 'mustRecompose' should be + // true if the entire frame must be recomposed. + virtual status_t beginFrame(bool mustRecompose) = 0; + + // Prepares the frame for rendering + virtual status_t prepareFrame(std::vector<CompositionInfo>& compositionData) = 0; + + // Allocates a buffer as scratch space for GPU composition + virtual sp<GraphicBuffer> dequeueBuffer() = 0; + + // Queues the drawn buffer for consumption by HWC + virtual void queueBuffer() = 0; + + // Called after the HWC calls are made to present the display + virtual void onPresentDisplayCompleted() = 0; + + // Marks the current buffer has finished, so that it can be presented and + // swapped out + virtual void finishBuffer() = 0; + + // Called to set the viewport and projection state for rendering into this + // surface + virtual void setViewportAndProjection() = 0; + + // Called after the surface has been rendering to signal the surface should + // be made ready for displaying + virtual void flip() = 0; + + // Debugging - Dumps the state of the RenderSurface to a string + virtual void dump(std::string& result) const = 0; + + // Debugging - gets the page flip count for the RenderSurface + virtual std::uint32_t getPageFlipCount() const = 0; +}; + +} // namespace compositionengine +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h new file mode 100644 index 0000000000..a1230b3c4d --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h @@ -0,0 +1,89 @@ +/* + * 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 <cstdint> +#include <memory> + +#include <compositionengine/DisplaySurface.h> +#include <utils/StrongPointer.h> + +struct ANativeWindow; + +namespace android { + +namespace compositionengine { + +class Display; + +/** + * A parameter object for creating RenderSurface instances + */ +struct RenderSurfaceCreationArgs { + // The initial width of the surface + int32_t displayWidth; + + // The initial height of the surface + int32_t displayHeight; + + // The ANativeWindow for the buffer queue for this surface + sp<ANativeWindow> nativeWindow; + + // The DisplaySurface for this surface + sp<DisplaySurface> displaySurface; +}; + +/** + * A helper for setting up a RenderSurfaceCreationArgs value in-line. + * Prefer this builder over raw structure initialization. + * + * Instead of: + * + * RenderSurfaceCreationArgs{1000, 1000, nativeWindow, displaySurface} + * + * Prefer: + * + * RenderSurfaceCreationArgsBuilder().setDisplayWidth(1000).setDisplayHeight(1000) + * .setNativeWindow(nativeWindow).setDisplaySurface(displaySurface).Build(); + */ +class RenderSurfaceCreationArgsBuilder { +public: + RenderSurfaceCreationArgs build() { return std::move(mArgs); } + + RenderSurfaceCreationArgsBuilder& setDisplayWidth(int32_t displayWidth) { + mArgs.displayWidth = displayWidth; + return *this; + } + RenderSurfaceCreationArgsBuilder& setDisplayHeight(int32_t displayHeight) { + mArgs.displayHeight = displayHeight; + return *this; + } + RenderSurfaceCreationArgsBuilder& setNativeWindow(sp<ANativeWindow> nativeWindow) { + mArgs.nativeWindow = nativeWindow; + return *this; + } + RenderSurfaceCreationArgsBuilder& setDisplaySurface(sp<DisplaySurface> displaySurface) { + mArgs.displaySurface = displaySurface; + return *this; + } + +private: + RenderSurfaceCreationArgs mArgs; +}; + +} // namespace compositionengine +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 7c38c49322..5609382d17 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -46,6 +46,7 @@ public: bool isSecure() const override; bool isVirtual() const override; void disconnect() override; + void createRenderSurface(compositionengine::RenderSurfaceCreationArgs&&) override; private: const bool mIsVirtual; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h index 663010ff82..782c8d772f 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h @@ -55,6 +55,7 @@ void dumpVal(std::string& out, const char* name, const FloatRect& rect); void dumpVal(std::string& out, const char* name, const Rect& rect); void dumpVal(std::string& out, const char* name, const Region& region); void dumpVal(std::string& out, const char* name, const ui::Transform&); +void dumpVal(std::string& out, const char* name, const ui::Size&); void dumpVal(std::string& out, const char* name, const mat4& tr); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 60b94a43aa..86a1662a9c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -37,7 +37,7 @@ public: void setCompositionEnabled(bool) override; void setProjection(const ui::Transform&, int32_t orientation, const Rect& frame, const Rect& viewport, const Rect& scissor, bool needsFiltering) override; - void setBounds(const Rect&) override; + void setBounds(const ui::Size&) override; void setLayerStackFilter(bool singleLayerStack, uint32_t singleLayerStackId) override; void setColorTransform(const mat4&) override; @@ -48,12 +48,18 @@ public: const std::string& getName() const override; void setName(const std::string&) override; + compositionengine::RenderSurface* getRenderSurface() const override; + void setRenderSurface(std::unique_ptr<compositionengine::RenderSurface>) override; + const OutputCompositionState& getState() const override; OutputCompositionState& editState() override; Region getPhysicalSpaceDirtyRegion(bool repaintEverything) const override; bool belongsInOutput(uint32_t) const override; + // Testing + void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>); + protected: const CompositionEngine& getCompositionEngine() const; void dumpBase(std::string&) const; @@ -66,6 +72,8 @@ private: std::string mName; OutputCompositionState mState; + + std::unique_ptr<compositionengine::RenderSurface> mRenderSurface; }; } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h new file mode 100644 index 0000000000..0489310e04 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -0,0 +1,94 @@ +/* + * 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 <memory> + +#include <android-base/unique_fd.h> +#include <compositionengine/RenderSurface.h> +#include <utils/StrongPointer.h> + +struct ANativeWindow; + +namespace android { + +namespace compositionengine { + +class CompositionEngine; +class Display; +class DisplaySurface; + +struct RenderSurfaceCreationArgs; + +namespace impl { + +class RenderSurface : public compositionengine::RenderSurface { +public: + RenderSurface(const CompositionEngine&, compositionengine::Display&, + compositionengine::RenderSurfaceCreationArgs&&); + ~RenderSurface() override; + + bool isValid() const override; + void initialize() override; + const ui::Size& getSize() const override; + + const sp<Fence>& getClientTargetAcquireFence() const override; + void setBufferDataspace(ui::Dataspace) override; + void setDisplaySize(const ui::Size&) override; + void setProtected(bool useProtected) override; + status_t beginFrame(bool mustRecompose) override; + status_t prepareFrame(std::vector<CompositionInfo>& compositionData) override; + sp<GraphicBuffer> dequeueBuffer() override; + void queueBuffer() override; + void onPresentDisplayCompleted() override; + void finishBuffer() override; + void setViewportAndProjection() override; + void flip() override; + + // Debugging + void dump(std::string& result) const override; + std::uint32_t getPageFlipCount() const override; + + // Testing + void setPageFlipCountForTest(std::uint32_t); + void setSizeForTest(const ui::Size&); + sp<GraphicBuffer>& mutableGraphicBufferForTest(); + base::unique_fd& mutableBufferReadyForTest(); + +private: + const compositionengine::CompositionEngine& mCompositionEngine; + const compositionengine::Display& mDisplay; + + // ANativeWindow being rendered into + const sp<ANativeWindow> mNativeWindow; + // Current buffer being rendered into + sp<GraphicBuffer> mGraphicBuffer; + // File descriptor indicating that mGraphicBuffer is ready for display, i.e. + // that drawing to the buffer is now complete. + base::unique_fd mBufferReady; + const sp<DisplaySurface> mDisplaySurface; + ui::Size mSize; + std::uint32_t mPageFlipCount{0}; +}; + +std::unique_ptr<compositionengine::RenderSurface> createRenderSurface( + const compositionengine::CompositionEngine&, compositionengine::Display&, + compositionengine::RenderSurfaceCreationArgs&&); + +} // namespace impl +} // namespace compositionengine +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h index 22eb8f5ccb..e4adfc550b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h @@ -17,8 +17,11 @@ #pragma once #include <compositionengine/Display.h> +#include <compositionengine/DisplaySurface.h> +#include <compositionengine/RenderSurfaceCreationArgs.h> #include <compositionengine/mock/Output.h> #include <gmock/gmock.h> +#include <system/window.h> #include "DisplayHardware/DisplayIdentification.h" @@ -34,6 +37,8 @@ public: MOCK_CONST_METHOD0(isVirtual, bool()); MOCK_METHOD0(disconnect, void()); + + MOCK_METHOD1(createRenderSurface, void(RenderSurfaceCreationArgs&&)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index ccdf804520..3f2cc0552a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -17,6 +17,7 @@ #pragma once #include <compositionengine/Output.h> +#include <compositionengine/RenderSurface.h> #include <compositionengine/impl/OutputCompositionState.h> #include <gmock/gmock.h> @@ -32,7 +33,7 @@ public: MOCK_METHOD1(setCompositionEnabled, void(bool)); MOCK_METHOD6(setProjection, void(const ui::Transform&, int32_t, const Rect&, const Rect&, const Rect&, bool)); - MOCK_METHOD1(setBounds, void(const Rect&)); + MOCK_METHOD1(setBounds, void(const ui::Size&)); MOCK_METHOD2(setLayerStackFilter, void(bool, uint32_t)); MOCK_METHOD1(setColorTransform, void(const mat4&)); @@ -42,6 +43,9 @@ public: MOCK_CONST_METHOD0(getName, const std::string&()); MOCK_METHOD1(setName, void(const std::string&)); + MOCK_CONST_METHOD0(getRenderSurface, RenderSurface*()); + MOCK_METHOD1(setRenderSurface, void(std::unique_ptr<RenderSurface>)); + MOCK_CONST_METHOD0(getState, const OutputCompositionState&()); MOCK_METHOD0(editState, OutputCompositionState&()); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h new file mode 100644 index 0000000000..2269e579c1 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -0,0 +1,51 @@ +/* + * 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 <compositionengine/RenderSurface.h> +#include <gmock/gmock.h> +#include <ui/GraphicBuffer.h> + +#include "LayerBE.h" + +namespace android::compositionengine::mock { + +class RenderSurface : public compositionengine::RenderSurface { +public: + RenderSurface(); + ~RenderSurface() override; + + MOCK_CONST_METHOD0(isValid, bool()); + MOCK_METHOD0(initialize, void()); + MOCK_CONST_METHOD0(getSize, const ui::Size&()); + MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&()); + MOCK_METHOD1(setDisplaySize, void(const ui::Size&)); + MOCK_METHOD1(setProtected, void(bool)); + MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace)); + MOCK_METHOD1(beginFrame, status_t(bool mustRecompose)); + MOCK_METHOD1(prepareFrame, status_t(std::vector<CompositionInfo>& compositionData)); + MOCK_METHOD0(dequeueBuffer, sp<GraphicBuffer>()); + MOCK_METHOD0(queueBuffer, void()); + MOCK_METHOD0(onPresentDisplayCompleted, void()); + MOCK_METHOD0(finishBuffer, void()); + MOCK_METHOD0(setViewportAndProjection, void()); + MOCK_METHOD0(flip, void()); + MOCK_CONST_METHOD1(dump, void(std::string& result)); + MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t()); +}; + +} // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/mock/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/mock/RenderSurface.cpp new file mode 100644 index 0000000000..fe718d681a --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/mock/RenderSurface.cpp @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#include <compositionengine/mock/RenderSurface.h> + +namespace android::compositionengine::mock { + +// Explicit default instantiation is recommended. +RenderSurface::RenderSurface() = default; +RenderSurface::~RenderSurface() = default; + +} // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index fb783e706f..ae77614536 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -17,8 +17,10 @@ #include <android-base/stringprintf.h> #include <compositionengine/CompositionEngine.h> #include <compositionengine/DisplayCreationArgs.h> +#include <compositionengine/DisplaySurface.h> #include <compositionengine/impl/Display.h> #include <compositionengine/impl/DumpHelpers.h> +#include <compositionengine/impl/RenderSurface.h> #include "DisplayHardware/HWComposer.h" @@ -107,4 +109,9 @@ void Display::dump(std::string& out) const { Output::dumpBase(out); } +void Display::createRenderSurface(RenderSurfaceCreationArgs&& args) { + setRenderSurface(compositionengine::impl::createRenderSurface(getCompositionEngine(), *this, + std::move(args))); +} + } // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp index ba86be7363..c49701315b 100644 --- a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp +++ b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp @@ -79,6 +79,10 @@ void dumpVal(std::string& out, const char* name, const ui::Transform& transform) transform.dump(out, name); } +void dumpVal(std::string& out, const char* name, const ui::Size& size) { + StringAppendF(&out, "%s=[%d %d] ", name, size.width, size.height); +} + void dumpVal(std::string& out, const char* name, const mat4& tr) { StringAppendF(&out, "%s=[" diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 8b2441f271..b74c5c6e83 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -16,6 +16,7 @@ #include <android-base/stringprintf.h> #include <compositionengine/CompositionEngine.h> +#include <compositionengine/RenderSurface.h> #include <compositionengine/impl/Output.h> #include <ui/DebugUtils.h> @@ -31,7 +32,7 @@ const CompositionEngine& Output::getCompositionEngine() const { } bool Output::isValid() const { - return true; + return mRenderSurface && mRenderSurface->isValid(); } const std::string& Output::getName() const { @@ -63,8 +64,11 @@ void Output::setProjection(const ui::Transform& transform, int32_t orientation, dirtyEntireOutput(); } -void Output::setBounds(const Rect& bounds) { - mState.bounds = bounds; +// TODO(lpique): Rename setSize() once more is moved. +void Output::setBounds(const ui::Size& size) { + mRenderSurface->setDisplaySize(size); + // TODO(lpique): Rename mState.size once more is moved. + mState.bounds = Rect(mRenderSurface->getSize()); dirtyEntireOutput(); } @@ -89,6 +93,8 @@ void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, mState.dataspace = dataspace; mState.renderIntent = renderIntent; + mRenderSurface->setBufferDataspace(dataspace); + ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)", decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), renderIntent); @@ -106,6 +112,27 @@ void Output::dump(std::string& out) const { void Output::dumpBase(std::string& out) const { mState.dump(out); + + if (mRenderSurface) { + mRenderSurface->dump(out); + } else { + out.append(" No render surface!\n"); + } +} + +compositionengine::RenderSurface* Output::getRenderSurface() const { + return mRenderSurface.get(); +} + +void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) { + mRenderSurface = std::move(surface); + mState.bounds = Rect(mRenderSurface->getSize()); + + dirtyEntireOutput(); +} + +void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) { + mRenderSurface = std::move(surface); } const OutputCompositionState& Output::getState() const { diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp new file mode 100644 index 0000000000..d546fc81ac --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -0,0 +1,271 @@ +/* + * 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. + */ + +#include <android-base/stringprintf.h> +#include <android/native_window.h> +#include <compositionengine/CompositionEngine.h> +#include <compositionengine/Display.h> +#include <compositionengine/DisplaySurface.h> +#include <compositionengine/RenderSurfaceCreationArgs.h> +#include <compositionengine/impl/DumpHelpers.h> +#include <compositionengine/impl/RenderSurface.h> +#include <log/log.h> +#include <renderengine/RenderEngine.h> +#include <sync/sync.h> +#include <system/window.h> +#include <ui/GraphicBuffer.h> +#include <ui/Rect.h> + +#include "DisplayHardware/HWComposer.h" + +namespace android::compositionengine { + +RenderSurface::~RenderSurface() = default; + +namespace impl { + +std::unique_ptr<compositionengine::RenderSurface> createRenderSurface( + const compositionengine::CompositionEngine& compositionEngine, + compositionengine::Display& display, compositionengine::RenderSurfaceCreationArgs&& args) { + return std::make_unique<RenderSurface>(compositionEngine, display, std::move(args)); +} + +RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display& display, + RenderSurfaceCreationArgs&& args) + : mCompositionEngine(compositionEngine), + mDisplay(display), + mNativeWindow(args.nativeWindow), + mDisplaySurface(args.displaySurface), + mSize(args.displayWidth, args.displayHeight) {} + +RenderSurface::~RenderSurface() = default; + +bool RenderSurface::isValid() const { + return mSize.isValid(); +} + +void RenderSurface::initialize() { + ANativeWindow* const window = mNativeWindow.get(); + + int status = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); + ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status); + status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); + ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status); + status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER); + ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status); +} + +const ui::Size& RenderSurface::getSize() const { + return mSize; +} + +const sp<Fence>& RenderSurface::getClientTargetAcquireFence() const { + return mDisplaySurface->getClientTargetAcquireFence(); +} + +void RenderSurface::setDisplaySize(const ui::Size& size) { + mDisplaySurface->resizeBuffers(size.width, size.height); + mSize = size; +} + +void RenderSurface::setBufferDataspace(ui::Dataspace dataspace) { + native_window_set_buffers_data_space(mNativeWindow.get(), + static_cast<android_dataspace>(dataspace)); +} + +void RenderSurface::setProtected(bool useProtected) { + uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER; + if (useProtected) { + usageFlags |= GRALLOC_USAGE_PROTECTED; + } + const int status = native_window_set_usage(mNativeWindow.get(), usageFlags); + ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status); +} + +status_t RenderSurface::beginFrame(bool mustRecompose) { + return mDisplaySurface->beginFrame(mustRecompose); +} + +status_t RenderSurface::prepareFrame(std::vector<CompositionInfo>& compositionData) { + auto& hwc = mCompositionEngine.getHwComposer(); + const auto id = mDisplay.getId(); + if (id) { + status_t error = hwc.prepare(*id, compositionData); + if (error != NO_ERROR) { + return error; + } + } + + DisplaySurface::CompositionType compositionType; + const bool hasClient = hwc.hasClientComposition(id); + const bool hasDevice = hwc.hasDeviceComposition(id); + if (hasClient && hasDevice) { + compositionType = DisplaySurface::COMPOSITION_MIXED; + } else if (hasClient) { + compositionType = DisplaySurface::COMPOSITION_GLES; + } else if (hasDevice) { + compositionType = DisplaySurface::COMPOSITION_HWC; + } else { + // Nothing to do -- when turning the screen off we get a frame like + // this. Call it a HWC frame since we won't be doing any GLES work but + // will do a prepare/set cycle. + compositionType = DisplaySurface::COMPOSITION_HWC; + } + return mDisplaySurface->prepareFrame(compositionType); +} + +sp<GraphicBuffer> RenderSurface::dequeueBuffer() { + int fd = -1; + ANativeWindowBuffer* buffer = nullptr; + + status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd); + + if (result != NO_ERROR) { + ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d", + mDisplay.getName().c_str(), result); + // Return fast here as we can't do much more - any rendering we do + // now will just be wrong. + return mGraphicBuffer; + } + + ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", + mGraphicBuffer->getNativeBuffer()->handle); + mGraphicBuffer = GraphicBuffer::from(buffer); + + // Block until the buffer is ready + // TODO(alecmouri): it's perhaps more appropriate to block renderengine so + // that the gl driver can block instead. + if (fd >= 0) { + sync_wait(fd, -1); + close(fd); + } + + return mGraphicBuffer; +} + +void RenderSurface::queueBuffer() { + auto& hwc = mCompositionEngine.getHwComposer(); + const auto id = mDisplay.getId(); + + if (hwc.hasClientComposition(id) || hwc.hasFlipClientTargetRequest(id)) { + // hasFlipClientTargetRequest could return true even if we haven't + // dequeued a buffer before. Try dequeueing one if we don't have a + // buffer ready. + if (mGraphicBuffer == nullptr) { + ALOGI("Attempting to queue a client composited buffer without one " + "previously dequeued for display [%s]. Attempting to dequeue " + "a scratch buffer now", + mDisplay.getName().c_str()); + // We shouldn't deadlock here, since mGraphicBuffer == nullptr only + // after a successful call to queueBuffer, or if dequeueBuffer has + // never been called. + dequeueBuffer(); + } + + if (mGraphicBuffer == nullptr) { + ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); + } else { + status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(), + mGraphicBuffer->getNativeBuffer(), + dup(mBufferReady)); + if (result != NO_ERROR) { + ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), + result); + // We risk blocking on dequeueBuffer if the primary display failed + // to queue up its buffer, so crash here. + if (!mDisplay.isVirtual()) { + LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); + } else { + mNativeWindow->cancelBuffer(mNativeWindow.get(), + mGraphicBuffer->getNativeBuffer(), + dup(mBufferReady)); + } + } + + mBufferReady.reset(); + mGraphicBuffer = nullptr; + } + } + + status_t result = mDisplaySurface->advanceFrame(); + if (result != NO_ERROR) { + ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result); + } +} + +void RenderSurface::onPresentDisplayCompleted() { + mDisplaySurface->onFrameCommitted(); +} + +void RenderSurface::setViewportAndProjection() { + auto& renderEngine = mCompositionEngine.getRenderEngine(); + Rect sourceCrop = Rect(mSize); + renderEngine.setViewportAndProjection(mSize.width, mSize.height, sourceCrop, + ui::Transform::ROT_0); +} + +void RenderSurface::finishBuffer() { + auto& renderEngine = mCompositionEngine.getRenderEngine(); + mBufferReady = renderEngine.flush(); + if (mBufferReady.get() < 0) { + renderEngine.finish(); + } +} + +void RenderSurface::flip() { + mPageFlipCount++; +} + +void RenderSurface::dump(std::string& out) const { + using android::base::StringAppendF; + + out.append(" Composition RenderSurface State:"); + + out.append("\n "); + + dumpVal(out, "size", mSize); + StringAppendF(&out, "ANativeWindow=%p (format %d) ", mNativeWindow.get(), + ANativeWindow_getFormat(mNativeWindow.get())); + dumpVal(out, "flips", mPageFlipCount); + out.append("\n"); + + String8 surfaceDump; + mDisplaySurface->dumpAsString(surfaceDump); + out.append(surfaceDump); +} + +std::uint32_t RenderSurface::getPageFlipCount() const { + return mPageFlipCount; +} + +void RenderSurface::setPageFlipCountForTest(std::uint32_t count) { + mPageFlipCount = count; +} + +void RenderSurface::setSizeForTest(const ui::Size& size) { + mSize = size; +} + +sp<GraphicBuffer>& RenderSurface::mutableGraphicBufferForTest() { + return mGraphicBuffer; +} + +base::unique_fd& RenderSurface::mutableBufferReadyForTest() { + return mBufferReady; +} + +} // namespace impl +} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index a04c2aaddd..589fdc35aa 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -17,15 +17,20 @@ #include <cmath> #include <compositionengine/DisplayCreationArgs.h> +#include <compositionengine/DisplaySurface.h> +#include <compositionengine/RenderSurfaceCreationArgs.h> #include <compositionengine/impl/Display.h> #include <compositionengine/mock/CompositionEngine.h> +#include <compositionengine/mock/RenderSurface.h> #include <gtest/gtest.h> +#include <system/window.h> #include "MockHWComposer.h" namespace android::compositionengine { namespace { +using testing::Return; using testing::ReturnRef; using testing::StrictMock; @@ -131,6 +136,9 @@ TEST_F(DisplayTest, setColorTransformSetsTransform) { */ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { + mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); + mDisplay.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); + EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); // These values are expected to be the initial state. @@ -147,6 +155,7 @@ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent); // Otherwise if the values are different, updates happen + EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::SRGB)).Times(1); EXPECT_CALL(mHwComposer, setActiveColorMode(DEFAULT_DISPLAY_ID, ui::ColorMode::BT2100_PQ, ui::RenderIntent::TONE_MAP_COLORIMETRIC)) @@ -172,5 +181,15 @@ TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) { EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, virtualDisplay.getState().renderIntent); } +/* ------------------------------------------------------------------------ + * Display::createRenderSurface() + */ + +TEST_F(DisplayTest, createRenderSurfaceSetsRenderSurface) { + EXPECT_TRUE(mDisplay.getRenderSurface() == nullptr); + mDisplay.createRenderSurface(RenderSurfaceCreationArgs{640, 480, nullptr, nullptr}); + EXPECT_TRUE(mDisplay.getRenderSurface() != nullptr); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 0cd0d23f90..4807445513 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -18,6 +18,7 @@ #include <compositionengine/impl/Output.h> #include <compositionengine/mock/CompositionEngine.h> +#include <compositionengine/mock/RenderSurface.h> #include <gtest/gtest.h> #include <ui/Rect.h> #include <ui/Region.h> @@ -28,14 +29,19 @@ namespace android::compositionengine { namespace { +using testing::Return; using testing::ReturnRef; using testing::StrictMock; class OutputTest : public testing::Test { public: + OutputTest() { + mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface)); + } ~OutputTest() override = default; StrictMock<mock::CompositionEngine> mCompositionEngine; + mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>(); impl::Output mOutput{mCompositionEngine}; }; @@ -43,7 +49,17 @@ public: * Basic construction */ -TEST_F(OutputTest, canInstantiateOutput) {} +TEST_F(OutputTest, canInstantiateOutput) { + // The validation check checks each required component. + EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true)); + + EXPECT_TRUE(mOutput.isValid()); + + // If we take away the required components, it is no longer valid. + mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>()); + + EXPECT_FALSE(mOutput.isValid()); +} /* ------------------------------------------------------------------------ * Output::setCompositionEnabled() @@ -109,12 +125,16 @@ TEST_F(OutputTest, setProjectionTriviallyWorks) { */ TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) { - const Rect displaySize{100, 200}; + const ui::Size displaySize{100, 200}; + + EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1); + EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize)); + mOutput.setBounds(displaySize); - EXPECT_EQ(displaySize, mOutput.getState().bounds); + EXPECT_EQ(Rect(displaySize), mOutput.getState().bounds); - EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(displaySize))); + EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(Rect(displaySize)))); } /* ------------------------------------------------------------------------ @@ -159,6 +179,8 @@ TEST_F(OutputTest, setColorTransformSetsTransform) { */ TEST_F(OutputTest, setColorModeSetsModeUnlessNoChange) { + EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::SRGB)).Times(1); + mOutput.setColorMode(ui::ColorMode::BT2100_PQ, ui::Dataspace::SRGB, ui::RenderIntent::TONE_MAP_COLORIMETRIC); @@ -168,6 +190,21 @@ TEST_F(OutputTest, setColorModeSetsModeUnlessNoChange) { } /* ------------------------------------------------------------------------ + * Output::setRenderSurface() + */ + +TEST_F(OutputTest, setRenderSurfaceResetsBounds) { + const ui::Size newDisplaySize{640, 480}; + + mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); + EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize)); + + mOutput.setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface)); + + EXPECT_EQ(Rect(newDisplaySize), mOutput.getState().bounds); +} + +/* ------------------------------------------------------------------------ * Output::getPhysicalSpaceDirtyRegion() */ diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp new file mode 100644 index 0000000000..13cc663c45 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -0,0 +1,504 @@ +/* + * 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. + */ + +#include <cstdarg> +#include <cstdint> + +#include <compositionengine/RenderSurfaceCreationArgs.h> +#include <compositionengine/impl/RenderSurface.h> +#include <compositionengine/mock/CompositionEngine.h> +#include <compositionengine/mock/Display.h> +#include <compositionengine/mock/DisplaySurface.h> +#include <gtest/gtest.h> +#include <renderengine/mock/RenderEngine.h> +#include <system/window.h> +#include <ui/ANativeObjectBase.h> + +#include "MockHWComposer.h" + +namespace android::compositionengine { +namespace { + +/* ------------------------------------------------------------------------ + * MockNativeWindow + * + * An intentionally simplified Mock which implements a minimal subset of the full + * ANativeWindow interface. + */ + +class MockNativeWindow : public ANativeObjectBase<ANativeWindow, MockNativeWindow, RefBase> { +public: + MockNativeWindow() { + ANativeWindow::setSwapInterval = &forwardSetSwapInterval; + ANativeWindow::dequeueBuffer = &forwardDequeueBuffer; + ANativeWindow::cancelBuffer = &forwardCancelBuffer; + ANativeWindow::queueBuffer = &forwardQueueBuffer; + ANativeWindow::query = &forwardQuery; + ANativeWindow::perform = &forwardPerform; + + ANativeWindow::dequeueBuffer_DEPRECATED = &forwardDequeueBufferDeprecated; + ANativeWindow::cancelBuffer_DEPRECATED = &forwardCancelBufferDeprecated; + ANativeWindow::lockBuffer_DEPRECATED = &forwardLockBufferDeprecated; + ANativeWindow::queueBuffer_DEPRECATED = &forwardQueueBufferDeprecated; + } + + MOCK_METHOD1(setSwapInterval, int(int)); + MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*)); + MOCK_METHOD2(cancelBuffer, int(struct ANativeWindowBuffer*, int)); + MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int)); + MOCK_CONST_METHOD2(query, int(int, int*)); + MOCK_METHOD1(connect, int(int)); + MOCK_METHOD1(lockBuffer_DEPRECATED, int(struct ANativeWindowBuffer*)); + MOCK_METHOD1(setBuffersFormat, int(PixelFormat)); + MOCK_METHOD1(setBuffersDataSpace, int(ui::Dataspace)); + MOCK_METHOD1(setUsage, int(uint64_t)); + + static void unexpectedCall(...) { LOG_ALWAYS_FATAL("Unexpected ANativeWindow API call"); } + + static int forwardSetSwapInterval(ANativeWindow* window, int interval) { + return getSelf(window)->setSwapInterval(interval); + } + + static int forwardDequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, + int* fenceFd) { + return getSelf(window)->dequeueBuffer(buffer, fenceFd); + } + + static int forwardCancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, + int fenceFd) { + return getSelf(window)->cancelBuffer(buffer, fenceFd); + } + + static int forwardQueueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { + return getSelf(window)->queueBuffer(buffer, fenceFd); + } + + static int forwardQuery(const ANativeWindow* window, int what, int* value) { + return getSelf(window)->query(what, value); + } + + static int forwardPerform(ANativeWindow* window, int operation, ...) { + va_list args; + va_start(args, operation); + int result = NO_ERROR; + switch (operation) { + case NATIVE_WINDOW_API_CONNECT: { + int api = va_arg(args, int); + result = getSelf(window)->connect(api); + break; + } + case NATIVE_WINDOW_SET_BUFFERS_FORMAT: { + PixelFormat format = va_arg(args, PixelFormat); + result = getSelf(window)->setBuffersFormat(format); + break; + } + case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: { + ui::Dataspace dataspace = static_cast<ui::Dataspace>(va_arg(args, int)); + result = getSelf(window)->setBuffersDataSpace(dataspace); + break; + } + case NATIVE_WINDOW_SET_USAGE: { + // Note: Intentionally widens usage from 32 to 64 bits so we + // just have one implementation. + uint64_t usage = va_arg(args, uint32_t); + result = getSelf(window)->setUsage(usage); + break; + } + case NATIVE_WINDOW_SET_USAGE64: { + uint64_t usage = va_arg(args, uint64_t); + result = getSelf(window)->setUsage(usage); + break; + } + default: + LOG_ALWAYS_FATAL("Unexpected operation %d", operation); + break; + } + + va_end(args); + return result; + } + + static int forwardDequeueBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer** buffer) { + int ignoredFenceFd = -1; + return getSelf(window)->dequeueBuffer(buffer, &ignoredFenceFd); + } + + static int forwardCancelBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) { + return getSelf(window)->cancelBuffer(buffer, -1); + } + + static int forwardLockBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) { + return getSelf(window)->lockBuffer_DEPRECATED(buffer); + } + + static int forwardQueueBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) { + return getSelf(window)->queueBuffer(buffer, -1); + } +}; + +/* ------------------------------------------------------------------------ + * RenderSurfaceTest + */ + +constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920; +constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080; +constexpr std::optional<DisplayId> DEFAULT_DISPLAY_ID = std::make_optional(DisplayId{123u}); +const std::string DEFAULT_DISPLAY_NAME = "Mock Display"; + +using testing::_; +using testing::ByMove; +using testing::DoAll; +using testing::Ref; +using testing::Return; +using testing::ReturnRef; +using testing::SetArgPointee; +using testing::StrictMock; + +class RenderSurfaceTest : public testing::Test { +public: + RenderSurfaceTest() { + EXPECT_CALL(mDisplay, getId()).WillRepeatedly(ReturnRef(DEFAULT_DISPLAY_ID)); + EXPECT_CALL(mDisplay, getName()).WillRepeatedly(ReturnRef(DEFAULT_DISPLAY_NAME)); + EXPECT_CALL(mCompositionEngine, getHwComposer).WillRepeatedly(ReturnRef(mHwComposer)); + EXPECT_CALL(mCompositionEngine, getRenderEngine).WillRepeatedly(ReturnRef(mRenderEngine)); + } + ~RenderSurfaceTest() override = default; + + StrictMock<android::mock::HWComposer> mHwComposer; + StrictMock<renderengine::mock::RenderEngine> mRenderEngine; + StrictMock<mock::CompositionEngine> mCompositionEngine; + StrictMock<mock::Display> mDisplay; + sp<MockNativeWindow> mNativeWindow = new StrictMock<MockNativeWindow>(); + sp<mock::DisplaySurface> mDisplaySurface = new StrictMock<mock::DisplaySurface>(); + impl::RenderSurface mSurface{mCompositionEngine, mDisplay, + RenderSurfaceCreationArgs{DEFAULT_DISPLAY_WIDTH, + DEFAULT_DISPLAY_HEIGHT, mNativeWindow, + mDisplaySurface}}; +}; + +/* ------------------------------------------------------------------------ + * Basic construction + */ + +TEST_F(RenderSurfaceTest, canInstantiate) { + EXPECT_TRUE(mSurface.isValid()); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::initialize() + */ + +TEST_F(RenderSurfaceTest, initializeConfiguresNativeWindow) { + EXPECT_CALL(*mNativeWindow, connect(NATIVE_WINDOW_API_EGL)).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*mNativeWindow, setBuffersFormat(HAL_PIXEL_FORMAT_RGBA_8888)) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER)).WillOnce(Return(NO_ERROR)); + + mSurface.initialize(); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::getSize() + */ + +TEST_F(RenderSurfaceTest, sizeReturnsConstructedSize) { + const ui::Size expected{DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}; + + EXPECT_EQ(expected, mSurface.getSize()); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::getClientTargetAcquireFence() + */ + +TEST_F(RenderSurfaceTest, getClientTargetAcquireFenceForwardsCall) { + sp<Fence> fence = new Fence(); + + EXPECT_CALL(*mDisplaySurface, getClientTargetAcquireFence()).WillOnce(ReturnRef(fence)); + + EXPECT_EQ(fence.get(), mSurface.getClientTargetAcquireFence().get()); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::setDisplaySize() + */ + +TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) { + EXPECT_CALL(*mDisplaySurface, resizeBuffers(640, 480)).Times(1); + + mSurface.setDisplaySize(ui::Size(640, 480)); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::setBufferDataspace() + */ + +TEST_F(RenderSurfaceTest, setBufferDataspaceAppliesChange) { + EXPECT_CALL(*mNativeWindow, setBuffersDataSpace(ui::Dataspace::DISPLAY_P3)) + .WillOnce(Return(NO_ERROR)); + + mSurface.setBufferDataspace(ui::Dataspace::DISPLAY_P3); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::setProtected() + */ + +TEST_F(RenderSurfaceTest, setProtectedTrueEnablesProtection) { + EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED)) + .WillOnce(Return(NO_ERROR)); + + mSurface.setProtected(true); +} + +TEST_F(RenderSurfaceTest, setProtectedFalseDisablesProtection) { + EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER)).WillOnce(Return(NO_ERROR)); + + mSurface.setProtected(false); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::beginFrame() + */ + +TEST_F(RenderSurfaceTest, beginFrameAppliesChange) { + EXPECT_CALL(*mDisplaySurface, beginFrame(true)).WillOnce(Return(NO_ERROR)); + + EXPECT_EQ(NO_ERROR, mSurface.beginFrame(true)); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::prepareFrame() + */ + +TEST_F(RenderSurfaceTest, prepareFrameTakesEarlyOutOnHwcError) { + std::vector<CompositionInfo> data; + + EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))) + .WillOnce(Return(INVALID_OPERATION)); + + EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame(data)); +} + +TEST_F(RenderSurfaceTest, prepareFrameHandlesMixedComposition) { + std::vector<CompositionInfo> data; + EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + + EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_MIXED)) + .WillOnce(Return(INVALID_OPERATION)); + + EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame(data)); +} + +TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyGlesComposition) { + std::vector<CompositionInfo> data; + + EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + + EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_GLES)) + .WillOnce(Return(NO_ERROR)); + + EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data)); +} + +TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyHwcComposition) { + std::vector<CompositionInfo> data; + + EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + + EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC)) + .WillOnce(Return(NO_ERROR)); + + EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data)); +} + +TEST_F(RenderSurfaceTest, prepareFrameHandlesNoComposition) { + std::vector<CompositionInfo> data; + + EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + + EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC)) + .WillOnce(Return(NO_ERROR)); + + EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data)); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::dequeueBuffer() + */ + +TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { + sp<GraphicBuffer> buffer = new GraphicBuffer(); + + EXPECT_CALL(*mNativeWindow, dequeueBuffer(_, _)) + .WillOnce( + DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); + + EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer().get()); + + EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::queueBuffer() + */ + +TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { + sp<GraphicBuffer> buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; + + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + EXPECT_CALL(mHwComposer, hasFlipClientTargetRequest(DEFAULT_DISPLAY_ID)) + .WillOnce(Return(false)); + EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); + + mSurface.queueBuffer(); + + EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); +} + +TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { + sp<GraphicBuffer> buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; + + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); + + mSurface.queueBuffer(); + + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); +} + +TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) { + sp<GraphicBuffer> buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; + + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + EXPECT_CALL(mHwComposer, hasFlipClientTargetRequest(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); + + mSurface.queueBuffer(); + + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); +} + +TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) { + sp<GraphicBuffer> buffer = new GraphicBuffer(); + + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false)); + EXPECT_CALL(mHwComposer, hasFlipClientTargetRequest(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + EXPECT_CALL(*mNativeWindow, dequeueBuffer(_, _)) + .WillOnce( + DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); + + mSurface.queueBuffer(); + + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); +} + +TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) { + sp<GraphicBuffer> buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; + + EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true)); + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + .WillOnce(Return(INVALID_OPERATION)); + EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true)); + EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getNativeBuffer(), -1)) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); + + mSurface.queueBuffer(); + + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::onPresentDisplayCompleted() + */ + +TEST_F(RenderSurfaceTest, onPresentDisplayCompletedForwardsSignal) { + EXPECT_CALL(*mDisplaySurface, onFrameCommitted()).Times(1); + + mSurface.onPresentDisplayCompleted(); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::finishBuffer() + */ + +TEST_F(RenderSurfaceTest, finishBufferJustFlushesRenderEngine) { + int fd = dup(1); + + EXPECT_CALL(mRenderEngine, flush()).WillOnce(Return(ByMove(base::unique_fd(fd)))); + + mSurface.finishBuffer(); + + EXPECT_EQ(fd, mSurface.mutableBufferReadyForTest().release()); +} + +TEST_F(RenderSurfaceTest, finishBufferFlushesAndFinishesRenderEngine) { + EXPECT_CALL(mRenderEngine, flush()).WillOnce(Return(ByMove(base::unique_fd(-2)))); + EXPECT_CALL(mRenderEngine, finish()).Times(1); + + mSurface.finishBuffer(); + + EXPECT_EQ(-2, mSurface.mutableBufferReadyForTest().release()); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::setViewportAndProjection() + */ + +TEST_F(RenderSurfaceTest, setViewportAndProjectionAppliesChang) { + mSurface.setSizeForTest(ui::Size(100, 200)); + + EXPECT_CALL(mRenderEngine, + setViewportAndProjection(100, 200, Rect(100, 200), ui::Transform::ROT_0)) + .Times(1); + + mSurface.setViewportAndProjection(); +} + +/* ------------------------------------------------------------------------ + * RenderSurface::flip() + */ + +TEST_F(RenderSurfaceTest, flipForwardsSignal) { + mSurface.setPageFlipCountForTest(500); + + mSurface.flip(); + + EXPECT_EQ(501, mSurface.getPageFlipCount()); +} + +} // namespace +} // namespace android::compositionengine diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 80004a10be..08e5db92d3 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -34,6 +34,8 @@ #include <compositionengine/Display.h> #include <compositionengine/DisplayCreationArgs.h> #include <compositionengine/DisplaySurface.h> +#include <compositionengine/RenderSurface.h> +#include <compositionengine/RenderSurfaceCreationArgs.h> #include <compositionengine/impl/OutputCompositionState.h> #include <configstore/Utils.h> #include <cutils/properties.h> @@ -230,10 +232,6 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay( compositionengine::DisplayCreationArgs{args.isSecure, args.isVirtual, args.displayId})}, - mNativeWindow(args.nativeWindow), - mGraphicBuffer(nullptr), - mDisplaySurface(args.displaySurface), - mPageFlipCount(0), mIsVirtual(args.isVirtual), mOrientation(), mActiveConfig(0), @@ -244,14 +242,20 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mHasDolbyVision(false), mSupportedPerFrameMetadata(args.supportedPerFrameMetadata), mIsPrimary(args.isPrimary) { + mCompositionDisplay->createRenderSurface( + compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth( + args.nativeWindow.get()), + ANativeWindow_getHeight( + args.nativeWindow.get()), + args.nativeWindow, args.displaySurface}); + if (!mCompositionDisplay->isValid()) { ALOGE("Composition Display did not validate!"); } - populateColorModes(args.hwcColorModes); + mCompositionDisplay->getRenderSurface()->initialize(); - ALOGE_IF(!mNativeWindow, "No native window was set for display"); - ALOGE_IF(!mDisplaySurface, "No display surface was set for display"); + populateColorModes(args.hwcColorModes); std::vector<Hdr> types = args.hdrCapabilities.getSupportedHdrTypes(); for (Hdr hdrType : types) { @@ -293,18 +297,6 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) } mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance); - ANativeWindow* const window = mNativeWindow.get(); - - int status = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status); - status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); - ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status); - status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER); - ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status); - - mCompositionDisplay->setBounds( - Rect(ANativeWindow_getWidth(window), ANativeWindow_getHeight(window))); - setPowerMode(args.initialPowerMode); // initialize the display orientation transform. @@ -334,151 +326,7 @@ void DisplayDevice::setDisplayName(const std::string& displayName) { } uint32_t DisplayDevice::getPageFlipCount() const { - return mPageFlipCount; -} - -void DisplayDevice::flip() const -{ - mPageFlipCount++; -} - -status_t DisplayDevice::beginFrame(bool mustRecompose) const { - return mDisplaySurface->beginFrame(mustRecompose); -} - -status_t DisplayDevice::prepareFrame(HWComposer& hwc, - std::vector<CompositionInfo>& compositionData) { - const auto id = getId(); - if (id) { - status_t error = hwc.prepare(id.value(), compositionData); - if (error != NO_ERROR) { - return error; - } - } - - compositionengine::DisplaySurface::CompositionType compositionType; - bool hasClient = hwc.hasClientComposition(id); - bool hasDevice = hwc.hasDeviceComposition(id); - if (hasClient && hasDevice) { - compositionType = compositionengine::DisplaySurface::COMPOSITION_MIXED; - } else if (hasClient) { - compositionType = compositionengine::DisplaySurface::COMPOSITION_GLES; - } else if (hasDevice) { - compositionType = compositionengine::DisplaySurface::COMPOSITION_HWC; - } else { - // Nothing to do -- when turning the screen off we get a frame like - // this. Call it a HWC frame since we won't be doing any GLES work but - // will do a prepare/set cycle. - compositionType = compositionengine::DisplaySurface::COMPOSITION_HWC; - } - return mDisplaySurface->prepareFrame(compositionType); -} - -void DisplayDevice::setProtected(bool useProtected) { - uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER; - if (useProtected) { - usageFlags |= GRALLOC_USAGE_PROTECTED; - } - const int status = native_window_set_usage(mNativeWindow.get(), usageFlags); - ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status); -} - -sp<GraphicBuffer> DisplayDevice::dequeueBuffer() { - int fd; - ANativeWindowBuffer* buffer; - - status_t res = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd); - - if (res != NO_ERROR) { - ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d", - getDisplayName().c_str(), res); - // Return fast here as we can't do much more - any rendering we do - // now will just be wrong. - return mGraphicBuffer; - } - - ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", - mGraphicBuffer->getNativeBuffer()->handle); - mGraphicBuffer = GraphicBuffer::from(buffer); - - // Block until the buffer is ready - // TODO(alecmouri): it's perhaps more appropriate to block renderengine so - // that the gl driver can block instead. - if (fd >= 0) { - sync_wait(fd, -1); - close(fd); - } - - return mGraphicBuffer; -} - -void DisplayDevice::queueBuffer(HWComposer& hwc) { - const auto id = getId(); - if (hwc.hasClientComposition(id) || hwc.hasFlipClientTargetRequest(id)) { - // hasFlipClientTargetRequest could return true even if we haven't - // dequeued a buffer before. Try dequeueing one if we don't have a - // buffer ready. - if (mGraphicBuffer == nullptr) { - ALOGI("Attempting to queue a client composited buffer without one " - "previously dequeued for display [%s]. Attempting to dequeue " - "a scratch buffer now", - mDisplayName.c_str()); - // We shouldn't deadlock here, since mGraphicBuffer == nullptr only - // after a successful call to queueBuffer, or if dequeueBuffer has - // never been called. - dequeueBuffer(); - } - - if (mGraphicBuffer == nullptr) { - ALOGE("No buffer is ready for display [%s]", mDisplayName.c_str()); - } else { - status_t res = mNativeWindow->queueBuffer(mNativeWindow.get(), - mGraphicBuffer->getNativeBuffer(), - dup(mBufferReady)); - if (res != NO_ERROR) { - ALOGE("Error when queueing buffer for display [%s]: %d", mDisplayName.c_str(), res); - // We risk blocking on dequeueBuffer if the primary display failed - // to queue up its buffer, so crash here. - if (isPrimary()) { - LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", res); - } else { - mNativeWindow->cancelBuffer(mNativeWindow.get(), - mGraphicBuffer->getNativeBuffer(), - dup(mBufferReady)); - } - } - - mBufferReady.reset(); - mGraphicBuffer = nullptr; - } - } - - status_t result = mDisplaySurface->advanceFrame(); - if (result != NO_ERROR) { - ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplayName.c_str(), result); - } -} - -void DisplayDevice::onPresentDisplayCompleted() { - mDisplaySurface->onFrameCommitted(); -} - -void DisplayDevice::setViewportAndProjection() const { - size_t w = getWidth(); - size_t h = getHeight(); - Rect sourceCrop(0, 0, w, h); - mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, ui::Transform::ROT_0); -} - -void DisplayDevice::finishBuffer() { - mBufferReady = mFlinger->getRenderEngine().flush(); - if (mBufferReady.get() < 0) { - mFlinger->getRenderEngine().finish(); - } -} - -const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const { - return mDisplaySurface->getClientTargetAcquireFence(); + return mCompositionDisplay->getRenderSurface()->getPageFlipCount(); } // ---------------------------------------------------------------------------- @@ -524,11 +372,6 @@ int DisplayDevice::getActiveConfig() const { // ---------------------------------------------------------------------------- -void DisplayDevice::setCompositionDataSpace(ui::Dataspace dataspace) { - ANativeWindow* const window = mNativeWindow.get(); - native_window_set_buffers_data_space(window, static_cast<android_dataspace>(dataspace)); -} - ui::Dataspace DisplayDevice::getCompositionDataSpace() const { return mCompositionDisplay->getState().dataspace; } @@ -566,8 +409,7 @@ status_t DisplayDevice::orientationToTransfrom(int orientation, int w, int h, ui } void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) { - mDisplaySurface->resizeBuffers(newWidth, newHeight); - mCompositionDisplay->setBounds(Rect(newWidth, newHeight)); + mCompositionDisplay->setBounds(ui::Size(newWidth, newHeight)); } void DisplayDevice::setProjection(int orientation, @@ -665,26 +507,16 @@ std::string DisplayDevice::getDebugName() const { } void DisplayDevice::dump(std::string& result) const { - ANativeWindow* const window = mNativeWindow.get(); StringAppendF(&result, "+ %s\n", getDebugName().c_str()); result.append(" "); - StringAppendF(&result, "ANativeWindow=%p (format %d), ", window, - ANativeWindow_getFormat(window)); - StringAppendF(&result, "flips=%u, ", getPageFlipCount()); StringAppendF(&result, "powerMode=%d, ", mPowerMode); StringAppendF(&result, "activeConfig=%d, ", mActiveConfig); StringAppendF(&result, "numLayers=%zu\n", mVisibleLayersSortedByZ.size()); + StringAppendF(&result, "wideColorGamut=%d, ", mHasWideColorGamut); + StringAppendF(&result, "hdr10plus=%d\n", mHasHdr10Plus); + StringAppendF(&result, "hdr10=%d\n", mHasHdr10); getCompositionDisplay()->dump(result); - auto const surface = static_cast<Surface*>(window); - ui::Dataspace dataspace = surface->getBuffersDataSpace(); - StringAppendF(&result, " wideColorGamut=%d, hdr10plus =%d, hdr10=%d, dataspace: %s (%d)\n", - mHasWideColorGamut, mHasHdr10Plus, mHasHdr10, - dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace); - - String8 surfaceDump; - mDisplaySurface->dumpAsString(surfaceDump); - result.append(surfaceDump.string(), surfaceDump.size()); } // Map dataspace/intent to the best matched dataspace/colorMode/renderIntent diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index c606659126..941d61c327 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -82,10 +82,6 @@ public: // secure surfaces. bool isSecure() const; - // Flip the front and back buffers if the back buffer is "dirty". Might - // be instantaneous, might involve copying the frame buffer around. - void flip() const; - int getWidth() const; int getHeight() const; int getInstallOrientation() const { return mDisplayInstallOrientation; } @@ -116,11 +112,6 @@ public: int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; } - // We pass in mustRecompose so we can keep VirtualDisplaySurface's state - // machine happy without actually queueing a buffer if nothing has changed - status_t beginFrame(bool mustRecompose) const; - status_t prepareFrame(HWComposer& hwc, std::vector<CompositionInfo>& compositionInfo); - bool hasWideColorGamut() const { return mHasWideColorGamut; } // Whether h/w composer has native support for specific HDR type. bool hasHDR10PlusSupport() const { return mHasHdr10Plus; } @@ -147,30 +138,12 @@ public: ui::Dataspace* outDataspace, ui::ColorMode* outMode, ui::RenderIntent* outIntent) const; - void setProtected(bool useProtected); - // Queues the drawn buffer for consumption by HWC. - void queueBuffer(HWComposer& hwc); - // Allocates a buffer as scratch space for GPU composition - sp<GraphicBuffer> dequeueBuffer(); - - // called after h/w composer has completed its set() call - void onPresentDisplayCompleted(); - const Rect& getBounds() const; const Rect& bounds() const { return getBounds(); } void setDisplayName(const std::string& displayName); const std::string& getDisplayName() const { return mDisplayName; } - // Acquires a new buffer for GPU composition. - void readyNewBuffer(); - // Marks the current buffer has finished, so that it can be presented and - // swapped out. - void finishBuffer(); - void setViewportAndProjection() const; - - const sp<Fence>& getClientTargetAcquireFence() const; - /* ------------------------------------------------------------------------ * Display power mode management. */ @@ -178,7 +151,6 @@ public: void setPowerMode(int mode); bool isPoweredOn() const; - void setCompositionDataSpace(ui::Dataspace dataspace); ui::Dataspace getCompositionDataSpace() const; /* ------------------------------------------------------------------------ @@ -208,18 +180,7 @@ private: const int mDisplayInstallOrientation; const std::shared_ptr<compositionengine::Display> mCompositionDisplay; - // ANativeWindow this display is rendering into - sp<ANativeWindow> mNativeWindow; - // Current buffer that this display can render to. - sp<GraphicBuffer> mGraphicBuffer; - sp<compositionengine::DisplaySurface> mDisplaySurface; - // File descriptor indicating that mGraphicBuffer is ready for display, i.e. - // that drawing to the buffer is now complete. - base::unique_fd mBufferReady; - - mutable uint32_t mPageFlipCount; - std::string mDisplayName; - + std::string mDisplayName; const bool mIsVirtual; /* diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fb15b249f6..89129e9218 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -37,6 +37,7 @@ #include <compositionengine/CompositionEngine.h> #include <compositionengine/Display.h> +#include <compositionengine/RenderSurface.h> #include <compositionengine/impl/OutputCompositionState.h> #include <dvr/vr_flinger.h> #include <gui/BufferQueue.h> @@ -1042,7 +1043,6 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col ALOGW("Attempt to set active color mode %s (%d) for virtual display", decodeColorMode(mode).c_str(), mode); } else { - display->setCompositionDataSpace(Dataspace::UNKNOWN); display->getCompositionDisplay()->setColorMode(mode, Dataspace::UNKNOWN, RenderIntent::COLORIMETRIC); } @@ -1760,7 +1760,6 @@ void SurfaceFlinger::calculateWorkingSet() { Dataspace dataSpace; RenderIntent renderIntent; pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent); - displayDevice->setCompositionDataSpace(dataSpace); display->setColorMode(colorMode, dataSpace, renderIntent); } } @@ -1805,7 +1804,7 @@ void SurfaceFlinger::doDebugFlashRegions(const sp<DisplayDevice>& displayDevice, auto& engine(getRenderEngine()); engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1); - displayDevice->queueBuffer(getHwComposer()); + display->getRenderSurface()->queueBuffer(); } } @@ -1989,7 +1988,9 @@ void SurfaceFlinger::postComposition() if (displayDevice && getHwComposer().hasClientComposition(displayDevice->getId())) { glCompositionDoneFenceTime = - std::make_shared<FenceTime>(displayDevice->getClientTargetAcquireFence()); + std::make_shared<FenceTime>(displayDevice->getCompositionDisplay() + ->getRenderSurface() + ->getClientTargetAcquireFence()); getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; @@ -2340,7 +2341,7 @@ void SurfaceFlinger::beginFrame(const sp<DisplayDevice>& displayDevice) { displayDevice->getDebugName().c_str(), flagPrefix[dirty], flagPrefix[empty], flagPrefix[wasEmpty]); - displayDevice->beginFrame(mustRecompose); + display->getRenderSurface()->beginFrame(mustRecompose); if (mustRecompose) { display->editState().lastCompositionHadVisibleLayers = !empty; @@ -2355,9 +2356,8 @@ void SurfaceFlinger::prepareFrame(const sp<DisplayDevice>& displayDevice) { return; } - status_t result = - displayDevice->prepareFrame(getHwComposer(), - getBE().mCompositionInfo[displayDevice->getDisplayToken()]); + status_t result = display->getRenderSurface()->prepareFrame( + getBE().mCompositionInfo[displayDevice->getDisplayToken()]); ALOGE_IF(result != NO_ERROR, "prepareFrame failed for %s: %d (%s)", displayDevice->getDebugName().c_str(), result, strerror(-result)); } @@ -2377,7 +2377,7 @@ void SurfaceFlinger::doComposition(const sp<DisplayDevice>& displayDevice, bool doDisplayComposition(displayDevice, dirtyRegion); display->editState().dirtyRegion.clear(); - displayDevice->flip(); + display->getRenderSurface()->flip(); } postFramebuffer(displayDevice); } @@ -2408,7 +2408,7 @@ void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& displayDevice) { if (displayId) { getHwComposer().presentAndGetReleaseFences(*displayId); } - displayDevice->onPresentDisplayCompleted(); + display->getRenderSurface()->onPresentDisplayCompleted(); for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { sp<Fence> releaseFence = Fence::NO_FENCE; @@ -2426,8 +2426,9 @@ void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& displayDevice) { // client target acquire fence when it is available, even though // this is suboptimal. if (layer->getCompositionType(displayId) == HWC2::Composition::Client) { - releaseFence = Fence::merge("LayerRelease", releaseFence, - displayDevice->getClientTargetAcquireFence()); + releaseFence = + Fence::merge("LayerRelease", releaseFence, + display->getRenderSurface()->getClientTargetAcquireFence()); } layer->getBE().onLayerDisplayed(releaseFence); @@ -2581,7 +2582,6 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( defaultColorMode = ColorMode::SRGB; defaultDataSpace = Dataspace::V0_SRGB; } - display->setCompositionDataSpace(defaultDataSpace); display->getCompositionDisplay()->setColorMode(defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); if (!state.isVirtual()) { @@ -3256,7 +3256,7 @@ void SurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& displayDevice if (!doComposeSurfaces(displayDevice)) return; // swap buffers (presentation) - displayDevice->queueBuffer(getHwComposer()); + display->getRenderSurface()->queueBuffer(); } bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice) { @@ -3280,7 +3280,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice) { if (hasClientComposition) { ALOGV("hasClientComposition"); - sp<GraphicBuffer> buf = displayDevice->dequeueBuffer(); + sp<GraphicBuffer> buf = display->getRenderSurface()->dequeueBuffer(); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " @@ -3319,7 +3319,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice) { colorMatrix = mDrawingState.colorMatrix; } - displayDevice->setViewportAndProjection(); + display->getRenderSurface()->setViewportAndProjection(); // Never touch the framebuffer if we don't have any framebuffer layers if (hasDeviceComposition) { @@ -3413,7 +3413,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice) { if (hasClientComposition) { getRenderEngine().setColorTransform(mat4()); getRenderEngine().disableScissor(); - displayDevice->finishBuffer(); + display->getRenderSurface()->finishBuffer(); // Clear out error flags here so that we don't wait until next // composition to log. getRenderEngine().checkErrors(); |