OSDN Git Service

test-hwc2: set layer buffer
authorMarissa Wall <marissaw@google.com>
Thu, 15 Dec 2016 20:34:06 +0000 (12:34 -0800)
committerMarissa Wall <marissaw@google.com>
Wed, 8 Mar 2017 21:36:36 +0000 (13:36 -0800)
Test: Add "#define HAVE_NO_SURFACE_FLINGER" to
          frameworks/native/libs/gui/BufferQueueCore.cpp.
      Recompile and flash.
      Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2.
      Push test-hwc2 to device.
      Run "adb root && adb shell stop".
      Run test case. Ex: "./test-hwc2"

Change-Id: Ie42d1fd4c2d0248c4a3ecf09a9b5871d501f6172

services/surfaceflinger/tests/hwc2/Android.mk
services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp [new file with mode: 0644]
services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h [new file with mode: 0644]
services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h

index 18437a9..79c3e92 100644 (file)
@@ -24,13 +24,27 @@ LOCAL_CFLAGS += \
     -g \
     -Wall -Wextra \
     -Werror \
-    -fno-builtin
-LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware liblog
-LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc
+    -fno-builtin \
+    -DEGL_EGLEXT_PROTOTYPES \
+    -DGL_GLEXT_PROTOTYPES
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libhardware \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libgui \
+    liblog
+LOCAL_STATIC_LIBRARIES := \
+    libbase \
+    libadf \
+    libadfhwc
 LOCAL_SRC_FILES := \
     Hwc2Test.cpp \
     Hwc2TestProperties.cpp \
     Hwc2TestLayer.cpp \
-    Hwc2TestLayers.cpp
+    Hwc2TestLayers.cpp \
+    Hwc2TestBuffer.cpp
 
 include $(BUILD_NATIVE_TEST)
index f441089..931cfc6 100644 (file)
@@ -18,6 +18,7 @@
 #include <unordered_set>
 #include <gtest/gtest.h>
 #include <dlfcn.h>
+#include <android-base/unique_fd.h>
 #include <hardware/hardware.h>
 
 #define HWC2_INCLUDE_STRINGIFICATION
@@ -391,6 +392,23 @@ public:
         }
     }
 
+    void setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
+            buffer_handle_t buffer, int32_t acquireFence,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BUFFER>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_BUFFER));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                buffer, acquireFence));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer buffer";
+        }
+    }
+
     void setLayerColor(hwc2_display_t display, hwc2_layer_t layer,
             hwc_color_t color, hwc2_error_t* outErr = nullptr)
     {
@@ -665,19 +683,19 @@ protected:
      * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */
     using TestLayerPropertyFunction = void (*)(Hwc2Test* test,
             hwc2_display_t display, hwc2_layer_t layer,
-            const Hwc2TestLayer& testLayer, hwc2_error_t* outErr);
+            Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
 
     /* Calls a set property function from Hwc2Test to set property values from
      * Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */
     using TestLayerPropertiesFunction = void (*)(Hwc2Test* test,
             hwc2_display_t display, hwc2_layer_t layer,
-            const Hwc2TestLayers& testLayers);
+            Hwc2TestLayers* testLayers);
 
     /* Calls a set property function from Hwc2Test to set a bad property value
      * on hwc2_layer_t on hwc2_display_t */
     using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test,
             hwc2_display_t display, hwc2_layer_t layer,
-            const Hwc2TestLayer& testLayer, hwc2_error_t* outErr);
+            Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
 
     /* Calls a set property function from Hwc2Test to set a bad property value
      * on hwc2_layer_t on hwc2_display_t */
@@ -711,7 +729,7 @@ protected:
                     ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
 
                     ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
-                            testLayer, nullptr));
+                            &testLayer, nullptr));
 
                     ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
                 } while (advance(&testLayer));
@@ -743,7 +761,7 @@ protected:
 
                 do {
                     ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
-                            testLayer, nullptr));
+                            &testLayer, nullptr));
                 } while (advance(&testLayer));
 
                 ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
