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_YV12,      true,  3, 16, 8,  8, 8,  0, 8,  0, 0},
    564     };
    565 
    566     const struct attrib *attrib;
    567     for (attrib = attributes; attrib < attributes + NUMA(attributes);
    568          attrib++) {
    569         if (attrib->format == format) { break; }
    570     }
    571     if (attrib >= attributes + NUMA(attributes)) {
    572         testPrintE("colorFract2Pixel unsupported format of: %u", format);
    573         exit(80);
    574     }
    575 
    576     uint32_t pixel;
    577     pixel = htonl((uint32_t) round((((1 << attrib->c1Size) - 1) * color.c1()))
    578          << ((sizeof(pixel) * BITSPERBYTE)
    579              - (attrib->c1Offset + attrib->c1Size)));
    580     pixel |= htonl((uint32_t) round((((1 << attrib->c2Size) - 1) * color.c2()))
    581          << ((sizeof(pixel) * BITSPERBYTE)
    582              - (attrib->c2Offset + attrib->c2Size)));
    583     pixel |= htonl((uint32_t) round((((1 << attrib->c3Size) - 1) * color.c3()))
    584          << ((sizeof(pixel) * BITSPERBYTE)
    585              - (attrib->c3Offset + attrib->c3Size)));
    586     if (attrib->aSize) {
    587         pixel |= htonl((uint32_t) round((((1 << attrib->aSize) - 1) * alpha))
    588              << ((sizeof(pixel) * BITSPERBYTE)
    589                  - (attrib->aOffset + attrib->aSize)));
    590     }
    591     if (attrib->hostByteOrder) {
    592         pixel = ntohl(pixel);
    593         pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
    594     }
    595 
    596     return pixel;
    597 }
    598 
    599 // Sets the pixel at the given x and y coordinates to the color and alpha
    600 // value given by pixel.  The contents of pixel is format specific.  It's
    601 // value should come from a call to hwcTestColor2Pixel().
    602 void hwcTestSetPixel(GraphicBuffer *gBuf, unsigned char *buf,
    603               uint32_t x, uint32_t y, uint32_t pixel)
    604 {
    605 
    606     const struct attrib {
    607         int format;
    608         size_t bytes;
    609     } attributes[] = {
    610         {HAL_PIXEL_FORMAT_RGBA_8888,  4},
    611         {HAL_PIXEL_FORMAT_RGBX_8888,  4},
    612         {HAL_PIXEL_FORMAT_RGB_888,    3},
    613         {HAL_PIXEL_FORMAT_RGB_565,    2},
    614         {HAL_PIXEL_FORMAT_BGRA_8888,  4},
    615     };
    616 
    617     if (gBuf->getPixelFormat() == HAL_PIXEL_FORMAT_YV12) {
    618         uint32_t yPlaneOffset, uPlaneOffset, vPlaneOffset;
    619         uint32_t yPlaneStride = gBuf->getStride();
    620         uint32_t uPlaneStride = ((gBuf->getStride() / 2) + 0xf) & ~0xf;
    621         uint32_t vPlaneStride = uPlaneStride;
    622         yPlaneOffset = 0;
    623         vPlaneOffset = yPlaneOffset + yPlaneStride * gBuf->getHeight();
    624         uPlaneOffset = vPlaneOffset
    625                        + vPlaneStride * (gBuf->getHeight() / 2);
    626         *(buf + yPlaneOffset + y * yPlaneStride + x) = pixel & 0xff;
    627         *(buf + uPlaneOffset + (y / 2) * uPlaneStride + (x / 2))
    628             = (pixel & 0xff00) >> 8;
    629         *(buf + vPlaneOffset + (y / 2) * vPlaneStride + (x / 2))
    630             = (pixel & 0xff0000) >> 16;
    631 
    632         return;
    633     }
    634 
    635     const struct attrib *attrib;
    636     for (attrib = attributes; attrib < attributes + NUMA(attributes);
    637          attrib++) {
    638         if (attrib->format == gBuf->getPixelFormat()) { break; }
    639     }
    640     if (attrib >= attributes + NUMA(attributes)) {
    641         testPrintE("setPixel unsupported format of: %u",
    642                    gBuf->getPixelFormat());
    643         exit(90);
    644     }
    645 
    646     memmove(buf + ((gBuf->getStride() * attrib->bytes) * y)
    647             + (attrib->bytes * x), &pixel, attrib->bytes);
    648 }
    649 
    650 // Fill a given graphic buffer with a uniform color and alpha
    651 void hwcTestFillColor(GraphicBuffer *gBuf, ColorFract color, float alpha)
    652 {
    653     unsigned char* buf = NULL;
    654     status_t err;
    655     uint32_t pixel;
    656 
    657     pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, alpha);
    658 
    659     err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
    660     if (err != 0) {
    661         testPrintE("hwcTestFillColor lock failed: %d", err);
    662         exit(100);
    663     }
    664 
    665     for (unsigned int x = 0; x < gBuf->getStride(); x++) {
    666         for (unsigned int y = 0; y < gBuf->getHeight(); y++) {
    667             uint32_t val = pixel;
    668             hwcTestSetPixel(gBuf, buf, x, y, (x < gBuf->getWidth())
    669                             ? pixel : testRand());
    670         }
    671     }
    672 
    673     err = gBuf->unlock();
    674     if (err != 0) {
    675         testPrintE("hwcTestFillColor unlock failed: %d", err);
    676         exit(101);
    677     }
    678 }
    679 
    680 // Fill the given buffer with a horizontal blend of colors, with the left
    681 // side color given by startColor and the right side color given by
    682 // endColor.  The startColor and endColor values are specified in the format
    683 // given by colorFormat, which might be different from the format of the
    684 // graphic buffer.  When different, a color conversion is done when possible
    685 // to the graphic format of the graphic buffer.  A color of black is
    686 // produced for cases where the conversion is impossible (e.g. out of gamut
    687 // values).
    688 void hwcTestFillColorHBlend(GraphicBuffer *gBuf, uint32_t colorFormat,
    689                             ColorFract startColor, ColorFract endColor)
    690 {
    691     status_t err;
    692     unsigned char* buf = NULL;
    693     const uint32_t width = gBuf->getWidth();
    694     const uint32_t height = gBuf->getHeight();
    695     const uint32_t stride = gBuf->getStride();
    696 
    697     err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
    698     if (err != 0) {
    699         testPrintE("hwcTestFillColorHBlend lock failed: %d", err);
    700         exit(110);
    701     }
    702 
    703     for (unsigned int x = 0; x < stride; x++) {
    704         uint32_t pixel;
    705         if (x < width) {
    706             ColorFract color(startColor.c1() + (endColor.c1() - startColor.c1())
    707                                  * ((float) x / (float) (width - 1)),
    708                              startColor.c2() + (endColor.c2() - startColor.c2())
    709                                  * ((float) x / (float) (width - 1)),
    710                              startColor.c3() + (endColor.c3() - startColor.c3())
    711                                  * ((float) x / (float) (width - 1)));
    712 
    713             // When formats differ, convert colors.
    714             // Important to not convert when formats are the same, since
    715             // out of gamut colors are always converted to black.
    716             if (colorFormat != (uint32_t) gBuf->getPixelFormat()) {
    717                 hwcTestColorConvert(colorFormat, gBuf->getPixelFormat(), color);
    718             }
    719             pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, 1.0);
    720         } else {
    721             // Fill pad with random values
    722             pixel = testRand();
    723         }
    724 
    725         for (unsigned int y = 0; y < height; y++) {
    726             hwcTestSetPixel(gBuf, buf, x, y, pixel);
    727         }
    728     }
    729 
    730     err = gBuf->unlock();
    731     if (err != 0) {
    732         testPrintE("hwcTestFillColorHBlend unlock failed: %d", err);
    733         exit(111);
    734     }
    735 }
    736 
    737 /*
    738  * When possible, converts color specified as a full range value in
    739  * the fromFormat, into an equivalent full range color in the toFormat.
    740  * When conversion is impossible (e.g. out of gamut color) a color
    741  * or black in the full range output format is produced.  The input
    742  * color is given as a fractional color in the parameter named color.
    743  * The produced color is written over the same parameter used to
    744  * provide the input color.
    745  *
    746  * Each graphic format has 3 color components and each of these
    747  * components has both a full and in gamut range.  This function uses
    748  * a table that provides the full and in gamut ranges of each of the
    749  * supported graphic formats.  The full range is given by members named
    750  * c[123]Min to c[123]Max, while the in gamut range is given by members
    751  * named c[123]Low to c[123]High.  In most cases the full and in gamut
    752  * ranges are equivalent.  This occurs when the c[123]Min == c[123]Low and
    753  * c[123]High == c[123]Max.
    754  *
    755  * The input and produced colors are both specified as a fractional amount
    756  * of the full range.  The diagram below provides an overview of the
    757  * conversion process.  The main steps are:
    758  *
    759  *   1. Produce black if the input color is out of gamut.
    760  *
    761  *   2. Convert the in gamut color into the fraction of the fromFromat
    762  *      in gamut range.
    763  *
    764  *   3. Convert from the fraction of the in gamut from format range to
    765  *      the fraction of the in gamut to format range.  Produce black
    766  *      if an equivalent color does not exists.
    767  *
    768  *   4. Covert from the fraction of the in gamut to format to the
    769  *      fraction of the full range to format.
    770  *
    771  *       From Format                 To Format
    772  *    max           high            high        max
    773  *    ----+                 +-----------+
    774  *    high \               /             \      high
    775  *    ------\-------------+               +-------->
    776  *           \
    777  *            \                   +--- black --+
    778  *             \                 /              \
    779  *              \               /                +-->
    780  *    low        \             /                  low
    781  *    -------- ---+-- black --+
    782  *    min             low           low           min
    783  *     ^               ^      ^      ^             ^
    784  *     |               |      |      |             |
    785  *     |               |      |      |             +-- fraction of full range
    786  *     |               |      |      +-- fraction of valid range
    787  *     |               |      +-- fromFormat to toFormat color conversion
    788  *     |               +-- fraction of valid range
    789  *     +-- fraction of full range
    790  */
    791 void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
    792                   ColorFract& color)
    793 {
    794     const struct attrib {
    795         uint32_t     format;
    796         bool         rgb;
    797         bool         yuv;
    798         int          c1Min, c1Low, c1High, c1Max;
    799         int          c2Min, c2Low, c2High, c2Max;
    800         int          c3Min, c3Low, c3High, c3Max;
    801     } attributes[] = {
    802         {HAL_PIXEL_FORMAT_RGBA_8888, true,  false,
    803          0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
    804         {HAL_PIXEL_FORMAT_RGBX_8888, true,  false,
    805          0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
    806         {HAL_PIXEL_FORMAT_RGB_888,   true,  false,
    807          0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
    808         {HAL_PIXEL_FORMAT_RGB_565,   true,  false,
    809          0, 0, 31, 31, 0, 0, 63, 63, 0, 0, 31, 31},
    810         {HAL_PIXEL_FORMAT_BGRA_8888, true,  false,
    811          0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
    812         {HAL_PIXEL_FORMAT_YV12,      false, true,
    813          0, 16, 235, 255, 0, 16, 240, 255, 0, 16, 240, 255},
    814     };
    815 
    816     const struct attrib *fromAttrib;
    817     for (fromAttrib = attributes; fromAttrib < attributes + NUMA(attributes);
    818          fromAttrib++) {
    819         if (fromAttrib->format == fromFormat) { break; }
    820     }
    821     if (fromAttrib >= attributes + NUMA(attributes)) {
    822         testPrintE("hwcTestColorConvert unsupported from format of: %u",
    823                    fromFormat);
    824         exit(120);
    825     }
    826 
    827     const struct attrib *toAttrib;
    828     for (toAttrib = attributes; toAttrib < attributes + NUMA(attributes);
    829          toAttrib++) {
    830         if (toAttrib->format == toFormat) { break; }
    831     }
    832     if (toAttrib >= attributes + NUMA(attributes)) {
    833         testPrintE("hwcTestColorConvert unsupported to format of: %u",
    834                    toFormat);
    835         exit(121);
    836     }
    837 
    838     // Produce black if any of the from components are outside the
    839     // valid color range
    840     float c1Val = fromAttrib->c1Min
    841         + ((float) (fromAttrib->c1Max - fromAttrib->c1Min) * color.c1());
    842     float c2Val = fromAttrib->c2Min
    843         + ((float) (fromAttrib->c2Max - fromAttrib->c2Min) * color.c2());
    844     float c3Val = fromAttrib->c3Min
    845         + ((float) (fromAttrib->c3Max - fromAttrib->c3Min) * color.c3());
    846     if ((c1Val < fromAttrib->c1Low) || (c1Val > fromAttrib->c1High)
    847         || (c2Val < fromAttrib->c2Low) || (c2Val > fromAttrib->c2High)
    848         || (c3Val < fromAttrib->c3Low) || (c3Val > fromAttrib->c3High)) {
    849 
    850         // Return black
    851         // Will use representation of black from RGBA8888 graphic format
    852         // and recursively convert it to the requested graphic format.
    853         color = ColorFract(0.0, 0.0, 0.0);
    854         hwcTestColorConvert(HAL_PIXEL_FORMAT_RGBA_8888, toFormat, color);
    855         return;
    856     }
    857 
    858     // Within from format, convert from fraction of full range
    859     // to fraction of valid range
    860     color = ColorFract((c1Val - fromAttrib->c1Low)
    861                            / (fromAttrib->c1High - fromAttrib->c1Low),
    862                        (c2Val - fromAttrib->c2Low)
    863                            / (fromAttrib->c2High - fromAttrib->c2Low),
    864                        (c3Val - fromAttrib->c3Low)
    865                            / (fromAttrib->c3High - fromAttrib->c3Low));
    866 
    867     // If needed perform RGB to YUV conversion
    868     float wr = 0.2126, wg = 0.7152, wb = 0.0722; // ITU709 recommended constants
    869     if (fromAttrib->rgb && toAttrib->yuv) {
    870         float r = color.c1(), g = color.c2(), b = color.c3();
    871         float y = wr * r + wg * g + wb * b;
    872         float u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5;
    873         float v = 0.5 * ((r - y) / (1.0 - wr)) + 0.5;
    874 
    875         // Produce black if color is outside the YUV gamut
    876         if ((y < 0.0) || (y > 1.0)
    877             || (u < 0.0) || (u > 1.0)
    878             || (v < 0.0) || (v > 1.0)) {
    879             y = 0.0;
    880             u = v = 0.5;
    881         }
    882 
    883         color = ColorFract(y, u, v);
    884     }
    885 
    886     // If needed perform YUV to RGB conversion
    887     // Equations determined from the ITU709 equations for RGB to YUV
    888     // conversion, plus the following algebra:
    889     //
    890     //   u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5
    891     //   0.5 * ((b - y) / (1.0 - wb)) = u - 0.5
    892     //   (b - y) / (1.0 - wb) = 2 * (u - 0.5)
    893     //   b - y = 2 * (u - 0.5) * (1.0 - wb)
    894     //   b = 2 * (u - 0.5) * (1.0 - wb) + y
    895     //
    896     //   v = 0.5 * ((r -y) / (1.0 - wr)) + 0.5
    897     //   0.5 * ((r - y) / (1.0 - wr)) = v - 0.5
    898     //   (r - y) / (1.0 - wr) = 2 * (v - 0.5)
    899     //   r - y = 2 * (v - 0.5) * (1.0 - wr)
    900     //   r = 2 * (v - 0.5) * (1.0 - wr) + y
    901     //
    902     //   y = wr * r + wg * g + wb * b
    903     //   wr * r + wg * g + wb * b = y
    904     //   wg * g = y - wr * r - wb * b
    905     //   g = (y - wr * r - wb * b) / wg
    906     if (fromAttrib->yuv && toAttrib->rgb) {
    907         float y = color.c1(), u = color.c2(), v = color.c3();
    908         float r = 2.0 * (v - 0.5) * (1.0 - wr) + y;
    909         float b = 2.0 * (u - 0.5) * (1.0 - wb) + y;
    910         float g = (y - wr * r - wb * b) / wg;
    911 
    912         // Produce black if color is outside the RGB gamut
    913         if ((r < 0.0) || (r > 1.0)
    914             || (g < 0.0) || (g > 1.0)
    915             || (b < 0.0) || (b > 1.0)) {
    916             r = g = b = 0.0;
    917         }
    918 
    919         color = ColorFract(r, g, b);
    920     }
    921 
    922     // Within to format, convert from fraction of valid range
    923     // to fraction of full range
    924     c1Val = (toAttrib->c1Low
    925         + (float) (toAttrib->c1High - toAttrib->c1Low) * color.c1());
    926     c2Val = (toAttrib->c1Low
    927         + (float) (toAttrib->c2High - toAttrib->c2Low) * color.c2());
    928     c3Val = (toAttrib->c1Low
    929         + (float) (toAttrib->c3High - toAttrib->c3Low) * color.c3());
    930     color = ColorFract((float) (c1Val - toAttrib->c1Min)
    931                            / (float) (toAttrib->c1Max - toAttrib->c1Min),
    932                        (float) (c2Val - toAttrib->c2Min)
    933                            / (float) (toAttrib->c2Max - toAttrib->c2Min),
    934                        (float) (c3Val - toAttrib->c3Min)
    935                            / (float) (toAttrib->c3Max - toAttrib->c3Min));
    936 }
    937 
    938 // TODO: Use PrintGLString, CechckGlError, and PrintEGLConfiguration
    939 //       from libglTest
    940 static void printGLString(const char *name, GLenum s)
    941 {
    942     const char *v = (const char *) glGetString(s);
    943 
    944     if (v == NULL) {
    945         testPrintI("GL %s unknown", name);
    946     } else {
    947         testPrintI("GL %s = %s", name, v);
    948     }
    949 }
    950 
    951 static void checkEglError(const char* op, EGLBoolean returnVal)
    952 {
    953     if (returnVal != EGL_TRUE) {
    954         testPrintE("%s() returned %d", op, returnVal);
    955     }
    956 
    957     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
    958             = eglGetError()) {
    959         testPrintE("after %s() eglError %s (0x%x)",
    960                    op, EGLUtils::strerror(error), error);
    961     }
    962 }
    963 
    964 static void checkGlError(const char* op)
    965 {
    966     for (GLint error = glGetError(); error; error
    967             = glGetError()) {
    968         testPrintE("after %s() glError (0x%x)", op, error);
    969     }
    970 }
    971 
    972 static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config)
    973 {
    974 
    975 #define X(VAL) {VAL, #VAL}
    976     struct {EGLint attribute; const char* name;} names[] = {
    977     X(EGL_BUFFER_SIZE),
    978     X(EGL_ALPHA_SIZE),
    979     X(EGL_BLUE_SIZE),
    980     X(EGL_GREEN_SIZE),
    981     X(EGL_RED_SIZE),
    982     X(EGL_DEPTH_SIZE),
    983     X(EGL_STENCIL_SIZE),
    984     X(EGL_CONFIG_CAVEAT),
    985     X(EGL_CONFIG_ID),
    986     X(EGL_LEVEL),
    987     X(EGL_MAX_PBUFFER_HEIGHT),
    988     X(EGL_MAX_PBUFFER_PIXELS),
    989     X(EGL_MAX_PBUFFER_WIDTH),
    990     X(EGL_NATIVE_RENDERABLE),
    991     X(EGL_NATIVE_VISUAL_ID),
    992     X(EGL_NATIVE_VISUAL_TYPE),
    993     X(EGL_SAMPLES),
    994     X(EGL_SAMPLE_BUFFERS),
    995     X(EGL_SURFACE_TYPE),
    996     X(EGL_TRANSPARENT_TYPE),
    997     X(EGL_TRANSPARENT_RED_VALUE),
    998     X(EGL_TRANSPARENT_GREEN_VALUE),
    999     X(EGL_TRANSPARENT_BLUE_VALUE),
   1000     X(EGL_BIND_TO_TEXTURE_RGB),
   1001     X(EGL_BIND_TO_TEXTURE_RGBA),
   1002     X(EGL_MIN_SWAP_INTERVAL),
   1003     X(EGL_MAX_SWAP_INTERVAL),
   1004     X(EGL_LUMINANCE_SIZE),
   1005     X(EGL_ALPHA_MASK_SIZE),
   1006     X(EGL_COLOR_BUFFER_TYPE),
   1007     X(EGL_RENDERABLE_TYPE),
   1008     X(EGL_CONFORMANT),
   1009    };
   1010 #undef X
   1011 
   1012     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
   1013         EGLint value = -1;
   1014         EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
   1015                                               &value);
   1016         EGLint error = eglGetError();
   1017         if (returnVal && error == EGL_SUCCESS) {
   1018             testPrintI(" %s: %d (%#x)", names[j].name, value, value);
   1019         }
   1020     }
   1021     testPrintI("");
   1022 }
   1023