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