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