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