1/*
2 * Copyright (C) 2011 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
18/*
19 * Hardware Composer Test Library
20 * Utility library functions for use by the Hardware Composer test cases
21 */
22
23#include <arpa/inet.h> // For ntohl() and htonl()
24
25#include <cmath>
26#include <sstream>
27#include <string>
28
29#include "hwcTestLib.h"
30
31#include "EGLUtils.h"
32
33// Defines
34#define NUMA(a) (sizeof(a) / sizeof((a)[0]))
35
36// Function Prototypes
37static void printGLString(const char *name, GLenum s);
38static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
39static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
40
41using namespace std;
42using namespace android;
43
44
45#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
46                                 // it has been added
47
48// Initialize Display
49void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
50    EGLint *width, EGLint *height)
51{
52    static EGLContext context;
53
54    EGLBoolean returnValue;
55    EGLConfig myConfig = {0};
56    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
57    EGLint sConfigAttribs[] = {
58        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
59        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
60        EGL_NONE };
61    EGLint majorVersion, minorVersion;
62
63    checkEglError("<init>");
64    *dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
65    checkEglError("eglGetDisplay");
66    if (*dpy == EGL_NO_DISPLAY) {
67        testPrintE("eglGetDisplay returned EGL_NO_DISPLAY");
68        exit(70);
69    }
70
71    returnValue = eglInitialize(*dpy, &majorVersion, &minorVersion);
72    checkEglError("eglInitialize", returnValue);
73    if (verbose) {
74        testPrintI("EGL version %d.%d", majorVersion, minorVersion);
75    }
76    if (returnValue != EGL_TRUE) {
77        testPrintE("eglInitialize failed");
78        exit(71);
79    }
80
81    // The tests want to stop the framework and play with the hardware
82    // composer, which means it doesn't make sense to use WindowSurface
83    // here.  android_createDisplaySurface() is going away, so just
84    // politely fail here.
85    EGLNativeWindowType window = NULL; //android_createDisplaySurface();
86    if (window == NULL) {
87        testPrintE("android_createDisplaySurface failed");
88        exit(72);
89    }
90    returnValue = EGLUtils::selectConfigForNativeWindow(*dpy,
91        sConfigAttribs, window, &myConfig);
92    if (returnValue) {
93        testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
94            returnValue);
95        exit(73);
96    }
97    checkEglError("EGLUtils::selectConfigForNativeWindow");
98
99    if (verbose) {
100        testPrintI("Chose this configuration:");
101        printEGLConfiguration(*dpy, myConfig);
102    }
103
104    *surface = eglCreateWindowSurface(*dpy, myConfig, window, NULL);
105    checkEglError("eglCreateWindowSurface");
106    if (*surface == EGL_NO_SURFACE) {
107        testPrintE("gelCreateWindowSurface failed.");
108        exit(74);
109    }
110
111    context = eglCreateContext(*dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
112    checkEglError("eglCreateContext");
113    if (context == EGL_NO_CONTEXT) {
114        testPrintE("eglCreateContext failed");
115        exit(75);
116    }
117    returnValue = eglMakeCurrent(*dpy, *surface, *surface, context);
118    checkEglError("eglMakeCurrent", returnValue);
119    if (returnValue != EGL_TRUE) {
120        testPrintE("eglMakeCurrent failed");
121        exit(76);
122    }
123    eglQuerySurface(*dpy, *surface, EGL_WIDTH, width);
124    checkEglError("eglQuerySurface");
125    eglQuerySurface(*dpy, *surface, EGL_HEIGHT, height);
126    checkEglError("eglQuerySurface");
127
128    if (verbose) {
129        testPrintI("Window dimensions: %d x %d", *width, *height);
130
131        printGLString("Version", GL_VERSION);
132        printGLString("Vendor", GL_VENDOR);
133        printGLString("Renderer", GL_RENDERER);
134        printGLString("Extensions", GL_EXTENSIONS);
135    }
136}
137
138// Open Hardware Composer Device
139void hwcTestOpenHwc(hwc_composer_device_1_t **hwcDevicePtr)
140{
141    int rv;
142    hw_module_t const *hwcModule;
143
144    if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
145        testPrintE("hw_get_module failed, rv: %i", rv);
146        errno = -rv;
147        perror(NULL);
148        exit(77);
149    }
150    if ((rv = hwc_open_1(hwcModule, hwcDevicePtr)) != 0) {
151        testPrintE("hwc_open failed, rv: %i", rv);
152        errno = -rv;
153        perror(NULL);
154        exit(78);
155    }
156}
157
158// Color fraction class to string conversion
159ColorFract::operator string()
160{
161    ostringstream out;
162
163    out << '[' << this->c1() << ", "
164        << this->c2() << ", "
165        << this->c3() << ']';
166
167    return out.str();
168}
169
170// Dimension class to string conversion
171HwcTestDim::operator string()
172{
173    ostringstream out;
174
175    out << '[' << this->width() << ", "
176        << this->height() << ']';
177
178    return out.str();
179}
180
181// Dimension class to hwc_rect conversion
182HwcTestDim::operator hwc_rect() const
183{
184    hwc_rect rect;
185
186    rect.left = rect.top = 0;
187
188    rect.right = this->_w;
189    rect.bottom = this->_h;
190
191    return rect;
192}
193
194// Hardware Composer rectangle to string conversion
195string hwcTestRect2str(const struct hwc_rect& rect)
196{
197    ostringstream out;
198
199    out << '[';
200    out << rect.left << ", ";
201    out << rect.top << ", ";
202    out << rect.right << ", ";
203    out << rect.bottom;
204    out << ']';
205
206    return out.str();
207}
208
209// Parse HWC rectangle description of form [left, top, right, bottom]
210struct hwc_rect hwcTestParseHwcRect(istringstream& in, bool& error)
211{
212    struct hwc_rect rect;
213    char chStart, ch;
214
215    // Defensively specify that an error occurred.  Will clear
216    // error flag if all of parsing succeeds.
217    error = true;
218
219    // First character should be a [ or <
220    in >> chStart;
221    if (!in || ((chStart != '<') && (chStart != '['))) { return rect; }
222
223    // Left
224    in >> rect.left;
225    if (!in) { return rect; }
226    in >> ch;
227    if (!in || (ch != ',')) { return rect; }
228
229    // Top
230    in >> rect.top;
231    if (!in) { return rect; }
232    in >> ch;
233    if (!in || (ch != ',')) { return rect; }
234
235    // Right
236    in >> rect.right;
237    if (!in) { return rect; }
238    in >> ch;
239    if (!in || (ch != ',')) { return rect; }
240
241    // Bottom
242    in >> rect.bottom;
243    if (!in) { return rect; }
244
245    // Closing > or ]
246    in >> ch;
247    if (!in) { return rect; }
248    if (((chStart == '<') && (ch != '>'))
249        || ((chStart == '[') && (ch != ']'))) { return rect; }
250
251    // Validate right and bottom are greater than left and top
252    if ((rect.right <= rect.left) || (rect.bottom <= rect.top)) { return rect; }
253
254    // Made It, clear error indicator
255    error = false;
256
257    return rect;
258}
259
260// Parse dimension of form [width, height]
261HwcTestDim hwcTestParseDim(istringstream& in, bool& error)
262{
263    HwcTestDim dim;
264    char chStart, ch;
265    uint32_t val;
266
267    // Defensively specify that an error occurred.  Will clear
268    // error flag if all of parsing succeeds.
269    error = true;
270
271    // First character should be a [ or <
272    in >> chStart;
273    if (!in || ((chStart != '<') && (chStart != '['))) { return dim; }
274
275    // Width
276    in >> val;
277    if (!in) { return dim; }
278    dim.setWidth(val);
279    in >> ch;
280    if (!in || (ch != ',')) { return dim; }
281
282    // Height
283    in >> val;
284    if (!in) { return dim; }
285    dim.setHeight(val);
286
287    // Closing > or ]
288    in >> ch;
289    if (!in) { return dim; }
290    if (((chStart == '<') && (ch != '>'))
291        || ((chStart == '[') && (ch != ']'))) { return dim; }
292
293    // Validate width and height greater than 0
294    if ((dim.width() <= 0) || (dim.height() <= 0)) { return dim; }
295
296    // Made It, clear error indicator
297    error = false;
298    return dim;
299}
300
301// Parse fractional color of form [0.##, 0.##, 0.##]
302// Fractional values can be from 0.0 to 1.0 inclusive.  Note, integer
303// values of 0.0 and 1.0, which are non-fractional, are considered valid.
304// They are an exception, all other valid inputs are fractions.
305ColorFract hwcTestParseColor(istringstream& in, bool& error)
306{
307    ColorFract color;
308    char chStart, ch;
309    float c1, c2, c3;
310
311    // Defensively specify that an error occurred.  Will clear
312    // error flag if all of parsing succeeds.
313    error = true;
314
315    // First character should be a [ or <
316    in >> chStart;
317    if (!in || ((chStart != '<') && (chStart != '['))) { return color; }
318
319    // 1st Component
320    in >> c1;
321    if (!in) { return color; }
322    if ((c1 < 0.0) || (c1 > 1.0)) { return color; }
323    in >> ch;
324    if (!in || (ch != ',')) { return color; }
325
326    // 2nd Component
327    in >> c2;
328    if (!in) { return color; }
329    if ((c2 < 0.0) || (c2 > 1.0)) { return color; }
330    in >> ch;
331    if (!in || (ch != ',')) { return color; }
332
333    // 3rd Component
334    in >> c3;
335    if (!in) { return color; }
336    if ((c3 < 0.0) || (c3 > 1.0)) { return color; }
337
338    // Closing > or ]
339    in >> ch;
340    if (!in) { return color; }
341    if (((chStart == '<') && (ch != '>'))
342        || ((chStart == '[') && (ch != ']'))) { return color; }
343
344    // Are all the components fractional
345    if ((c1 < 0.0) || (c1 > 1.0)
346        || (c2 < 0.0) || (c2 > 1.0)
347        || (c3 < 0.0) || (c3 > 1.0)) { return color; }
348
349    // Made It, clear error indicator
350    error = false;
351
352    return ColorFract(c1, c2, c3);
353}
354
355// Look up and return pointer to structure with the characteristics
356// of the graphic format named by the desc parameter.  Search failure
357// indicated by the return of NULL.
358const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc)
359{
360    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
361        if (string(desc) == string(hwcTestGraphicFormat[n1].desc)) {
362            return &hwcTestGraphicFormat[n1];
363        }
364    }
365
366    return NULL;
367}
368
369// Look up and return pointer to structure with the characteristics
370// of the graphic format specified by the id parameter.  Search failure
371// indicated by the return of NULL.
372const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id)
373{
374    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
375        if (id == hwcTestGraphicFormat[n1].format) {
376            return &hwcTestGraphicFormat[n1];
377        }
378    }
379
380    return NULL;
381}
382
383
384// Given the integer ID of a graphic format, return a pointer to
385// a string that describes the format.
386const char *hwcTestGraphicFormat2str(uint32_t format)
387{
388    const static char *unknown = "unknown";
389
390    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
391        if (format == hwcTestGraphicFormat[n1].format) {
392            return hwcTestGraphicFormat[n1].desc;
393        }
394    }
395
396    return unknown;
397}
398
399/*
400 * hwcTestCreateLayerList
401 * Dynamically creates layer list with numLayers worth
402 * of hwLayers entries.
403 */
404hwc_display_contents_1_t *hwcTestCreateLayerList(size_t numLayers)
405{
406    hwc_display_contents_1_t *list;
407
408    size_t size = sizeof(hwc_display_contents_1_t) + numLayers * sizeof(hwc_layer_1_t);
409    if ((list = (hwc_display_contents_1_t *) calloc(1, size)) == NULL) {
410        return NULL;
411    }
412    list->flags = HWC_GEOMETRY_CHANGED;
413    list->numHwLayers = numLayers;
414
415    return list;
416}
417
418/*
419 * hwcTestFreeLayerList
420 * Frees memory previous allocated via hwcTestCreateLayerList().
421 */
422void hwcTestFreeLayerList(hwc_display_contents_1_t *list)
423{
424    free(list);
425}
426
427// Display the settings of the layer list pointed to by list
428void hwcTestDisplayList(hwc_display_contents_1_t *list)
429{
430    testPrintI("  flags: %#x%s", list->flags,
431               (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
432    testPrintI("  numHwLayers: %u", list->numHwLayers);
433
434    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
435        testPrintI("    layer %u compositionType: %#x%s%s", layer,
436                   list->hwLayers[layer].compositionType,
437                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
438                       ? " FRAMEBUFFER" : "",
439                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
440                       ? " OVERLAY" : "");
441
442        testPrintI("      hints: %#x",
443                   list->hwLayers[layer].hints,
444                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
445                       ? " TRIPLE_BUFFER" : "",
446                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
447                       ? " CLEAR_FB" : "");
448
449        testPrintI("      flags: %#x%s",
450                   list->hwLayers[layer].flags,
451                   (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
452                       ? " SKIP_LAYER" : "");
453
454        testPrintI("      handle: %p",
455                   list->hwLayers[layer].handle);
456
457        // Intentionally skipped display of ROT_180 & ROT_270,
458        // which are formed from combinations of the other flags.
459        testPrintI("      transform: %#x%s%s%s",
460                   list->hwLayers[layer].transform,
461                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
462                       ? " FLIP_H" : "",
463                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
464                       ? " FLIP_V" : "",
465                   (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
466                       ? " ROT_90" : "");
467
468        testPrintI("      blending: %#x%s%s%s",
469                   list->hwLayers[layer].blending,
470                   (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
471                       ? " NONE" : "",
472                   (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
473                       ? " PREMULT" : "",
474                   (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
475                       ? " COVERAGE" : "");
476
477        testPrintI("      sourceCrop: %s",
478                   hwcTestRect2str(list->hwLayers[layer].sourceCrop).c_str());
479        testPrintI("      displayFrame: %s",
480                   hwcTestRect2str(list->hwLayers[layer].displayFrame).c_str());
481        testPrintI("      scaleFactor: [%f, %f]",
482                   (float) (list->hwLayers[layer].sourceCrop.right
483                            - list->hwLayers[layer].sourceCrop.left)
484                       / (float) (list->hwLayers[layer].displayFrame.right
485                            - list->hwLayers[layer].displayFrame.left),
486                   (float) (list->hwLayers[layer].sourceCrop.bottom
487                            - list->hwLayers[layer].sourceCrop.top)
488                       / (float) (list->hwLayers[layer].displayFrame.bottom
489                            - list->hwLayers[layer].displayFrame.top));
490    }
491}
492
493/*
494 * Display List Prepare Modifiable
495 *
496 * Displays the portions of a list that are meant to be modified by
497 * a prepare call.
498 */
499void hwcTestDisplayListPrepareModifiable(hwc_display_contents_1_t *list)
500{
501    uint32_t numOverlays = 0;
502    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
503        if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
504            numOverlays++;
505        }
506        testPrintI("    layer %u compositionType: %#x%s%s", layer,
507                   list->hwLayers[layer].compositionType,
508                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
509                       ? " FRAMEBUFFER" : "",
510                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
511                       ? " OVERLAY" : "");
512        testPrintI("      hints: %#x%s%s",
513                   list->hwLayers[layer].hints,
514                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
515                       ? " TRIPLE_BUFFER" : "",
516                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
517                       ? " CLEAR_FB" : "");
518    }
519    testPrintI("    numOverlays: %u", numOverlays);
520}
521
522/*
523 * Display List Handles
524 *
525 * Displays the handles of all the graphic buffers in the list.
526 */
527void hwcTestDisplayListHandles(hwc_display_contents_1_t *list)
528{
529    const unsigned int maxLayersPerLine = 6;
530
531    ostringstream str("  layers:");
532    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
533        str << ' ' << list->hwLayers[layer].handle;
534        if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
535            && (layer != list->numHwLayers - 1)) {
536            testPrintI("%s", str.str().c_str());
537            str.str("    ");
538        }
539    }
540    testPrintI("%s", str.str().c_str());
541}
542
543// Returns a uint32_t that contains a format specific representation of a
544// single pixel of the given color and alpha values.
545uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha)
546{
547    const struct attrib {
548        uint32_t format;
549        bool   hostByteOrder;
550        size_t bytes;
551        size_t c1Offset;
552        size_t c1Size;
553        size_t c2Offset;
554        size_t c2Size;
555        size_t c3Offset;
556        size_t c3Size;
557        size_t aOffset;
558        size_t aSize;
559    } attributes[] = {
560        {HAL_PIXEL_FORMAT_RGBA_8888, false, 4,  0, 8,  8, 8, 16, 8, 24, 8},
561        {HAL_PIXEL_FORMAT_RGBX_8888, false, 4,  0, 8,  8, 8, 16, 8,  0, 0},
562        {HAL_PIXEL_FORMAT_RGB_888,   false, 3,  0, 8,  8, 8, 16, 8,  0, 0},
563        {HAL_PIXEL_FORMAT_RGB_565,   true,  2,  0, 5,  5, 6, 11, 5,  0, 0},
564        {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8,  8, 8,  0, 8, 24, 8},
565        {HAL_PIXEL_FORMAT_YV12,      true,  3, 16, 8,  8, 8,  0, 8,  0, 0},
566    };
567
568    const struct attrib *attrib;
569    for (attrib = attributes; attrib < attributes + NUMA(attributes);
570         attrib++) {
571        if (attrib->format == format) { break; }
572    }
573    if (attrib >= attributes + NUMA(attributes)) {
574        testPrintE("colorFract2Pixel unsupported format of: %u", format);
575        exit(80);
576    }
577
578    uint32_t pixel;
579    pixel = htonl((uint32_t) round((((1 << attrib->c1Size) - 1) * color.c1()))
580         << ((sizeof(pixel) * BITSPERBYTE)
581             - (attrib->c1Offset + attrib->c1Size)));
582    pixel |= htonl((uint32_t) round((((1 << attrib->c2Size) - 1) * color.c2()))
583         << ((sizeof(pixel) * BITSPERBYTE)
584             - (attrib->c2Offset + attrib->c2Size)));
585    pixel |= htonl((uint32_t) round((((1 << attrib->c3Size) - 1) * color.c3()))
586         << ((sizeof(pixel) * BITSPERBYTE)
587             - (attrib->c3Offset + attrib->c3Size)));
588    if (attrib->aSize) {
589        pixel |= htonl((uint32_t) round((((1 << attrib->aSize) - 1) * alpha))
590             << ((sizeof(pixel) * BITSPERBYTE)
591                 - (attrib->aOffset + attrib->aSize)));
592    }
593    if (attrib->hostByteOrder) {
594        pixel = ntohl(pixel);
595        pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
596    }
597
598    return pixel;
599}
600
601// Sets the pixel at the given x and y coordinates to the color and alpha
602// value given by pixel.  The contents of pixel is format specific.  It's
603// value should come from a call to hwcTestColor2Pixel().
604void hwcTestSetPixel(GraphicBuffer *gBuf, unsigned char *buf,
605              uint32_t x, uint32_t y, uint32_t pixel)
606{
607
608    const struct attrib {
609        int format;
610        size_t bytes;
611    } attributes[] = {
612        {HAL_PIXEL_FORMAT_RGBA_8888,  4},
613        {HAL_PIXEL_FORMAT_RGBX_8888,  4},
614        {HAL_PIXEL_FORMAT_RGB_888,    3},
615        {HAL_PIXEL_FORMAT_RGB_565,    2},
616        {HAL_PIXEL_FORMAT_BGRA_8888,  4},
617    };
618
619    if (gBuf->getPixelFormat() == HAL_PIXEL_FORMAT_YV12) {
620        uint32_t yPlaneOffset, uPlaneOffset, vPlaneOffset;
621        uint32_t yPlaneStride = gBuf->getStride();
622        uint32_t uPlaneStride = ((gBuf->getStride() / 2) + 0xf) & ~0xf;
623        uint32_t vPlaneStride = uPlaneStride;
624        yPlaneOffset = 0;
625        vPlaneOffset = yPlaneOffset + yPlaneStride * gBuf->getHeight();
626        uPlaneOffset = vPlaneOffset
627                       + vPlaneStride * (gBuf->getHeight() / 2);
628        *(buf + yPlaneOffset + y * yPlaneStride + x) = pixel & 0xff;
629        *(buf + uPlaneOffset + (y / 2) * uPlaneStride + (x / 2))
630            = (pixel & 0xff00) >> 8;
631        *(buf + vPlaneOffset + (y / 2) * vPlaneStride + (x / 2))
632            = (pixel & 0xff0000) >> 16;
633
634        return;
635    }
636
637    const struct attrib *attrib;
638    for (attrib = attributes; attrib < attributes + NUMA(attributes);
639         attrib++) {
640        if (attrib->format == gBuf->getPixelFormat()) { break; }
641    }
642    if (attrib >= attributes + NUMA(attributes)) {
643        testPrintE("setPixel unsupported format of: %u",
644                   gBuf->getPixelFormat());
645        exit(90);
646    }
647
648    memmove(buf + ((gBuf->getStride() * attrib->bytes) * y)
649            + (attrib->bytes * x), &pixel, attrib->bytes);
650}
651
652// Fill a given graphic buffer with a uniform color and alpha
653void hwcTestFillColor(GraphicBuffer *gBuf, ColorFract color, float alpha)
654{
655    unsigned char* buf = NULL;
656    status_t err;
657    uint32_t pixel;
658
659    pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, alpha);
660
661    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
662    if (err != 0) {
663        testPrintE("hwcTestFillColor lock failed: %d", err);
664        exit(100);
665    }
666
667    for (unsigned int x = 0; x < gBuf->getStride(); x++) {
668        for (unsigned int y = 0; y < gBuf->getHeight(); y++) {
669            hwcTestSetPixel(gBuf, buf, x, y, (x < gBuf->getWidth())
670                            ? pixel : testRand());
671        }
672    }
673
674    err = gBuf->unlock();
675    if (err != 0) {
676        testPrintE("hwcTestFillColor unlock failed: %d", err);
677        exit(101);
678    }
679}
680
681// Fill the given buffer with a horizontal blend of colors, with the left
682// side color given by startColor and the right side color given by
683// endColor.  The startColor and endColor values are specified in the format
684// given by colorFormat, which might be different from the format of the
685// graphic buffer.  When different, a color conversion is done when possible
686// to the graphic format of the graphic buffer.  A color of black is
687// produced for cases where the conversion is impossible (e.g. out of gamut
688// values).
689void hwcTestFillColorHBlend(GraphicBuffer *gBuf, uint32_t colorFormat,
690                            ColorFract startColor, ColorFract endColor)
691{
692    status_t err;
693    unsigned char* buf = NULL;
694    const uint32_t width = gBuf->getWidth();
695    const uint32_t height = gBuf->getHeight();
696    const uint32_t stride = gBuf->getStride();
697
698    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
699    if (err != 0) {
700        testPrintE("hwcTestFillColorHBlend lock failed: %d", err);
701        exit(110);
702    }
703
704    for (unsigned int x = 0; x < stride; x++) {
705        uint32_t pixel;
706        if (x < width) {
707            ColorFract color(startColor.c1() + (endColor.c1() - startColor.c1())
708                                 * ((float) x / (float) (width - 1)),
709                             startColor.c2() + (endColor.c2() - startColor.c2())
710                                 * ((float) x / (float) (width - 1)),
711                             startColor.c3() + (endColor.c3() - startColor.c3())
712                                 * ((float) x / (float) (width - 1)));
713
714            // When formats differ, convert colors.
715            // Important to not convert when formats are the same, since
716            // out of gamut colors are always converted to black.
717            if (colorFormat != (uint32_t) gBuf->getPixelFormat()) {
718                hwcTestColorConvert(colorFormat, gBuf->getPixelFormat(), color);
719            }
720            pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, 1.0);
721        } else {
722            // Fill pad with random values
723            pixel = testRand();
724        }
725
726        for (unsigned int y = 0; y < height; y++) {
727            hwcTestSetPixel(gBuf, buf, x, y, pixel);
728        }
729    }
730
731    err = gBuf->unlock();
732    if (err != 0) {
733        testPrintE("hwcTestFillColorHBlend unlock failed: %d", err);
734        exit(111);
735    }
736}
737
738/*
739 * When possible, converts color specified as a full range value in
740 * the fromFormat, into an equivalent full range color in the toFormat.
741 * When conversion is impossible (e.g. out of gamut color) a color
742 * or black in the full range output format is produced.  The input
743 * color is given as a fractional color in the parameter named color.
744 * The produced color is written over the same parameter used to
745 * provide the input color.
746 *
747 * Each graphic format has 3 color components and each of these
748 * components has both a full and in gamut range.  This function uses
749 * a table that provides the full and in gamut ranges of each of the
750 * supported graphic formats.  The full range is given by members named
751 * c[123]Min to c[123]Max, while the in gamut range is given by members
752 * named c[123]Low to c[123]High.  In most cases the full and in gamut
753 * ranges are equivalent.  This occurs when the c[123]Min == c[123]Low and
754 * c[123]High == c[123]Max.
755 *
756 * The input and produced colors are both specified as a fractional amount
757 * of the full range.  The diagram below provides an overview of the
758 * conversion process.  The main steps are:
759 *
760 *   1. Produce black if the input color is out of gamut.
761 *
762 *   2. Convert the in gamut color into the fraction of the fromFromat
763 *      in gamut range.
764 *
765 *   3. Convert from the fraction of the in gamut from format range to
766 *      the fraction of the in gamut to format range.  Produce black
767 *      if an equivalent color does not exists.
768 *
769 *   4. Covert from the fraction of the in gamut to format to the
770 *      fraction of the full range to format.
771 *
772 *       From Format                 To Format
773 *    max           high            high        max
774 *    ----+                 +-----------+
775 *    high \               /             \      high
776 *    ------\-------------+               +-------->
777 *           \
778 *            \                   +--- black --+
779 *             \                 /              \
780 *              \               /                +-->
781 *    low        \             /                  low
782 *    -------- ---+-- black --+
783 *    min             low           low           min
784 *     ^               ^      ^      ^             ^
785 *     |               |      |      |             |
786 *     |               |      |      |             +-- fraction of full range
787 *     |               |      |      +-- fraction of valid range
788 *     |               |      +-- fromFormat to toFormat color conversion
789 *     |               +-- fraction of valid range
790 *     +-- fraction of full range
791 */
792void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
793                  ColorFract& color)
794{
795    const struct attrib {
796        uint32_t     format;
797        bool         rgb;
798        bool         yuv;
799        int          c1Min, c1Low, c1High, c1Max;
800        int          c2Min, c2Low, c2High, c2Max;
801        int          c3Min, c3Low, c3High, c3Max;
802    } attributes[] = {
803        {HAL_PIXEL_FORMAT_RGBA_8888, true,  false,
804         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
805        {HAL_PIXEL_FORMAT_RGBX_8888, true,  false,
806         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
807        {HAL_PIXEL_FORMAT_RGB_888,   true,  false,
808         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
809        {HAL_PIXEL_FORMAT_RGB_565,   true,  false,
810         0, 0, 31, 31, 0, 0, 63, 63, 0, 0, 31, 31},
811        {HAL_PIXEL_FORMAT_BGRA_8888, true,  false,
812         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
813        {HAL_PIXEL_FORMAT_YV12,      false, true,
814         0, 16, 235, 255, 0, 16, 240, 255, 0, 16, 240, 255},
815    };
816
817    const struct attrib *fromAttrib;
818    for (fromAttrib = attributes; fromAttrib < attributes + NUMA(attributes);
819         fromAttrib++) {
820        if (fromAttrib->format == fromFormat) { break; }
821    }
822    if (fromAttrib >= attributes + NUMA(attributes)) {
823        testPrintE("hwcTestColorConvert unsupported from format of: %u",
824                   fromFormat);
825        exit(120);
826    }
827
828    const struct attrib *toAttrib;
829    for (toAttrib = attributes; toAttrib < attributes + NUMA(attributes);
830         toAttrib++) {
831        if (toAttrib->format == toFormat) { break; }
832    }
833    if (toAttrib >= attributes + NUMA(attributes)) {
834        testPrintE("hwcTestColorConvert unsupported to format of: %u",
835                   toFormat);
836        exit(121);
837    }
838
839    // Produce black if any of the from components are outside the
840    // valid color range
841    float c1Val = fromAttrib->c1Min
842        + ((float) (fromAttrib->c1Max - fromAttrib->c1Min) * color.c1());
843    float c2Val = fromAttrib->c2Min
844        + ((float) (fromAttrib->c2Max - fromAttrib->c2Min) * color.c2());
845    float c3Val = fromAttrib->c3Min
846        + ((float) (fromAttrib->c3Max - fromAttrib->c3Min) * color.c3());
847    if ((c1Val < fromAttrib->c1Low) || (c1Val > fromAttrib->c1High)
848        || (c2Val < fromAttrib->c2Low) || (c2Val > fromAttrib->c2High)
849        || (c3Val < fromAttrib->c3Low) || (c3Val > fromAttrib->c3High)) {
850
851        // Return black
852        // Will use representation of black from RGBA8888 graphic format
853        // and recursively convert it to the requested graphic format.
854        color = ColorFract(0.0, 0.0, 0.0);
855        hwcTestColorConvert(HAL_PIXEL_FORMAT_RGBA_8888, toFormat, color);
856        return;
857    }
858
859    // Within from format, convert from fraction of full range
860    // to fraction of valid range
861    color = ColorFract((c1Val - fromAttrib->c1Low)
862                           / (fromAttrib->c1High - fromAttrib->c1Low),
863                       (c2Val - fromAttrib->c2Low)
864                           / (fromAttrib->c2High - fromAttrib->c2Low),
865                       (c3Val - fromAttrib->c3Low)
866                           / (fromAttrib->c3High - fromAttrib->c3Low));
867
868    // If needed perform RGB to YUV conversion
869    float wr = 0.2126, wg = 0.7152, wb = 0.0722; // ITU709 recommended constants
870    if (fromAttrib->rgb && toAttrib->yuv) {
871        float r = color.c1(), g = color.c2(), b = color.c3();
872        float y = wr * r + wg * g + wb * b;
873        float u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5;
874        float v = 0.5 * ((r - y) / (1.0 - wr)) + 0.5;
875
876        // Produce black if color is outside the YUV gamut
877        if ((y < 0.0) || (y > 1.0)
878            || (u < 0.0) || (u > 1.0)
879            || (v < 0.0) || (v > 1.0)) {
880            y = 0.0;
881            u = v = 0.5;
882        }
883
884        color = ColorFract(y, u, v);
885    }
886
887    // If needed perform YUV to RGB conversion
888    // Equations determined from the ITU709 equations for RGB to YUV
889    // conversion, plus the following algebra:
890    //
891    //   u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5
892    //   0.5 * ((b - y) / (1.0 - wb)) = u - 0.5
893    //   (b - y) / (1.0 - wb) = 2 * (u - 0.5)
894    //   b - y = 2 * (u - 0.5) * (1.0 - wb)
895    //   b = 2 * (u - 0.5) * (1.0 - wb) + y
896    //
897    //   v = 0.5 * ((r -y) / (1.0 - wr)) + 0.5
898    //   0.5 * ((r - y) / (1.0 - wr)) = v - 0.5
899    //   (r - y) / (1.0 - wr) = 2 * (v - 0.5)
900    //   r - y = 2 * (v - 0.5) * (1.0 - wr)
901    //   r = 2 * (v - 0.5) * (1.0 - wr) + y
902    //
903    //   y = wr * r + wg * g + wb * b
904    //   wr * r + wg * g + wb * b = y
905    //   wg * g = y - wr * r - wb * b
906    //   g = (y - wr * r - wb * b) / wg
907    if (fromAttrib->yuv && toAttrib->rgb) {
908        float y = color.c1(), u = color.c2(), v = color.c3();
909        float r = 2.0 * (v - 0.5) * (1.0 - wr) + y;
910        float b = 2.0 * (u - 0.5) * (1.0 - wb) + y;
911        float g = (y - wr * r - wb * b) / wg;
912
913        // Produce black if color is outside the RGB gamut
914        if ((r < 0.0) || (r > 1.0)
915            || (g < 0.0) || (g > 1.0)
916            || (b < 0.0) || (b > 1.0)) {
917            r = g = b = 0.0;
918        }
919
920        color = ColorFract(r, g, b);
921    }
922
923    // Within to format, convert from fraction of valid range
924    // to fraction of full range
925    c1Val = (toAttrib->c1Low
926        + (float) (toAttrib->c1High - toAttrib->c1Low) * color.c1());
927    c2Val = (toAttrib->c1Low
928        + (float) (toAttrib->c2High - toAttrib->c2Low) * color.c2());
929    c3Val = (toAttrib->c1Low
930        + (float) (toAttrib->c3High - toAttrib->c3Low) * color.c3());
931    color = ColorFract((float) (c1Val - toAttrib->c1Min)
932                           / (float) (toAttrib->c1Max - toAttrib->c1Min),
933                       (float) (c2Val - toAttrib->c2Min)
934                           / (float) (toAttrib->c2Max - toAttrib->c2Min),
935                       (float) (c3Val - toAttrib->c3Min)
936                           / (float) (toAttrib->c3Max - toAttrib->c3Min));
937}
938
939// TODO: Use PrintGLString, CechckGlError, and PrintEGLConfiguration
940//       from libglTest
941static void printGLString(const char *name, GLenum s)
942{
943    const char *v = (const char *) glGetString(s);
944
945    if (v == NULL) {
946        testPrintI("GL %s unknown", name);
947    } else {
948        testPrintI("GL %s = %s", name, v);
949    }
950}
951
952static void checkEglError(const char* op, EGLBoolean returnVal)
953{
954    if (returnVal != EGL_TRUE) {
955        testPrintE("%s() returned %d", op, returnVal);
956    }
957
958    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
959            = eglGetError()) {
960        testPrintE("after %s() eglError %s (0x%x)",
961                   op, EGLUtils::strerror(error), error);
962    }
963}
964
965static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config)
966{
967
968#define X(VAL) {VAL, #VAL}
969    struct {EGLint attribute; const char* name;} names[] = {
970    X(EGL_BUFFER_SIZE),
971    X(EGL_ALPHA_SIZE),
972    X(EGL_BLUE_SIZE),
973    X(EGL_GREEN_SIZE),
974    X(EGL_RED_SIZE),
975    X(EGL_DEPTH_SIZE),
976    X(EGL_STENCIL_SIZE),
977    X(EGL_CONFIG_CAVEAT),
978    X(EGL_CONFIG_ID),
979    X(EGL_LEVEL),
980    X(EGL_MAX_PBUFFER_HEIGHT),
981    X(EGL_MAX_PBUFFER_PIXELS),
982    X(EGL_MAX_PBUFFER_WIDTH),
983    X(EGL_NATIVE_RENDERABLE),
984    X(EGL_NATIVE_VISUAL_ID),
985    X(EGL_NATIVE_VISUAL_TYPE),
986    X(EGL_SAMPLES),
987    X(EGL_SAMPLE_BUFFERS),
988    X(EGL_SURFACE_TYPE),
989    X(EGL_TRANSPARENT_TYPE),
990    X(EGL_TRANSPARENT_RED_VALUE),
991    X(EGL_TRANSPARENT_GREEN_VALUE),
992    X(EGL_TRANSPARENT_BLUE_VALUE),
993    X(EGL_BIND_TO_TEXTURE_RGB),
994    X(EGL_BIND_TO_TEXTURE_RGBA),
995    X(EGL_MIN_SWAP_INTERVAL),
996    X(EGL_MAX_SWAP_INTERVAL),
997    X(EGL_LUMINANCE_SIZE),
998    X(EGL_ALPHA_MASK_SIZE),
999    X(EGL_COLOR_BUFFER_TYPE),
1000    X(EGL_RENDERABLE_TYPE),
1001    X(EGL_CONFORMANT),
1002   };
1003#undef X
1004
1005    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
1006        EGLint value = -1;
1007        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
1008                                              &value);
1009        EGLint error = eglGetError();
1010        if (returnVal && error == EGL_SUCCESS) {
1011            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
1012        }
1013    }
1014    testPrintI("");
1015}
1016