| 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 |  | 
| Dan Albert | bcc1ae0 | 2014-11-04 17:25:12 -0800 | [diff] [blame] | 23 | #include <arpa/inet.h> // For ntohl() and htonl() | 
 | 24 |  | 
 | 25 | #include <cmath> | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 26 | #include <sstream> | 
 | 27 | #include <string> | 
 | 28 |  | 
| Mathias Agopian | 622cfad | 2012-03-05 13:57:02 -0800 | [diff] [blame] | 29 | #include "hwcTestLib.h" | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 30 |  | 
| Mathias Agopian | 870b8aa | 2012-02-24 16:42:46 -0800 | [diff] [blame] | 31 | #include "EGLUtils.h" | 
 | 32 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 33 | // Defines | 
| Dan Albert | bcc1ae0 | 2014-11-04 17:25:12 -0800 | [diff] [blame] | 34 | #define NUMA(a) (sizeof(a) / sizeof((a)[0])) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 35 |  | 
 | 36 | // Function Prototypes | 
 | 37 | static void printGLString(const char *name, GLenum s); | 
 | 38 | static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  | 
| Andy McFadden | 6ef57d7 | 2014-03-05 15:06:53 -0800 | [diff] [blame] | 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(); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 139 | void hwcTestOpenHwc(hwc_composer_device_1_t **hwcDevicePtr) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |     } | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 150 |     if ((rv = hwc_open_1(hwcModule, hwcDevicePtr)) != 0) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 | 
 | 159 | ColorFract::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 | 
 | 171 | HwcTestDim::operator string() | 
 | 172 | { | 
 | 173 |     ostringstream out; | 
 | 174 |  | 
 | 175 |     out << '[' << this->width() << ", " | 
 | 176 |         << this->height() << ']'; | 
 | 177 |  | 
 | 178 |     return out.str(); | 
 | 179 | } | 
 | 180 |  | 
| Louis Huemiller | 653f810 | 2011-01-09 10:59:31 -0800 | [diff] [blame] | 181 | // Dimension class to hwc_rect conversion | 
 | 182 | HwcTestDim::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 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 194 | // Hardware Composer rectangle to string conversion | 
 | 195 | string 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] | 
 | 210 | struct 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] | 
 | 261 | HwcTestDim 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. | 
 | 305 | ColorFract 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. | 
 | 358 | const 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 |  | 
| Louis Huemiller | 653f810 | 2011-01-09 10:59:31 -0800 | [diff] [blame] | 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. | 
 | 372 | const 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 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 384 | // Given the integer ID of a graphic format, return a pointer to | 
 | 385 | // a string that describes the format. | 
 | 386 | const 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 |  */ | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 404 | hwc_display_contents_1_t *hwcTestCreateLayerList(size_t numLayers) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 405 | { | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 406 |     hwc_display_contents_1_t *list; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 407 |  | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 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) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  */ | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 422 | void hwcTestFreeLayerList(hwc_display_contents_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 423 | { | 
 | 424 |     free(list); | 
 | 425 | } | 
 | 426 |  | 
 | 427 | // Display the settings of the layer list pointed to by list | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 428 | void hwcTestDisplayList(hwc_display_contents_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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]", | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 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)); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  */ | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 499 | void hwcTestDisplayListPrepareModifiable(hwc_display_contents_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 500 | { | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 501 |     uint32_t numOverlays = 0; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 502 |     for (unsigned int layer = 0; layer < list->numHwLayers; layer++) { | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 503 |         if (list->hwLayers[layer].compositionType == HWC_OVERLAY) { | 
 | 504 |             numOverlays++; | 
 | 505 |         } | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |     } | 
