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