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