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