Hwc2TestBuffer.cpp revision 0fa8676f2f301bc2a071a2ded35e21fcb9323212
15a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/*
25a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * Copyright (C) 2016 The Android Open Source Project
35a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall *
45a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * Licensed under the Apache License, Version 2.0 (the "License");
55a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * you may not use this file except in compliance with the License.
65a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * You may obtain a copy of the License at
75a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall *
85a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall *      http://www.apache.org/licenses/LICENSE-2.0
95a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall *
105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * Unless required by applicable law or agreed to in writing, software
115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * distributed under the License is distributed on an "AS IS" BASIS,
125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * See the License for the specific language governing permissions and
145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * limitations under the License.
155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall */
165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <mutex>
185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <array>
195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <sstream>
205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <algorithm>
215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <gui/Surface.h>
235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <gui/BufferItemConsumer.h>
245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <ui/GraphicBuffer.h>
265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <ui/vec4.h>
275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <GLES3/gl3.h>
295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include "Hwc2TestBuffer.h"
315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include "Hwc2TestLayers.h"
325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallusing namespace android;
345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Returns a fence from egl */
365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Walltypedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Returns fence to fence generator */
395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallstatic void setFence(int32_t fence, void* fenceGenerator);
405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * away. The fences are sent to the requester via a callback */
445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallclass Hwc2TestSurfaceManager {
455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallpublic:
465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Listens for a new frame, detaches the buffer and returns the fence
475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * through saved callback. */
485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    class BufferListener : public ConsumerBase::FrameAvailableListener {
495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    public:
505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        BufferListener(sp<IGraphicBufferConsumer> consumer,
515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                FenceCallback callback, void* callbackArgs)
525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            : mConsumer(consumer),
535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall              mCallback(callback),
545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall              mCallbackArgs(callbackArgs) { }
555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        void onFrameAvailable(const BufferItem& /*item*/)
575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        {
585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            BufferItem item;
595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mConsumer->acquireBuffer(&item, 0))
615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return;
625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mConsumer->detachBuffer(item.mSlot))
635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return;
645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            mCallback(item.mFence->dup(), mCallbackArgs);
665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    private:
695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        sp<IGraphicBufferConsumer> mConsumer;
705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        FenceCallback mCallback;
715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        void* mCallbackArgs;
725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    };
735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Creates a buffer listener that waits on a new frame from the buffer
755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * queue. */
765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void initialize(const Area& bufferArea, android_pixel_format_t format,
775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            FenceCallback callback, void* callbackArgs)
785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        sp<IGraphicBufferProducer> producer;
805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        sp<IGraphicBufferConsumer> consumer;
815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        BufferQueue::createBufferQueue(&producer, &consumer);
825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        consumer->setDefaultBufferFormat(format);
855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mListener = new BufferListener(consumer, callback, callbackArgs);
895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mBufferItemConsumer->setFrameAvailableListener(mListener);
905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mSurface = new Surface(producer, true);
925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Used by Egl manager. The surface is never displayed. */
955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<Surface> getSurface() const
965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return mSurface;
985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallprivate:
1015a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<BufferItemConsumer> mBufferItemConsumer;
1025a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<BufferListener> mListener;
1035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Used by Egl manager. The surface is never displayed */
1045a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<Surface> mSurface;
1055a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall};
1065a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Used to generate valid fences. It is not possible to create a dummy sync
1095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * fence for testing. Egl can generate buffers along with a valid fence.
1105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * The buffer cannot be guaranteed to be the same format across all devices so
1115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * a CPU filled buffer is used instead. The Egl fence is used along with the
1125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * CPU filled buffer. */
1135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallclass Hwc2TestEglManager {
1145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallpublic:
1155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestEglManager()
1165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        : mEglDisplay(EGL_NO_DISPLAY),
1175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall          mEglSurface(EGL_NO_SURFACE),
1185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall          mEglContext(EGL_NO_CONTEXT) { }
1195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    ~Hwc2TestEglManager()
1215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
1225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        cleanup();
1235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
1245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    int initialize(sp<Surface> surface)
1265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
1275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mSurface = surface;
1285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglDisplay == EGL_NO_DISPLAY) return false;
1315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint major;
1335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint minor;
1345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!eglInitialize(mEglDisplay, &major, &minor)) {
1355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not initialize EGL");
1365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* We're going to use a 1x1 pbuffer surface later on
1405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * The configuration distance doesn't really matter for what we're
1415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * trying to do */
1425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint configAttrs[] = {
1435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_RED_SIZE, 8,
1455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_GREEN_SIZE, 8,
1465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_BLUE_SIZE, 8,
1475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_ALPHA_SIZE, 0,
1485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_DEPTH_SIZE, 24,
1495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_STENCIL_SIZE, 0,
1505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_NONE
1515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        };
1525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLConfig configs[1];
1545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint configCnt;
1555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
1565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                &configCnt)) {
1575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not select EGL configuration");
1585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglReleaseThread();
1595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglTerminate(mEglDisplay);
1605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (configCnt <= 0) {
1645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not find EGL configuration");
1655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglReleaseThread();
1665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglTerminate(mEglDisplay);
1675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* These objects are initialized below but the default "null" values are
1715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * used to cleanup properly at any point in the initialization sequence */
1725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
1735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
1745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                attrs);
1755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglContext == EGL_NO_CONTEXT) {
1765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not create EGL context");
1775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            cleanup();
1785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint surfaceAttrs[] = { EGL_NONE };
1825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
1835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                mSurface.get(), surfaceAttrs);
1845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglSurface == EGL_NO_SURFACE) {
1855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not create EGL surface");
1865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            cleanup();
1875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
1915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not change current EGL context");
1925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            cleanup();
1935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return true;
1975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
1985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void makeCurrent() const
2005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2015a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
2025a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2045a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void present() const
2055a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2065a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglSwapBuffers(mEglDisplay, mEglSurface);
2075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallprivate:
2105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void cleanup()
2115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglDisplay == EGL_NO_DISPLAY)
2135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return;
2145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglSurface != EGL_NO_SURFACE)
2155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglDestroySurface(mEglDisplay, mEglSurface);
2165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglContext != EGL_NO_CONTEXT)
2175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglDestroyContext(mEglDisplay, mEglContext);
2185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_NO_CONTEXT);
2215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglReleaseThread();
2225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglTerminate(mEglDisplay);
2235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<Surface> mSurface;
2265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    EGLDisplay mEglDisplay;
2275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    EGLSurface mEglSurface;
2285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    EGLContext mEglContext;
2295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall};
2305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallstatic const std::array<vec2, 4> triangles = {{
2335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {  1.0f,  1.0f },
2345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    { -1.0f,  1.0f },
2355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {  1.0f, -1.0f },
2365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    { -1.0f, -1.0f },
2375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}};
2385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallclass Hwc2TestFenceGenerator {
2405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallpublic:
2415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestFenceGenerator()
2435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
2455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                setFence, this);
2465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
2485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return;
2495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.makeCurrent();
2515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glClearColor(0.0, 0.0, 0.0, 1.0);
2535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glEnableVertexAttribArray(0);
2545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    ~Hwc2TestFenceGenerator()
2575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mFence >= 0)
2595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            close(mFence);
2605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mFence = -1;
2615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.makeCurrent();
2635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* It is not possible to simply generate a fence. The easiest way is to
2665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * generate a buffer using egl and use the associated fence. The buffer
2675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * cannot be guaranteed to be a certain format across all devices using this
2685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * method. Instead the buffer is generated using the CPU */
2695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    int32_t get()
2705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mFence >= 0) {
2725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return dup(mFence);
2735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
2745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        std::unique_lock<std::mutex> lock(mMutex);
2765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* If the pending is still set to false and times out, we cannot recover.
2785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * Set an error and return */
2795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        while (mPending != false) {
2805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
2815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return -ETIME;
2825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
2835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Generate a fence. The fence will be returned through the setFence
2855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * callback */
2865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.makeCurrent();
2875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
2895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glClear(GL_COLOR_BUFFER_BIT);
2905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.present();
2925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Wait for the setFence callback */
2945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        while (mPending != true) {
2955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
2965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return -ETIME;
2975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
2985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mPending = false;
3005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3015a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return dup(mFence);
3025a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
3035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3045a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Callback that sets the fence */
3055a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void set(int32_t fence)
3065a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
3075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mFence = fence;
3085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mPending = true;
3095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mCv.notify_all();
3115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
3125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallprivate:
3145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestSurfaceManager mSurfaceManager;
3165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestEglManager mEglManager;
3175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    std::mutex mMutex;
3195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    std::condition_variable mCv;
3205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    int32_t mFence = -1;
3225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    bool mPending = false;
3235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall};
3245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallstatic void setFence(int32_t fence, void* fenceGenerator)
3275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
3295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
3305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
332f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall/* Sets the pixel of a buffer given the location, format, stride and color.
333f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall * Currently only supports RGBA_8888 */
334f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wallstatic void setColor(int32_t x, int32_t y,
335f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
336f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        uint8_t g, uint8_t b, uint8_t a)
337f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall{
338f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       switch (format) {
339f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       case HAL_PIXEL_FORMAT_RGBA_8888:
340f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 0] = r;
341f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 1] = g;
342f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 2] = b;
343f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 3] = a;
344f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           break;
345f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       default:
346f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           break;
347f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       }
348f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall}
349f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
3505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa WallHwc2TestBuffer::Hwc2TestBuffer()
3515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
3525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa WallHwc2TestBuffer::~Hwc2TestBuffer() = default;
3545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* When the buffer changes sizes, save the new size and invalidate the current
3565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * buffer */
3575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallvoid Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
3585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    if (mBufferArea.width == bufferArea.width
3605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            && mBufferArea.height == bufferArea.height)
3615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return;
3625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mBufferArea.width = bufferArea.width;
3645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mBufferArea.height = bufferArea.height;
3655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mValidBuffer = false;
3675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
3685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Returns a valid buffer handle and fence. The handle is filled using the CPU
3705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * to ensure the correct format across all devices. The fence is created using
3715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * egl. */
3725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallint Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
3735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    if (mBufferArea.width == -1 || mBufferArea.height == -1)
3755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return -EINVAL;
3765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* If the current buffer is valid, the previous buffer can be reused.
3785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * Otherwise, create new buffer */
3795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    if (!mValidBuffer) {
3805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        int ret = generateBuffer();
3815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (ret)
3825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return ret;
3835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
3845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    *outFence = mFenceGenerator->get();
3865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    *outHandle = mHandle;
3875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mValidBuffer = true;
3895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    return 0;
3915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
3925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* CPU fills a buffer to guarantee the correct buffer format across all
3945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * devices */
3955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallint Hwc2TestBuffer::generateBuffer()
3965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Create new graphic buffer with correct dimensions */
3980fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
3990fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
4000fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall            "hwc2_test_buffer");
4010fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    int ret = mGraphicBuffer->initCheck();
4020fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    if (ret) {
4035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return ret;
4040fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    }
4050fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    if (!mGraphicBuffer->handle) {
4060fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall        return -EINVAL;
4070fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    }
4085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Locks the buffer for writing */
4105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    uint8_t* img;
4115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
4125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    uint32_t stride = mGraphicBuffer->getStride();
4145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Iterate from the top row of the buffer to the bottom row */
4165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    for (int32_t y = 0; y < mBufferArea.height; y++) {
4175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Will be used as R, G and B values for pixel colors */
4195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        uint8_t max = 255;
4205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        uint8_t min = 0;
4215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Divide the rows into 3 sections. The first section will contain
4235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * the lighest colors. The last section will contain the darkest
4245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * colors. */
4255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (y < mBufferArea.height * 1.0 / 3.0) {
4265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            min = 255 / 2;
4275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
4285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            max = 255 / 2;
4295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Divide the columns into 3 sections. The first section is red,
4325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * the second is green and the third is blue */
4335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        int32_t x = 0;
4345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        for (; x < mBufferArea.width / 3; x++) {
4355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            setColor(x, y, mFormat, stride, img, max, min, min, 255);
4365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        for (; x < mBufferArea.width * 2 / 3; x++) {
4395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            setColor(x, y, mFormat, stride, img, min, max, min, 255);
4405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        for (; x < mBufferArea.width; x++) {
4435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            setColor(x, y, mFormat, stride, img, min, min, max, 255);
4445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
4465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Unlock the buffer for reading */
4485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mGraphicBuffer->unlock();
4495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mHandle = mGraphicBuffer->handle;
4515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    return 0;
4535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
4545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
455f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
456f18cfb0a780c69f12439457ccc3f5272db767fddMarissa WallHwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
457f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
458f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
459f18cfb0a780c69f12439457ccc3f5272db767fddMarissa WallHwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
460f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
461f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall/* Generates a client target buffer using the layers assigned for client
462f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall * composition. Takes into account the individual layer properties such as
463f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall * transform, blend mode, source crop, etc. */
464f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wallint Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
465f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        int32_t* outFence, const Area& bufferArea,
466f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        const Hwc2TestLayers* testLayers,
467f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        const std::set<hwc2_layer_t>* clientLayers,
468f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        const std::set<hwc2_layer_t>* clearLayers)
4695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
4700fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    /* Create new graphic buffer with correct dimensions */
4710fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
4720fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
4730fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall            "hwc2_test_buffer");
4740fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    int ret = mGraphicBuffer->initCheck();
4750fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    if (ret) {
4760fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall        return ret;
4770fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    }
4780fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    if (!mGraphicBuffer->handle) {
4790fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall        return -EINVAL;
4800fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    }
481f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
482f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    uint8_t* img;
483f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
484f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
485f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    uint32_t stride = mGraphicBuffer->getStride();
486f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
487f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bWDiv3 = bufferArea.width / 3;
488f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bW2Div3 = bufferArea.width * 2 / 3;
489f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bHDiv3 = bufferArea.height / 3;
490f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bH2Div3 = bufferArea.height * 2 / 3;
491f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
492f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    /* Cycle through every pixel in the buffer and determine what color it
493f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall     * should be. */
494f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    for (int32_t y = 0; y < bufferArea.height; y++) {
495f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        for (int32_t x = 0; x < bufferArea.width; x++) {
496f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
497f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            uint8_t r = 0, g = 0, b = 0;
498f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            float a = 0.0f;
499f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
500f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            /* Cycle through each client layer from back to front and
501f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall             * update the pixel color. */
502f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            for (auto layer = clientLayers->rbegin();
503f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    layer != clientLayers->rend(); ++layer) {
504f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
505f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
506f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
507f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfL = df.left;
508f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfT = df.top;
509f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfR = df.right;
510f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfB = df.bottom;
511f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
512f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If the pixel location falls outside of the layer display
513f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * frame, skip the layer. */
514f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (x < dfL || x >= dfR || y < dfT || y >= dfB)
515f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    continue;
516f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
517f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If the device has requested the layer be clear, clear
518f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * the pixel and continue. */
519f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (clearLayers->count(*layer) != 0) {
520f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = 0;
521f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = 0;
522f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = 0;
523f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = 0.0f;
524f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    continue;
525f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
526f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
527f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float planeAlpha = testLayers->getPlaneAlpha(*layer);
528f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
529f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If the layer is a solid color, fill the color and
530f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * continue. */
531f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (testLayers->getComposition(*layer)
532f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        == HWC2_COMPOSITION_SOLID_COLOR) {
533f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    const auto color = testLayers->getColor(*layer);
534f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = color.r;
535f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = color.g;
536f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = color.b;
537f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = color.a * planeAlpha;
538f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    continue;
539f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
540f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
541f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float xPos = x;
542f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float yPos = y;
543f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
544f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                hwc_transform_t transform = testLayers->getTransform(*layer);
545f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
546f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfW = dfR - dfL;
547f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfH = dfB - dfT;
548f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
549f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If a layer has a transform, find which location on the
550f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * layer will end up in the current pixel location. We
551f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * can calculate the color of the current pixel using that
552f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * location. */
553f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (transform > 0) {
554f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Change origin to be the center of the layer. */
555f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    xPos = xPos - dfL - dfW / 2.0;
556f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    yPos = yPos - dfT - dfH / 2.0;
557f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
558f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Flip Horizontal by reflecting across the y axis. */
559f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    if (transform & HWC_TRANSFORM_FLIP_H)
560f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        xPos = -xPos;
561f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
562f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Flip vertical by reflecting across the x axis. */
563f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    if (transform & HWC_TRANSFORM_FLIP_V)
564f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        yPos = -yPos;
565f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
566f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Rotate 90 by using a basic linear algebra rotation
567f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * and scaling the result so the display frame remains
568f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * the same. For example, a buffer of size 100x50 should
569f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * rotate 90 degress but remain the same dimension
570f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * (100x50) at the end of the transformation. */
571f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    if (transform & HWC_TRANSFORM_ROT_90) {
572f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        float tmp = xPos;
573f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        xPos = -yPos * dfW / dfH;
574f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        yPos = tmp * dfH / dfW;
575f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    }
576f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
577f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Change origin back to the top left corner of the
578f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * layer. */
579f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    xPos = xPos + dfL + dfW / 2.0;
580f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    yPos = yPos + dfT + dfH / 2.0;
581f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
582f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
583f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                hwc_frect_t sc = testLayers->getSourceCrop(*layer);
584f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float scL = sc.left, scT = sc.top;
585f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
586f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfWDivScW = dfW / (sc.right - scL);
587f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfHDivScH = dfH / (sc.bottom - scT);
588f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
589f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float max = 255, min = 0;
590f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
591f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* Choose the pixel color. Similar to generateBuffer,
592f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * each layer will be divided into 3x3 colors. Because
593f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * both the source crop and display frame must be taken into
594f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * account, the formulas are more complicated.
595f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
596f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the source crop and display frame were not taken into
597f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * account, we would simply divide the buffer into three
598f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * sections by height. Each section would get one color.
599f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * For example the formula for the first section would be:
600f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
601f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < bufferArea.height / 3)
602f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
603f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
604f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * However the pixel color is chosen based on the source
605f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * crop and displayed based on the display frame.
606f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
607f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the display frame top was 0 and the source crop height
608f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * and display frame height were the same. The only factor
609f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * would be the source crop top. To calculate the new
610f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * section boundary, the section boundary would be moved up
611f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * by the height of the source crop top. The formula would
612f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * be:
613f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
614f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
615f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
616f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the display frame top could also vary but source crop
617f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * and display frame heights were the same, the formula
618f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * would be:
619f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top
620f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *              + displayFrameTop)
621f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
622f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
623f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the heights were not the same, the conversion between
624f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * the source crop and display frame dimensions must be
625f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * taken into account. The formula would be:
626f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
627f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *              * displayFrameHeight / sourceCropHeight
628f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *              + displayFrameTop)
629f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
630f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 */
631f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
632f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    min = 255 / 2;
633f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
634f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    max = 255 / 2;
635f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
636f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
637f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                uint8_t rCur = min, gCur = min, bCur = min;
638f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float aCur = 1.0f;
639f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
640f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* This further divides the color sections from 3 to 3x3.
641f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * The math behind it follows the same logic as the previous
642f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * comment */
643f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
644f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    rCur = max;
645f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
646f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    gCur = max;
647f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else {
648f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    bCur = max;
649f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
650f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
651f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
652f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* Blend the pixel color with the previous layers' pixel
653f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * colors using the plane alpha and blend mode. The final
654f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * pixel color is chosen using the plane alpha and blend
655f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * mode formulas found in hwcomposer2.h */
656f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
657f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
658f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
659f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    rCur *= planeAlpha;
660f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    gCur *= planeAlpha;
661f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    bCur *= planeAlpha;
662f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
663f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
664f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                aCur *= planeAlpha;
665f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
666f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
667f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = rCur + r * (1.0 - aCur);
668f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = gCur + g * (1.0 - aCur);
669f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = bCur + b * (1.0 - aCur);
670f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = aCur + a * (1.0 - aCur);
671f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
672f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = rCur * aCur + r * (1.0 - aCur);
673f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = gCur * aCur + g * (1.0 - aCur);
674f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = bCur * aCur + b * (1.0 - aCur);
675f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = aCur * aCur + a * (1.0 - aCur);
676f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else {
677f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = rCur;
678f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = gCur;
679f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = bCur;
680f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = aCur;
681f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
682f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            }
683f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
684f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            /* Set the pixel color */
685f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
686f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        }
687f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    }
688f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
689f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    mGraphicBuffer->unlock();
690f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
691f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    *outFence = mFenceGenerator->get();
692f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    *outHandle = mGraphicBuffer->handle;
693f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
694f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    return 0;
6955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
696