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