blob: 7fae5e598dcf7c74f1e7c25a90b9e148b6d926d8 [file] [log] [blame]
Louis Huemiller734d8d82011-01-05 18:53:47 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18/*
19 * Hardware Composer Test Library
20 * Utility library functions for use by the Hardware Composer test cases
21 */
22
23#include <sstream>
24#include <string>
25
26#include <arpa/inet.h> // For ntohl() and htonl()
27
Mathias Agopian622cfad2012-03-05 13:57:02 -080028#include "hwcTestLib.h"
Louis Huemiller734d8d82011-01-05 18:53:47 -080029
Mathias Agopian870b8aa2012-02-24 16:42:46 -080030#include "EGLUtils.h"
31
Louis Huemiller734d8d82011-01-05 18:53:47 -080032// Defines
33#define NUMA(a) (sizeof(a) / sizeof(a [0]))
34
35// Function Prototypes
36static void printGLString(const char *name, GLenum s);
37static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
38static void checkGlError(const char* op);
39static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
40
41using namespace std;
42using namespace android;
43
44
45#define BITSPERBYTE 8 // TODO: Obtain from <values.h>, once
46 // it has been added
47
48// Initialize Display
49void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
50 EGLint *width, EGLint *height)
51{
52 static EGLContext context;
53
54 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
Andy McFadden6ef57d72014-03-05 15:06:53 -080083 // 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();
Louis Huemiller734d8d82011-01-05 18:53:47 -080088 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
Jesse Hall5880cc52012-06-05 23:40:32 -0700141void hwcTestOpenHwc(hwc_composer_device_1_t **hwcDevicePtr)
Louis Huemiller734d8d82011-01-05 18:53:47 -0800142{
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 }
Jesse Hall5880cc52012-06-05 23:40:32 -0700152 if ((rv = hwc_open_1(hwcModule, hwcDevicePtr)) != 0) {
Louis Huemiller734d8d82011-01-05 18:53:47 -0800153 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
161ColorFract::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
173HwcTestDim::operator string()
174{
175 ostringstream out;
176
177 out << '[' << this->width() << ", "
178 << this->height() << ']';
179
180 return out.str();
181}
182
Louis Huemiller653f8102011-01-09 10:59:31 -0800183// Dimension class to hwc_rect conversion
184HwcTestDim::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
Louis Huemiller734d8d82011-01-05 18:53:47 -0800196// Hardware Composer rectangle to string conversion
197string 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]
212struct 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]
263HwcTestDim 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.
307ColorFract 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.
360const 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
Louis Huemiller653f8102011-01-09 10:59:31 -0800371// 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.
374const 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
Louis Huemiller734d8d82011-01-05 18:53:47 -0800386// Given the integer ID of a graphic format, return a pointer to
387// a string that describes the format.
388const 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 */
Jesse Hallb685c542012-07-31 14:32:56 -0700406hwc_display_contents_1_t *hwcTestCreateLayerList(size_t numLayers)
Louis Huemiller734d8d82011-01-05 18:53:47 -0800407{
Jesse Hallb685c542012-07-31 14:32:56 -0700408 hwc_display_contents_1_t *list;
Louis Huemiller734d8d82011-01-05 18:53:47 -0800409
Jesse Hallb685c542012-07-31 14:32:56 -0700410 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) {
Louis Huemiller734d8d82011-01-05 18:53:47 -0800412 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 */
Jesse Hallb685c542012-07-31 14:32:56 -0700424void hwcTestFreeLayerList(hwc_display_contents_1_t *list)
Louis Huemiller734d8d82011-01-05 18:53:47 -0800425{
426 free(list);
427}
428
429// Display the settings of the layer list pointed to by list
Jesse Hallb685c542012-07-31 14:32:56 -0700430void hwcTestDisplayList(hwc_display_contents_1_t *list)
Louis Huemiller734d8d82011-01-05 18:53:47 -0800431{
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]",
Louis Huemiller06c3ae92011-01-10 17:21:15 -0800484 (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));
Louis Huemiller734d8d82011-01-05 18:53:47 -0800492 }
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 */
Jesse Hallb685c542012-07-31 14:32:56 -0700501void hwcTestDisplayListPrepareModifiable(hwc_display_contents_1_t *list)
Louis Huemiller734d8d82011-01-05 18:53:47 -0800502{
Louis Huemiller06c3ae92011-01-10 17:21:15 -0800503 uint32_t numOverlays = 0;
Louis Huemiller734d8d82011-01-05 18:53:47 -0800504 for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
Louis Huemiller06c3ae92011-01-10 17:21:15 -0800505 if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
506 numOverlays++;
507 }
Louis Huemiller734d8d82011-01-05 18:53:47 -0800508 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 }
Louis Huemiller06c3ae92011-01-10 17:21:15 -0800521 testPrintI(" numOverlays: %u", numOverlays);
Louis Huemiller734d8d82011-01-05 18:53:47 -0800522}
523
524/*
525 * Display List Handles
526 *
527 * Displays the handles of all the graphic buffers in the list.
528 */
Jesse Hallb685c542012-07-31 14:32:56 -0700529void hwcTestDisplayListHandles(hwc_display_contents_1_t *list)
Louis Huemiller734d8d82011-01-05 18:53:47 -0800530{
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.
547uint32_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},
Louis Huemiller734d8d82011-01-05 18:53:47 -0800567 {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().
606void 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},
Louis Huemiller734d8d82011-01-05 18:53:47 -0800619 };
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
655void 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).
692void hwcTestFillColorHBlend(GraphicBuffer *gBuf, uint32_t colorFormat,
693 ColorFract startColor, ColorFract endColor)
694{
695 status_t err;
696 unsigned char* buf = NULL;
697 const uint32_t width = gBuf->getWidth();
698 const uint32_t height = gBuf->getHeight();
699 const uint32_t stride = gBuf->getStride();
700
701 err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
702 if (err != 0) {
703 testPrintE("hwcTestFillColorHBlend lock failed: %d", err);
704 exit(110);
705 }
706
707 for (unsigned int x = 0; x < stride; x++) {
708 uint32_t pixel;
709 if (x < width) {
710 ColorFract color(startColor.c1() + (endColor.c1() - startColor.c1())
711 * ((float) x / (float) (width - 1)),
712 startColor.c2() + (endColor.c2() - startColor.c2())
713 * ((float) x / (float) (width - 1)),
714 startColor.c3() + (endColor.c3() - startColor.c3())
715 * ((float) x / (float) (width - 1)));
716
717 // When formats differ, convert colors.
718 // Important to not convert when formats are the same, since
719 // out of gamut colors are always converted to black.
720 if (colorFormat != (uint32_t) gBuf->getPixelFormat()) {
721 hwcTestColorConvert(colorFormat, gBuf->getPixelFormat(), color);
722 }
723 pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, 1.0);
724 } else {
725 // Fill pad with random values
726 pixel = testRand();
727 }
728
Louis Huemiller9a8244b2011-01-09 19:02:05 -0800729 for (unsigned int y = 0; y < height; y++) {
Louis Huemiller734d8d82011-01-05 18:53:47 -0800730 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 */
795void 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},
Louis Huemiller734d8d82011-01-05 18:53:47 -0800816 {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
944static 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
955static 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
968static 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
976static 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}