| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2010 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 stress test | 
 | 20 |  * | 
 | 21 |  * Performs a pseudo-random (prandom) sequence of operations to the | 
 | 22 |  * Hardware Composer (HWC), for a specified number of passes or for | 
 | 23 |  * a specified period of time.  By default the period of time is FLT_MAX, | 
 | 24 |  * so that the number of passes will take precedence. | 
 | 25 |  * | 
 | 26 |  * The passes are grouped together, where (pass / passesPerGroup) specifies | 
 | 27 |  * which group a particular pass is in.  This causes every passesPerGroup | 
 | 28 |  * worth of sequential passes to be within the same group.  Computationally | 
 | 29 |  * intensive operations are performed just once at the beginning of a group | 
 | 30 |  * of passes and then used by all the passes in that group.  This is done | 
 | 31 |  * so as to increase both the average and peak rate of graphic operations, | 
 | 32 |  * by moving computationally intensive operations to the beginning of a group. | 
 | 33 |  * In particular, at the start of each group of passes a set of | 
 | 34 |  * graphic buffers are created, then used by the first and remaining | 
 | 35 |  * passes of that group of passes. | 
 | 36 |  * | 
 | 37 |  * The per-group initialization of the graphic buffers is performed | 
 | 38 |  * by a function called initFrames.  This function creates an array | 
 | 39 |  * of smart pointers to the graphic buffers, in the form of a vector | 
 | 40 |  * of vectors.  The array is accessed in row major order, so each | 
 | 41 |  * row is a vector of smart pointers.  All the pointers of a single | 
 | 42 |  * row point to graphic buffers which use the same pixel format and | 
 | 43 |  * have the same dimension, although it is likely that each one is | 
 | 44 |  * filled with a different color.  This is done so that after doing | 
 | 45 |  * the first HWC prepare then set call, subsequent set calls can | 
 | 46 |  * be made with each of the layer handles changed to a different | 
 | 47 |  * graphic buffer within the same row.  Since the graphic buffers | 
 | 48 |  * in a particular row have the same pixel format and dimension, | 
 | 49 |  * additional HWC set calls can be made, without having to perform | 
 | 50 |  * an HWC prepare call. | 
 | 51 |  * | 
 | 52 |  * This test supports the following command-line options: | 
 | 53 |  * | 
 | 54 |  *   -v        Verbose | 
 | 55 |  *   -s num    Starting pass | 
 | 56 |  *   -e num    Ending pass | 
 | 57 |  *   -p num    Execute the single pass specified by num | 
 | 58 |  *   -n num    Number of set operations to perform after each prepare operation | 
 | 59 |  *   -t float  Maximum time in seconds to execute the test | 
 | 60 |  *   -d float  Delay in seconds performed after each set operation | 
 | 61 |  *   -D float  Delay in seconds performed after the last pass is executed | 
 | 62 |  * | 
 | 63 |  * Typically the test is executed for a large range of passes.  By default | 
 | 64 |  * passes 0 through 99999 (100,000 passes) are executed.  Although this test | 
 | 65 |  * does not validate the generated image, at times it is useful to reexecute | 
 | 66 |  * a particular pass and leave the displayed image on the screen for an | 
 | 67 |  * extended period of time.  This can be done either by setting the -s | 
 | 68 |  * and -e options to the desired pass, along with a large value for -D. | 
 | 69 |  * This can also be done via the -p option, again with a large value for | 
 | 70 |  * the -D options. | 
 | 71 |  * | 
 | 72 |  * So far this test only contains code to create graphic buffers with | 
 | 73 |  * a continuous solid color.  Although this test is unable to validate the | 
 | 74 |  * image produced, any image that contains other than rectangles of a solid | 
 | 75 |  * color are incorrect.  Note that the rectangles may use a transparent | 
 | 76 |  * color and have a blending operation that causes the color in overlapping | 
 | 77 |  * rectangles to be mixed.  In such cases the overlapping portions may have | 
 | 78 |  * a different color from the rest of the rectangle. | 
 | 79 |  */ | 
 | 80 |  | 
