diff options
Diffstat (limited to 'opengl/tests/hwc/hwcStress.cpp')
-rw-r--r-- | opengl/tests/hwc/hwcStress.cpp | 644 |
1 files changed, 0 insertions, 644 deletions
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp deleted file mode 100644 index b02a424..0000000 --- a/opengl/tests/hwc/hwcStress.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * Hardware Composer stress test - * - * Performs a pseudo-random (prandom) sequence of operations to the - * Hardware Composer (HWC), for a specified number of passes or for - * a specified period of time. By default the period of time is FLT_MAX, - * so that the number of passes will take precedence. - * - * The passes are grouped together, where (pass / passesPerGroup) specifies - * which group a particular pass is in. This causes every passesPerGroup - * worth of sequential passes to be within the same group. Computationally - * intensive operations are performed just once at the beginning of a group - * of passes and then used by all the passes in that group. This is done - * so as to increase both the average and peak rate of graphic operations, - * by moving computationally intensive operations to the beginning of a group. - * In particular, at the start of each group of passes a set of - * graphic buffers are created, then used by the first and remaining - * passes of that group of passes. - * - * The per-group initialization of the graphic buffers is performed - * by a function called initFrames. This function creates an array - * of smart pointers to the graphic buffers, in the form of a vector - * of vectors. The array is accessed in row major order, so each - * row is a vector of smart pointers. All the pointers of a single - * row point to graphic buffers which use the same pixel format and - * have the same dimension, although it is likely that each one is - * filled with a different color. This is done so that after doing - * the first HWC prepare then set call, subsequent set calls can - * be made with each of the layer handles changed to a different - * graphic buffer within the same row. Since the graphic buffers - * in a particular row have the same pixel format and dimension, - * additional HWC set calls can be made, without having to perform - * an HWC prepare call. - * - * This test supports the following command-line options: - * - * -v Verbose - * -s num Starting pass - * -e num Ending pass - * -p num Execute the single pass specified by num - * -n num Number of set operations to perform after each prepare operation - * -t float Maximum time in seconds to execute the test - * -d float Delay in seconds performed after each set operation - * -D float Delay in seconds performed after the last pass is executed - * - * Typically the test is executed for a large range of passes. By default - * passes 0 through 99999 (100,000 passes) are executed. Although this test - * does not validate the generated image, at times it is useful to reexecute - * a particular pass and leave the displayed image on the screen for an - * extended period of time. This can be done either by setting the -s - * and -e options to the desired pass, along with a large value for -D. - * This can also be done via the -p option, again with a large value for - * the -D options. - * - * So far this test only contains code to create graphic buffers with - * a continuous solid color. Although this test is unable to validate the - * image produced, any image that contains other than rectangles of a solid - * color are incorrect. Note that the rectangles may use a transparent - * color and have a blending operation that causes the color in overlapping - * rectangles to be mixed. In such cases the overlapping portions may have - * a different color from the rest of the rectangle. - */ - -#include <algorithm> -#include <assert.h> -#include <cerrno> -#include <cmath> -#include <cstdlib> -#include <ctime> -#include <libgen.h> -#include <sched.h> -#include <sstream> -#include <stdint.h> -#include <string.h> -#include <unistd.h> -#include <vector> - -#include <sys/syscall.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#include <ui/FramebufferNativeWindow.h> -#include <ui/GraphicBuffer.h> - -#define LOG_TAG "hwcStressTest" -#include <utils/Log.h> -#include <testUtil.h> - -#include <hardware/hwcomposer.h> - -#include <glTestLib.h> -#include "hwcTestLib.h" - -using namespace std; -using namespace android; - -const float maxSizeRatio = 1.3; // Graphic buffers can be upto this munch - // larger than the default screen size -const unsigned int passesPerGroup = 10; // A group of passes all use the same - // graphic buffers - -// Ratios at which rare and frequent conditions should be produced -const float rareRatio = 0.1; -const float freqRatio = 0.9; - -// Defaults for command-line options -const bool defaultVerbose = false; -const unsigned int defaultStartPass = 0; -const unsigned int defaultEndPass = 99999; -const unsigned int defaultPerPassNumSet = 10; -const float defaultPerSetDelay = 0.0; // Default delay after each set - // operation. Default delay of - // zero used so as to perform the - // the set operations as quickly - // as possible. -const float defaultEndDelay = 2.0; // Default delay between completion of - // final pass and restart of framework -const float defaultDuration = FLT_MAX; // A fairly long time, so that - // range of passes will have - // precedence - -// Command-line option settings -static bool verbose = defaultVerbose; -static unsigned int startPass = defaultStartPass; -static unsigned int endPass = defaultEndPass; -static unsigned int numSet = defaultPerPassNumSet; -static float perSetDelay = defaultPerSetDelay; -static float endDelay = defaultEndDelay; -static float duration = defaultDuration; - -// Command-line mutual exclusion detection flags. -// Corresponding flag set true once an option is used. -bool eFlag, sFlag, pFlag; - -#define MAXSTR 100 -#define MAXCMD 200 -#define BITSPERBYTE 8 // TODO: Obtain from <values.h>, once - // it has been added - -#define CMD_STOP_FRAMEWORK "stop 2>&1" -#define CMD_START_FRAMEWORK "start 2>&1" - -#define NUMA(a) (sizeof(a) / sizeof(a [0])) -#define MEMCLR(addr, size) do { \ - memset((addr), 0, (size)); \ - } while (0) - -// File scope constants -const unsigned int blendingOps[] = { - HWC_BLENDING_NONE, - HWC_BLENDING_PREMULT, - HWC_BLENDING_COVERAGE, -}; -const unsigned int layerFlags[] = { - HWC_SKIP_LAYER, -}; -const vector<unsigned int> vecLayerFlags(layerFlags, - layerFlags + NUMA(layerFlags)); - -const unsigned int transformFlags[] = { - HWC_TRANSFORM_FLIP_H, - HWC_TRANSFORM_FLIP_V, - HWC_TRANSFORM_ROT_90, - // ROT_180 & ROT_270 intentionally not listed, because they - // they are formed from combinations of the flags already listed. -}; -const vector<unsigned int> vecTransformFlags(transformFlags, - transformFlags + NUMA(transformFlags)); - -// File scope globals -static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE | - GraphicBuffer::USAGE_SW_WRITE_RARELY; -static hwc_composer_device_t *hwcDevice; -static EGLDisplay dpy; -static EGLSurface surface; -static EGLint width, height; -static vector <vector <sp<GraphicBuffer> > > frames; - -// File scope prototypes -void init(void); -void initFrames(unsigned int seed); -template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num); -template <class T> T vectorOr(const vector<T>& vec); - -/* - * Main - * - * Performs the following high-level sequence of operations: - * - * 1. Command-line parsing - * - * 2. Initialization - * - * 3. For each pass: - * - * a. If pass is first pass or in a different group from the - * previous pass, initialize the array of graphic buffers. - * - * b. Create a HWC list with room to specify a prandomly - * selected number of layers. - * - * c. Select a subset of the rows from the graphic buffer array, - * such that there is a unique row to be used for each - * of the layers in the HWC list. - * - * d. Prandomly fill in the HWC list with handles - * selected from any of the columns of the selected row. - * - * e. Pass the populated list to the HWC prepare call. - * - * f. Pass the populated list to the HWC set call. - * - * g. If additional set calls are to be made, then for each - * additional set call, select a new set of handles and - * perform the set call. - */ -int -main(int argc, char *argv[]) -{ - int rv, opt; - char *chptr; - unsigned int pass; - char cmd[MAXCMD]; - struct timeval startTime, currentTime, delta; - - testSetLogCatTag(LOG_TAG); - - // Parse command line arguments - while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) { - switch (opt) { - case 'd': // Delay after each set operation - perSetDelay = strtod(optarg, &chptr); - if ((*chptr != '\0') || (perSetDelay < 0.0)) { - testPrintE("Invalid command-line specified per pass delay of: " - "%s", optarg); - exit(1); - } - break; - - case 'D': // End of test delay - // Delay between completion of final pass and restart - // of framework - endDelay = strtod(optarg, &chptr); - if ((*chptr != '\0') || (endDelay < 0.0)) { - testPrintE("Invalid command-line specified end of test delay " - "of: %s", optarg); - exit(2); - } - break; - - case 't': // Duration - duration = strtod(optarg, &chptr); - if ((*chptr != '\0') || (duration < 0.0)) { - testPrintE("Invalid command-line specified duration of: %s", - optarg); - exit(3); - } - break; - - case 'n': // Num set operations per pass - numSet = strtoul(optarg, &chptr, 10); - if (*chptr != '\0') { - testPrintE("Invalid command-line specified num set per pass " - "of: %s", optarg); - exit(4); - } - break; - - case 's': // Starting Pass - sFlag = true; - if (pFlag) { - testPrintE("Invalid combination of command-line options."); - testPrintE(" The -p option is mutually exclusive from the"); - testPrintE(" -s and -e options."); - exit(5); - } - startPass = strtoul(optarg, &chptr, 10); - if (*chptr != '\0') { - testPrintE("Invalid command-line specified starting pass " - "of: %s", optarg); - exit(6); - } - break; - - case 'e': // Ending Pass - eFlag = true; - if (pFlag) { - testPrintE("Invalid combination of command-line options."); - testPrintE(" The -p option is mutually exclusive from the"); - testPrintE(" -s and -e options."); - exit(7); - } - endPass = strtoul(optarg, &chptr, 10); - if (*chptr != '\0') { - testPrintE("Invalid command-line specified ending pass " - "of: %s", optarg); - exit(8); - } - break; - - case 'p': // Run a single specified pass - pFlag = true; - if (sFlag || eFlag) { - testPrintE("Invalid combination of command-line options."); - testPrintE(" The -p option is mutually exclusive from the"); - testPrintE(" -s and -e options."); - exit(9); - } - startPass = endPass = strtoul(optarg, &chptr, 10); - if (*chptr != '\0') { - testPrintE("Invalid command-line specified pass of: %s", - optarg); - exit(10); - } - break; - - case 'v': // Verbose - verbose = true; - break; - - case 'h': // Help - case '?': - default: - testPrintE(" %s [options]", basename(argv[0])); - testPrintE(" options:"); - testPrintE(" -p Execute specified pass"); - testPrintE(" -s Starting pass"); - testPrintE(" -e Ending pass"); - testPrintE(" -t Duration"); - testPrintE(" -d Delay after each set operation"); - testPrintE(" -D End of test delay"); - testPrintE(" -n Num set operations per pass"); - testPrintE(" -v Verbose"); - exit(((optopt == 0) || (optopt == '?')) ? 0 : 11); - } - } - if (endPass < startPass) { - testPrintE("Unexpected ending pass before starting pass"); - testPrintE(" startPass: %u endPass: %u", startPass, endPass); - exit(12); - } - if (argc != optind) { - testPrintE("Unexpected command-line postional argument"); - testPrintE(" %s [-s start_pass] [-e end_pass] [-t duration]", - basename(argv[0])); - exit(13); - } - testPrintI("duration: %g", duration); - testPrintI("startPass: %u", startPass); - testPrintI("endPass: %u", endPass); - testPrintI("numSet: %u", numSet); - - // Stop framework - rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK); - if (rv >= (signed) sizeof(cmd) - 1) { - testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK); - exit(14); - } - testExecCmd(cmd); - testDelay(1.0); // TODO - need means to query whether asyncronous stop - // framework operation has completed. For now, just wait - // a long time. - - init(); - - // For each pass - gettimeofday(&startTime, NULL); - for (pass = startPass; pass <= endPass; pass++) { - // Stop if duration of work has already been performed - gettimeofday(¤tTime, NULL); - delta = tvDelta(&startTime, ¤tTime); - if (tv2double(&delta) > duration) { break; } - - // Regenerate a new set of test frames when this pass is - // either the first pass or is in a different group then - // the previous pass. A group of passes are passes that - // all have the same quotient when their pass number is - // divided by passesPerGroup. - if ((pass == startPass) - || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) { - initFrames(pass / passesPerGroup); - } - - testPrintI("==== Starting pass: %u", pass); - - // Cause deterministic sequence of prandom numbers to be - // generated for this pass. - srand48(pass); - - hwc_layer_list_t *list; - list = hwcTestCreateLayerList(testRandMod(frames.size()) + 1); - if (list == NULL) { - testPrintE("hwcTestCreateLayerList failed"); - exit(20); - } - - // Prandomly select a subset of frames to be used by this pass. - vector <vector <sp<GraphicBuffer> > > selectedFrames; - selectedFrames = vectorRandSelect(frames, list->numHwLayers); - - // Any transform tends to create a layer that the hardware - // composer is unable to support and thus has to leave for - // SurfaceFlinger. Place heavy bias on specifying no transforms. - bool noTransform = testRandFract() > rareRatio; - - for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) { - unsigned int idx = testRandMod(selectedFrames[n1].size()); - sp<GraphicBuffer> gBuf = selectedFrames[n1][idx]; - hwc_layer_t *layer = &list->hwLayers[n1]; - layer->handle = gBuf->handle; - - layer->blending = blendingOps[testRandMod(NUMA(blendingOps))]; - layer->flags = (testRandFract() > rareRatio) ? 0 - : vectorOr(vectorRandSelect(vecLayerFlags, - testRandMod(vecLayerFlags.size() + 1))); - layer->transform = (noTransform || testRandFract() > rareRatio) ? 0 - : vectorOr(vectorRandSelect(vecTransformFlags, - testRandMod(vecTransformFlags.size() + 1))); - layer->sourceCrop.left = testRandMod(gBuf->getWidth()); - layer->sourceCrop.top = testRandMod(gBuf->getHeight()); - layer->sourceCrop.right = layer->sourceCrop.left - + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1; - layer->sourceCrop.bottom = layer->sourceCrop.top - + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1; - layer->displayFrame.left = testRandMod(width); - layer->displayFrame.top = testRandMod(height); - layer->displayFrame.right = layer->displayFrame.left - + testRandMod(width - layer->displayFrame.left) + 1; - layer->displayFrame.bottom = layer->displayFrame.top - + testRandMod(height - layer->displayFrame.top) + 1; - - // Increase the frequency that a scale factor of 1.0 from - // the sourceCrop to displayFrame occurs. This is the - // most common scale factor used by applications and would - // be rarely produced by this stress test without this - // logic. - if (testRandFract() <= freqRatio) { - // Only change to scale factor to 1.0 if both the - // width and height will fit. - int sourceWidth = layer->sourceCrop.right - - layer->sourceCrop.left; - int sourceHeight = layer->sourceCrop.bottom - - layer->sourceCrop.top; - if (((layer->displayFrame.left + sourceWidth) <= width) - && ((layer->displayFrame.top + sourceHeight) <= height)) { - layer->displayFrame.right = layer->displayFrame.left - + sourceWidth; - layer->displayFrame.bottom = layer->displayFrame.top - + sourceHeight; - } - } - - layer->visibleRegionScreen.numRects = 1; - layer->visibleRegionScreen.rects = &layer->displayFrame; - } - - // Perform prepare operation - if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); } - hwcDevice->prepare(hwcDevice, list); - if (verbose) { - testPrintI("Post Prepare:"); - hwcTestDisplayListPrepareModifiable(list); - } - - // Turn off the geometry changed flag - list->flags &= ~HWC_GEOMETRY_CHANGED; - - // Perform the set operation(s) - if (verbose) {testPrintI("Set:"); } - for (unsigned int n1 = 0; n1 < numSet; n1++) { - if (verbose) { hwcTestDisplayListHandles(list); } - hwcDevice->set(hwcDevice, dpy, surface, list); - - // Prandomly select a new set of handles - for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) { - unsigned int idx = testRandMod(selectedFrames[n1].size()); - sp<GraphicBuffer> gBuf = selectedFrames[n1][idx]; - hwc_layer_t *layer = &list->hwLayers[n1]; - layer->handle = (native_handle_t *) gBuf->handle; - } - - testDelay(perSetDelay); - } - - hwcTestFreeLayerList(list); - testPrintI("==== Completed pass: %u", pass); - } - - testDelay(endDelay); - - // Start framework - rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK); - if (rv >= (signed) sizeof(cmd) - 1) { - testPrintE("Command too long for: %s", CMD_START_FRAMEWORK); - exit(21); - } - testExecCmd(cmd); - - testPrintI("Successfully completed %u passes", pass - startPass); - - return 0; -} - -void init(void) -{ - srand48(0); // Defensively set pseudo random number generator. - // Should not need to set this, because a stress test - // sets the seed on each pass. Defensively set it here - // so that future code that uses pseudo random numbers - // before the first pass will be deterministic. - - hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height); - - hwcTestOpenHwc(&hwcDevice); -} - -/* - * Initialize Frames - * - * Creates an array of graphic buffers, within the global variable - * named frames. The graphic buffers are contained within a vector of - * vectors. All the graphic buffers in a particular row are of the same - * format and dimension. Each graphic buffer is uniformly filled with a - * prandomly selected color. It is likely that each buffer, even - * in the same row, will be filled with a unique color. - */ -void initFrames(unsigned int seed) -{ - int rv; - const size_t maxRows = 5; - const size_t minCols = 2; // Need at least double buffering - const size_t maxCols = 4; // One more than triple buffering - - if (verbose) { testPrintI("initFrames seed: %u", seed); } - srand48(seed); - size_t rows = testRandMod(maxRows) + 1; - - frames.clear(); - frames.resize(rows); - - for (unsigned int row = 0; row < rows; row++) { - // All frames within a row have to have the same format and - // dimensions. Width and height need to be >= 1. - unsigned int formatIdx = testRandMod(NUMA(hwcTestGraphicFormat)); - const struct hwcTestGraphicFormat *formatPtr - = &hwcTestGraphicFormat[formatIdx]; - int format = formatPtr->format; - - // Pick width and height, which must be >= 1 and the size - // mod the wMod/hMod value must be equal to 0. - size_t w = (width * maxSizeRatio) * testRandFract(); - size_t h = (height * maxSizeRatio) * testRandFract(); - w = max(1u, w); - h = max(1u, h); - if ((w % formatPtr->wMod) != 0) { - w += formatPtr->wMod - (w % formatPtr->wMod); - } - if ((h % formatPtr->hMod) != 0) { - h += formatPtr->hMod - (h % formatPtr->hMod); - } - if (verbose) { - testPrintI(" frame %u width: %u height: %u format: %u %s", - row, w, h, format, hwcTestGraphicFormat2str(format)); - } - - size_t cols = testRandMod((maxCols + 1) - minCols) + minCols; - frames[row].resize(cols); - for (unsigned int col = 0; col < cols; col++) { - ColorFract color(testRandFract(), testRandFract(), testRandFract()); - float alpha = testRandFract(); - - frames[row][col] = new GraphicBuffer(w, h, format, texUsage); - if ((rv = frames[row][col]->initCheck()) != NO_ERROR) { - testPrintE("GraphicBuffer initCheck failed, rv: %i", rv); - testPrintE(" frame %u width: %u height: %u format: %u %s", - row, w, h, format, hwcTestGraphicFormat2str(format)); - exit(80); - } - - hwcTestFillColor(frames[row][col].get(), color, alpha); - if (verbose) { - testPrintI(" buf: %p handle: %p color: %s alpha: %f", - frames[row][col].get(), frames[row][col]->handle, - string(color).c_str(), alpha); - } - } - } -} - -/* - * Vector Random Select - * - * Prandomly selects and returns num elements from vec. - */ -template <class T> -vector<T> vectorRandSelect(const vector<T>& vec, size_t num) -{ - vector<T> rv = vec; - - while (rv.size() > num) { - rv.erase(rv.begin() + testRandMod(rv.size())); - } - - return rv; -} - -/* - * Vector Or - * - * Or's togethen the values of each element of vec and returns the result. - */ -template <class T> -T vectorOr(const vector<T>& vec) -{ - T rv = 0; - - for (size_t n1 = 0; n1 < vec.size(); n1++) { - rv |= vec[n1]; - } - - return rv; -} |