| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  | 
| Mathias Agopian | 622cfad | 2012-03-05 13:57:02 -0800 | [diff] [blame] | 28 | #include "hwcTestLib.h" | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 29 |  | 
| Mathias Agopian | 870b8aa | 2012-02-24 16:42:46 -0800 | [diff] [blame] | 30 | #include "EGLUtils.h" | 
 | 31 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 137 | void hwcTestOpenHwc(hwc_composer_device_1_t **hwcDevicePtr) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |     } | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 148 |     if ((rv = hwc_open_1(hwcModule, hwcDevicePtr)) != 0) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  | 
| Louis Huemiller | 653f810 | 2011-01-09 10:59:31 -0800 | [diff] [blame] | 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 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  | 
| Louis Huemiller | 653f810 | 2011-01-09 10:59:31 -0800 | [diff] [blame] | 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 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  */ | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 402 | hwc_layer_list_1_t *hwcTestCreateLayerList(size_t numLayers) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 403 | { | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 404 |     hwc_layer_list_1_t *list; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 405 |  | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 406 |     size_t size = sizeof(hwc_layer_list_1_t) + numLayers * sizeof(hwc_layer_1_t); | 
 | 407 |     if ((list = (hwc_layer_list_1_t *) calloc(1, size)) == NULL) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  */ | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 420 | void hwcTestFreeLayerList(hwc_layer_list_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 421 | { | 
 | 422 |     free(list); | 
 | 423 | } | 
 | 424 |  | 
 | 425 | // Display the settings of the layer list pointed to by list | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 426 | void hwcTestDisplayList(hwc_layer_list_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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]", | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 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)); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  */ | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 497 | void hwcTestDisplayListPrepareModifiable(hwc_layer_list_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 498 | { | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 499 |     uint32_t numOverlays = 0; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 500 |     for (unsigned int layer = 0; layer < list->numHwLayers; layer++) { | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 501 |         if (list->hwLayers[layer].compositionType == HWC_OVERLAY) { | 
 | 502 |             numOverlays++; | 
 | 503 |         } | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |     } | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 517 |     testPrintI("    numOverlays: %u", numOverlays); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 518 | } | 
 | 519 |  | 
 | 520 | /* | 
 | 521 |  * Display List Handles | 
 | 522 |  * | 
 | 523 |  * Displays the handles of all the graphic buffers in the list. | 
 | 524 |  */ | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 525 | void hwcTestDisplayListHandles(hwc_layer_list_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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_RGBA_5551, true , 2,  0, 5,  5, 5, 10, 5, 15, 1}, | 
 | 564 |         {HAL_PIXEL_FORMAT_RGBA_4444, false, 2, 12, 4,  0, 4,  4, 4,  8, 4}, | 
 | 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(). | 
 | 604 | void 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 |         {HAL_PIXEL_FORMAT_RGBA_5551,  2}, | 
 | 618 |         {HAL_PIXEL_FORMAT_RGBA_4444,  2}, | 
 | 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 |  | 
