SF: Separate out render surface code

This creates a new class for the purpose of holding all the
functionality related to flipping the output display surface.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I108ccb75f3cd6aa1204487b0aed7c67d9fe1b85f
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index d089bf6..e8b038b 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -68,6 +68,7 @@
         "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 0000000..d2996d1
--- /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 e9da087..1768805 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 @@
         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 @@
         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 0000000..c39d8af
--- /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 0000000..fd2b21b
--- /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 665469e..373fa4f 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -71,3 +71,10 @@
     ],
     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 0000000..69e1ac8
--- /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