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