@@ -776,7 +794,7 @@ protected:
 
                 for (auto layer : layers) {
                     EXPECT_NO_FATAL_FAILURE(function(this, display, layer,
-                            testLayers));
+                            &testLayers));
                 }
 
                 ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
@@ -810,19 +828,19 @@ protected:
                 Hwc2TestLayer testLayer(coverage, displayArea);
 
                 ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
-                        testLayer, &err));
+                        &testLayer, &err));
                 EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
 
                 ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
 
                 ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1,
-                        testLayer, &err));
+                        &testLayer, &err));
                 EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
 
                 ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
 
                 ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
-                        testLayer, &err));
+                        &testLayer, &err));
                 EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
             }
         }
@@ -918,29 +936,50 @@ void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
 }
 
 void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
-            testLayer.getBlendMode(), outErr));
+            testLayer->getBlendMode(), outErr));
+}
+
+void setBuffer(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    buffer_handle_t handle;
+    android::base::unique_fd acquireFence;
+    hwc2_composition_t composition = testLayer->getComposition();
+
+    if (composition == HWC2_COMPOSITION_CLIENT
+            || composition == HWC2_COMPOSITION_SOLID_COLOR
+            || composition == HWC2_COMPOSITION_SIDEBAND)
+        return;
+
+    if (testLayer->getBuffer(&handle, &acquireFence) < 0)
+        return;
+
+    ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
+            composition));
+    EXPECT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
+            handle, acquireFence, outErr));
 }
 
 void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
             layer, HWC2_COMPOSITION_SOLID_COLOR));
     ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
-            layer, testLayer.getPlaneAlpha()));
+            layer, testLayer->getPlaneAlpha()));
     ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
-            layer, testLayer.getBlendMode()));
+            layer, testLayer->getBlendMode()));
     EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
-            testLayer.getColor(), outErr));
+            testLayer->getColor(), outErr));
 }
 
 void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
-    hwc2_composition_t composition = testLayer.getComposition();
+    hwc2_composition_t composition = testLayer->getComposition();
     hwc2_error_t err = HWC2_ERROR_NONE;
 
     ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
@@ -959,65 +998,65 @@ void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
 }
 
 void setCursorPosition(Hwc2Test* test, hwc2_display_t display,
-        hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
             layer, HWC2_COMPOSITION_CURSOR));
 
-    const hwc_rect_t cursorPosition = testLayer.getCursorPosition();
+    const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
     EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
             cursorPosition.left, cursorPosition.top, outErr));
 }
 
 void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer,
-            testLayer.getDataspace(), outErr));
+            testLayer->getDataspace(), outErr));
 }
 
 void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer,
-            testLayer.getDisplayFrame(), outErr));
+            testLayer->getDisplayFrame(), outErr));
 }
 
 void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t *outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t *outErr)
 {
     ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
-            testLayer.getBlendMode()));
+            testLayer->getBlendMode()));
     EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer,
-            testLayer.getPlaneAlpha(), outErr));
+            testLayer->getPlaneAlpha(), outErr));
 }
 
 void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer,
-            testLayer.getSourceCrop(), outErr));
+            testLayer->getSourceCrop(), outErr));
 }
 
 void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer,
-            testLayer.getSurfaceDamage(), outErr));
+            testLayer->getSurfaceDamage(), outErr));
 }
 
 void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer,
-            testLayer.getTransform(), outErr));
+            testLayer->getTransform(), outErr));
 }
 
 void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
 {
     EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
-            testLayer.getZOrder(), outErr));
+            testLayer->getZOrder(), outErr));
 }
 
 bool advanceBlendMode(Hwc2TestLayer* testLayer)
@@ -1025,6 +1064,13 @@ bool advanceBlendMode(Hwc2TestLayer* testLayer)
     return testLayer->advanceBlendMode();
 }
 
