Hwc2TestBuffer.cpp revision dde19448624ca514e0598f0343029c1ca4960c05
12fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers/*
22fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * Copyright (C) 2016 The Android Open Source Project
32fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *
42fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * Licensed under the Apache License, Version 2.0 (the "License");
52fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * you may not use this file except in compliance with the License.
62fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * You may obtain a copy of the License at
72fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *
82fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *      http://www.apache.org/licenses/LICENSE-2.0
92fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *
102fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * Unless required by applicable law or agreed to in writing, software
112fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * distributed under the License is distributed on an "AS IS" BASIS,
122fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * See the License for the specific language governing permissions and
142fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * limitations under the License.
152fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers */
162fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
178ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz#include <mutex>
18b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include <array>
19d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include <sstream>
202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include <algorithm>
21b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
22b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include <gui/Surface.h>
232fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers#include <gui/BufferItemConsumer.h>
242fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers#include <gui/GraphicBufferAlloc.h>
252fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
2664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers#include <ui/GraphicBuffer.h>
27ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include <math/vec4.h>
285d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
2964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers#include <GLES3/gl3.h>
3064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
31a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers#include "Hwc2TestBuffer.h"
32a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers#include "Hwc2TestLayers.h"
33a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers
34a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogersusing namespace android;
35a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers
36b74cd29802f364b4cec88f4913fa38ade26b8fabMathieu Chartier/* Returns a fence from egl */
37a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogerstypedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
38a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers
39f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi/* Returns fence to fence generator */
40f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchistatic void setFence(int32_t fence, void* fenceGenerator);
41a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers
4264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
4364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
447a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers * away. The fences are sent to the requester via a callback */
4564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogersclass Hwc2TestSurfaceManager {
4664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogerspublic:
4764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    /* Listens for a new frame, detaches the buffer and returns the fence
485d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     * through saved callback. */
495d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    class BufferListener : public ConsumerBase::FrameAvailableListener {
505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    public:
5164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        BufferListener(sp<IGraphicBufferConsumer> consumer,
52f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier                FenceCallback callback, void* callbackArgs)
53f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier            : mConsumer(consumer),
5464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers              mCallback(callback),
555d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao              mCallbackArgs(callbackArgs) { }
5664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
575d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        void onFrameAvailable(const BufferItem& /*item*/)
5864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        {
595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao            BufferItem item;
605d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
615d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao            if (mConsumer->acquireBuffer(&item, 0))
6264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                return;
6364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            if (mConsumer->detachBuffer(item.mSlot))
6464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                return;
6505f3057d6a4d23d712092ccd36a531590bff323bIan Rogers
6664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            mCallback(item.mFence->dup(), mCallbackArgs);
675d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        }
6864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
6964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    private:
7064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        sp<IGraphicBufferConsumer> mConsumer;
7164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        FenceCallback mCallback;
7264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        void* mCallbackArgs;
735d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    };
7464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
75eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    /* Creates a buffer listener that waits on a new frame from the buffer
76eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier     * queue. */
77eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    void initialize(const Area& bufferArea, android_pixel_format_t format,
78eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier            FenceCallback callback, void* callbackArgs)
7964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    {
8064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        sp<IGraphicBufferProducer> producer;
815d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers        sp<IGraphicBufferConsumer> consumer;
825d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers        BufferQueue::createBufferQueue(&producer, &consumer);
835d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers
845d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
855d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers        consumer->setDefaultBufferFormat(format);
86f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz
87f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
88f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz
8964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mListener = new BufferListener(consumer, callback, callbackArgs);
90f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz        mBufferItemConsumer->setFrameAvailableListener(mListener);
9164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
925d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        mSurface = new Surface(producer, true);
935d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    }
945d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
955d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    /* Used by Egl manager. The surface is never displayed. */
965d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    sp<Surface> getSurface() const
975d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    {
98d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm        return mSurface;
99d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm    }
1005d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers
101d8434439dc64add41cdfa69ddf96b960af9050deHans Boehmprivate:
102d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm    sp<BufferItemConsumer> mBufferItemConsumer;
1035d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    sp<BufferListener> mListener;
104f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz    /* Used by Egl manager. The surface is never displayed */
10564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    sp<Surface> mSurface;
1065d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao};
107f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz
1085d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
1095d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers/* Used to generate valid fences. It is not possible to create a dummy sync
1105d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers * fence for testing. Egl can generate buffers along with a valid fence.
1115d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers * The buffer cannot be guaranteed to be the same format across all devices so
1125d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers * a CPU filled buffer is used instead. The Egl fence is used along with the
1135d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers * CPU filled buffer. */
1144d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchiclass Hwc2TestEglManager {
1154d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchipublic:
1164d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    Hwc2TestEglManager()
1174d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi        : mEglDisplay(EGL_NO_DISPLAY),
1184d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi          mEglSurface(EGL_NO_SURFACE),
1194d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi          mEglContext(EGL_NO_CONTEXT) { }
1204d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi
1214d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    ~Hwc2TestEglManager()
1225d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    {
123b2c7ead6bb5c98282cdfbc89db8984a004bea030Mathieu Chartier        cleanup();
124b2c7ead6bb5c98282cdfbc89db8984a004bea030Mathieu Chartier    }
1255d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers
1265d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    int initialize(sp<Surface> surface)
1275d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    {
1285d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers        mSurface = surface;
12964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
13064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
13164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (mEglDisplay == EGL_NO_DISPLAY) return false;
132fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers
1335d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        EGLint major;
13464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        EGLint minor;
13564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (!eglInitialize(mEglDisplay, &major, &minor)) {
13664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            ALOGW("Could not initialize EGL");
13764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            return false;
13864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        }
13964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
140460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        /* We're going to use a 1x1 pbuffer surface later on
141460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer         * The configuration distance doesn't really matter for what we're
14264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers         * trying to do */
14364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        EGLint configAttrs[] = {
144556d637764b71563030c479bc35364a75188d559Ian Rogers                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
145556d637764b71563030c479bc35364a75188d559Ian Rogers                EGL_RED_SIZE, 8,
146556d637764b71563030c479bc35364a75188d559Ian Rogers                EGL_GREEN_SIZE, 8,
147556d637764b71563030c479bc35364a75188d559Ian Rogers                EGL_BLUE_SIZE, 8,
148556d637764b71563030c479bc35364a75188d559Ian Rogers                EGL_ALPHA_SIZE, 0,
149556d637764b71563030c479bc35364a75188d559Ian Rogers                EGL_DEPTH_SIZE, 24,
15064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                EGL_STENCIL_SIZE, 0,
151460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer                EGL_NONE
152460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        };
15364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
15464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        EGLConfig configs[1];
15564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        EGLint configCnt;
15664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
15764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                &configCnt)) {
158460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            ALOGW("Could not select EGL configuration");
159460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            eglReleaseThread();
16064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            eglTerminate(mEglDisplay);
16164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            return false;
16264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        }
16364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
16464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (configCnt <= 0) {
165460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            ALOGW("Could not find EGL configuration");
166460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            eglReleaseThread();
16764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            eglTerminate(mEglDisplay);
16864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            return false;
16964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        }
1705d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
17164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        /* These objects are initialized below but the default "null" values are
172460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer         * used to cleanup properly at any point in the initialization sequence */
173460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
17464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
17564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                attrs);
17664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (mEglContext == EGL_NO_CONTEXT) {
1775d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao            ALOGW("Could not create EGL context");
17864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            cleanup();
179460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            return false;
180460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        }
18164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
18264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        EGLint surfaceAttrs[] = { EGL_NONE };
18364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
1845d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                mSurface.get(), surfaceAttrs);
185556d637764b71563030c479bc35364a75188d559Ian Rogers        if (mEglSurface == EGL_NO_SURFACE) {
186556d637764b71563030c479bc35364a75188d559Ian Rogers            ALOGW("Could not create EGL surface");
187556d637764b71563030c479bc35364a75188d559Ian Rogers            cleanup();
188556d637764b71563030c479bc35364a75188d559Ian Rogers            return false;
189556d637764b71563030c479bc35364a75188d559Ian Rogers        }
190556d637764b71563030c479bc35364a75188d559Ian Rogers
19164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
192460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            ALOGW("Could not change current EGL context");
193460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            cleanup();
19464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            return false;
19564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        }
19664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
1975d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        return true;
19864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
199460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer
200460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer    void makeCurrent() const
20164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    {
20264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
20364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
2045d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
20564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    void present() const
2065d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    {
20764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        eglSwapBuffers(mEglDisplay, mEglSurface);
208460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer    }
209460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer
21064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogersprivate:
21164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    void cleanup()
21264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    {
2135d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        if (mEglDisplay == EGL_NO_DISPLAY)
21464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            return;
215460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        if (mEglSurface != EGL_NO_SURFACE)
216460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            eglDestroySurface(mEglDisplay, mEglSurface);
21764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (mEglContext != EGL_NO_CONTEXT)
21864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            eglDestroyContext(mEglDisplay, mEglContext);
21964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2205d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
22164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                EGL_NO_CONTEXT);
222460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        eglReleaseThread();
223460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        eglTerminate(mEglDisplay);
22464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
22564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
22664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    sp<Surface> mSurface;
2275d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    EGLDisplay mEglDisplay;
22864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    EGLSurface mEglSurface;
2295d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    EGLContext mEglContext;
23064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers};
23164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
23264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
233460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzerstatic const std::array<vec2, 4> triangles = {{
234460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer    {  1.0f,  1.0f },
23564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    { -1.0f,  1.0f },
23664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    {  1.0f, -1.0f },
23764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    { -1.0f, -1.0f },
2385d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao}};
23964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2405d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Haoclass Hwc2TestFenceGenerator {
24164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogerspublic:
2425d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
24364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    Hwc2TestFenceGenerator()
244460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer    {
245460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
24664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                setFence, this);
24764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
24864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
2495d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao            return;
25064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2515d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        mEglManager.makeCurrent();
25264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
253460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        glClearColor(0.0, 0.0, 0.0, 1.0);
254460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        glEnableVertexAttribArray(0);
25564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
25664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
25764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    ~Hwc2TestFenceGenerator()
2585d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    {
25964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (mFence >= 0)
2605d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao            close(mFence);
26164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mFence = -1;
2625d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
26364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mEglManager.makeCurrent();
26464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
26564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
26664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    /* It is not possible to simply generate a fence. The easiest way is to
26764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers     * generate a buffer using egl and use the associated fence. The buffer
26864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers     * cannot be guaranteed to be a certain format across all devices using this
269460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer     * method. Instead the buffer is generated using the CPU */
270460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer    int32_t get()
27164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    {
27264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        if (mFence >= 0) {
273556d637764b71563030c479bc35364a75188d559Ian Rogers            return dup(mFence);
274556d637764b71563030c479bc35364a75188d559Ian Rogers        }
275556d637764b71563030c479bc35364a75188d559Ian Rogers
276556d637764b71563030c479bc35364a75188d559Ian Rogers        std::unique_lock<std::mutex> lock(mMutex);
277556d637764b71563030c479bc35364a75188d559Ian Rogers
278556d637764b71563030c479bc35364a75188d559Ian Rogers        /* If the pending is still set to false and times out, we cannot recover.
2793dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao         * Set an error and return */
280460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        while (mPending != false) {
281460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
2823dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao                return -ETIME;
2833dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao        }
2843dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao
2853dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao        /* Generate a fence. The fence will be returned through the setFence
28664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers         * callback */
287460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        mEglManager.makeCurrent();
288460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer
28964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
29064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        glClear(GL_COLOR_BUFFER_BIT);
29164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2925d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        mEglManager.present();
293556d637764b71563030c479bc35364a75188d559Ian Rogers
294556d637764b71563030c479bc35364a75188d559Ian Rogers        /* Wait for the setFence callback */
295556d637764b71563030c479bc35364a75188d559Ian Rogers        while (mPending != true) {
296556d637764b71563030c479bc35364a75188d559Ian Rogers            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
297556d637764b71563030c479bc35364a75188d559Ian Rogers                return -ETIME;
298556d637764b71563030c479bc35364a75188d559Ian Rogers        }
29964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
30064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mPending = false;
301460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer
302460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer        return dup(mFence);
30364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
30464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
30564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    /* Callback that sets the fence */
3065d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    void set(int32_t fence)
30764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    {
30864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mFence = fence;
30964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mPending = true;
31064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
31164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers        mCv.notify_all();
31264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
31364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
3148ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzprivate:
315b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers
316b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers    Hwc2TestSurfaceManager mSurfaceManager;
3178ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    Hwc2TestEglManager mEglManager;
318277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
3196a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    std::mutex mMutex;
3206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    std::condition_variable mCv;
3216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers
322fa46d3ee8cba2985c5c8bdfe47d15daf0613ebdcIan Rogers    int32_t mFence = -1;
323fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz    bool mPending = false;
324b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers};
325fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz
326fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz
327fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertzstatic void setFence(int32_t fence, void* fenceGenerator)
328fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz{
3296a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
330fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz}
3312c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers
332fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz
333fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz/* Sets the pixel of a buffer given the location, format, stride and color.
334fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz * Currently only supports RGBA_8888 */
335fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertzstatic void setColor(int32_t x, int32_t y,
336fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
337fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz        uint8_t g, uint8_t b, uint8_t a)
338fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz{
339fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz       switch (format) {
340fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz       case HAL_PIXEL_FORMAT_RGBA_8888:
341fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz           img[(y * stride + x) * 4 + 0] = r;
342fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz           img[(y * stride + x) * 4 + 1] = g;
343fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz           img[(y * stride + x) * 4 + 2] = b;
344fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz           img[(y * stride + x) * 4 + 3] = a;
345fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz           break;
346fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz       default:
347fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz           break;
348fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz       }
349fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz}
350fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz
3512fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan RogersHwc2TestBuffer::Hwc2TestBuffer()
352233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
353233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
354233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien HertzHwc2TestBuffer::~Hwc2TestBuffer() = default;
355233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
356233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz/* When the buffer changes sizes, save the new size and invalidate the current
357233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz * buffer */
358848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogersvoid Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
359848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers{
360848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    if (mBufferArea.width == bufferArea.width
361848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers            && mBufferArea.height == bufferArea.height)
3624e99b3d8955131f3fc71aa113f0fa71f0092cb6fSebastien Hertz        return;
3638ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz
364d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mBufferArea.width = bufferArea.width;
3658ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    mBufferArea.height = bufferArea.height;
366233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
3678ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    mValidBuffer = false;
368d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
369d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
370d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz/* Returns a valid buffer handle and fence. The handle is filled using the CPU
371d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * to ensure the correct format across all devices. The fence is created using
372d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * egl. */
3738ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzint Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
3748ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz{
375d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (mBufferArea.width == -1 || mBufferArea.height == -1)
376d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return -EINVAL;
377d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
378d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    /* If the current buffer is valid, the previous buffer can be reused.
379d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz     * Otherwise, create new buffer */
3808ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (!mValidBuffer) {
381233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz        int ret = generateBuffer();
382233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz        if (ret)
3838ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz            return ret;
384d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
385d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
386d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    *outFence = mFenceGenerator->get();
387d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    *outHandle = mHandle;
388d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
3898ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    mValidBuffer = true;
3908ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz
391d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    return 0;
392d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
393d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
394d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz/* CPU fills a buffer to guarantee the correct buffer format across all
395d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * devices */
3968ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzint Hwc2TestBuffer::generateBuffer()
397233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz{
398233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    int ret;
399233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
400ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    /* Create new graphic buffer with correct dimensions */
4016474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao    mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(
40264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            mBufferArea.width, mBufferArea.height, mFormat,
403535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
404535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray            "hwc2_test_buffer", &ret);
405d752132c73072084a3def9257cca4fcee76047b6jeffhao    if (ret)
406d752132c73072084a3def9257cca4fcee76047b6jeffhao        return ret;
407d752132c73072084a3def9257cca4fcee76047b6jeffhao
408d752132c73072084a3def9257cca4fcee76047b6jeffhao    /* Locks the buffer for writing */
409e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    uint8_t* img;
410bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
4112fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4122fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    uint32_t stride = mGraphicBuffer->getStride();
4132fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4142fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    /* Iterate from the top row of the buffer to the bottom row */
4152fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    for (int32_t y = 0; y < mBufferArea.height; y++) {
4160a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao
417e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier        /* Will be used as R, G and B values for pixel colors */
41856adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz        uint8_t max = 255;
4190a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao        uint8_t min = 0;
4202fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4212fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        /* Divide the rows into 3 sections. The first section will contain
422bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier         * the lighest colors. The last section will contain the darkest
4232fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers         * colors. */
4242fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        if (y < mBufferArea.height * 1.0 / 3.0) {
4252fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers            min = 255 / 2;
4262fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
4272fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers            max = 255 / 2;
4282fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        }
4292fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4306613519990bdb5616f2858c146f162ef760f03d2Jeff Hao        /* Divide the columns into 3 sections. The first section is red,
4316613519990bdb5616f2858c146f162ef760f03d2Jeff Hao         * the second is green and the third is blue */
4326613519990bdb5616f2858c146f162ef760f03d2Jeff Hao        int32_t x = 0;
433e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier        for (; x < mBufferArea.width / 3; x++) {
4342fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers            setColor(x, y, mFormat, stride, img, max, min, min, 255);
4352fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        }
4362fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
437ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa        for (; x < mBufferArea.width * 2 / 3; x++) {
4382fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers            setColor(x, y, mFormat, stride, img, min, max, min, 255);
4392fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        }
440bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier
441bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        for (; x < mBufferArea.width; x++) {
4425d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao            setColor(x, y, mFormat, stride, img, min, min, max, 255);
443bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        }
4445d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    }
4452fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
446ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    /* Unlock the buffer for reading */
447ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    mGraphicBuffer->unlock();
4482fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4492fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    mHandle = mGraphicBuffer->handle;
4505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
4515d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    return 0;
4525d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao}
4532fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4545d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
4552fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan RogersHwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
4565d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
4572fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4585d9173014c1ca09f7249a6b07629aa37778b5f8fJeff HaoHwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
4592fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4602fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers/* Generates a client target buffer using the layers assigned for client
4612fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * composition. Takes into account the individual layer properties such as
46292246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier * transform, blend mode, source crop, etc. */
46392246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartierint Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
4646c5cb212fa7010ae7caf9dc765533aa967c95342Ian Rogers        int32_t* outFence, const Area& bufferArea,
46592246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier        const Hwc2TestLayers* testLayers,
466eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        const std::set<hwc2_layer_t>* clientLayers,
467eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        const std::set<hwc2_layer_t>* clearLayers)
4687b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers{
46992246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    int err;
47092246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier
47192246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    /* Create new graphic buffer with updated size */
47292246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(bufferArea.width,
47392246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier            bufferArea.height, mFormat,
47464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
475bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier            "hwc2_test_buffer", &err);
476bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    if (err)
4776613519990bdb5616f2858c146f162ef760f03d2Jeff Hao        return err;
4786474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao
4796474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao    uint8_t* img;
4802fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
4812fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
48264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    uint32_t stride = mGraphicBuffer->getStride();
48364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
48492246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    float bWDiv3 = bufferArea.width / 3;
48592246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    float bW2Div3 = bufferArea.width * 2 / 3;
48692246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    float bHDiv3 = bufferArea.height / 3;
48764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    float bH2Div3 = bufferArea.height * 2 / 3;
4886474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao
4892fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    /* Cycle through every pixel in the buffer and determine what color it
4906474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     * should be. */
4912fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    for (int32_t y = 0; y < bufferArea.height; y++) {
4922fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        for (int32_t x = 0; x < bufferArea.width; x++) {
4932fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
4942fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers            uint8_t r = 0, g = 0, b = 0;
4952fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers            float a = 0.0f;
49662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
49711ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao            /* Cycle through each client layer from back to front and
49811ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao             * update the pixel color. */
49962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers            for (auto layer = clientLayers->rbegin();
50011ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                    layer != clientLayers->rend(); ++layer) {
50162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
502bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier                const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
503bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier
504bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier                float dfL = df.left;
50511ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                float dfT = df.top;
50611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                float dfR = df.right;
50711ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                float dfB = df.bottom;
50811ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao
50911ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                /* If the pixel location falls outside of the layer display
51011ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                 * frame, skip the layer. */
51111ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                if (x < dfL || x >= dfR || y < dfT || y >= dfB)
51211ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao                    continue;
5136f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers
5146f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                /* If the device has requested the layer be clear, clear
5156f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                 * the pixel and continue. */
516f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers                if (clearLayers->count(*layer) != 0) {
517535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray                    r = 0;
518535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray                    g = 0;
519f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers                    b = 0;
520f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers                    a = 0.0f;
521f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers                    continue;
522f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers                }
5236f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers
5247db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers                float planeAlpha = testLayers->getPlaneAlpha(*layer);
5257db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
5266f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                /* If the layer is a solid color, fill the color and
527848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                 * continue. */
528848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                if (testLayers->getComposition(*layer)
529535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray                        == HWC2_COMPOSITION_SOLID_COLOR) {
530535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray                    const auto color = testLayers->getColor(*layer);
531167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    r = color.r;
5326951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao                    g = color.g;
533167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    b = color.b;
534167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    a = color.a * planeAlpha;
535e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier                    continue;
5366f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                }
537c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz
5386f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                float xPos = x;
5396f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                float yPos = y;
5406c5cb212fa7010ae7caf9dc765533aa967c95342Ian Rogers
5410cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier                hwc_transform_t transform = testLayers->getTransform(*layer);
5420cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier
5430cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier                float dfW = dfR - dfL;
5447b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers                float dfH = dfB - dfT;
5450cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier
546e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier                /* If a layer has a transform, find which location on the
547c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz                 * layer will end up in the current pixel location. We
548c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz                 * can calculate the color of the current pixel using that
5490cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier                 * location. */
550167436311a08a65dea28dda079a137893821c9c7Jeff Hao                if (transform > 0) {
551167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    /* Change origin to be the center of the layer. */
552167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    xPos = xPos - dfL - dfW / 2.0;
5536f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                    yPos = yPos - dfT - dfH / 2.0;
5546f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers
555167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    /* Flip Horizontal by reflecting across the y axis. */
556167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    if (transform & HWC_TRANSFORM_FLIP_H)
557167436311a08a65dea28dda079a137893821c9c7Jeff Hao                        xPos = -xPos;
558167436311a08a65dea28dda079a137893821c9c7Jeff Hao
5596f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                    /* Flip vertical by reflecting across the x axis. */
5606f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                    if (transform & HWC_TRANSFORM_FLIP_V)
5616f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                        yPos = -yPos;
562167436311a08a65dea28dda079a137893821c9c7Jeff Hao
563167436311a08a65dea28dda079a137893821c9c7Jeff Hao                    /* Rotate 90 by using a basic linear algebra rotation
564167436311a08a65dea28dda079a137893821c9c7Jeff Hao                     * and scaling the result so the display frame remains
565167436311a08a65dea28dda079a137893821c9c7Jeff Hao                     * the same. For example, a buffer of size 100x50 should
566167436311a08a65dea28dda079a137893821c9c7Jeff Hao                     * rotate 90 degress but remain the same dimension
5672fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers                     * (100x50) at the end of the transformation. */
5682fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers                    if (transform & HWC_TRANSFORM_ROT_90) {
569                        float tmp = xPos;
570                        xPos = -yPos * dfW / dfH;
571                        yPos = tmp * dfH / dfW;
572                    }
573
574                    /* Change origin back to the top left corner of the
575                     * layer. */
576                    xPos = xPos + dfL + dfW / 2.0;
577                    yPos = yPos + dfT + dfH / 2.0;
578                }
579
580                hwc_frect_t sc = testLayers->getSourceCrop(*layer);
581                float scL = sc.left, scT = sc.top;
582
583                float dfWDivScW = dfW / (sc.right - scL);
584                float dfHDivScH = dfH / (sc.bottom - scT);
585
586                float max = 255, min = 0;
587
588                /* Choose the pixel color. Similar to generateBuffer,
589                 * each layer will be divided into 3x3 colors. Because
590                 * both the source crop and display frame must be taken into
591                 * account, the formulas are more complicated.
592                 *
593                 * If the source crop and display frame were not taken into
594                 * account, we would simply divide the buffer into three
595                 * sections by height. Each section would get one color.
596                 * For example the formula for the first section would be:
597                 *
598                 * if (yPos < bufferArea.height / 3)
599                 *        //Select first section color
600                 *
601                 * However the pixel color is chosen based on the source
602                 * crop and displayed based on the display frame.
603                 *
604                 * If the display frame top was 0 and the source crop height
605                 * and display frame height were the same. The only factor
606                 * would be the source crop top. To calculate the new
607                 * section boundary, the section boundary would be moved up
608                 * by the height of the source crop top. The formula would
609                 * be:
610                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
611                 *        //Select first section color
612                 *
613                 * If the display frame top could also vary but source crop
614                 * and display frame heights were the same, the formula
615                 * would be:
616                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top
617                 *              + displayFrameTop)
618                 *        //Select first section color
619                 *
620                 * If the heights were not the same, the conversion between
621                 * the source crop and display frame dimensions must be
622                 * taken into account. The formula would be:
623                 * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
624                 *              * displayFrameHeight / sourceCropHeight
625                 *              + displayFrameTop)
626                 *        //Select first section color
627                 */
628                if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
629                    min = 255 / 2;
630                } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
631                    max = 255 / 2;
632                }
633
634                uint8_t rCur = min, gCur = min, bCur = min;
635                float aCur = 1.0f;
636
637                /* This further divides the color sections from 3 to 3x3.
638                 * The math behind it follows the same logic as the previous
639                 * comment */
640                if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
641                    rCur = max;
642                } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
643                    gCur = max;
644                } else {
645                    bCur = max;
646                }
647
648
649                /* Blend the pixel color with the previous layers' pixel
650                 * colors using the plane alpha and blend mode. The final
651                 * pixel color is chosen using the plane alpha and blend
652                 * mode formulas found in hwcomposer2.h */
653                hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
654
655                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
656                    rCur *= planeAlpha;
657                    gCur *= planeAlpha;
658                    bCur *= planeAlpha;
659                }
660
661                aCur *= planeAlpha;
662
663                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
664                    r = rCur + r * (1.0 - aCur);
665                    g = gCur + g * (1.0 - aCur);
666                    b = bCur + b * (1.0 - aCur);
667                    a = aCur + a * (1.0 - aCur);
668                } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
669                    r = rCur * aCur + r * (1.0 - aCur);
670                    g = gCur * aCur + g * (1.0 - aCur);
671                    b = bCur * aCur + b * (1.0 - aCur);
672                    a = aCur * aCur + a * (1.0 - aCur);
673                } else {
674                    r = rCur;
675                    g = gCur;
676                    b = bCur;
677                    a = aCur;
678                }
679            }
680
681            /* Set the pixel color */
682            setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
683        }
684    }
685
686    mGraphicBuffer->unlock();
687
688    *outFence = mFenceGenerator->get();
689    *outHandle = mGraphicBuffer->handle;
690
691    return 0;
692}
693