| Louis Huemiller | 9a8244b | 2011-01-09 19:02:05 -0800 | [diff] [blame] | 729 |         for (unsigned int y = 0; y < height; y++) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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_RGBA_5551, true,  false, | 
 | 817 |          0, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31}, | 
 | 818 |         {HAL_PIXEL_FORMAT_RGBA_4444, true,  false, | 
 | 819 |          0, 0, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15}, | 
 | 820 |         {HAL_PIXEL_FORMAT_YV12,      false, true, | 
 | 821 |          0, 16, 235, 255, 0, 16, 240, 255, 0, 16, 240, 255}, | 
 | 822 |     }; | 
 | 823 |  | 
 | 824 |     const struct attrib *fromAttrib; | 
 | 825 |     for (fromAttrib = attributes; fromAttrib < attributes + NUMA(attributes); | 
 | 826 |          fromAttrib++) { | 
 | 827 |         if (fromAttrib->format == fromFormat) { break; } | 
 | 828 |     } | 
 | 829 |     if (fromAttrib >= attributes + NUMA(attributes)) { | 
 | 830 |         testPrintE("hwcTestColorConvert unsupported from format of: %u", | 
 | 831 |                    fromFormat); | 
 | 832 |         exit(120); | 
 | 833 |     } | 
 | 834 |  | 
 | 835 |     const struct attrib *toAttrib; | 
 | 836 |     for (toAttrib = attributes; toAttrib < attributes + NUMA(attributes); | 
 | 837 |          toAttrib++) { | 
 | 838 |         if (toAttrib->format == toFormat) { break; } | 
 | 839 |     } | 
 | 840 |     if (toAttrib >= attributes + NUMA(attributes)) { | 
 | 841 |         testPrintE("hwcTestColorConvert unsupported to format of: %u", | 
 | 842 |                    toFormat); | 
 | 843 |         exit(121); | 
 | 844 |     } | 
 | 845 |  | 
 | 846 |     // Produce black if any of the from components are outside the | 
 | 847 |     // valid color range | 
 | 848 |     float c1Val = fromAttrib->c1Min | 
 | 849 |         + ((float) (fromAttrib->c1Max - fromAttrib->c1Min) * color.c1()); | 
 | 850 |     float c2Val = fromAttrib->c2Min | 
 | 851 |         + ((float) (fromAttrib->c2Max - fromAttrib->c2Min) * color.c2()); | 
 | 852 |     float c3Val = fromAttrib->c3Min | 
 | 853 |         + ((float) (fromAttrib->c3Max - fromAttrib->c3Min) * color.c3()); | 
 | 854 |     if ((c1Val < fromAttrib->c1Low) || (c1Val > fromAttrib->c1High) | 
 | 855 |         || (c2Val < fromAttrib->c2Low) || (c2Val > fromAttrib->c2High) | 
 | 856 |         || (c3Val < fromAttrib->c3Low) || (c3Val > fromAttrib->c3High)) { | 
 | 857 |  | 
 | 858 |         // Return black | 
 | 859 |         // Will use representation of black from RGBA8888 graphic format | 
 | 860 |         // and recursively convert it to the requested graphic format. | 
 | 861 |         color = ColorFract(0.0, 0.0, 0.0); | 
 | 862 |         hwcTestColorConvert(HAL_PIXEL_FORMAT_RGBA_8888, toFormat, color); | 
 | 863 |         return; | 
 | 864 |     } | 
 | 865 |  | 
 | 866 |     // Within from format, convert from fraction of full range | 
 | 867 |     // to fraction of valid range | 
 | 868 |     color = ColorFract((c1Val - fromAttrib->c1Low) | 
 | 869 |                            / (fromAttrib->c1High - fromAttrib->c1Low), | 
 | 870 |                        (c2Val - fromAttrib->c2Low) | 
 | 871 |                            / (fromAttrib->c2High - fromAttrib->c2Low), | 
 | 872 |                        (c3Val - fromAttrib->c3Low) | 
 | 873 |                            / (fromAttrib->c3High - fromAttrib->c3Low)); | 
 | 874 |  | 
 | 875 |     // If needed perform RGB to YUV conversion | 
 | 876 |     float wr = 0.2126, wg = 0.7152, wb = 0.0722; // ITU709 recommended constants | 
 | 877 |     if (fromAttrib->rgb && toAttrib->yuv) { | 
 | 878 |         float r = color.c1(), g = color.c2(), b = color.c3(); | 
 | 879 |         float y = wr * r + wg * g + wb * b; | 
 | 880 |         float u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5; | 
 | 881 |         float v = 0.5 * ((r - y) / (1.0 - wr)) + 0.5; | 
 | 882 |  | 
 | 883 |         // Produce black if color is outside the YUV gamut | 
 | 884 |         if ((y < 0.0) || (y > 1.0) | 
 | 885 |             || (u < 0.0) || (u > 1.0) | 
 | 886 |             || (v < 0.0) || (v > 1.0)) { | 
 | 887 |             y = 0.0; | 
 | 888 |             u = v = 0.5; | 
 | 889 |         } | 
 | 890 |  | 
 | 891 |         color = ColorFract(y, u, v); | 
 | 892 |     } | 
 | 893 |  | 
 | 894 |     // If needed perform YUV to RGB conversion | 
 | 895 |     // Equations determined from the ITU709 equations for RGB to YUV | 
 | 896 |     // conversion, plus the following algebra: | 
 | 897 |     // | 
 | 898 |     //   u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5 | 
 | 899 |     //   0.5 * ((b - y) / (1.0 - wb)) = u - 0.5 | 
 | 900 |     //   (b - y) / (1.0 - wb) = 2 * (u - 0.5) | 
 | 901 |     //   b - y = 2 * (u - 0.5) * (1.0 - wb) | 
 | 902 |     //   b = 2 * (u - 0.5) * (1.0 - wb) + y | 
 | 903 |     // | 
 | 904 |     //   v = 0.5 * ((r -y) / (1.0 - wr)) + 0.5 | 
 | 905 |     //   0.5 * ((r - y) / (1.0 - wr)) = v - 0.5 | 
 | 906 |     //   (r - y) / (1.0 - wr) = 2 * (v - 0.5) | 
 | 907 |     //   r - y = 2 * (v - 0.5) * (1.0 - wr) | 
 | 908 |     //   r = 2 * (v - 0.5) * (1.0 - wr) + y | 
 | 909 |     // | 
 | 910 |     //   y = wr * r + wg * g + wb * b | 
 | 911 |     //   wr * r + wg * g + wb * b = y | 
 | 912 |     //   wg * g = y - wr * r - wb * b | 
 | 913 |     //   g = (y - wr * r - wb * b) / wg | 
 | 914 |     if (fromAttrib->yuv && toAttrib->rgb) { | 
 | 915 |         float y = color.c1(), u = color.c2(), v = color.c3(); | 
 | 916 |         float r = 2.0 * (v - 0.5) * (1.0 - wr) + y; | 
 | 917 |         float b = 2.0 * (u - 0.5) * (1.0 - wb) + y; | 
 | 918 |         float g = (y - wr * r - wb * b) / wg; | 
 | 919 |  | 
 | 920 |         // Produce black if color is outside the RGB gamut | 
 | 921 |         if ((r < 0.0) || (r > 1.0) | 
 | 922 |             || (g < 0.0) || (g > 1.0) | 
 | 923 |             || (b < 0.0) || (b > 1.0)) { | 
 | 924 |             r = g = b = 0.0; | 
 | 925 |         } | 
 | 926 |  | 
 | 927 |         color = ColorFract(r, g, b); | 
 | 928 |     } | 
 | 929 |  | 
 | 930 |     // Within to format, convert from fraction of valid range | 
 | 931 |     // to fraction of full range | 
 | 932 |     c1Val = (toAttrib->c1Low | 
 | 933 |         + (float) (toAttrib->c1High - toAttrib->c1Low) * color.c1()); | 
 | 934 |     c2Val = (toAttrib->c1Low | 
 | 935 |         + (float) (toAttrib->c2High - toAttrib->c2Low) * color.c2()); | 
 | 936 |     c3Val = (toAttrib->c1Low | 
 | 937 |         + (float) (toAttrib->c3High - toAttrib->c3Low) * color.c3()); | 
 | 938 |     color = ColorFract((float) (c1Val - toAttrib->c1Min) | 
 | 939 |                            / (float) (toAttrib->c1Max - toAttrib->c1Min), | 
 | 940 |                        (float) (c2Val - toAttrib->c2Min) | 
 | 941 |                            / (float) (toAttrib->c2Max - toAttrib->c2Min), | 
 | 942 |                        (float) (c3Val - toAttrib->c3Min) | 
 | 943 |                            / (float) (toAttrib->c3Max - toAttrib->c3Min)); | 
 | 944 | } | 
 | 945 |  | 
 | 946 | // TODO: Use PrintGLString, CechckGlError, and PrintEGLConfiguration | 
 | 947 | //       from libglTest | 
 | 948 | static void printGLString(const char *name, GLenum s) | 
 | 949 | { | 
 | 950 |     const char *v = (const char *) glGetString(s); | 
 | 951 |  | 
 | 952 |     if (v == NULL) { | 
 | 953 |         testPrintI("GL %s unknown", name); | 
 | 954 |     } else { | 
 | 955 |         testPrintI("GL %s = %s", name, v); | 
 | 956 |     } | 
 | 957 | } | 
 | 958 |  | 
 | 959 | static void checkEglError(const char* op, EGLBoolean returnVal) | 
 | 960 | { | 
 | 961 |     if (returnVal != EGL_TRUE) { | 
 | 962 |         testPrintE("%s() returned %d", op, returnVal); | 
 | 963 |     } | 
 | 964 |  | 
 | 965 |     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error | 
 | 966 |             = eglGetError()) { | 
 | 967 |         testPrintE("after %s() eglError %s (0x%x)", | 
 | 968 |                    op, EGLUtils::strerror(error), error); | 
 | 969 |     } | 
 | 970 | } | 
 | 971 |  | 
 | 972 | static void checkGlError(const char* op) | 
 | 973 | { | 
 | 974 |     for (GLint error = glGetError(); error; error | 
 | 975 |             = glGetError()) { | 
 | 976 |         testPrintE("after %s() glError (0x%x)", op, error); | 
 | 977 |     } | 
 | 978 | } | 
 | 979 |  | 
 | 980 | static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) | 
 | 981 | { | 
 | 982 |  | 
 | 983 | #define X(VAL) {VAL, #VAL} | 
 | 984 |     struct {EGLint attribute; const char* name;} names[] = { | 
 | 985 |     X(EGL_BUFFER_SIZE), | 
 | 986 |     X(EGL_ALPHA_SIZE), | 
 | 987 |     X(EGL_BLUE_SIZE), | 
 | 988 |     X(EGL_GREEN_SIZE), | 
 | 989 |     X(EGL_RED_SIZE), | 
 | 990 |     X(EGL_DEPTH_SIZE), | 
 | 991 |     X(EGL_STENCIL_SIZE), | 
 | 992 |     X(EGL_CONFIG_CAVEAT), | 
 | 993 |     X(EGL_CONFIG_ID), | 
 | 994 |     X(EGL_LEVEL), | 
 | 995 |     X(EGL_MAX_PBUFFER_HEIGHT), | 
 | 996 |     X(EGL_MAX_PBUFFER_PIXELS), | 
 | 997 |     X(EGL_MAX_PBUFFER_WIDTH), | 
 | 998 |     X(EGL_NATIVE_RENDERABLE), | 
 | 999 |     X(EGL_NATIVE_VISUAL_ID), | 
 | 1000 |     X(EGL_NATIVE_VISUAL_TYPE), | 
 | 1001 |     X(EGL_SAMPLES), | 
 | 1002 |     X(EGL_SAMPLE_BUFFERS), | 
 | 1003 |     X(EGL_SURFACE_TYPE), | 
 | 1004 |     X(EGL_TRANSPARENT_TYPE), | 
 | 1005 |     X(EGL_TRANSPARENT_RED_VALUE), | 
 | 1006 |     X(EGL_TRANSPARENT_GREEN_VALUE), | 
 | 1007 |     X(EGL_TRANSPARENT_BLUE_VALUE), | 
 | 1008 |     X(EGL_BIND_TO_TEXTURE_RGB), | 
 | 1009 |     X(EGL_BIND_TO_TEXTURE_RGBA), | 
 | 1010 |     X(EGL_MIN_SWAP_INTERVAL), | 
 | 1011 |     X(EGL_MAX_SWAP_INTERVAL), | 
 | 1012 |     X(EGL_LUMINANCE_SIZE), | 
 | 1013 |     X(EGL_ALPHA_MASK_SIZE), | 
 | 1014 |     X(EGL_COLOR_BUFFER_TYPE), | 
 | 1015 |     X(EGL_RENDERABLE_TYPE), | 
 | 1016 |     X(EGL_CONFORMANT), | 
 | 1017 |    }; | 
 | 1018 | #undef X | 
 | 1019 |  | 
 | 1020 |     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { | 
 | 1021 |         EGLint value = -1; | 
 | 1022 |         EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, | 
 | 1023 |                                               &value); | 
 | 1024 |         EGLint error = eglGetError(); | 
 | 1025 |         if (returnVal && error == EGL_SUCCESS) { | 
 | 1026 |             testPrintI(" %s: %d (%#x)", names[j].name, value, value); | 
 | 1027 |         } | 
 | 1028 |     } | 
 | 1029 |     testPrintI(""); | 
 | 1030 | } |