+bool advanceBuffer(Hwc2TestLayer* testLayer)
+{
+    if (testLayer->advanceComposition())
+        return true;
+    return testLayer->advanceBufferArea();
+}
+
 bool advanceColor(Hwc2TestLayer* testLayer)
 {
     /* Color depends on blend mode so advance blend mode last so color is not
@@ -1948,9 +1994,9 @@ TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset)
 {
     ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
             [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-                    const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) {
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
 
-                const hwc_rect_t cursorPosition = testLayer.getCursorPosition();
+                const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
                 EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
                         cursorPosition.left, cursorPosition.top, outErr));
             },
@@ -1978,9 +2024,9 @@ TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer)
 {
     ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
             [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
-                    const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) {
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
 
-                const hwc_rect_t cursorPosition = testLayer.getCursorPosition();
+                const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
                 EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display,
                         badLayer, cursorPosition.left, cursorPosition.top,
                         outErr));
@@ -2022,6 +2068,59 @@ TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter)
     ));
 }
 
+/* TESTCASE: Tests that the HWC2 can set the buffer of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setBuffer, advanceBuffer));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the buffer of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setBuffer, advanceBuffer));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the buffer of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+                buffer_handle_t handle = nullptr;
+                android::base::unique_fd acquireFence;
+
+                /* If there is not available buffer for the given buffer
+                 * properties, it should not fail this test case */
+                if (testLayer->getBuffer(&handle, &acquireFence) == 0) {
+                    *outErr = HWC2_ERROR_BAD_LAYER;
+                    return;
+                }
+
+                ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, badLayer,
+                        handle, acquireFence, outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set an invalid buffer for a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    hwc2_error_t* outErr) {
+
+                buffer_handle_t handle = nullptr;
+                int32_t acquireFence = -1;
+
+                ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
+                        handle, acquireFence, outErr));
+            }
+    ));
+}
+
 /* TESTCASE: Tests that the HWC2 can set the color of a layer. */
 TEST_F(Hwc2Test, SET_LAYER_COLOR)
 {
@@ -2042,10 +2141,10 @@ TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset)
 {
     ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic,
             [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-                    const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) {
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
 
                 EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
-                        testLayer.getColor(), outErr));
+                        testLayer->getColor(), outErr));
             },
 
             advanceColor));
@@ -2056,10 +2155,10 @@ TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer)
 {
     ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
             [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
-                    const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) {
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
 
                 EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer,
-                        testLayer.getColor(), outErr));
+                        testLayer->getColor(), outErr));
             }
     ));
 }
@@ -2125,10 +2224,10 @@ TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer)
 {
     ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
             [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
-                    const Hwc2TestLayer& testLayer, hwc2_error_t *outErr) {
+                    Hwc2TestLayer* testLayer, hwc2_error_t *outErr) {
 
                     EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
-                            badLayer, testLayer.getPlaneAlpha(), outErr));
+                            badLayer, testLayer->getPlaneAlpha(), outErr));
             }
     ));
 }
