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     // The tests want to stop the framework and play with the hardware
     84     // composer, which means it doesn't make sense to use WindowSurface
     85     // here.  android_createDisplaySurface() is going away, so just
     86     // politely fail here.
     87     EGLNativeWindowType window = NULL; //android_createDisplaySurface();
     88     if (window == NULL) {
     89         testPrintE("android_createDisplaySurface failed");
     90         exit(72);
     91     }
     92     returnValue = EGLUtils::selectConfigForNativeWindow(*dpy,
     93         sConfigAttribs, window, &myConfig);
     94     if (returnValue) {
     95         testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
     96             returnValue);
     97         exit(73);
     98     }
     99     checkEglError("EGLUtils::selectConfigForNativeWindow");
    100 
    101     if (verbose) {
    102         testPrintI("Chose this configuration:");
    103         printEGLConfiguration(*dpy, myConfig);
    104     }
    105 
    106     *surface = eglCreateWindowSurface(*dpy, myConfig, window, NULL);
    107     checkEglError("eglCreateWindowSurface");
    108     if (*surface == EGL_NO_SURFACE) {
    109         testPrintE("gelCreateWindowSurface failed.");
    110         exit(74);
    111     }
    112 
    113     context = eglCreateContext(*dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
    114     checkEglError("eglCreateContext");
    115     if (context == EGL_NO_CONTEXT) {
    116         testPrintE("eglCreateContext failed");
    117         exit(75);
    118     }
    119     returnValue = eglMakeCurrent(*dpy, *surface, *surface, context);
    120     checkEglError("eglMakeCurrent", returnValue);
    121     if (returnValue != EGL_TRUE) {
    122         testPrintE("eglMakeCurrent failed");
    123         exit(76);
    124     }
    125     eglQuerySurface(*dpy, *surface, EGL_WIDTH, width);
    126     checkEglError("eglQuerySurface");
    127     eglQuerySurface(*dpy, *surface, EGL_HEIGHT, height);
    128     checkEglError("eglQuerySurface");
    129 
    130     if (verbose) {
    131         testPrintI("Window dimensions: %d x %d", *width, *height);
    132 
    133         printGLString("Version", GL_VERSION);
    134         printGLString("Vendor", GL_VENDOR);
    135         printGLString("Renderer", GL_RENDERER);
    136         printGLString("Extensions", GL_EXTENSIONS);
    137     }
    138 }
    139 
    140 // Open Hardware Composer Device
    141 void hwcTestOpenHwc(hwc_composer_device_1_t **hwcDevicePtr)
    142 {
    143     int rv;
    144     hw_module_t const *hwcModule;
    145 
    146     if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
    147         testPrintE("hw_get_module failed, rv: %i", rv);
    148         errno = -rv;
    149         perror(NULL);
    150         exit(77);
    151     }
    152     if ((rv = hwc_open_1(hwcModule, hwcDevicePtr)) != 0) {
    153         testPrintE("hwc_open failed, rv: %i", rv);
    154         errno = -rv;
    155         perror(NULL);
    156         exit(78);
    157     }
    158 }
    159 
    160 // Color fraction class to string conversion
    161 ColorFract::operator string()
    162 {
    163     ostringstream out;
    164 
    165     out << '[' << this->c1() << ", "
    166         << this->c2() << ", "
    167         << this->c3() << ']';
    168 
    169     return out.str();
    170 }
    171 
    172 // Dimension class to string conversion
    173 HwcTestDim::operator string()
    174 {
    175     ostringstream out;
    176 
    177     out << '[' << this->width() << ", "
    178         << this->height() << ']';
    179 
    180     return out.str();
    181 }
    182 
    183 // Dimension class to hwc_rect conversion
    184 HwcTestDim::operator hwc_rect() const
    185 {
    186     hwc_rect rect;
    187 
    188     rect.left = rect.top = 0;
    189 
    190     rect.right = this->_w;
    191     rect.bottom = this->_h;
    192 
    193     return rect;
    194 }
    195 
    196 // Hardware Composer rectangle to string conversion
    197 string hwcTestRect2str(const struct hwc_rect& rect)
    198 {
    199     ostringstream out;
    200 
    201     out << '[';
    202     out << rect.left << ", ";
    203     out << rect.top << ", ";
    204     out << rect.right << ", ";
    205     out << rect.bottom;
    206     out << ']';
    207 
    208     return out.str();
    209 }
    210 
    211 // Parse HWC rectangle description of form [left, top, right, bottom]
    212 struct hwc_rect hwcTestParseHwcRect(istringstream& in, bool& error)
    213 {
    214     struct hwc_rect rect;
    215     char chStart, ch;
    216 
    217     // Defensively specify that an error occurred.  Will clear
    218     // error flag if all of parsing succeeds.
    219     error = true;
    220 
    221     // First character should be a [ or <
    222     in >> chStart;
    223     if (!in || ((chStart != '<') && (chStart != '['))) { return rect; }
    224 
    225     // Left
    226     in >> rect.left;
    227     if (!in) { return rect; }
    228     in >> ch;
    229     if (!in || (ch != ',')) { return rect; }
    230 
    231     // Top
    232     in >> rect.top;
    233     if (!in) { return rect; }
    234     in >> ch;
    235     if (!in || (ch != ',')) { return rect; }
    236 
    237     // Right
    238     in >> rect.right;
    239     if (!in) { return rect; }
    240     in >> ch;
    241     if (!in || (ch != ',')) { return rect; }
    242 
    243     // Bottom
    244     in >> rect.bottom;
    245     if (!in) { return rect; }
    246 
    247     // Closing > or ]
    248     in >> ch;
    249     if (!in) { return rect; }
    250     if (((chStart == '<') && (ch != '>'))
    251         || ((chStart == '[') && (ch != ']'))) { return rect; }
    252 
    253     // Validate right and bottom are greater than left and top
    254     if ((rect.right <= rect.left) || (rect.bottom <= rect.top)) { return rect; }
    255 
    256     // Made It, clear error indicator
    257     error = false;
    258 
    259     return rect;
    260 }
    261 
    262 // Parse dimension of form [width, height]
    263 HwcTestDim hwcTestParseDim(istringstream& in, bool& error)
    264 {
    265     HwcTestDim dim;
    266     char chStart, ch;
    267     uint32_t val;
    268 
    269     // Defensively specify that an error occurred.  Will clear
    270     // error flag if all of parsing succeeds.
    271     error = true;
    272 
    273     // First character should be a [ or <
    274     in >> chStart;
    275     if (!in || ((chStart != '<') && (chStart != '['))) { return dim; }
    276 
    277     // Width
    278     in >> val;
    279     if (!in) { return dim; }
    280     dim.setWidth(val);
    281     in >> ch;
    282     if (!in || (ch != ',')) { return dim; }
    283 
    284     // Height
    285     in >> val;
    286     if (!in) { return dim; }
    287     dim.setHeight(val);
    288 
    289     // Closing > or ]
    290     in >> ch;
    291     if (!in) { return dim; }
    292     if (((chStart == '<') && (ch != '>'))
    293         || ((chStart == '[') && (ch != ']'))) { return dim; }
    294 
    295     // Validate width and height greater than 0
    296     if ((dim.width() <= 0) || (dim.height() <= 0)) { return dim; }
    297 
    298     // Made It, clear error indicator
    299     error = false;
    300     return dim;
    301 }
    302 
    303 // Parse fractional color of form [0.##, 0.##, 0.##]
    304 // Fractional values can be from 0.0 to 1.0 inclusive.  Note, integer
    305 // values of 0.0 and 1.0, which are non-fractional, are considered valid.
    306 // They are an exception, all other valid inputs are fractions.
    307 ColorFract hwcTestParseColor(istringstream& in, bool& error)
    308 {
    309     ColorFract color;
    310     char chStart, ch;
    311     float c1, c2, c3;
    312 
    313     // Defensively specify that an error occurred.  Will clear
    314     // error flag if all of parsing succeeds.
    315     error = true;
    316 
    317     // First character should be a [ or <
    318     in >> chStart;
    319     if (!in || ((chStart != '<') && (chStart != '['))) { return color; }
    320 
    321     // 1st Component
    322     in >> c1;
    323     if (!in) { return color; }
    324     if ((c1 < 0.0) || (c1 > 1.0)) { return color; }
    325     in >> ch;
    326     if (!in || (ch != ',')) { return color; }
    327 
    328     // 2nd Component
    329     in >> c2;
    330     if (!in) { return color; }
    331     if ((c2 < 0.0) || (c2 > 1.0)) { return color; }
    332     in >> ch;
    333     if (!in || (ch != ',')) { return color; }
    334 
    335     // 3rd Component
    336     in >> c3;
    337     if (!in) { return color; }
    338     if ((c3 < 0.0) || (c3 > 1.0)) { return color; }
    339 
    340     // Closing > or ]
    341     in >> ch;
    342     if (!in) { return color; }
    343     if (((chStart == '<') && (ch != '>'))
    344         || ((chStart == '[') && (ch != ']'))) { return color; }
    345 
    346     // Are all the components fractional
    347     if ((c1 < 0.0) || (c1 > 1.0)
    348         || (c2 < 0.0) || (c2 > 1.0)
    349         || (c3 < 0.0) || (c3 > 1.0)) { return color; }
    350 
    351     // Made It, clear error indicator
    352     error = false;
    353 
    354     return ColorFract(c1, c2, c3);
    355 }
    356 
    357 // Look up and return pointer to structure with the characteristics
    358 // of the graphic format named by the desc parameter.  Search failure
    359 // indicated by the return of NULL.
    360 const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc)
    361 {
    362     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
    363         if (string(desc) == string(hwcTestGraphicFormat[n1].desc)) {
    364             return &hwcTestGraphicFormat[n1];
    365         }
    366     }
    367 
    368     return NULL;
    369 }
    370 
    371 // Look up and return pointer to structure with the characteristics
    372 // of the graphic format specified by the id parameter.  Search failure
    373 // indicated by the return of NULL.
    374 const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id)
    375 {
    376     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
    377         if (id == hwcTestGraphicFormat[n1].format) {
    378             return &hwcTestGraphicFormat[n1];
    379         }
    380     }
    381 
    382     return NULL;
    383 }
    384 
    385 
    386 // Given the integer ID of a graphic format, return a pointer to
    387 // a string that describes the format.
    388 const char *hwcTestGraphicFormat2str(uint32_t format)
    389 {
    390     const static char *unknown = "unknown";
    391 
    392     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
    393         if (format == hwcTestGraphicFormat[n1].format) {
    394             return hwcTestGraphicFormat[n1].desc;
    395         }
    396     }
    397 
    398     return unknown;
    399 }
    400 
    401 /*
    402  * hwcTestCreateLayerList
    403  * Dynamically creates layer list with numLayers worth
    404  * of hwLayers entries.
    405  */
    406 hwc_display_contents_1_t *hwcTestCreateLayerList(size_t numLayers)
    407 {
    408     hwc_display_contents_1_t *list;
    409 
    410     size_t size = sizeof(hwc_display_contents_1_t) + numLayers * sizeof(hwc_layer_1_t);
    411     if ((list = (hwc_display_contents_1_t *) calloc(1, size)) == NULL) {
    412         return NULL;
    413     }
    414     list->flags = HWC_GEOMETRY_CHANGED;
    415     list->numHwLayers = numLayers;
    416 
    417     return list;
    418 }
    419 
    420 /*
    421  * hwcTestFreeLayerList
    422  * Frees memory previous allocated via hwcTestCreateLayerList().
    423  */
    424 void hwcTestFreeLayerList(hwc_display_contents_1_t *list)
    425 {
    426     free(list);
    427 }
    428 
    429 // Display the settings of the layer list pointed to by list
    430 void hwcTestDisplayList(hwc_display_contents_1_t *list)
    431 {
    432     testPrintI("  flags: %#x%s", list->flags,
    433                (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
    434     testPrintI("  numHwLayers: %u", list->numHwLayers);
    435 
    436     for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
    437         testPrintI("    layer %u compositionType: %#x%s%s", layer,
    438                    list->hwLayers[layer].compositionType,
    439                    (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
    440                        ? " FRAMEBUFFER" : "",
    441                    (list->hwLayers[layer].compositionType == HWC_OVERLAY)
    442                        ? " OVERLAY" : "");
    443 
    444         testPrintI("      hints: %#x",
    445                    list->hwLayers[layer].hints,
    446                    (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
    447                        ? " TRIPLE_BUFFER" : "",
    448                    (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
    449                        ? " CLEAR_FB" : "");
    450 
    451         testPrintI("      flags: %#x%s",
    452                    list->hwLayers[layer].flags,
    453                    (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
    454                        ? " SKIP_LAYER" : "");
    455 
    456         testPrintI("      handle: %p",
    457                    list->hwLayers[layer].handle);
    458 
    459         // Intentionally skipped display of ROT_180 & ROT_270,
    460         // which are formed from combinations of the other flags.
    461         testPrintI("      transform: %#x%s%s%s",
    462                    list->hwLayers[layer].transform,
    463                    (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
    464                        ? " FLIP_H" : "",
    465                    (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
    466                        ? " FLIP_V" : "",
    467                    (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
    468                        ? " ROT_90" : "");
    469 
    470         testPrintI("      blending: %#x%s%s%s",
    471                    list->hwLayers[layer].blending,
    472                    (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
    473                        ? " NONE" : "",
    474                    (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
    475                        ? " PREMULT" : "",
    476                    (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
    477                        ? " COVERAGE" : "");
    478 
    479         testPrintI("      sourceCrop: %s",
    480                    hwcTestRect2str(list->hwLayers[layer].sourceCrop).c_str());
    481         testPrintI("      displayFrame: %s",
    482                    hwcTestRect2str(list->hwLayers[layer].displayFrame).c_str());
    483         testPrintI("      scaleFactor: [%f, %f]",
    484                    (float) (list->hwLayers[layer].sourceCrop.right
    485                             - list->hwLayers[layer].sourceCrop.left)
    486                        / (float) (list->hwLayers[layer].displayFrame.right
    487                             - list->hwLayers[layer].displayFrame.left),
    488                    (float) (list->hwLayers[layer].sourceCrop.bottom
    489                             - list->hwLayers[layer].sourceCrop.top)
    490                        / (float) (list->hwLayers[layer].displayFrame.bottom
    491                             - list->hwLayers[layer].displayFrame.top));
    492     }
    493 }
    494 
    495 /*
    496  * Display List Prepare Modifiable
    497  *
    498  * Displays the portions of a list that are meant to be modified by
    499  * a prepare call.
    500  */
    501 void hwcTestDisplayListPrepareModifiable(hwc_display_contents_1_t *list)
    502 {
    503     uint32_t numOverlays = 0;
    504     for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
    505         if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
    506             numOverlays++;
    507         }
    508         testPrintI("    layer %u compositionType: %#x%s%s", layer,
    509                    list->hwLayers[layer].compositionType,
    510                    (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
    511                        ? " FRAMEBUFFER" : "",
    512                    (list->hwLayers[layer].compositionType == HWC_OVERLAY)
    513                        ? " OVERLAY" : "");
    514         testPrintI("      hints: %#x%s%s",
    515                    list->hwLayers[layer].hints,
    516                    (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
    517                        ? " TRIPLE_BUFFER" : "",
    518                    (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
    519                        ? " CLEAR_FB" : "");
    520     }
    521     testPrintI("    numOverlays: %u", numOverlays);
    522 }
    523 
    524 /*
    525  * Display List Handles
    526  *
    527  * Displays the handles of all the graphic buffers in the list.
    528  */
    529 void hwcTestDisplayListHandles(hwc_display_contents_1_t *list)
    530 {
    531     const unsigned int maxLayersPerLine = 6;
    532 
    533     ostringstream str("  layers:");
    534     for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
    535         str << ' ' << list->hwLayers[layer].handle;
    536         if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
    537             && (layer != list->numHwLayers - 1)) {
    538             testPrintI("%s", str.str().c_str());
    539             str.str("    ");
    540         }
    541     }
    542     testPrintI("%s", str.str().c_str());
    543 }
    544 
    545 // Returns a uint32_t that contains a format specific representation of a
    546 // single pixel of the given color and alpha values.
    547 uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha)
    548 {
    549     const struct attrib {
    550         uint32_t format;
    551         bool   hostByteOrder;
    552         size_t bytes;
    553         size_t c1Offset;
    554         size_t c1Size;
    555         size_t c2Offset;
    556         size_t c2Size;
    557         size_t c3Offset;
    558         size_t c3Size;
    559         size_t aOffset;
    560         size_t aSize;
    561     } attributes[] = {
    562         {HAL_PIXEL_FORMAT_RGBA_8888, false, 4,  0, 8,  8, 8, 16, 8, 24, 8},
    563         {HAL_PIXEL_FORMAT_RGBX_8888, false, 4,  0, 8,  8, 8, 16, 8,  0, 0},
    564         {HAL_PIXEL_FORMAT_RGB_888,   false, 3,  0, 8,  8, 8, 16, 8,  0, 0},
    565         {HAL_PIXEL_FORMAT_RGB_565,   true,  2,  0, 5,  5, 6, 11, 5,  0, 0},
    566         {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8,  8, 8,  0, 8, 24, 8},
    567         {HAL_PIXEL_FORMAT_YV12,      true,  3, 16, 8,  8, 8,  0, 8,  0, 0},
    568     };
    569 
    570     const struct attrib *attrib;
    571     for (attrib = attributes; attrib < attributes + NUMA(attributes);
    572          attrib++) {
    573         if (attrib->format == format) { break; }
    574     }
    575     if (attrib >= attributes + NUMA(attributes)) {
    576         testPrintE("colorFract2Pixel unsupported format of: %u", format);
    577         exit(80);
    578     }
    579 
    580     uint32_t pixel;
    581     pixel = htonl((uint32_t) round((((1 << attrib->c1Size) - 1) * color.c1()))
    582          << ((sizeof(pixel) * BITSPERBYTE)
    583              - (attrib->c1Offset + attrib->c1Size)));
    584     pixel |= htonl((uint32_t) round((((1 << attrib->c2Size) - 1) * color.c2()))
    585          << ((sizeof(pixel) * BITSPERBYTE)
    586              - (attrib->c2Offset + attrib->c2Size)));
    587     pixel |= htonl((uint32_t) round((((1 << attrib->c3Size) - 1) * color.c3()))
    588          << ((sizeof(pixel) * BITSPERBYTE)
    589              - (attrib->c3Offset + attrib->c3Size)));
    590     if (attrib->aSize) {
    591         pixel |= htonl((uint32_t) round((((1 << attrib->aSize) - 1) * alpha))
    592              << ((sizeof(pixel) * BITSPERBYTE)
    593                  - (attrib->aOffset + attrib->aSize)));
    594     }
    595     if (attrib->hostByteOrder) {
    596         pixel = ntohl(pixel);
    597         pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
    598     }
    599 
    600     return pixel;
    601 }
    602 
    603 // Sets the pixel at the given x and y coordinates to the color and alpha
    604 // value given by pixel.  The contents of pixel is format specific.  It's
    605 // value should come from a call to hwcTestColor2Pixel().
    606 void hwcTestSetPixel(GraphicBuffer *gBuf, unsigned char *buf,
    607               uint32_t x, uint32_t y, uint32_t pixel)
    608 {
    609 
    610     const struct attrib {
    611         int format;
    612         size_t bytes;
    613     } attributes[] = {
    614         {HAL_PIXEL_FORMAT_RGBA_8888,  4},
    615         {HAL_PIXEL_FORMAT_RGBX_8888,  4},
    616         {HAL_PIXEL_FORMAT_RGB_888,    3},
    617         {HAL_PIXEL_FORMAT_RGB_565,    2},
    618         {HAL_PIXEL_FORMAT_BGRA_8888,  4},
    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_YV12,      false, true,
    817          0, 16, 235, 255, 0, 16, 240, 255, 0, 16, 240, 255},
    818     };
    819 
    820     const struct attrib *fromAttrib;
    821     for (fromAttrib = attributes; fromAttrib < attributes + NUMA(attributes);
    822          fromAttrib++) {
    823         if (fromAttrib->format == fromFormat) { break; }
    824     }
    825     if (fromAttrib >= attributes + NUMA(attributes)) {
    826         testPrintE("hwcTestColorConvert unsupported from format of: %u",
    827                    fromFormat);
    828         exit(120);
    829     }
    830 
    831     const struct attrib *toAttrib;
    832     for (toAttrib = attributes; toAttrib < attributes + NUMA(attributes);
    833          toAttrib++) {
    834         if (toAttrib->format == toFormat) { break; }
    835     }
    836     if (toAttrib >= attributes + NUMA(attributes)) {
    837         testPrintE("hwcTestColorConvert unsupported to format of: %u",
    838                    toFormat);
    839         exit(121);
    840     }
    841 
    842     // Produce black if any of the from components are outside the
    843     // valid color range
    844     float c1Val = fromAttrib->c1Min
    845         + ((float) (fromAttrib->c1Max - fromAttrib->c1Min) * color.c1());
    846     float c2Val = fromAttrib->c2Min
    847         + ((float) (fromAttrib->c2Max - fromAttrib->c2Min) * color.c2());
    848     float c3Val = fromAttrib->c3Min
    849         + ((float) (fromAttrib->c3Max - fromAttrib->c3Min) * color.c3());
    850     if ((c1Val < fromAttrib->c1Low) || (c1Val > fromAttrib->c1High)
    851         || (c2Val < fromAttrib->c2Low) || (c2Val > fromAttrib->c2High)
    852         || (c3Val < fromAttrib->c3Low) || (c3Val > fromAttrib->c3High)) {
    853 
    854         // Return black
    855         // Will use representation of black from RGBA8888 graphic format
    856         // and recursively convert it to the requested graphic format.
    857         color = ColorFract(0.0, 0.0, 0.0);
    858         hwcTestColorConvert(HAL_PIXEL_FORMAT_RGBA_8888, toFormat, color);
    859         return;
    860     }
    861 
    862     // Within from format, convert from fraction of full range
    863     // to fraction of valid range
    864     color = ColorFract((c1Val - fromAttrib->c1Low)
    865                            / (fromAttrib->c1High - fromAttrib->c1Low),
    866                        (c2Val - fromAttrib->c2Low)
    867                            / (fromAttrib->c2High - fromAttrib->c2Low),
    868                        (c3Val - fromAttrib->c3Low)
    869                            / (fromAttrib->c3High - fromAttrib->c3Low));
    870 
    871     // If needed perform RGB to YUV conversion
    872     float wr = 0.2126, wg = 0.7152, wb = 0.0722; // ITU709 recommended constants
    873     if (fromAttrib->rgb && toAttrib->yuv) {
    874         float r = color.c1(), g = color.c2(), b = color.c3();
    875         float y = wr * r + wg * g + wb * b;
    876         float u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5;
    877         float v = 0.5 * ((r - y) / (1.0 - wr)) + 0.5;
    878 
    879         // Produce black if color is outside the YUV gamut
    880         if ((y < 0.0) || (y > 1.0)
    881             || (u < 0.0) || (u > 1.0)
    882             || (v < 0.0) || (v > 1.0)) {
    883             y = 0.0;
    884             u = v = 0.5;
    885         }
    886 
    887         color = ColorFract(y, u, v);
    888     }
    889 
    890     // If needed perform YUV to RGB conversion
    891     // Equations determined from the ITU709 equations for RGB to YUV
    892     // conversion, plus the following algebra:
    893     //
    894     //   u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5
    895     //   0.5 * ((b - y) / (1.0 - wb)) = u - 0.5
    896     //   (b - y) / (1.0 - wb) = 2 * (u - 0.5)
    897     //   b - y = 2 * (u - 0.5) * (1.0 - wb)
    898     //   b = 2 * (u - 0.5) * (1.0 - wb) + y
    899     //
    900     //   v = 0.5 * ((r -y) / (1.0 - wr)) + 0.5
    901     //   0.5 * ((r - y) / (1.0 - wr)) = v - 0.5
    902     //   (r - y) / (1.0 - wr) = 2 * (v - 0.5)
    903     //   r - y = 2 * (v - 0.5) * (1.0 - wr)
    904     //   r = 2 * (v - 0.5) * (1.0 - wr) + y
    905     //
    906     //   y = wr * r + wg * g + wb * b
    907     //   wr * r + wg * g + wb * b = y
    908     //   wg * g = y - wr * r - wb * b
    909     //   g = (y - wr * r - wb * b) / wg
    910     if (fromAttrib->yuv && toAttrib->rgb) {
    911         float y = color.c1(), u = color.c2(), v = color.c3();
    912         float r = 2.0 * (v - 0.5) * (1.0 - wr) + y;
    913         float b = 2.0 * (u - 0.5) * (1.0 - wb) + y;
    914         float g = (y - wr * r - wb * b) / wg;
    915 
    916         // Produce black if color is outside the RGB gamut
    917         if ((r < 0.0) || (r > 1.0)
    918             || (g < 0.0) || (g > 1.0)
    919             || (b < 0.0) || (b > 1.0)) {
    920             r = g = b = 0.0;
    921         }
    922 
    923         color = ColorFract(r, g, b);
    924     }
    925 
    926     // Within to format, convert from fraction of valid range
    927     // to fraction of full range
    928     c1Val = (toAttrib->c1Low
    929         + (float) (toAttrib->c1High - toAttrib->c1Low) * color.c1());
    930     c2Val = (toAttrib->c1Low
    931         + (float) (toAttrib->c2High - toAttrib->c2Low) * color.c2());
    932     c3Val = (toAttrib->c1Low
    933         + (float) (toAttrib->c3High - toAttrib->c3Low) * color.c3());
    934     color = ColorFract((float) (c1Val - toAttrib->c1Min)
    935                            / (float) (toAttrib->c1Max - toAttrib->c1Min),
    936                        (float) (c2Val - toAttrib->c2Min)
    937                            / (float) (toAttrib->c2Max - toAttrib->c2Min),
    938                        (float) (c3Val - toAttrib->c3Min)
    939                            / (float) (toAttrib->c3Max - toAttrib->c3Min));
    940 }
    941 
    942 // TODO: Use PrintGLString, CechckGlError, and PrintEGLConfiguration
    943 //       from libglTest
    944 static void printGLString(const char *name, GLenum s)
    945 {
    946     const char *v = (const char *) glGetString(s);
    947 
    948     if (v == NULL) {
    949         testPrintI("GL %s unknown", name);
    950     } else {
    951         testPrintI("GL %s = %s", name, v);
    952     }
    953 }
    954 
    955 static void checkEglError(const char* op, EGLBoolean returnVal)
    956 {
    957     if (returnVal != EGL_TRUE) {
    958         testPrintE("%s() returned %d", op, returnVal);
    959     }
    960 
    961     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
    962             = eglGetError()) {
    963         testPrintE("after %s() eglError %s (0x%x)",
    964                    op, EGLUtils::strerror(error), error);
    965     }
    966 }
    967 
    968 static void checkGlError(const char* op)
    969 {
    970     for (GLint error = glGetError(); error; error
    971             = glGetError()) {
    972         testPrintE("after %s() glError (0x%x)", op, error);
    973     }
    974 }
    975 
    976 static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config)
    977 {
    978 
    979 #define X(VAL) {VAL, #VAL}
    980     struct {EGLint attribute; const char* name;} names[] = {
    981     X(EGL_BUFFER_SIZE),
    982     X(EGL_ALPHA_SIZE),
    983     X(EGL_BLUE_SIZE),
    984     X(EGL_GREEN_SIZE),
    985     X(EGL_RED_SIZE),
    986     X(EGL_DEPTH_SIZE),
    987     X(EGL_STENCIL_SIZE),
    988     X(EGL_CONFIG_CAVEAT),
    989     X(EGL_CONFIG_ID),
    990     X(EGL_LEVEL),
    991     X(EGL_MAX_PBUFFER_HEIGHT),
    992     X(EGL_MAX_PBUFFER_PIXELS),
    993     X(EGL_MAX_PBUFFER_WIDTH),
    994     X(EGL_NATIVE_RENDERABLE),
    995     X(EGL_NATIVE_VISUAL_ID),
    996     X(EGL_NATIVE_VISUAL_TYPE),
    997     X(EGL_SAMPLES),
    998     X(EGL_SAMPLE_BUFFERS),
    999     X(EGL_SURFACE_TYPE),
   1000     X(EGL_TRANSPARENT_TYPE),
   1001     X(EGL_TRANSPARENT_RED_VALUE),
   1002     X(EGL_TRANSPARENT_GREEN_VALUE),
   1003     X(EGL_TRANSPARENT_BLUE_VALUE),
   1004     X(EGL_BIND_TO_TEXTURE_RGB),
   1005     X(EGL_BIND_TO_TEXTURE_RGBA),
   1006     X(EGL_MIN_SWAP_INTERVAL),
   1007     X(EGL_MAX_SWAP_INTERVAL),
   1008     X(EGL_LUMINANCE_SIZE),
   1009     X(EGL_ALPHA_MASK_SIZE),
   1010     X(EGL_COLOR_BUFFER_TYPE),
   1011     X(EGL_RENDERABLE_TYPE),
   1012     X(EGL_CONFORMANT),
   1013    };
   1014 #undef X
   1015 
   1016     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
   1017         EGLint value = -1;
   1018         EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
   1019                                               &value);
   1020         EGLint error = eglGetError();
   1021         if (returnVal && error == EGL_SUCCESS) {
   1022             testPrintI(" %s: %d (%#x)", names[j].name, value, value);
   1023         }
   1024     }
   1025     testPrintI("");
   1026 }
   1027