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