@@ -2201,10 +2300,10 @@ TEST_F(Hwc2Test, SET_LAYER_Z_ORDER)
 {
     ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10,
             [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
-                    const Hwc2TestLayers& testLayers) {
+                    Hwc2TestLayers* testLayers) {
 
                 EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
-                        testLayers.getZOrder(layer)));
+                        testLayers->getZOrder(layer)));
             }
     ));
 }
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
new file mode 100644 (file)
index 0000000..c9d8f4f
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2016 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 <mutex>
+#include <array>
+#include <sstream>
+#include <algorithm>
+
+#include <gui/Surface.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/GraphicBufferAlloc.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/vec4.h>
+
+#include <GLES3/gl3.h>
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestLayers.h"
+
+using namespace android;
+
+/* Returns a fence from egl */
+typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
+
+/* Returns fence to fence generator */
+static void setFence(int32_t fence, void* fenceGenerator);
+
+
+/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
+ * away. The fences are sent to the requester via a callback */
+class Hwc2TestSurfaceManager {
+public:
+    /* Listens for a new frame, detaches the buffer and returns the fence
+     * through saved callback. */
+    class BufferListener : public ConsumerBase::FrameAvailableListener {
+    public:
+        BufferListener(sp<IGraphicBufferConsumer> consumer,
+                FenceCallback callback, void* callbackArgs)
+            : mConsumer(consumer),
+              mCallback(callback),
+              mCallbackArgs(callbackArgs) { }
+
+        void onFrameAvailable(const BufferItem& /*item*/)
+        {
+            BufferItem item;
+
+            if (mConsumer->acquireBuffer(&item, 0))
+                return;
+            if (mConsumer->detachBuffer(item.mSlot))
+                return;
+
+            mCallback(item.mFence->dup(), mCallbackArgs);
+        }
+
+    private:
+        sp<IGraphicBufferConsumer> mConsumer;
+        FenceCallback mCallback;
+        void* mCallbackArgs;
+    };
+
+    /* Creates a buffer listener that waits on a new frame from the buffer
+     * queue. */
+    void initialize(const Area& bufferArea, android_pixel_format_t format,
+            FenceCallback callback, void* callbackArgs)
+    {
+        sp<IGraphicBufferProducer> producer;
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+
+        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
+        consumer->setDefaultBufferFormat(format);
+
+        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
+
+        mListener = new BufferListener(consumer, callback, callbackArgs);
+        mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+        mSurface = new Surface(producer, true);
+    }
+
+    /* Used by Egl manager. The surface is never displayed. */
+    sp<Surface> getSurface() const
+    {
+        return mSurface;
+    }
+
+private:
+    sp<BufferItemConsumer> mBufferItemConsumer;
+    sp<BufferListener> mListener;
+    /* Used by Egl manager. The surface is never displayed */
+    sp<Surface> mSurface;
+};
+
+
+/* Used to generate valid fences. It is not possible to create a dummy sync
+ * fence for testing. Egl can generate buffers along with a valid fence.
+ * The buffer cannot be guaranteed to be the same format across all devices so
+ * a CPU filled buffer is used instead. The Egl fence is used along with the
+ * CPU filled buffer. */
+class Hwc2TestEglManager {
+public:
+    Hwc2TestEglManager()
+        : mEglDisplay(EGL_NO_DISPLAY),
+          mEglSurface(EGL_NO_SURFACE),
+          mEglContext(EGL_NO_CONTEXT) { }
+
+    ~Hwc2TestEglManager()
+    {
+        cleanup();
+    }
+
+    int initialize(sp<Surface> surface)
+    {
+        mSurface = surface;
+
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+        EGLint major;
+        EGLint minor;
+        if (!eglInitialize(mEglDisplay, &major, &minor)) {
+            ALOGW("Could not initialize EGL");
+            return false;
+        }
+
+        /* We're going to use a 1x1 pbuffer surface later on
+         * The configuration distance doesn't really matter for what we're
+         * trying to do */
+        EGLint configAttrs[] = {
+                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                EGL_RED_SIZE, 8,
+                EGL_GREEN_SIZE, 8,
+                EGL_BLUE_SIZE, 8,
+                EGL_ALPHA_SIZE, 0,
+                EGL_DEPTH_SIZE, 24,
+                EGL_STENCIL_SIZE, 0,
+                EGL_NONE
+        };
+
+        EGLConfig configs[1];
+        EGLint configCnt;
+        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
+                &configCnt)) {
+            ALOGW("Could not select EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        if (configCnt <= 0) {
+            ALOGW("Could not find EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        /* These objects are initialized below but the default "null" values are
+         * used to cleanup properly at any point in the initialization sequence */
+        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
+                attrs);
+        if (mEglContext == EGL_NO_CONTEXT) {
+            ALOGW("Could not create EGL context");
+            cleanup();
+            return false;
+        }
+
+        EGLint surfaceAttrs[] = { EGL_NONE };
+        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
+                mSurface.get(), surfaceAttrs);
+        if (mEglSurface == EGL_NO_SURFACE) {
+            ALOGW("Could not create EGL surface");
+            cleanup();
+            return false;
+        }
+
+        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            ALOGW("Could not change current EGL context");
+            cleanup();
+            return false;
+        }
+
+        return true;
+    }
+
+    void makeCurrent() const
+    {
+        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
+    }
+
+    void present() const
+    {
+        eglSwapBuffers(mEglDisplay, mEglSurface);
+    }
+
+private:
+    void cleanup()
+    {
+        if (mEglDisplay == EGL_NO_DISPLAY)
+            return;
+        if (mEglSurface != EGL_NO_SURFACE)
+            eglDestroySurface(mEglDisplay, mEglSurface);
+        if (mEglContext != EGL_NO_CONTEXT)
+            eglDestroyContext(mEglDisplay, mEglContext);
+
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                EGL_NO_CONTEXT);
+        eglReleaseThread();
+        eglTerminate(mEglDisplay);
+    }
+
+    sp<Surface> mSurface;
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
+};
+
+
+static const std::array<vec2, 4> triangles = {{
+    {  1.0f,  1.0f },
+    { -1.0f,  1.0f },
+    {  1.0f, -1.0f },
+    { -1.0f, -1.0f },
+}};
+
+class Hwc2TestFenceGenerator {
+public:
+
+    Hwc2TestFenceGenerator()
+    {
+        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
+                setFence, this);
+
+        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
+            return;
+
+        mEglManager.makeCurrent();
+
+        glClearColor(0.0, 0.0, 0.0, 1.0);
+        glEnableVertexAttribArray(0);
+    }
+
+    ~Hwc2TestFenceGenerator()
+    {
+        if (mFence >= 0)
+            close(mFence);
+        mFence = -1;
+
+        mEglManager.makeCurrent();
+    }
+
+    /* It is not possible to simply generate a fence. The easiest way is to
+     * generate a buffer using egl and use the associated fence. The buffer
+     * cannot be guaranteed to be a certain format across all devices using this
+     * method. Instead the buffer is generated using the CPU */
+    int32_t get()
+    {
+        if (mFence >= 0) {
+            return dup(mFence);
+        }
+
+        std::unique_lock<std::mutex> lock(mMutex);
+
+        /* If the pending is still set to false and times out, we cannot recover.
+         * Set an error and return */
+        while (mPending != false) {
+            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
+                return -ETIME;
+        }
+
+        /* Generate a fence. The fence will be returned through the setFence
+         * callback */
+        mEglManager.makeCurrent();
+
+        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        mEglManager.present();
+
+        /* Wait for the setFence callback */
+        while (mPending != true) {
+            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
+                return -ETIME;
+        }
+
+        mPending = false;
+
+        return dup(mFence);
+    }
+
+    /* Callback that sets the fence */
+    void set(int32_t fence)
+    {
+        mFence = fence;
+        mPending = true;
+
+        mCv.notify_all();
+    }
+
+private:
+
+    Hwc2TestSurfaceManager mSurfaceManager;
+    Hwc2TestEglManager mEglManager;
+
+    std::mutex mMutex;
+    std::condition_variable mCv;
+
+    int32_t mFence = -1;
+    bool mPending = false;
+};
+
+
+static void setFence(int32_t fence, void* fenceGenerator)
+{
+    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
+}
+
+
+Hwc2TestBuffer::Hwc2TestBuffer()
+    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
+
+Hwc2TestBuffer::~Hwc2TestBuffer() = default;
+
+/* When the buffer changes sizes, save the new size and invalidate the current
+ * buffer */
+void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
+{
+    if (mBufferArea.width == bufferArea.width
+            && mBufferArea.height == bufferArea.height)
+        return;
+
+    mBufferArea.width = bufferArea.width;
+    mBufferArea.height = bufferArea.height;
+
+    mValidBuffer = false;
+}
+
+/* Returns a valid buffer handle and fence. The handle is filled using the CPU
+ * to ensure the correct format across all devices. The fence is created using
+ * egl. */
+int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
+{
+    if (mBufferArea.width == -1 || mBufferArea.height == -1)
+        return -EINVAL;
+
+    /* If the current buffer is valid, the previous buffer can be reused.
+     * Otherwise, create new buffer */
+    if (!mValidBuffer) {
+        int ret = generateBuffer();
+        if (ret)
+            return ret;
+    }
+
+    *outFence = mFenceGenerator->get();
+    *outHandle = mHandle;
+
+    mValidBuffer = true;
+
+    return 0;
+}
+
+/* CPU fills a buffer to guarantee the correct buffer format across all
+ * devices */
+int Hwc2TestBuffer::generateBuffer()
+{
+    int ret;
+
+    /* Create new graphic buffer with correct dimensions */
+    mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(
+            mBufferArea.width, mBufferArea.height, mFormat,
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
+            "hwc2_test_buffer", &ret);
+    if (ret)
+        return ret;
+
+    /* Locks the buffer for writing */
+    uint8_t* img;
+    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+    uint32_t stride = mGraphicBuffer->getStride();
+
+    /* Iterate from the top row of the buffer to the bottom row */
+    for (int32_t y = 0; y < mBufferArea.height; y++) {
+
+        /* Will be used as R, G and B values for pixel colors */
+        uint8_t max = 255;
+        uint8_t min = 0;
+
+        /* Divide the rows into 3 sections. The first section will contain
+         * the lighest colors. The last section will contain the darkest
+         * colors. */
+        if (y < mBufferArea.height * 1.0 / 3.0) {
+            min = 255 / 2;
+        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
+            max = 255 / 2;
+        }
+
+        /* Divide the columns into 3 sections. The first section is red,
+         * the second is green and the third is blue */
+        int32_t x = 0;
+        for (; x < mBufferArea.width / 3; x++) {
+            setColor(x, y, mFormat, stride, img, max, min, min, 255);
+        }
+
+        for (; x < mBufferArea.width * 2 / 3; x++) {
+            setColor(x, y, mFormat, stride, img, min, max, min, 255);
+        }
+
+        for (; x < mBufferArea.width; x++) {
+            setColor(x, y, mFormat, stride, img, min, min, max, 255);
+        }
+    }
+
+    /* Unlock the buffer for reading */
+    mGraphicBuffer->unlock();
+
+    mHandle = mGraphicBuffer->handle;
+
+    return 0;
+}
+
+/* Sets the pixel of a buffer given the location, format, stride and color.
+ * Currently only supports RGBA_8888 */
+void Hwc2TestBuffer::setColor(int32_t x, int32_t y,
+        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
+        uint8_t g, uint8_t b, uint8_t a)
+{
+       switch (format) {
+       case HAL_PIXEL_FORMAT_RGBA_8888:
+           img[(y * stride + x) * 4 + 0] = r;
+           img[(y * stride + x) * 4 + 1] = g;
+           img[(y * stride + x) * 4 + 2] = b;
+           img[(y * stride + x) * 4 + 3] = a;
+           break;
+       default:
+           break;
+       }
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
new file mode 100644 (file)
index 0000000..721540f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_BUFFER_H
+#define _HWC2_TEST_BUFFER_H
+
+#include <android-base/unique_fd.h>
+#include <hardware/hwcomposer2.h>
+
+#include <gui/GraphicBufferAlloc.h>
+#include <ui/GraphicBuffer.h>
+
+#include "Hwc2TestProperties.h"
+
+class Hwc2TestFenceGenerator;
+
+class Hwc2TestBuffer {
+public:
+    Hwc2TestBuffer();
+    ~Hwc2TestBuffer();
+
+    void updateBufferArea(const Area& bufferArea);
+
+    int  get(buffer_handle_t* outHandle, int32_t* outFence);
+
+protected:
+    int generateBuffer();
+
+    void setColor(int32_t x, int32_t y, android_pixel_format_t format,
+            uint32_t stride, uint8_t* img, uint8_t r, uint8_t g, uint8_t b,
+            uint8_t a);
+
+    android::GraphicBufferAlloc mGraphicBufferAlloc;
+    android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+    std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
+
+    Area mBufferArea = {-1, -1};
+    const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+    bool mValidBuffer = false;
+    buffer_handle_t mHandle = nullptr;
+};
+
+#endif /* ifndef _HWC2_TEST_BUFFER_H */
index 01d48c4..fcf5768 100644 (file)
@@ -32,6 +32,7 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea,
       mTransform(coverage),
       mZOrder(zOrder)
 {
+    mBufferArea.setDependent(&mBuffer);
     mBufferArea.setDependent(&mSourceCrop);
     mBufferArea.setDependent(&mSurfaceDamage);
     mBlendMode.setDependent(&mColor);
@@ -52,6 +53,15 @@ std::string Hwc2TestLayer::dump() const
     return dmp.str();
 }
 
+int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
+        android::base::unique_fd* outAcquireFence)
+{
+    int32_t acquireFence;
+    int ret = mBuffer.get(outHandle, &acquireFence);
+    outAcquireFence->reset(acquireFence);
+    return ret;
+}
+
 void Hwc2TestLayer::reset()
 {
     for (auto property : mProperties) {
index f5b2c39..27885ab 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef _HWC2_TEST_LAYER_H
 #define _HWC2_TEST_LAYER_H
 
+#include <android-base/unique_fd.h>
+
+#include "Hwc2TestBuffer.h"
 #include "Hwc2TestProperties.h"
 
 #define HWC2_INCLUDE_STRINGIFICATION
@@ -32,6 +35,9 @@ public:
 
     std::string dump() const;
 
+    int getBuffer(buffer_handle_t* outHandle,
+            android::base::unique_fd* outAcquireFence);
+
     void reset();
 
     hwc2_blend_mode_t      getBlendMode() const;
@@ -64,6 +70,8 @@ private:
         &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform
     }};
 
