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