• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Color Equivalence
20  *
21  * Synopsis
22  *   hwc_colorequiv [options] eFmt
23  *
24  *     options:
25          -v - verbose
26  *       -s <0.##, 0.##, 0.##> - Start color (default: <0.0, 0.0, 0.0>
27  *       -e <0.##, 0.##, 0.##> - Ending color (default: <1.0, 1.0, 1.0>
28  *       -r fmt - reference graphic format
29  *       -D #.## - End of test delay
30  *
31  *     graphic formats:
32  *       RGBA8888 (reference frame default)
33  *       RGBX8888
34  *       RGB888
35  *       RGB565
36  *       BGRA8888
37  *       RGBA5551
38  *       RGBA4444
39  *       YV12
40  *
41  * Description
42  *   Renders a horizontal blend in two frames.  The first frame is rendered
43  *   in the upper third of the display and is called the reference frame.
44  *   The second frame is displayed in the middle third and is called the
45  *   equivalence frame.  The primary purpose of this utility is to verify
46  *   that the colors produced in the reference and equivalence frames are
47  *   the same.  The colors are the same when the colors are the same
48  *   vertically between the reference and equivalence frames.
49  *
50  *   By default the reference frame is rendered through the use of the
51  *   RGBA8888 graphic format.  The -r option can be used to specify a
52  *   non-default reference frame graphic format.  The graphic format of
53  *   the equivalence frame is determined by a single required positional
54  *   parameter.  Intentionally there is no default for the graphic format
55  *   of the equivalence frame.
56  *
57  *   The horizontal blend in the reference frame is produced from a linear
58  *   interpolation from a start color (default: <0.0, 0.0, 0.0> on the left
59  *   side to an end color (default <1.0, 1.0, 1.0> on the right side.  Where
60  *   possible the equivalence frame is rendered with the equivalent color
61  *   from the reference frame.  A color of black is used in the equivalence
62  *   frame for cases where an equivalent color does not exist.
63  */
64 
65 #include <algorithm>
66 #include <assert.h>
67 #include <cerrno>
68 #include <cmath>
69 #include <cstdlib>
70 #include <ctime>
71 #include <libgen.h>
72 #include <sched.h>
73 #include <sstream>
74 #include <stdint.h>
75 #include <string.h>
76 #include <unistd.h>
77 #include <vector>
78 
79 #include <sys/syscall.h>
80 #include <sys/types.h>
81 #include <sys/wait.h>
82 
83 #include <EGL/egl.h>
84 #include <EGL/eglext.h>
85 #include <GLES2/gl2.h>
86 #include <GLES2/gl2ext.h>
87 
88 #include <ui/GraphicBuffer.h>
89 
90 #define LOG_TAG "hwcColorEquivTest"
91 #include <utils/Log.h>
92 #include <testUtil.h>
93 
94 #include <hardware/hwcomposer.h>
95 
96 #include "hwcTestLib.h"
97 
98 using namespace std;
99 using namespace android;
100 
101 // Defaults for command-line options
102 const bool defaultVerbose = false;
103 const ColorFract defaultStartColor(0.0, 0.0, 0.0);
104 const ColorFract defaultEndColor(1.0, 1.0, 1.0);
105 const char *defaultRefFormat = "RGBA8888";
106 const float defaultEndDelay = 2.0; // Default delay after rendering graphics
107 
108 // Defines
109 #define MAXSTR               100
110 #define MAXCMD               200
111 #define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
112                                  // it has been added
113 
114 #define CMD_STOP_FRAMEWORK   "stop 2>&1"
115 #define CMD_START_FRAMEWORK  "start 2>&1"
116 
117 // Macros
118 #define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
119 #define MEMCLR(addr, size) do { \
120         memset((addr), 0, (size)); \
121     } while (0)
122 
123 // Globals
124 static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
125         GraphicBuffer::USAGE_SW_WRITE_RARELY;
126 static hwc_composer_device_1_t *hwcDevice;
127 static EGLDisplay dpy;
128 static EGLSurface surface;
129 static EGLint width, height;
130 
131 // Functions prototypes
132 void init(void);
133 void printSyntax(const char *cmd);
134 
135 // Command-line option settings
136 static bool verbose = defaultVerbose;
137 static ColorFract startRefColor = defaultStartColor;
138 static ColorFract endRefColor = defaultEndColor;
139 static float endDelay = defaultEndDelay;
140 static const struct hwcTestGraphicFormat *refFormat
141     = hwcTestGraphicFormatLookup(defaultRefFormat);
142 static const struct hwcTestGraphicFormat *equivFormat;
143 
144 /*
145  * Main
146  *
147  * Performs the following high-level sequence of operations:
148  *
149  *   1. Command-line parsing
150  *
151  *   2. Stop framework
152  *
153  *   3. Initialization
154  *
155  *   4. Create Hardware Composer description of reference and equivalence frames
156  *
157  *   5. Have Hardware Composer render the reference and equivalence frames
158  *
159  *   6. Delay for amount of time given by endDelay
160  *
161  *   7. Start framework
162  */
163 int
main(int argc,char * argv[])164 main(int argc, char *argv[])
165 {
166     int rv, opt;
167     bool error;
168     char *chptr;
169     char cmd[MAXCMD];
170     string str;
171 
172     testSetLogCatTag(LOG_TAG);
173 
174     assert(refFormat != NULL);
175 
176     testSetLogCatTag(LOG_TAG);
177 
178     // Parse command line arguments
179     while ((opt = getopt(argc, argv, "vs:e:r:D:?h")) != -1) {
180         switch (opt) {
181           case 'D': // End of test delay
182                     // Delay between completion of final pass and restart
183                     // of framework
184             endDelay = strtod(optarg, &chptr);
185             if ((*chptr != '\0') || (endDelay < 0.0)) {
186                 testPrintE("Invalid command-line specified end of test delay "
187                            "of: %s", optarg);
188                 exit(1);
189             }
190             break;
191 
192           case 's': // Starting reference color
193             str = optarg;
194             while (optind < argc) {
195                 if (*argv[optind] == '-') { break; }
196                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
197                 if ((endChar == '>') || (endChar == ']')) { break; }
198                 str += " " + string(argv[optind++]);
199             }
200             {
201                 istringstream in(str);
202                 startRefColor = hwcTestParseColor(in, error);
203                 // Any parse error or characters not used by parser
204                 if (error
205                     || (((unsigned int) in.tellg() != in.str().length())
206                         && (in.tellg() != (streampos) -1))) {
207                     testPrintE("Invalid command-line specified start "
208                                "reference color of: %s", str.c_str());
209                     exit(2);
210                 }
211             }
212             break;
213 
214           case 'e': // Ending reference color
215             str = optarg;
216             while (optind < argc) {
217                 if (*argv[optind] == '-') { break; }
218                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
219                 if ((endChar == '>') || (endChar == ']')) { break; }
220                 str += " " + string(argv[optind++]);
221             }
222             {
223                 istringstream in(str);
224                 endRefColor = hwcTestParseColor(in, error);
225                 // Any parse error or characters not used by parser
226                 if (error
227                     || (((unsigned int) in.tellg() != in.str().length())
228                         && (in.tellg() != (streampos) -1))) {
229                     testPrintE("Invalid command-line specified end "
230                                "reference color of: %s", str.c_str());
231                     exit(3);
232                 }
233             }
234             break;
235 
236           case 'r': // Reference graphic format
237             refFormat = hwcTestGraphicFormatLookup(optarg);
238             if (refFormat == NULL) {
239                 testPrintE("Unkown command-line specified reference graphic "
240                            "format of: %s", optarg);
241                 printSyntax(basename(argv[0]));
242                 exit(4);
243             }
244             break;
245 
246           case 'v': // Verbose
247             verbose = true;
248             break;
249 
250           case 'h': // Help
251           case '?':
252           default:
253             printSyntax(basename(argv[0]));
254             exit(((optopt == 0) || (optopt == '?')) ? 0 : 5);
255         }
256     }
257 
258     // Expect a single positional parameter, which specifies the
259     // equivalence graphic format.
260     if (argc != (optind + 1)) {
261         testPrintE("Expected a single command-line postional parameter");
262         printSyntax(basename(argv[0]));
263         exit(6);
264     }
265     equivFormat = hwcTestGraphicFormatLookup(argv[optind]);
266     if (equivFormat == NULL) {
267         testPrintE("Unkown command-line specified equivalence graphic "
268                    "format of: %s", argv[optind]);
269         printSyntax(basename(argv[0]));
270         exit(7);
271     }
272 
273     testPrintI("refFormat: %u %s", refFormat->format, refFormat->desc);
274     testPrintI("equivFormat: %u %s", equivFormat->format, equivFormat->desc);
275     testPrintI("startRefColor: %s", ((string) startRefColor).c_str());
276     testPrintI("endRefColor: %s", ((string) endRefColor).c_str());
277     testPrintI("endDelay: %f", endDelay);
278 
279     // Stop framework
280     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
281     if (rv >= (signed) sizeof(cmd) - 1) {
282         testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
283         exit(8);
284     }
285     testExecCmd(cmd);
286     testDelay(1.0); // TODO - needs means to query whether asynchronous stop
287                     // framework operation has completed.  For now, just wait
288                     // a long time.
289 
290     init();
291 
292     // Use the upper third of the display for the reference frame and
293     // the middle third for the equivalence frame.
294     unsigned int refHeight = height / 3;
295     unsigned int refPosX = 0; // Reference frame X position
296     unsigned int refWidth = width - refPosX;
297     if ((refWidth & refFormat->wMod) != 0) {
298         refWidth += refFormat->wMod - (refWidth % refFormat->wMod);
299     }
300     unsigned int equivHeight = height / 3;
301     unsigned int equivPosX = 0;         // Equivalence frame X position
302     unsigned int equivWidth = width - equivPosX;
303     if ((equivWidth & equivFormat->wMod) != 0) {
304         equivWidth += equivFormat->wMod - (equivWidth % equivFormat->wMod);
305     }
306 
307     // Create reference and equivalence graphic buffers
308     const unsigned int numFrames = 2;
309     sp<GraphicBuffer> refFrame;
310     refFrame = new GraphicBuffer(refWidth, refHeight,
311                                  refFormat->format, texUsage);
312     if ((rv = refFrame->initCheck()) != NO_ERROR) {
313         testPrintE("refFrame initCheck failed, rv: %i", rv);
314         testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
315                    refFormat->format,
316                    hwcTestGraphicFormat2str(refFormat->format));
317         exit(9);
318     }
319     testPrintI("refFrame width: %u height: %u format: %u %s",
320                refWidth, refHeight, refFormat->format,
321                hwcTestGraphicFormat2str(refFormat->format));
322 
323     sp<GraphicBuffer> equivFrame;
324     equivFrame = new GraphicBuffer(equivWidth, equivHeight,
325                                    equivFormat->format, texUsage);
326     if ((rv = refFrame->initCheck()) != NO_ERROR) {
327         testPrintE("refFrame initCheck failed, rv: %i", rv);
328         testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
329                    refFormat->format,
330                    hwcTestGraphicFormat2str(refFormat->format));
331         exit(10);
332     }
333     testPrintI("equivFrame width: %u height: %u format: %u %s",
334                equivWidth, equivHeight, equivFormat->format,
335                hwcTestGraphicFormat2str(equivFormat->format));
336 
337     // Fill the frames with a horizontal blend
338     hwcTestFillColorHBlend(refFrame.get(), refFormat->format,
339                            startRefColor, endRefColor);
340     hwcTestFillColorHBlend(equivFrame.get(), refFormat->format,
341                            startRefColor, endRefColor);
342 
343     hwc_display_contents_1_t *list;
344     size_t size = sizeof(hwc_display_contents_1_t) + numFrames * sizeof(hwc_layer_1_t);
345     if ((list = (hwc_display_contents_1_t *) calloc(1, size)) == NULL) {
346         testPrintE("Allocate list failed");
347         exit(11);
348     }
349     list->flags = HWC_GEOMETRY_CHANGED;
350     list->numHwLayers = numFrames;
351 
352     hwc_layer_1_t *layer = &list->hwLayers[0];
353     layer->handle = refFrame->handle;
354     layer->blending = HWC_BLENDING_NONE;
355     layer->sourceCrop.left = 0;
356     layer->sourceCrop.top = 0;
357     layer->sourceCrop.right = width;
358     layer->sourceCrop.bottom = refHeight;
359     layer->displayFrame.left = 0;
360     layer->displayFrame.top = 0;
361     layer->displayFrame.right = width;
362     layer->displayFrame.bottom = refHeight;
363     layer->visibleRegionScreen.numRects = 1;
364     layer->visibleRegionScreen.rects = &layer->displayFrame;
365 
366     layer++;
367     layer->handle = equivFrame->handle;
368     layer->blending = HWC_BLENDING_NONE;
369     layer->sourceCrop.left = 0;
370     layer->sourceCrop.top = 0;
371     layer->sourceCrop.right = width;
372     layer->sourceCrop.bottom = equivHeight;
373     layer->displayFrame.left = 0;
374     layer->displayFrame.top = refHeight;
375     layer->displayFrame.right = width;
376     layer->displayFrame.bottom = layer->displayFrame.top + equivHeight;
377     layer->visibleRegionScreen.numRects = 1;
378     layer->visibleRegionScreen.rects = &layer->displayFrame;
379 
380     // Perform prepare operation
381     if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
382     hwcDevice->prepare(hwcDevice, 1, &list);
383     if (verbose) {
384         testPrintI("Post Prepare:");
385         hwcTestDisplayListPrepareModifiable(list);
386     }
387 
388     // Turn off the geometry changed flag
389     list->flags &= ~HWC_GEOMETRY_CHANGED;
390 
391     if (verbose) {hwcTestDisplayListHandles(list); }
392     list->dpy = dpy;
393     list->sur = surface;
394     hwcDevice->set(hwcDevice, 1, &list);
395 
396     testDelay(endDelay);
397 
398     // Start framework
399     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
400     if (rv >= (signed) sizeof(cmd) - 1) {
401         testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
402         exit(12);
403     }
404     testExecCmd(cmd);
405 
406     return 0;
407 }
408 
init(void)409 void init(void)
410 {
411     // Seed pseudo random number generator
412     // Seeding causes fill horizontal blend to fill the pad area with
413     // a deterministic set of values.
414     srand48(0);
415 
416     hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
417 
418     hwcTestOpenHwc(&hwcDevice);
419 }
420 
printSyntax(const char * cmd)421 void printSyntax(const char *cmd)
422 {
423     testPrintE("  %s [options] graphicFormat", cmd);
424     testPrintE("    options:");
425     testPrintE("      -s <0.##, 0.##, 0.##> - Starting reference color");
426     testPrintE("      -e <0.##, 0.##, 0.##> - Ending reference color");
427     testPrintE("      -r format - Reference graphic format");
428     testPrintE("      -D #.## - End of test delay");
429     testPrintE("      -v Verbose");
430     testPrintE("");
431     testPrintE("    graphic formats:");
432     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
433         testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
434     }
435 }
436