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