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