1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <mutex>
18#include <array>
19#include <sstream>
20#include <algorithm>
21
22#include <gui/Surface.h>
23#include <gui/BufferItemConsumer.h>
24
25#include <ui/GraphicBuffer.h>
26#include <math/vec4.h>
27
28#include <GLES3/gl3.h>
29
30#include "Hwc2TestBuffer.h"
31#include "Hwc2TestLayers.h"
32
33using namespace android;
34
35/* Returns a fence from egl */
36typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
37
38/* Returns fence to fence generator */
39static void setFence(int32_t fence, void* fenceGenerator);
40
41
42/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
43 * away. The fences are sent to the requester via a callback */
44class Hwc2TestSurfaceManager {
45public:
46    /* Listens for a new frame, detaches the buffer and returns the fence
47     * through saved callback. */
48    class BufferListener : public ConsumerBase::FrameAvailableListener {
49    public:
50        BufferListener(sp<IGraphicBufferConsumer> consumer,
51                FenceCallback callback, void* callbackArgs)
52            : mConsumer(consumer),
53              mCallback(callback),
54              mCallbackArgs(callbackArgs) { }
55
56        void onFrameAvailable(const BufferItem& /*item*/)
57        {
58            BufferItem item;
59
60            if (mConsumer->acquireBuffer(&item, 0))
61                return;
62            if (mConsumer->detachBuffer(item.mSlot))
63                return;
64
65            mCallback(item.mFence->dup(), mCallbackArgs);
66        }
67
68    private:
69        sp<IGraphicBufferConsumer> mConsumer;
70        FenceCallback mCallback;
71        void* mCallbackArgs;
72    };
73
74    /* Creates a buffer listener that waits on a new frame from the buffer
75     * queue. */
76    void initialize(const Area& bufferArea, android_pixel_format_t format,
77            FenceCallback callback, void* callbackArgs)
78    {
79        sp<IGraphicBufferProducer> producer;
80        sp<IGraphicBufferConsumer> consumer;
81        BufferQueue::createBufferQueue(&producer, &consumer);
82
83        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
84        consumer->setDefaultBufferFormat(format);
85
86        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
87
88        mListener = new BufferListener(consumer, callback, callbackArgs);
89        mBufferItemConsumer->setFrameAvailableListener(mListener);
90
91        mSurface = new Surface(producer, true);
92    }
93
94    /* Used by Egl manager. The surface is never displayed. */
95    sp<Surface> getSurface() const
96    {
97        return mSurface;
98    }
99
100private:
101    sp<BufferItemConsumer> mBufferItemConsumer;
102    sp<BufferListener> mListener;
103    /* Used by Egl manager. The surface is never displayed */
104    sp<Surface> mSurface;
105};
106
107
108/* Used to generate valid fences. It is not possible to create a dummy sync
109 * fence for testing. Egl can generate buffers along with a valid fence.
110 * The buffer cannot be guaranteed to be the same format across all devices so
111 * a CPU filled buffer is used instead. The Egl fence is used along with the
112 * CPU filled buffer. */
113class Hwc2TestEglManager {
114public:
115    Hwc2TestEglManager()
116        : mEglDisplay(EGL_NO_DISPLAY),
117          mEglSurface(EGL_NO_SURFACE),
118          mEglContext(EGL_NO_CONTEXT) { }
119
120    ~Hwc2TestEglManager()
121    {
122        cleanup();
123    }
124
125    int initialize(sp<Surface> surface)
126    {
127        mSurface = surface;
128
129        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
130        if (mEglDisplay == EGL_NO_DISPLAY) return false;
131
132        EGLint major;
133        EGLint minor;
134        if (!eglInitialize(mEglDisplay, &major, &minor)) {
135            ALOGW("Could not initialize EGL");
136            return false;
137        }
138
139        /* We're going to use a 1x1 pbuffer surface later on
140         * The configuration distance doesn't really matter for what we're
141         * trying to do */
142        EGLint configAttrs[] = {
143                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
144                EGL_RED_SIZE, 8,
145                EGL_GREEN_SIZE, 8,
146                EGL_BLUE_SIZE, 8,
147                EGL_ALPHA_SIZE, 0,
148                EGL_DEPTH_SIZE, 24,
149                EGL_STENCIL_SIZE, 0,
150                EGL_NONE
151        };
152
153        EGLConfig configs[1];
154        EGLint configCnt;
155        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
156                &configCnt)) {
157            ALOGW("Could not select EGL configuration");
158            eglReleaseThread();
159            eglTerminate(mEglDisplay);
160            return false;
161        }
162
163        if (configCnt <= 0) {
164            ALOGW("Could not find EGL configuration");
165            eglReleaseThread();
166            eglTerminate(mEglDisplay);
167            return false;
168        }
169
170        /* These objects are initialized below but the default "null" values are
171         * used to cleanup properly at any point in the initialization sequence */
172        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
173        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
174                attrs);
175        if (mEglContext == EGL_NO_CONTEXT) {
176            ALOGW("Could not create EGL context");
177            cleanup();
178            return false;
179        }
180
181        EGLint surfaceAttrs[] = { EGL_NONE };
182        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
183                mSurface.get(), surfaceAttrs);
184        if (mEglSurface == EGL_NO_SURFACE) {
185            ALOGW("Could not create EGL surface");
186            cleanup();
187            return false;
188        }
189
190        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
191            ALOGW("Could not change current EGL context");
192            cleanup();
193            return false;
194        }
195
196        return true;
197    }
198
199    void makeCurrent() const
200    {
201        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
202    }
203
204    void present() const
205    {
206        eglSwapBuffers(mEglDisplay, mEglSurface);
207    }
208
209private:
210    void cleanup()
211    {
212        if (mEglDisplay == EGL_NO_DISPLAY)
213            return;
214        if (mEglSurface != EGL_NO_SURFACE)
215            eglDestroySurface(mEglDisplay, mEglSurface);
216        if (mEglContext != EGL_NO_CONTEXT)
217            eglDestroyContext(mEglDisplay, mEglContext);
218
219        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
220                EGL_NO_CONTEXT);
221        eglReleaseThread();
222        eglTerminate(mEglDisplay);
223    }
224
225    sp<Surface> mSurface;
226    EGLDisplay mEglDisplay;
227    EGLSurface mEglSurface;
228    EGLContext mEglContext;
229};
230
231
232static const std::array<vec2, 4> triangles = {{
233    {  1.0f,  1.0f },
234    { -1.0f,  1.0f },
235    {  1.0f, -1.0f },
236    { -1.0f, -1.0f },
237}};
238
239class Hwc2TestFenceGenerator {
240public:
241
242    Hwc2TestFenceGenerator()
243    {
244        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
245                setFence, this);
246
247        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
248            return;
249
250        mEglManager.makeCurrent();
251
252        glClearColor(0.0, 0.0, 0.0, 1.0);
253        glEnableVertexAttribArray(0);
254    }
255
256    ~Hwc2TestFenceGenerator()
257    {
258        if (mFence >= 0)
259            close(mFence);
260        mFence = -1;
261
262        mEglManager.makeCurrent();
263    }
264
265    /* It is not possible to simply generate a fence. The easiest way is to
266     * generate a buffer using egl and use the associated fence. The buffer
267     * cannot be guaranteed to be a certain format across all devices using this
268     * method. Instead the buffer is generated using the CPU */
269    int32_t get()
270    {
271        if (mFence >= 0) {
272            return dup(mFence);
273        }
274
275        std::unique_lock<std::mutex> lock(mMutex);
276
277        /* If the pending is still set to false and times out, we cannot recover.
278         * Set an error and return */
279        while (mPending != false) {
280            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
281                return -ETIME;
282        }
283
284        /* Generate a fence. The fence will be returned through the setFence
285         * callback */
286        mEglManager.makeCurrent();
287
288        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
289        glClear(GL_COLOR_BUFFER_BIT);
290
291        mEglManager.present();
292
293        /* Wait for the setFence callback */
294        while (mPending != true) {
295            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
296                return -ETIME;
297        }
298
299        mPending = false;
300
301        return dup(mFence);
302    }
303
304    /* Callback that sets the fence */
305    void set(int32_t fence)
306    {
307        mFence = fence;
308        mPending = true;
309
310        mCv.notify_all();
311    }
312
313private:
314
315    Hwc2TestSurfaceManager mSurfaceManager;
316    Hwc2TestEglManager mEglManager;
317
318    std::mutex mMutex;
319    std::condition_variable mCv;
320
321    int32_t mFence = -1;
322    bool mPending = false;
323};
324
325
326static void setFence(int32_t fence, void* fenceGenerator)
327{
328    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
329}
330
331
332/* Sets the pixel of a buffer given the location, format, stride and color.
333 * Currently only supports RGBA_8888 */
334static void setColor(int32_t x, int32_t y,
335        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
336        uint8_t g, uint8_t b, uint8_t a)
337{
338       switch (format) {
339       case HAL_PIXEL_FORMAT_RGBA_8888:
340           img[(y * stride + x) * 4 + 0] = r;
341           img[(y * stride + x) * 4 + 1] = g;
342           img[(y * stride + x) * 4 + 2] = b;
343           img[(y * stride + x) * 4 + 3] = a;
344           break;
345       default:
346           break;
347       }
348}
349
350Hwc2TestBuffer::Hwc2TestBuffer()
351    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
352
353Hwc2TestBuffer::~Hwc2TestBuffer() = default;
354
355/* When the buffer changes sizes, save the new size and invalidate the current
356 * buffer */
357void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
358{
359    if (mBufferArea.width == bufferArea.width
360            && mBufferArea.height == bufferArea.height)
361        return;
362
363    mBufferArea.width = bufferArea.width;
364    mBufferArea.height = bufferArea.height;
365
366    mValidBuffer = false;
367}
368
369/* Returns a valid buffer handle and fence. The handle is filled using the CPU
370 * to ensure the correct format across all devices. The fence is created using
371 * egl. */
372int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
373{
374    if (mBufferArea.width == -1 || mBufferArea.height == -1)
375        return -EINVAL;
376
377    /* If the current buffer is valid, the previous buffer can be reused.
378     * Otherwise, create new buffer */
379    if (!mValidBuffer) {
380        int ret = generateBuffer();
381        if (ret)
382            return ret;
383    }
384
385    *outFence = mFenceGenerator->get();
386    *outHandle = mHandle;
387
388    mValidBuffer = true;
389
390    return 0;
391}
392
393/* CPU fills a buffer to guarantee the correct buffer format across all
394 * devices */
395int Hwc2TestBuffer::generateBuffer()
396{
397    /* Create new graphic buffer with correct dimensions */
398    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
399            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
400            "hwc2_test_buffer");
401    int ret = mGraphicBuffer->initCheck();
402    if (ret) {
403        return ret;
404    }
405    if (!mGraphicBuffer->handle) {
406        return -EINVAL;
407    }
408
409    /* Locks the buffer for writing */
410    uint8_t* img;
411    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
412
413    uint32_t stride = mGraphicBuffer->getStride();
414
415    /* Iterate from the top row of the buffer to the bottom row */
416    for (int32_t y = 0; y < mBufferArea.height; y++) {
417
418        /* Will be used as R, G and B values for pixel colors */
419        uint8_t max = 255;
420        uint8_t min = 0;
421
422        /* Divide the rows into 3 sections. The first section will contain
423         * the lighest colors. The last section will contain the darkest
424         * colors. */
425        if (y < mBufferArea.height * 1.0 / 3.0) {
426            min = 255 / 2;
427        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
428            max = 255 / 2;
429        }
430
431        /* Divide the columns into 3 sections. The first section is red,
432         * the second is green and the third is blue */
433        int32_t x = 0;
434        for (; x < mBufferArea.width / 3; x++) {
435            setColor(x, y, mFormat, stride, img, max, min, min, 255);
436        }
437
438        for (; x < mBufferArea.width * 2 / 3; x++) {
439            setColor(x, y, mFormat, stride, img, min, max, min, 255);
440        }
441
442        for (; x < mBufferArea.width; x++) {
443            setColor(x, y, mFormat, stride, img, min, min, max, 255);
444        }
445    }
446
447    /* Unlock the buffer for reading */
448    mGraphicBuffer->unlock();
449
450    mHandle = mGraphicBuffer->handle;
451
452    return 0;
453}
454
455
456Hwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
457    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
458
459Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
460
461/* Generates a client target buffer using the layers assigned for client
462 * composition. Takes into account the individual layer properties such as
463 * transform, blend mode, source crop, etc. */
464int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
465        int32_t* outFence, const Area& bufferArea,
466        const Hwc2TestLayers* testLayers,
467        const std::set<hwc2_layer_t>* clientLayers,
468        const std::set<hwc2_layer_t>* clearLayers)
469{
470    /* Create new graphic buffer with correct dimensions */
471    mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
472            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
473            "hwc2_test_buffer");
474    int ret = mGraphicBuffer->initCheck();
475    if (ret) {
476        return ret;
477    }
478    if (!mGraphicBuffer->handle) {
479        return -EINVAL;
480    }
481
482    uint8_t* img;
483    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
484
485    uint32_t stride = mGraphicBuffer->getStride();
486
487    float bWDiv3 = bufferArea.width / 3;
488    float bW2Div3 = bufferArea.width * 2 / 3;
489    float bHDiv3 = bufferArea.height / 3;
490    float bH2Div3 = bufferArea.height * 2 / 3;
491
492    /* Cycle through every pixel in the buffer and determine what color it
493     * should be. */
494    for (int32_t y = 0; y < bufferArea.height; y++) {
495        for (int32_t x = 0; x < bufferArea.width; x++) {
496
497            uint8_t r = 0, g = 0, b = 0;
498            float a = 0.0f;
499
500            /* Cycle through each client layer from back to front and
501             * update the pixel color. */
502            for (auto layer = clientLayers->rbegin();
503                    layer != clientLayers->rend(); ++layer) {
504
505                const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
506
507                float dfL = df.left;
508                float dfT = df.top;
509                float dfR = df.right;
510                float dfB = df.bottom;
511
512                /* If the pixel location falls outside of the layer display
513                 * frame, skip the layer. */
514                if (x < dfL || x >= dfR || y < dfT || y >= dfB)
515                    continue;
516
517                /* If the device has requested the layer be clear, clear
518                 * the pixel and continue. */
519                if (clearLayers->count(*layer) != 0) {
520                    r = 0;
521                    g = 0;
522                    b = 0;
523                    a = 0.0f;
524                    continue;
525                }
526
527                float planeAlpha = testLayers->getPlaneAlpha(*layer);
528
529                /* If the layer is a solid color, fill the color and
530                 * continue. */
531                if (testLayers->getComposition(*layer)
532                        == HWC2_COMPOSITION_SOLID_COLOR) {
533                    const auto color = testLayers->getColor(*layer);
534                    r = color.r;
535                    g = color.g;
536                    b = color.b;
537                    a = color.a * planeAlpha;
538                    continue;
539                }
540
541                float xPos = x;
542                float yPos = y;
543
544                hwc_transform_t transform = testLayers->getTransform(*layer);
545
546                float dfW = dfR - dfL;
547                float dfH = dfB - dfT;
548
549                /* If a layer has a transform, find which location on the
550                 * layer will end up in the current pixel location. We
551                 * can calculate the color of the current pixel using that
552                 * location. */
553                if (transform > 0) {
554                    /* Change origin to be the center of the layer. */
555                    xPos = xPos - dfL - dfW / 2.0;
556                    yPos = yPos - dfT - dfH / 2.0;
557
558                    /* Flip Horizontal by reflecting across the y axis. */
559                    if (transform & HWC_TRANSFORM_FLIP_H)
560                        xPos = -xPos;
561
562                    /* Flip vertical by reflecting across the x axis. */
563                    if (transform & HWC_TRANSFORM_FLIP_V)
564                        yPos = -yPos;
565
566                    /* Rotate 90 by using a basic linear algebra rotation
567                     * and scaling the result so the display frame remains
568                     * the same. For example, a buffer of size 100x50 should
569                     * rotate 90 degress but remain the same dimension
570                     * (100x50) at the end of the transformation. */
571                    if (transform & HWC_TRANSFORM_ROT_90) {
572                        float tmp = xPos;
573                        xPos = -yPos * dfW / dfH;
574                        yPos = tmp * dfH / dfW;
575                    }
576
577                    /* Change origin back to the top left corner of the
578                     * layer. */
579                    xPos = xPos + dfL + dfW / 2.0;
580                    yPos = yPos + dfT + dfH / 2.0;
581                }
582
583                hwc_frect_t sc = testLayers->getSourceCrop(*layer);
584                float scL = sc.left, scT = sc.top;
585
586                float dfWDivScW = dfW / (sc.right - scL);
587                float dfHDivScH = dfH / (sc.bottom - scT);
588
589                float max = 255, min = 0;
590
591                /* Choose the pixel color. Similar to generateBuffer,
592                 * each layer will be divided into 3x3 colors. Because
593                 * both the source crop and display frame must be taken into
594                 * account, the formulas are more complicated.
595                 *
596                 * If the source crop and display frame were not taken into
597                 * account, we would simply divide the buffer into three
598                 * sections by height. Each section would get one color.
599                 * For example the formula for the first section would be:
600                 *
601                 * if (yPos < bufferArea.height / 3)
602                 *        //Select first section color
603                 *
604                 * However the pixel color is chosen based on the source
605                 * crop and displayed based on the display frame.
606                 *
607                 * If the display frame top was 0 and the source crop height
608                 * and display frame height were the same. The only factor
609                 * would be the source crop top. To calculate the new
610                 * section boundary, the section boundary would be moved up
611                 * by the height of the source crop top. The formula would
612                 * be:
613                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
614                 *        //Select first section color
615                 *
616                 * If the display frame top could also vary but source crop
617                 * and display frame heights were the same, the formula
618                 * would be:
619                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top
620                 *              + displayFrameTop)
621                 *        //Select first section color
622                 *
623                 * If the heights were not the same, the conversion between
624                 * the source crop and display frame dimensions must be
625                 * taken into account. The formula would be:
626                 * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
627                 *              * displayFrameHeight / sourceCropHeight
628                 *              + displayFrameTop)
629                 *        //Select first section color
630                 */
631                if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
632                    min = 255 / 2;
633                } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
634                    max = 255 / 2;
635                }
636
637                uint8_t rCur = min, gCur = min, bCur = min;
638                float aCur = 1.0f;
639
640                /* This further divides the color sections from 3 to 3x3.
641                 * The math behind it follows the same logic as the previous
642                 * comment */
643                if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
644                    rCur = max;
645                } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
646                    gCur = max;
647                } else {
648                    bCur = max;
649                }
650
651
652                /* Blend the pixel color with the previous layers' pixel
653                 * colors using the plane alpha and blend mode. The final
654                 * pixel color is chosen using the plane alpha and blend
655                 * mode formulas found in hwcomposer2.h */
656                hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
657
658                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
659                    rCur *= planeAlpha;
660                    gCur *= planeAlpha;
661                    bCur *= planeAlpha;
662                }
663
664                aCur *= planeAlpha;
665
666                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
667                    r = rCur + r * (1.0 - aCur);
668                    g = gCur + g * (1.0 - aCur);
669                    b = bCur + b * (1.0 - aCur);
670                    a = aCur + a * (1.0 - aCur);
671                } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
672                    r = rCur * aCur + r * (1.0 - aCur);
673                    g = gCur * aCur + g * (1.0 - aCur);
674                    b = bCur * aCur + b * (1.0 - aCur);
675                    a = aCur * aCur + a * (1.0 - aCur);
676                } else {
677                    r = rCur;
678                    g = gCur;
679                    b = bCur;
680                    a = aCur;
681                }
682            }
683
684            /* Set the pixel color */
685            setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
686        }
687    }
688
689    mGraphicBuffer->unlock();
690
691    *outFence = mFenceGenerator->get();
692    *outHandle = mGraphicBuffer->handle;
693
694    return 0;
695}
696