| Aurimas Liutikas | d1d1699 | 2016-02-23 17:10:37 -0800 | [diff] [blame] | 81 | #define LOG_TAG "hwcStressTest" | 
 | 82 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 83 | #include <algorithm> | 
 | 84 | #include <assert.h> | 
 | 85 | #include <cerrno> | 
 | 86 | #include <cmath> | 
 | 87 | #include <cstdlib> | 
 | 88 | #include <ctime> | 
 | 89 | #include <libgen.h> | 
 | 90 | #include <sched.h> | 
 | 91 | #include <sstream> | 
 | 92 | #include <stdint.h> | 
 | 93 | #include <string.h> | 
 | 94 | #include <unistd.h> | 
 | 95 | #include <vector> | 
 | 96 |  | 
 | 97 | #include <sys/syscall.h> | 
 | 98 | #include <sys/types.h> | 
 | 99 | #include <sys/wait.h> | 
 | 100 |  | 
 | 101 | #include <EGL/egl.h> | 
 | 102 | #include <EGL/eglext.h> | 
 | 103 | #include <GLES2/gl2.h> | 
 | 104 | #include <GLES2/gl2ext.h> | 
 | 105 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 106 | #include <ui/GraphicBuffer.h> | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 107 |  | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 108 | #include <utils/Log.h> | 
 | 109 | #include <testUtil.h> | 
 | 110 |  | 
 | 111 | #include <hardware/hwcomposer.h> | 
 | 112 |  | 
 | 113 | #include <glTestLib.h> | 
| Mathias Agopian | 622cfad | 2012-03-05 13:57:02 -0800 | [diff] [blame] | 114 | #include "hwcTestLib.h" | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 115 |  | 
 | 116 | using namespace std; | 
 | 117 | using namespace android; | 
 | 118 |  | 
 | 119 | const float maxSizeRatio = 1.3;  // Graphic buffers can be upto this munch | 
 | 120 |                                  // larger than the default screen size | 
 | 121 | const unsigned int passesPerGroup = 10; // A group of passes all use the same | 
 | 122 |                                         // graphic buffers | 
 | 123 |  | 
 | 124 | // Ratios at which rare and frequent conditions should be produced | 
 | 125 | const float rareRatio = 0.1; | 
 | 126 | const float freqRatio = 0.9; | 
 | 127 |  | 
 | 128 | // Defaults for command-line options | 
 | 129 | const bool defaultVerbose = false; | 
 | 130 | const unsigned int defaultStartPass = 0; | 
 | 131 | const unsigned int defaultEndPass = 99999; | 
 | 132 | const unsigned int defaultPerPassNumSet = 10; | 
 | 133 | const float defaultPerSetDelay = 0.0; // Default delay after each set | 
 | 134 |                                       // operation.  Default delay of | 
 | 135 |                                       // zero used so as to perform the | 
 | 136 |                                       // the set operations as quickly | 
 | 137 |                                       // as possible. | 
 | 138 | const float defaultEndDelay = 2.0; // Default delay between completion of | 
 | 139 |                                    // final pass and restart of framework | 
 | 140 | const float defaultDuration = FLT_MAX; // A fairly long time, so that | 
 | 141 |                                        // range of passes will have | 
 | 142 |                                        // precedence | 
 | 143 |  | 
 | 144 | // Command-line option settings | 
 | 145 | static bool verbose = defaultVerbose; | 
 | 146 | static unsigned int startPass = defaultStartPass; | 
 | 147 | static unsigned int endPass = defaultEndPass; | 
 | 148 | static unsigned int numSet = defaultPerPassNumSet; | 
 | 149 | static float perSetDelay = defaultPerSetDelay; | 
 | 150 | static float endDelay = defaultEndDelay; | 
 | 151 | static float duration = defaultDuration; | 
 | 152 |  | 
 | 153 | // Command-line mutual exclusion detection flags. | 
 | 154 | // Corresponding flag set true once an option is used. | 
 | 155 | bool eFlag, sFlag, pFlag; | 
 | 156 |  | 
 | 157 | #define MAXSTR               100 | 
 | 158 | #define MAXCMD               200 | 
 | 159 | #define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once | 
 | 160 |                                  // it has been added | 
 | 161 |  | 
 | 162 | #define CMD_STOP_FRAMEWORK   "stop 2>&1" | 
 | 163 | #define CMD_START_FRAMEWORK  "start 2>&1" | 
 | 164 |  | 
