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