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