| Chih-Hung Hsieh | 21c6128 | 2016-05-20 11:27:11 -0700 | [diff] [blame] | 165 | #define NUMA(a) (sizeof(a) / sizeof((a)[0])) | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 166 | #define MEMCLR(addr, size) do { \ | 
 | 167 |         memset((addr), 0, (size)); \ | 
 | 168 |     } while (0) | 
 | 169 |  | 
 | 170 | // File scope constants | 
 | 171 | const unsigned int blendingOps[] = { | 
 | 172 |     HWC_BLENDING_NONE, | 
 | 173 |     HWC_BLENDING_PREMULT, | 
 | 174 |     HWC_BLENDING_COVERAGE, | 
 | 175 | }; | 
 | 176 | const unsigned int layerFlags[] = { | 
 | 177 |     HWC_SKIP_LAYER, | 
 | 178 | }; | 
 | 179 | const vector<unsigned int> vecLayerFlags(layerFlags, | 
 | 180 |     layerFlags + NUMA(layerFlags)); | 
 | 181 |  | 
 | 182 | const unsigned int transformFlags[] = { | 
 | 183 |     HWC_TRANSFORM_FLIP_H, | 
 | 184 |     HWC_TRANSFORM_FLIP_V, | 
 | 185 |     HWC_TRANSFORM_ROT_90, | 
 | 186 |     // ROT_180 & ROT_270 intentionally not listed, because they | 
 | 187 |     // they are formed from combinations of the flags already listed. | 
 | 188 | }; | 
 | 189 | const vector<unsigned int> vecTransformFlags(transformFlags, | 
 | 190 |     transformFlags + NUMA(transformFlags)); | 
 | 191 |  | 
 | 192 | // File scope globals | 
 | 193 | static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE | | 
 | 194 |         GraphicBuffer::USAGE_SW_WRITE_RARELY; | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 195 | static hwc_composer_device_1_t *hwcDevice; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 196 | static EGLDisplay dpy; | 
 | 197 | static EGLSurface surface; | 
 | 198 | static EGLint width, height; | 
 | 199 | static vector <vector <sp<GraphicBuffer> > > frames; | 
 | 200 |  | 
 | 201 | // File scope prototypes | 
 | 202 | void init(void); | 
 | 203 | void initFrames(unsigned int seed); | 
 | 204 | template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num); | 
 | 205 | template <class T> T vectorOr(const vector<T>& vec); | 
 | 206 |  | 
 | 207 | /* | 
 | 208 |  * Main | 
 | 209 |  * | 
 | 210 |  * Performs the following high-level sequence of operations: | 
 | 211 |  * | 
 | 212 |  *   1. Command-line parsing | 
 | 213 |  * | 
 | 214 |  *   2. Initialization | 
 | 215 |  * | 
 | 216 |  *   3. For each pass: | 
 | 217 |  * | 
 | 218 |  *        a. If pass is first pass or in a different group from the | 
 | 219 |  *           previous pass, initialize the array of graphic buffers. | 
 | 220 |  * | 
 | 221 |  *        b. Create a HWC list with room to specify a prandomly | 
 | 222 |  *           selected number of layers. | 
 | 223 |  * | 
 | 224 |  *        c. Select a subset of the rows from the graphic buffer array, | 
 | 225 |  *           such that there is a unique row to be used for each | 
 | 226 |  *           of the layers in the HWC list. | 
 | 227 |  * | 
 | 228 |  *        d. Prandomly fill in the HWC list with handles | 
 | 229 |  *           selected from any of the columns of the selected row. | 
 | 230 |  * | 
 | 231 |  *        e. Pass the populated list to the HWC prepare call. | 
 | 232 |  * | 
 | 233 |  *        f. Pass the populated list to the HWC set call. | 
 | 234 |  * | 
 | 235 |  *        g. If additional set calls are to be made, then for each | 
 | 236 |  *           additional set call, select a new set of handles and | 
 | 237 |  *           perform the set call. | 
 | 238 |  */ | 
 | 239 | int | 
 | 240 | main(int argc, char *argv[]) | 
 | 241 | { | 
 | 242 |     int rv, opt; | 
 | 243 |     char *chptr; | 
 | 244 |     unsigned int pass; | 
 | 245 |     char cmd[MAXCMD]; | 
 | 246 |     struct timeval startTime, currentTime, delta; | 
 | 247 |  | 
 | 248 |     testSetLogCatTag(LOG_TAG); | 
 | 249 |  | 
 | 250 |     // Parse command line arguments | 
 | 251 |     while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) { | 
 | 252 |         switch (opt) { | 
 | 253 |           case 'd': // Delay after each set operation | 
 | 254 |             perSetDelay = strtod(optarg, &chptr); | 
 | 255 |             if ((*chptr != '\0') || (perSetDelay < 0.0)) { | 
 | 256 |                 testPrintE("Invalid command-line specified per pass delay of: " | 
 | 257 |                            "%s", optarg); | 
 | 258 |                 exit(1); | 
 | 259 |             } | 
 | 260 |             break; | 
 | 261 |  | 
 | 262 |           case 'D': // End of test delay | 
 | 263 |                     // Delay between completion of final pass and restart | 
 | 264 |                     // of framework | 
 | 265 |             endDelay = strtod(optarg, &chptr); | 
 | 266 |             if ((*chptr != '\0') || (endDelay < 0.0)) { | 
 | 267 |                 testPrintE("Invalid command-line specified end of test delay " | 
 | 268 |                            "of: %s", optarg); | 
 | 269 |                 exit(2); | 
 | 270 |             } | 
 | 271 |             break; | 
 | 272 |  | 
 | 273 |           case 't': // Duration | 
 | 274 |             duration = strtod(optarg, &chptr); | 
 | 275 |             if ((*chptr != '\0') || (duration < 0.0)) { | 
 | 276 |                 testPrintE("Invalid command-line specified duration of: %s", | 
 | 277 |                            optarg); | 
 | 278 |                 exit(3); | 
 | 279 |             } | 
 | 280 |             break; | 
 | 281 |  | 
 | 282 |           case 'n': // Num set operations per pass | 
 | 283 |             numSet = strtoul(optarg, &chptr, 10); | 
 | 284 |             if (*chptr != '\0') { | 
 | 285 |                 testPrintE("Invalid command-line specified num set per pass " | 
 | 286 |                            "of: %s", optarg); | 
 | 287 |                 exit(4); | 
 | 288 |             } | 
 | 289 |             break; | 
 | 290 |  | 
 | 291 |           case 's': // Starting Pass | 
 | 292 |             sFlag = true; | 
 | 293 |             if (pFlag) { | 
 | 294 |                 testPrintE("Invalid combination of command-line options."); | 
 | 295 |                 testPrintE("  The -p option is mutually exclusive from the"); | 
 | 296 |                 testPrintE("  -s and -e options."); | 
 | 297 |                 exit(5); | 
 | 298 |             } | 
 | 299 |             startPass = strtoul(optarg, &chptr, 10); | 
 | 300 |             if (*chptr != '\0') { | 
 | 301 |                 testPrintE("Invalid command-line specified starting pass " | 
 | 302 |                            "of: %s", optarg); | 
 | 303 |                 exit(6); | 
 | 304 |             } | 
 | 305 |             break; | 
 | 306 |  | 
 | 307 |           case 'e': // Ending Pass | 
 | 308 |             eFlag = true; | 
 | 309 |             if (pFlag) { | 
 | 310 |                 testPrintE("Invalid combination of command-line options."); | 
 | 311 |                 testPrintE("  The -p option is mutually exclusive from the"); | 
 | 312 |                 testPrintE("  -s and -e options."); | 
 | 313 |                 exit(7); | 
 | 314 |             } | 
 | 315 |             endPass = strtoul(optarg, &chptr, 10); | 
 | 316 |             if (*chptr != '\0') { | 
 | 317 |                 testPrintE("Invalid command-line specified ending pass " | 
 | 318 |                            "of: %s", optarg); | 
 | 319 |                 exit(8); | 
 | 320 |             } | 
 | 321 |             break; | 
 | 322 |  | 
 | 323 |           case 'p': // Run a single specified pass | 
 | 324 |             pFlag = true; | 
 | 325 |             if (sFlag || eFlag) { | 
 | 326 |                 testPrintE("Invalid combination of command-line options."); | 
 | 327 |                 testPrintE("  The -p option is mutually exclusive from the"); | 
 | 328 |                 testPrintE("  -s and -e options."); | 
 | 329 |                 exit(9); | 
 | 330 |             } | 
 | 331 |             startPass = endPass = strtoul(optarg, &chptr, 10); | 
 | 332 |             if (*chptr != '\0') { | 
 | 333 |                 testPrintE("Invalid command-line specified pass of: %s", | 
 | 334 |                            optarg); | 
 | 335 |                 exit(10); | 
 | 336 |             } | 
 | 337 |             break; | 
 | 338 |  | 
 | 339 |           case 'v': // Verbose | 
 | 340 |             verbose = true; | 
 | 341 |             break; | 
 | 342 |  | 
 | 343 |           case 'h': // Help | 
 | 344 |           case '?': | 
 | 345 |           default: | 
 | 346 |             testPrintE("  %s [options]", basename(argv[0])); | 
 | 347 |             testPrintE("    options:"); | 
 | 348 |             testPrintE("      -p Execute specified pass"); | 
 | 349 |             testPrintE("      -s Starting pass"); | 
 | 350 |             testPrintE("      -e Ending pass"); | 
 | 351 |             testPrintE("      -t Duration"); | 
 | 352 |             testPrintE("      -d Delay after each set operation"); | 
 | 353 |             testPrintE("      -D End of test delay"); | 
 | 354 |             testPrintE("      -n Num set operations per pass"); | 
 | 355 |             testPrintE("      -v Verbose"); | 
 | 356 |             exit(((optopt == 0) || (optopt == '?')) ? 0 : 11); | 
 | 357 |         } | 
 | 358 |     } | 
 | 359 |     if (endPass < startPass) { | 
 | 360 |         testPrintE("Unexpected ending pass before starting pass"); | 
 | 361 |         testPrintE("  startPass: %u endPass: %u", startPass, endPass); | 
 | 362 |         exit(12); | 
 | 363 |     } | 
 | 364 |     if (argc != optind) { | 
 | 365 |         testPrintE("Unexpected command-line postional argument"); | 
 | 366 |         testPrintE("  %s [-s start_pass] [-e end_pass] [-t duration]", | 
 | 367 |             basename(argv[0])); | 
 | 368 |         exit(13); | 
 | 369 |     } | 
 | 370 |     testPrintI("duration: %g", duration); | 
 | 371 |     testPrintI("startPass: %u", startPass); | 
 | 372 |     testPrintI("endPass: %u", endPass); | 
 | 373 |     testPrintI("numSet: %u", numSet); | 
 | 374 |  | 
 | 375 |     // Stop framework | 
 | 376 |     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK); | 
 | 377 |     if (rv >= (signed) sizeof(cmd) - 1) { | 
 | 378 |         testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK); | 
 | 379 |         exit(14); | 
 | 380 |     } | 
 | 381 |     testExecCmd(cmd); | 
 | 382 |     testDelay(1.0); // TODO - need means to query whether asyncronous stop | 
 | 383 |                     // framework operation has completed.  For now, just wait | 
 | 384 |                     // a long time. | 
 | 385 |  | 
 | 386 |     init(); | 
 | 387 |  | 
 | 388 |     // For each pass | 
 | 389 |     gettimeofday(&startTime, NULL); | 
 | 390 |     for (pass = startPass; pass <= endPass; pass++) { | 
 | 391 |         // Stop if duration of work has already been performed | 
 | 392 |         gettimeofday(¤tTime, NULL); | 
 | 393 |         delta = tvDelta(&startTime, ¤tTime); | 
 | 394 |         if (tv2double(&delta) > duration) { break; } | 
 | 395 |  | 
 | 396 |         // Regenerate a new set of test frames when this pass is | 
 | 397 |         // either the first pass or is in a different group then | 
 | 398 |         // the previous pass.  A group of passes are passes that | 
 | 399 |         // all have the same quotient when their pass number is | 
 | 400 |         // divided by passesPerGroup. | 
 | 401 |         if ((pass == startPass) | 
 | 402 |             || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) { | 
 | 403 |             initFrames(pass / passesPerGroup); | 
 | 404 |         } | 
 | 405 |  | 
 | 406 |         testPrintI("==== Starting pass: %u", pass); | 
 | 407 |  | 
 | 408 |         // Cause deterministic sequence of prandom numbers to be | 
 | 409 |         // generated for this pass. | 
 | 410 |         srand48(pass); | 
 | 411 |  | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 412 |         hwc_display_contents_1_t *list; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 413 |         list = hwcTestCreateLayerList(testRandMod(frames.size()) + 1); | 
 | 414 |         if (list == NULL) { | 
 | 415 |             testPrintE("hwcTestCreateLayerList failed"); | 
 | 416 |             exit(20); | 
 | 417 |         } | 
 | 418 |  | 
 | 419 |         // Prandomly select a subset of frames to be used by this pass. | 
 | 420 |         vector <vector <sp<GraphicBuffer> > > selectedFrames; | 
 | 421 |         selectedFrames = vectorRandSelect(frames, list->numHwLayers); | 
 | 422 |  | 
 | 423 |         // Any transform tends to create a layer that the hardware | 
 | 424 |         // composer is unable to support and thus has to leave for | 
 | 425 |         // SurfaceFlinger.  Place heavy bias on specifying no transforms. | 
 | 426 |         bool noTransform = testRandFract() > rareRatio; | 
 | 427 |  | 
 | 428 |         for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) { | 
 | 429 |             unsigned int idx = testRandMod(selectedFrames[n1].size()); | 
 | 430 |             sp<GraphicBuffer> gBuf = selectedFrames[n1][idx]; | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 431 |             hwc_layer_1_t *layer = &list->hwLayers[n1]; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 432 |             layer->handle = gBuf->handle; | 
 | 433 |  | 
 | 434 |             layer->blending = blendingOps[testRandMod(NUMA(blendingOps))]; | 
 | 435 |             layer->flags = (testRandFract() > rareRatio) ? 0 | 
 | 436 |                 : vectorOr(vectorRandSelect(vecLayerFlags, | 
 | 437 |                            testRandMod(vecLayerFlags.size() + 1))); | 
 | 438 |             layer->transform = (noTransform || testRandFract() > rareRatio) ? 0 | 
 | 439 |                 : vectorOr(vectorRandSelect(vecTransformFlags, | 
 | 440 |                            testRandMod(vecTransformFlags.size() + 1))); | 
 | 441 |             layer->sourceCrop.left = testRandMod(gBuf->getWidth()); | 
 | 442 |             layer->sourceCrop.top = testRandMod(gBuf->getHeight()); | 
 | 443 |             layer->sourceCrop.right = layer->sourceCrop.left | 
 | 444 |                 + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1; | 
 | 445 |             layer->sourceCrop.bottom = layer->sourceCrop.top | 
 | 446 |                 + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1; | 
 | 447 |             layer->displayFrame.left = testRandMod(width); | 
 | 448 |             layer->displayFrame.top = testRandMod(height); | 
 | 449 |             layer->displayFrame.right = layer->displayFrame.left | 
 | 450 |                 + testRandMod(width - layer->displayFrame.left) + 1; | 
 | 451 |             layer->displayFrame.bottom = layer->displayFrame.top | 
 | 452 |                 + testRandMod(height - layer->displayFrame.top) + 1; | 
 | 453 |  | 
 | 454 |             // Increase the frequency that a scale factor of 1.0 from | 
 | 455 |             // the sourceCrop to displayFrame occurs.  This is the | 
 | 456 |             // most common scale factor used by applications and would | 
 | 457 |             // be rarely produced by this stress test without this | 
 | 458 |             // logic. | 
 | 459 |             if (testRandFract() <= freqRatio) { | 
 | 460 |                 // Only change to scale factor to 1.0 if both the | 
 | 461 |                 // width and height will fit. | 
 | 462 |                 int sourceWidth = layer->sourceCrop.right | 
 | 463 |                                   - layer->sourceCrop.left; | 
 | 464 |                 int sourceHeight = layer->sourceCrop.bottom | 
 | 465 |                                    - layer->sourceCrop.top; | 
 | 466 |                 if (((layer->displayFrame.left + sourceWidth) <= width) | 
 | 467 |                     && ((layer->displayFrame.top + sourceHeight) <= height)) { | 
 | 468 |                     layer->displayFrame.right = layer->displayFrame.left | 
 | 469 |                                                 + sourceWidth; | 
 | 470 |                     layer->displayFrame.bottom = layer->displayFrame.top | 
 | 471 |                                                  + sourceHeight; | 
 | 472 |                 } | 
 | 473 |             } | 
 | 474 |  | 
 | 475 |             layer->visibleRegionScreen.numRects = 1; | 
 | 476 |             layer->visibleRegionScreen.rects = &layer->displayFrame; | 
 | 477 |         } | 
 | 478 |  | 
 | 479 |         // Perform prepare operation | 
 | 480 |         if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); } | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 481 |         hwcDevice->prepare(hwcDevice, 1, &list); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 482 |         if (verbose) { | 
 | 483 |             testPrintI("Post Prepare:"); | 
 | 484 |             hwcTestDisplayListPrepareModifiable(list); | 
 | 485 |         } | 
 | 486 |  | 
 | 487 |         // Turn off the geometry changed flag | 
 | 488 |         list->flags &= ~HWC_GEOMETRY_CHANGED; | 
 | 489 |  | 
 | 490 |         // Perform the set operation(s) | 
 | 491 |         if (verbose) {testPrintI("Set:"); } | 
 | 492 |         for (unsigned int n1 = 0; n1 < numSet; n1++) { | 
 | 493 |             if (verbose) { hwcTestDisplayListHandles(list); } | 
| Jesse Hall | b685c54 | 2012-07-31 14:32:56 -0700 | [diff] [blame] | 494 |             list->dpy = dpy; | 
 | 495 |             list->sur = surface; | 
 | 496 |             hwcDevice->set(hwcDevice, 1, &list); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 497 |  | 
 | 498 |             // Prandomly select a new set of handles | 
 | 499 |             for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) { | 
 | 500 |                 unsigned int idx = testRandMod(selectedFrames[n1].size()); | 
 | 501 |                 sp<GraphicBuffer> gBuf = selectedFrames[n1][idx]; | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 502 |                 hwc_layer_1_t *layer = &list->hwLayers[n1]; | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 503 |                 layer->handle = (native_handle_t *) gBuf->handle; | 
 | 504 |             } | 
 | 505 |  | 
 | 506 |             testDelay(perSetDelay); | 
 | 507 |         } | 
 | 508 |  | 
 | 509 |         hwcTestFreeLayerList(list); | 
 | 510 |         testPrintI("==== Completed pass: %u", pass); | 
 | 511 |     } | 
 | 512 |  | 
 | 513 |     testDelay(endDelay); | 
 | 514 |  | 
 | 515 |     // Start framework | 
 | 516 |     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK); | 
 | 517 |     if (rv >= (signed) sizeof(cmd) - 1) { | 
 | 518 |         testPrintE("Command too long for: %s", CMD_START_FRAMEWORK); | 
 | 519 |         exit(21); | 
 | 520 |     } | 
 | 521 |     testExecCmd(cmd); | 
 | 522 |  | 
 | 523 |     testPrintI("Successfully completed %u passes", pass - startPass); | 
 | 524 |  | 
 | 525 |     return 0; | 
 | 526 | } | 
 | 527 |  | 
 | 528 | void init(void) | 
 | 529 | { | 
 | 530 |     srand48(0); // Defensively set pseudo random number generator. | 
 | 531 |                 // Should not need to set this, because a stress test | 
 | 532 |                 // sets the seed on each pass.  Defensively set it here | 
 | 533 |                 // so that future code that uses pseudo random numbers | 
 | 534 |                 // before the first pass will be deterministic. | 
 | 535 |  | 
 | 536 |     hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height); | 
 | 537 |  | 
 | 538 |     hwcTestOpenHwc(&hwcDevice); | 
 | 539 | } | 
 | 540 |  | 
 | 541 | /* | 
 | 542 |  * Initialize Frames | 
 | 543 |  * | 
 | 544 |  * Creates an array of graphic buffers, within the global variable | 
 | 545 |  * named frames.  The graphic buffers are contained within a vector of | 
 | 546 |  * vectors.  All the graphic buffers in a particular row are of the same | 
 | 547 |  * format and dimension.  Each graphic buffer is uniformly filled with a | 
 | 548 |  * prandomly selected color.  It is likely that each buffer, even | 
 | 549 |  * in the same row, will be filled with a unique color. | 
 | 550 |  */ | 
 | 551 | void initFrames(unsigned int seed) | 
 | 552 | { | 
 | 553 |     int rv; | 
 | 554 |     const size_t maxRows = 5; | 
 | 555 |     const size_t minCols = 2;  // Need at least double buffering | 
 | 556 |     const size_t maxCols = 4;  // One more than triple buffering | 
 | 557 |  | 
 | 558 |     if (verbose) { testPrintI("initFrames seed: %u", seed); } | 
 | 559 |     srand48(seed); | 
 | 560 |     size_t rows = testRandMod(maxRows) + 1; | 
 | 561 |  | 
 | 562 |     frames.clear(); | 
 | 563 |     frames.resize(rows); | 
 | 564 |  | 
 | 565 |     for (unsigned int row = 0; row < rows; row++) { | 
 | 566 |         // All frames within a row have to have the same format and | 
 | 567 |         // dimensions.  Width and height need to be >= 1. | 
 | 568 |         unsigned int formatIdx = testRandMod(NUMA(hwcTestGraphicFormat)); | 
 | 569 |         const struct hwcTestGraphicFormat *formatPtr | 
 | 570 |             = &hwcTestGraphicFormat[formatIdx]; | 
 | 571 |         int format = formatPtr->format; | 
 | 572 |  | 
 | 573 |         // Pick width and height, which must be >= 1 and the size | 
 | 574 |         // mod the wMod/hMod value must be equal to 0. | 
 | 575 |         size_t w = (width * maxSizeRatio) * testRandFract(); | 
 | 576 |         size_t h = (height * maxSizeRatio) * testRandFract(); | 
| Mark Salyzyn | e933c03 | 2014-03-04 09:11:04 -0800 | [diff] [blame] | 577 |         w = max(size_t(1u), w); | 
 | 578 |         h = max(size_t(1u), h); | 
| Louis Huemiller | 734d8d8 | 2011-01-05 18:53:47 -0800 | [diff] [blame] | 579 |         if ((w % formatPtr->wMod) != 0) { | 
 | 580 |             w += formatPtr->wMod - (w % formatPtr->wMod); | 
 | 581 |         } | 
 | 582 |         if ((h % formatPtr->hMod) != 0) { | 
 | 583 |             h += formatPtr->hMod - (h % formatPtr->hMod); | 
 | 584 |         } | 
 | 585 |         if (verbose) { | 
 | 586 |             testPrintI("  frame %u width: %u height: %u format: %u %s", | 
 | 587 |                        row, w, h, format, hwcTestGraphicFormat2str(format)); | 
 | 588 |         } | 
 | 589 |  | 
 | 590 |         size_t cols = testRandMod((maxCols + 1) - minCols) + minCols; | 
 | 591 |         frames[row].resize(cols); | 
 | 592 |         for (unsigned int col = 0; col < cols; col++) { | 
 | 593 |             ColorFract color(testRandFract(), testRandFract(), testRandFract()); | 
 | 594 |             float alpha = testRandFract(); | 
 | 595 |  | 
 | 596 |             frames[row][col] = new GraphicBuffer(w, h, format, texUsage); | 
 | 597 |             if ((rv = frames[row][col]->initCheck()) != NO_ERROR) { | 
 | 598 |                 testPrintE("GraphicBuffer initCheck failed, rv: %i", rv); | 
 | 599 |                 testPrintE("  frame %u width: %u height: %u format: %u %s", | 
 | 600 |                            row, w, h, format, hwcTestGraphicFormat2str(format)); | 
 | 601 |                 exit(80); | 
 | 602 |             } | 
 | 603 |  | 
 | 604 |             hwcTestFillColor(frames[row][col].get(), color, alpha); | 
 | 605 |             if (verbose) { | 
 | 606 |                 testPrintI("    buf: %p handle: %p color: %s alpha: %f", | 
 | 607 |                            frames[row][col].get(), frames[row][col]->handle, | 
 | 608 |                            string(color).c_str(), alpha); | 
 | 609 |             } | 
 | 610 |         } | 
 | 611 |     } | 
 | 612 | } | 
 | 613 |  | 
 | 614 | /* | 
 | 615 |  * Vector Random Select | 
 | 616 |  * | 
 | 617 |  * Prandomly selects and returns num elements from vec. | 
 | 618 |  */ | 
 | 619 | template <class T> | 
 | 620 | vector<T> vectorRandSelect(const vector<T>& vec, size_t num) | 
 | 621 | { | 
 | 622 |     vector<T> rv = vec; | 
 | 623 |  | 
 | 624 |     while (rv.size() > num) { | 
 | 625 |         rv.erase(rv.begin() + testRandMod(rv.size())); | 
 | 626 |     } | 
 | 627 |  | 
 | 628 |     return rv; | 
 | 629 | } | 
 | 630 |  | 
 | 631 | /* | 
 | 632 |  * Vector Or | 
 | 633 |  * | 
 | 634 |  * Or's togethen the values of each element of vec and returns the result. | 
 | 635 |  */ | 
 | 636 | template <class T> | 
 | 637 | T vectorOr(const vector<T>& vec) | 
 | 638 | { | 
 | 639 |     T rv = 0; | 
 | 640 |  | 
 | 641 |     for (size_t n1 = 0; n1 < vec.size(); n1++) { | 
 | 642 |         rv |= vec[n1]; | 
 | 643 |     } | 
 | 644 |  | 
 | 645 |     return rv; | 
 | 646 | } |