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