| Louis Huemiller | 06c3ae9 | 2011-01-10 17:21:15 -0800 | [diff] [blame] | 519 |     testPrintI("    numOverlays: %u", numOverlays); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 520 | } | 
 | 521 |  | 
 | 522 | /* | 
 | 523 |  * Display List Handles | 
 | 524 |  * | 
 | 525 |  * Displays the handles of all the graphic buffers in the list. | 
 | 526 |  */ | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 527 | void hwcTestDisplayListHandles(hwc_display_contents_1_t *list) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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. | 
 | 545 | uint32_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}, | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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}, | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 617 |     }; | 
 | 618 |  | 
 | 619 |     if (gBuf->getPixelFormat() == HAL_PIXEL_FORMAT_YV12) { | 
 | 620 |         uint32_t yPlaneOffset, uPlaneOffset, vPlaneOffset; | 
 | 621 |         uint32_t yPlaneStride = gBuf->getStride(); | 
 | 622 |         uint32_t uPlaneStride = ((gBuf->getStride() / 2) + 0xf) & ~0xf; | 
 | 623 |         uint32_t vPlaneStride = uPlaneStride; | 
 | 624 |         yPlaneOffset = 0; | 
 | 625 |         vPlaneOffset = yPlaneOffset + yPlaneStride * gBuf->getHeight(); | 
 | 626 |         uPlaneOffset = vPlaneOffset | 
 | 627 |                        + vPlaneStride * (gBuf->getHeight() / 2); | 
 | 628 |         *(buf + yPlaneOffset + y * yPlaneStride + x) = pixel & 0xff; | 
 | 629 |         *(buf + uPlaneOffset + (y / 2) * uPlaneStride + (x / 2)) | 
 | 630 |             = (pixel & 0xff00) >> 8; | 
 | 631 |         *(buf + vPlaneOffset + (y / 2) * vPlaneStride + (x / 2)) | 
 | 632 |             = (pixel & 0xff0000) >> 16; | 
 | 633 |  | 
 | 634 |         return; | 
 | 635 |     } | 
 | 636 |  | 
 | 637 |     const struct attrib *attrib; | 
 | 638 |     for (attrib = attributes; attrib < attributes + NUMA(attributes); | 
 | 639 |          attrib++) { | 
 | 640 |         if (attrib->format == gBuf->getPixelFormat()) { break; } | 
 | 641 |     } | 
 | 642 |     if (attrib >= attributes + NUMA(attributes)) { | 
 | 643 |         testPrintE("setPixel unsupported format of: %u", | 
 | 644 |                    gBuf->getPixelFormat()); | 
 | 645 |         exit(90); | 
 | 646 |     } | 
 | 647 |  | 
 | 648 |     memmove(buf + ((gBuf->getStride() * attrib->bytes) * y) | 
 | 649 |             + (attrib->bytes * x), &pixel, attrib->bytes); | 
 | 650 | } | 
 | 651 |  | 
 | 652 | // Fill a given graphic buffer with a uniform color and alpha | 
 | 653 | void hwcTestFillColor(GraphicBuffer *gBuf, ColorFract color, float alpha) | 
 | 654 | { | 
 | 655 |     unsigned char* buf = NULL; | 
 | 656 |     status_t err; | 
 | 657 |     uint32_t pixel; | 
 | 658 |  | 
 | 659 |     pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, alpha); | 
 | 660 |  | 
 | 661 |     err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf)); | 
 | 662 |     if (err != 0) { | 
 | 663 |         testPrintE("hwcTestFillColor lock failed: %d", err); | 
 | 664 |         exit(100); | 
 | 665 |     } | 
 | 666 |  | 
 | 667 |     for (unsigned int x = 0; x < gBuf->getStride(); x++) { | 
 | 668 |         for (unsigned int y = 0; y < gBuf->getHeight(); y++) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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). | 
 | 689 | void 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 |  | 
| Louis Huemiller | 9a8244b | 2011-01-09 19:02:05 -0800 | [diff] [blame] | 726 |         for (unsigned int y = 0; y < height; y++) { | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 |  */ | 
 | 792 | void 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}, | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 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 | 
 | 941 | static 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 |  | 
 | 952 | static 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 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 965 | static 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 | } |