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>
264cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr#include <android/hardware/graphics/common/1.0/types.h>
27dde19448624ca514e0598f0343029c1ca4960c05Marissa Wall#include <math/vec4.h>
285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include <GLES3/gl3.h>
303f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr#include <SkImageEncoder.h>
313f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr#include <SkStream.h>
325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include "Hwc2TestBuffer.h"
335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall#include "Hwc2TestLayers.h"
345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallusing namespace android;
364cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jrusing android::hardware::graphics::common::V1_0::BufferUsage;
375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Returns a fence from egl */
395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Walltypedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Returns fence to fence generator */
425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallstatic void setFence(int32_t fence, void* fenceGenerator);
435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * away. The fences are sent to the requester via a callback */
475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallclass Hwc2TestSurfaceManager {
485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallpublic:
495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Listens for a new frame, detaches the buffer and returns the fence
505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * through saved callback. */
515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    class BufferListener : public ConsumerBase::FrameAvailableListener {
525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    public:
535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        BufferListener(sp<IGraphicBufferConsumer> consumer,
545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                FenceCallback callback, void* callbackArgs)
555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            : mConsumer(consumer),
565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall              mCallback(callback),
575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall              mCallbackArgs(callbackArgs) { }
585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        void onFrameAvailable(const BufferItem& /*item*/)
605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        {
615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            BufferItem item;
625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mConsumer->acquireBuffer(&item, 0))
645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return;
655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mConsumer->detachBuffer(item.mSlot))
665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return;
675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            mCallback(item.mFence->dup(), mCallbackArgs);
695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    private:
725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        sp<IGraphicBufferConsumer> mConsumer;
735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        FenceCallback mCallback;
745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        void* mCallbackArgs;
755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    };
765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Creates a buffer listener that waits on a new frame from the buffer
785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * queue. */
795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void initialize(const Area& bufferArea, android_pixel_format_t format,
805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            FenceCallback callback, void* callbackArgs)
815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        sp<IGraphicBufferProducer> producer;
835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        sp<IGraphicBufferConsumer> consumer;
845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        BufferQueue::createBufferQueue(&producer, &consumer);
855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        consumer->setDefaultBufferFormat(format);
885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mListener = new BufferListener(consumer, callback, callbackArgs);
925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mBufferItemConsumer->setFrameAvailableListener(mListener);
935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mSurface = new Surface(producer, true);
955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Used by Egl manager. The surface is never displayed. */
985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<Surface> getSurface() const
995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
1005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return mSurface;
1015a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
1025a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallprivate:
1045a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<BufferItemConsumer> mBufferItemConsumer;
1055a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<BufferListener> mListener;
1065a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Used by Egl manager. The surface is never displayed */
1075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<Surface> mSurface;
1085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall};
1095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Used to generate valid fences. It is not possible to create a dummy sync
1125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * fence for testing. Egl can generate buffers along with a valid fence.
1135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * The buffer cannot be guaranteed to be the same format across all devices so
1145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * a CPU filled buffer is used instead. The Egl fence is used along with the
1155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * CPU filled buffer. */
1165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallclass Hwc2TestEglManager {
1175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallpublic:
1185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestEglManager()
1195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        : mEglDisplay(EGL_NO_DISPLAY),
1205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall          mEglSurface(EGL_NO_SURFACE),
1215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall          mEglContext(EGL_NO_CONTEXT) { }
1225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    ~Hwc2TestEglManager()
1245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
1255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        cleanup();
1265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
1275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    int initialize(sp<Surface> surface)
1295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
1305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mSurface = surface;
1315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglDisplay == EGL_NO_DISPLAY) return false;
1345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint major;
1365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint minor;
1375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!eglInitialize(mEglDisplay, &major, &minor)) {
1385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not initialize EGL");
1395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* We're going to use a 1x1 pbuffer surface later on
1435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * The configuration distance doesn't really matter for what we're
1445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * trying to do */
1455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint configAttrs[] = {
1465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_RED_SIZE, 8,
1485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_GREEN_SIZE, 8,
1495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_BLUE_SIZE, 8,
1505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_ALPHA_SIZE, 0,
1515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_DEPTH_SIZE, 24,
1525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_STENCIL_SIZE, 0,
1535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_NONE
1545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        };
1555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLConfig configs[1];
1575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint configCnt;
1585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
1595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                &configCnt)) {
1605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not select EGL configuration");
1615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglReleaseThread();
1625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglTerminate(mEglDisplay);
1635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (configCnt <= 0) {
1675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not find EGL configuration");
1685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglReleaseThread();
1695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglTerminate(mEglDisplay);
1705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* These objects are initialized below but the default "null" values are
1745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * used to cleanup properly at any point in the initialization sequence */
1755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
1765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
1775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                attrs);
1785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglContext == EGL_NO_CONTEXT) {
1795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not create EGL context");
1805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            cleanup();
1815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        EGLint surfaceAttrs[] = { EGL_NONE };
1855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
1865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                mSurface.get(), surfaceAttrs);
1875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglSurface == EGL_NO_SURFACE) {
1885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not create EGL surface");
1895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            cleanup();
1905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
1945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            ALOGW("Could not change current EGL context");
1955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            cleanup();
1965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return false;
1975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
1985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
1995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return true;
2005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2015a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2025a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void makeCurrent() const
2035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2045a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
2055a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2065a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void present() const
2085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglSwapBuffers(mEglDisplay, mEglSurface);
2105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallprivate:
2135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void cleanup()
2145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglDisplay == EGL_NO_DISPLAY)
2165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return;
2175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglSurface != EGL_NO_SURFACE)
2185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglDestroySurface(mEglDisplay, mEglSurface);
2195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mEglContext != EGL_NO_CONTEXT)
2205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            eglDestroyContext(mEglDisplay, mEglContext);
2215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                EGL_NO_CONTEXT);
2245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglReleaseThread();
2255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        eglTerminate(mEglDisplay);
2265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    sp<Surface> mSurface;
2295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    EGLDisplay mEglDisplay;
2305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    EGLSurface mEglSurface;
2315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    EGLContext mEglContext;
2325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall};
2335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallstatic const std::array<vec2, 4> triangles = {{
2365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {  1.0f,  1.0f },
2375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    { -1.0f,  1.0f },
2385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {  1.0f, -1.0f },
2395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    { -1.0f, -1.0f },
2405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}};
2415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallclass Hwc2TestFenceGenerator {
2435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallpublic:
2445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestFenceGenerator()
2465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
2485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                setFence, this);
2495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
2515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return;
2525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.makeCurrent();
2545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glClearColor(0.0, 0.0, 0.0, 1.0);
2565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glEnableVertexAttribArray(0);
2575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    ~Hwc2TestFenceGenerator()
2605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mFence >= 0)
2625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            close(mFence);
2635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mFence = -1;
2645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.makeCurrent();
2665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
2675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* It is not possible to simply generate a fence. The easiest way is to
2695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * generate a buffer using egl and use the associated fence. The buffer
2705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * cannot be guaranteed to be a certain format across all devices using this
2715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * method. Instead the buffer is generated using the CPU */
2725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    int32_t get()
2735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
2745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (mFence >= 0) {
2755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return dup(mFence);
2765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
2775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        std::unique_lock<std::mutex> lock(mMutex);
2795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* If the pending is still set to false and times out, we cannot recover.
2815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * Set an error and return */
2825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        while (mPending != false) {
2835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
2845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return -ETIME;
2855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
2865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Generate a fence. The fence will be returned through the setFence
2885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * callback */
2895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.makeCurrent();
2905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
2925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        glClear(GL_COLOR_BUFFER_BIT);
2935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mEglManager.present();
2955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
2965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Wait for the setFence callback */
2975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        while (mPending != true) {
2985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
2995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall                return -ETIME;
3005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
3015a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3025a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mPending = false;
3035a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3045a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return dup(mFence);
3055a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
3065a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Callback that sets the fence */
3085a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    void set(int32_t fence)
3095a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    {
3105a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mFence = fence;
3115a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mPending = true;
3125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        mCv.notify_all();
3145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
3155a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallprivate:
3175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestSurfaceManager mSurfaceManager;
3195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    Hwc2TestEglManager mEglManager;
3205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    std::mutex mMutex;
3225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    std::condition_variable mCv;
3235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    int32_t mFence = -1;
3255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    bool mPending = false;
3265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall};
3275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallstatic void setFence(int32_t fence, void* fenceGenerator)
3305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
3325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
3335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
335f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall/* Sets the pixel of a buffer given the location, format, stride and color.
336f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall * Currently only supports RGBA_8888 */
337f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wallstatic void setColor(int32_t x, int32_t y,
338f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
339f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        uint8_t g, uint8_t b, uint8_t a)
340f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall{
341f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       switch (format) {
342f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       case HAL_PIXEL_FORMAT_RGBA_8888:
343f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 0] = r;
344f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 1] = g;
345f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 2] = b;
346f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           img[(y * stride + x) * 4 + 3] = a;
347f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           break;
348f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       default:
349f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall           break;
350f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall       }
351f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall}
352f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
3535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa WallHwc2TestBuffer::Hwc2TestBuffer()
3545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
3555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa WallHwc2TestBuffer::~Hwc2TestBuffer() = default;
3575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* When the buffer changes sizes, save the new size and invalidate the current
3595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * buffer */
3605a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallvoid Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
3615a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3625a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    if (mBufferArea.width == bufferArea.width
3635a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            && mBufferArea.height == bufferArea.height)
3645a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return;
3655a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3665a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mBufferArea.width = bufferArea.width;
3675a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mBufferArea.height = bufferArea.height;
3685a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3695a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mValidBuffer = false;
3705a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
3715a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3725a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* Returns a valid buffer handle and fence. The handle is filled using the CPU
3735a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * to ensure the correct format across all devices. The fence is created using
3745a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * egl. */
3755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallint Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
3765a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
3775a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    if (mBufferArea.width == -1 || mBufferArea.height == -1)
3785a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return -EINVAL;
3795a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3805a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* If the current buffer is valid, the previous buffer can be reused.
3815a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall     * Otherwise, create new buffer */
3825a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    if (!mValidBuffer) {
3835a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        int ret = generateBuffer();
3845a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (ret)
3855a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            return ret;
3865a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
3875a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3885a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    *outFence = mFenceGenerator->get();
3895a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    *outHandle = mHandle;
3905a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3915a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mValidBuffer = true;
3925a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3935a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    return 0;
3945a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
3955a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
3965a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall/* CPU fills a buffer to guarantee the correct buffer format across all
3975a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall * devices */
3985a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wallint Hwc2TestBuffer::generateBuffer()
3995a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
4005a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Create new graphic buffer with correct dimensions */
4010fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
4024cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr            mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
4034cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr            BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
4044cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr
4050fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    int ret = mGraphicBuffer->initCheck();
4060fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    if (ret) {
4075a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        return ret;
4080fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    }
4090fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    if (!mGraphicBuffer->handle) {
4100fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall        return -EINVAL;
4110fa8676f2f301bc2a071a2ded35e21fcb9323212Marissa Wall    }
4125a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4135a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Locks the buffer for writing */
4145a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    uint8_t* img;
4154cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr    mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
4164cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr            (void**)(&img));
4175a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4185a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    uint32_t stride = mGraphicBuffer->getStride();
4195a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4205a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Iterate from the top row of the buffer to the bottom row */
4215a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    for (int32_t y = 0; y < mBufferArea.height; y++) {
4225a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4235a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Will be used as R, G and B values for pixel colors */
4245a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        uint8_t max = 255;
4255a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        uint8_t min = 0;
4265a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4275a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Divide the rows into 3 sections. The first section will contain
4285a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * the lighest colors. The last section will contain the darkest
4295a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * colors. */
4305a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        if (y < mBufferArea.height * 1.0 / 3.0) {
4315a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            min = 255 / 2;
4325a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
4335a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            max = 255 / 2;
4345a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4355a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4365a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        /* Divide the columns into 3 sections. The first section is red,
4375a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall         * the second is green and the third is blue */
4385a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        int32_t x = 0;
4395a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        for (; x < mBufferArea.width / 3; x++) {
4405a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            setColor(x, y, mFormat, stride, img, max, min, min, 255);
4415a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4425a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4435a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        for (; x < mBufferArea.width * 2 / 3; x++) {
4445a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            setColor(x, y, mFormat, stride, img, min, max, min, 255);
4455a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4465a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4475a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        for (; x < mBufferArea.width; x++) {
4485a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall            setColor(x, y, mFormat, stride, img, min, min, max, 255);
4495a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall        }
4505a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    }
4515a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4525a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    /* Unlock the buffer for reading */
4535a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mGraphicBuffer->unlock();
4545a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4555a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    mHandle = mGraphicBuffer->handle;
4565a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
4575a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall    return 0;
4585a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
4595a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall
460f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
461f18cfb0a780c69f12439457ccc3f5272db767fddMarissa WallHwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
462f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
463f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
464f18cfb0a780c69f12439457ccc3f5272db767fddMarissa WallHwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
465f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
4663f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr/* Generates a buffer from layersToDraw.
4673f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr * Takes into account the individual layer properties such as
468f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall * transform, blend mode, source crop, etc. */
4693f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jrstatic void compositeBufferFromLayers(
4703f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const android::sp<android::GraphicBuffer>& graphicBuffer,
4713f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        android_pixel_format_t format, const Area& bufferArea,
472f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        const Hwc2TestLayers* testLayers,
4733f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const std::set<hwc2_layer_t>* layersToDraw,
474f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        const std::set<hwc2_layer_t>* clearLayers)
4755a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall{
4763f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    /* Locks the buffer for writing */
477f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    uint8_t* img;
4783f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    graphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
4794cab6aac0dca13a79701e86ac6ff3cbb1584a8abDavid Hanna Jr            (void**)(&img));
480f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
4813f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    uint32_t stride = graphicBuffer->getStride();
482f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
483f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bWDiv3 = bufferArea.width / 3;
484f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bW2Div3 = bufferArea.width * 2 / 3;
485f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bHDiv3 = bufferArea.height / 3;
486f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    float bH2Div3 = bufferArea.height * 2 / 3;
487f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
488f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    /* Cycle through every pixel in the buffer and determine what color it
489f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall     * should be. */
490f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    for (int32_t y = 0; y < bufferArea.height; y++) {
491f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        for (int32_t x = 0; x < bufferArea.width; x++) {
492f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
493f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            uint8_t r = 0, g = 0, b = 0;
494f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            float a = 0.0f;
495f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
4963f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            /* Cycle through each layer from back to front and
497f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall             * update the pixel color. */
4983f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            for (auto layer = layersToDraw->rbegin();
4993f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr                    layer != layersToDraw->rend(); ++layer) {
500f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
501f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
502f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
503f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfL = df.left;
504f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfT = df.top;
505f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfR = df.right;
506f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfB = df.bottom;
507f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
508f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If the pixel location falls outside of the layer display
509f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * frame, skip the layer. */
510f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (x < dfL || x >= dfR || y < dfT || y >= dfB)
511f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    continue;
512f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
513f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If the device has requested the layer be clear, clear
514f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * the pixel and continue. */
515f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (clearLayers->count(*layer) != 0) {
516f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = 0;
517f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = 0;
518f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = 0;
519f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = 0.0f;
520f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    continue;
521f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
522f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
523f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float planeAlpha = testLayers->getPlaneAlpha(*layer);
524f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
525f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If the layer is a solid color, fill the color and
526f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * continue. */
527f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (testLayers->getComposition(*layer)
528f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        == HWC2_COMPOSITION_SOLID_COLOR) {
529f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    const auto color = testLayers->getColor(*layer);
530f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = color.r;
531f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = color.g;
532f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = color.b;
533f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = color.a * planeAlpha;
534f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    continue;
535f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
536f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
537f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float xPos = x;
538f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float yPos = y;
539f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
540f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                hwc_transform_t transform = testLayers->getTransform(*layer);
541f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
542f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfW = dfR - dfL;
543f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfH = dfB - dfT;
544f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
545f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* If a layer has a transform, find which location on the
546f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * layer will end up in the current pixel location. We
547f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * can calculate the color of the current pixel using that
548f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * location. */
549f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (transform > 0) {
550f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Change origin to be the center of the layer. */
551f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    xPos = xPos - dfL - dfW / 2.0;
552f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    yPos = yPos - dfT - dfH / 2.0;
553f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
554f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Flip Horizontal by reflecting across the y axis. */
555f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    if (transform & HWC_TRANSFORM_FLIP_H)
556f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        xPos = -xPos;
557f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
558f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Flip vertical by reflecting across the x axis. */
559f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    if (transform & HWC_TRANSFORM_FLIP_V)
560f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        yPos = -yPos;
561f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
562f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Rotate 90 by using a basic linear algebra rotation
563f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * and scaling the result so the display frame remains
564f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * the same. For example, a buffer of size 100x50 should
565f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * rotate 90 degress but remain the same dimension
566f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * (100x50) at the end of the transformation. */
567f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    if (transform & HWC_TRANSFORM_ROT_90) {
568f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                        float tmp = xPos;
5691d8d412b5d8c294c7a141bd62141c9e1750dcf73David Hanna Jr                        xPos = yPos * dfW / dfH;
5701d8d412b5d8c294c7a141bd62141c9e1750dcf73David Hanna Jr                        yPos = -tmp * dfH / dfW;
571f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    }
572f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
573f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    /* Change origin back to the top left corner of the
574f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                     * layer. */
575f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    xPos = xPos + dfL + dfW / 2.0;
576f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    yPos = yPos + dfT + dfH / 2.0;
577f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
578f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
579f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                hwc_frect_t sc = testLayers->getSourceCrop(*layer);
580f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float scL = sc.left, scT = sc.top;
581f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
582f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfWDivScW = dfW / (sc.right - scL);
583f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float dfHDivScH = dfH / (sc.bottom - scT);
584f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
585f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float max = 255, min = 0;
586f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
587f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* Choose the pixel color. Similar to generateBuffer,
588f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * each layer will be divided into 3x3 colors. Because
589f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * both the source crop and display frame must be taken into
590f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * account, the formulas are more complicated.
591f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
592f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the source crop and display frame were not taken into
593f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * account, we would simply divide the buffer into three
594f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * sections by height. Each section would get one color.
595f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * For example the formula for the first section would be:
596f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
597f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < bufferArea.height / 3)
598f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
599f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
600f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * However the pixel color is chosen based on the source
601f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * crop and displayed based on the display frame.
602f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
603f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the display frame top was 0 and the source crop height
604f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * and display frame height were the same. The only factor
605f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * would be the source crop top. To calculate the new
606f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * section boundary, the section boundary would be moved up
607f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * by the height of the source crop top. The formula would
608f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * be:
609f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
610f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
611f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
612f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the display frame top could also vary but source crop
613f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * and display frame heights were the same, the formula
614f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * would be:
615f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top
616f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *              + displayFrameTop)
617f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
618f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *
619f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * If the heights were not the same, the conversion between
620f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * the source crop and display frame dimensions must be
621f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * taken into account. The formula would be:
622f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
623f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *              * displayFrameHeight / sourceCropHeight
624f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *              + displayFrameTop)
625f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 *        //Select first section color
626f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 */
627f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
628f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    min = 255 / 2;
629f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
630f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    max = 255 / 2;
631f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
632f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
633f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                uint8_t rCur = min, gCur = min, bCur = min;
634f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                float aCur = 1.0f;
635f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
636f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* This further divides the color sections from 3 to 3x3.
637f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * The math behind it follows the same logic as the previous
638f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * comment */
639f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
640f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    rCur = max;
641f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
642f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    gCur = max;
643f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else {
644f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    bCur = max;
645f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
646f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
647f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
648f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                /* Blend the pixel color with the previous layers' pixel
649f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * colors using the plane alpha and blend mode. The final
650f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * pixel color is chosen using the plane alpha and blend
651f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                 * mode formulas found in hwcomposer2.h */
652f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
653f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
654f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
655f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    rCur *= planeAlpha;
656f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    gCur *= planeAlpha;
657f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    bCur *= planeAlpha;
658f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
659f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
660f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                aCur *= planeAlpha;
661f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
662f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
663f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = rCur + r * (1.0 - aCur);
664f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = gCur + g * (1.0 - aCur);
665f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = bCur + b * (1.0 - aCur);
666f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = aCur + a * (1.0 - aCur);
667f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
668f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = rCur * aCur + r * (1.0 - aCur);
669f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = gCur * aCur + g * (1.0 - aCur);
670f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = bCur * aCur + b * (1.0 - aCur);
671f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = aCur * aCur + a * (1.0 - aCur);
672f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                } else {
673f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    r = rCur;
674f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    g = gCur;
675f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    b = bCur;
676f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                    a = aCur;
677f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall                }
678f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            }
679f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
680f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall            /* Set the pixel color */
6813f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            setColor(x, y, format, stride, img, r, g, b, a * 255);
682f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall        }
683f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    }
684f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
6853f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    graphicBuffer->unlock();
6863f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr}
6873f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
6883f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr/* Generates a client target buffer using the layers assigned for client
6893f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr * composition. Takes into account the individual layer properties such as
6903f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr * transform, blend mode, source crop, etc. */
6913f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jrint Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
6923f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        int32_t* outFence, const Area& bufferArea,
6933f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const Hwc2TestLayers* testLayers,
6943f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const std::set<hwc2_layer_t>* clientLayers,
6953f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const std::set<hwc2_layer_t>* clearLayers)
6963f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr{
6973f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    /* Create new graphic buffer with correct dimensions */
6983f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
6993f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
7003f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
7013f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7023f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    int ret = mGraphicBuffer->initCheck();
7033f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (ret)
7043f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return ret;
7053f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7063f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (!mGraphicBuffer->handle)
7073f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return -EINVAL;
7083f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7093f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    compositeBufferFromLayers(mGraphicBuffer, mFormat, bufferArea, testLayers,
7103f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            clientLayers, clearLayers);
711f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
712f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    *outFence = mFenceGenerator->get();
713f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    *outHandle = mGraphicBuffer->handle;
714f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall
715f18cfb0a780c69f12439457ccc3f5272db767fddMarissa Wall    return 0;
7165a240aaf0e3a1dd52be6a8d0811ec727369a210dMarissa Wall}
7173f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7183f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jrvoid Hwc2TestVirtualBuffer::updateBufferArea(const Area& bufferArea)
7193f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr{
7203f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mBufferArea.width = bufferArea.width;
7213f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mBufferArea.height = bufferArea.height;
7223f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr}
7233f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7243f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jrbool Hwc2TestVirtualBuffer::writeBufferToFile(std::string path)
7253f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr{
7263f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    SkFILEWStream file(path.c_str());
7273f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    const SkImageInfo info = SkImageInfo::Make(mBufferArea.width,
7283f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            mBufferArea.height, SkColorType::kRGBA_8888_SkColorType,
7293f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            SkAlphaType::kPremul_SkAlphaType);
7303f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7313f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    uint8_t* img;
7323f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
7333f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            (void**)(&img));
7343f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7353f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    SkPixmap pixmap(info, img, mGraphicBuffer->getStride());
7363f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    bool result = file.isValid() && SkEncodeImage(&file, pixmap,
7373f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            SkEncodedImageFormat::kPNG, 100);
7383f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7393f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mGraphicBuffer->unlock();
7403f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    return result;
7413f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr}
7423f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7433f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr/* Generates a buffer that holds the expected result of compositing all of our
7443f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr * layers */
7453f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jrint Hwc2TestExpectedBuffer::generateExpectedBuffer(
7463f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const Hwc2TestLayers* testLayers,
7473f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const std::vector<hwc2_layer_t>* allLayers,
7483f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        const std::set<hwc2_layer_t>* clearLayers)
7493f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr{
7503f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
7513f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
7523f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            "hwc2_test_buffer");
7533f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7543f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    int ret = mGraphicBuffer->initCheck();
7553f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (ret)
7563f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return ret;
7573f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7583f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (!mGraphicBuffer->handle)
7593f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return -EINVAL;
7603f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7613f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    const std::set<hwc2_layer_t> allLayerSet(allLayers->begin(),
7623f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            allLayers->end());
7633f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7643f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    compositeBufferFromLayers(mGraphicBuffer, mFormat, mBufferArea, testLayers,
7653f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            &allLayerSet, clearLayers);
7663f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7673f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    return 0;
7683f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr}
7693f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7703f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jrint Hwc2TestOutputBuffer::getOutputBuffer(buffer_handle_t* outHandle,
7713f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        int32_t* outFence)
7723f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr{
7733f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (mBufferArea.width == -1 || mBufferArea.height == -1)
7743f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return -EINVAL;
7753f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7763f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
7773f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            mFormat, BufferUsage::CPU_READ_OFTEN |
7783f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr            BufferUsage::GPU_RENDER_TARGET, "hwc2_test_buffer");
7793f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7803f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    int ret = mGraphicBuffer->initCheck();
7813f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (ret)
7823f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return ret;
7833f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7843f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    if (!mGraphicBuffer->handle)
7853f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr        return -EINVAL;
7863f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7873f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    *outFence = -1;
7883f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    *outHandle = mGraphicBuffer->handle;
7893f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr
7903f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr    return 0;
7913f05602a8c33a4b66a47dc077eaba95f9f1e3977David Hanna Jr}
792