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 <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
     37 static void printGLString(const char *name, GLenum s);
     38 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
     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     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
    139 void 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
    159 ColorFract::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
    171 HwcTestDim::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
    182 HwcTestDim::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
    195 string 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]
    210 struct 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]
    261 HwcTestDim 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.
    305 ColorFract 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.
    358 const 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.
    372 const 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.
    386 const 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  */
    404 hwc_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  */
    422 void 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
    428 void 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  */
    499 void 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  */
    527 void 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.
    545 uint32_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().
    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     };
    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
    653 void 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).
    689 void 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  */
    792 void 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
    941 static 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 
    952 static 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 
    965 static 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