+    Hwc2TestBuffer mBuffer;
+
     Hwc2TestBlendMode mBlendMode;
     Hwc2TestBufferArea mBufferArea;
     Hwc2TestColor mColor;
index 8ef3d59..bfd076f 100644 (file)
 #include <sstream>
 #include <cutils/log.h>
 
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestBuffer.h"
 #include "Hwc2TestProperties.h"
 
 Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage,
@@ -39,6 +46,14 @@ std::string Hwc2TestBufferArea::dump() const
     return dmp.str();
 }
 
+void Hwc2TestBufferArea::setDependent(Hwc2TestBuffer* buffer)
+{
+    mBuffer = buffer;
+    if (buffer) {
+        buffer->updateBufferArea(get());
+    }
+}
+
 void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop)
 {
     mSourceCrop = sourceCrop;
@@ -76,6 +91,8 @@ void Hwc2TestBufferArea::updateDependents()
 {
     const Area& curr = get();
 
+    if (mBuffer)
+        mBuffer->updateBufferArea(curr);
     if (mSourceCrop)
         mSourceCrop->updateBufferArea(curr);
     if (mSurfaceDamage)
index 6f3bd0f..048d6e9 100644 (file)
@@ -96,6 +96,7 @@ protected:
 };
 
 
+class Hwc2TestBuffer;
 class Hwc2TestSourceCrop;
 class Hwc2TestSurfaceDamage;
 
@@ -105,6 +106,7 @@ public:
 
     std::string dump() const override;
 
+    void setDependent(Hwc2TestBuffer* buffer);
     void setDependent(Hwc2TestSourceCrop* sourceCrop);
     void setDependent(Hwc2TestSurfaceDamage* surfaceDamage);
 
@@ -119,6 +121,7 @@ protected:
 
     Area mDisplayArea;
 
+    Hwc2TestBuffer* mBuffer = nullptr;
     Hwc2TestSourceCrop* mSourceCrop = nullptr;
     Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr;