diff options
Diffstat (limited to 'opengl/tests/hwc/hwcCommit.cpp')
| -rw-r--r-- | opengl/tests/hwc/hwcCommit.cpp | 1561 |
1 files changed, 0 insertions, 1561 deletions
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp deleted file mode 100644 index efa646c..0000000 --- a/opengl/tests/hwc/hwcCommit.cpp +++ /dev/null @@ -1,1561 +0,0 @@ -/* - * Copyright (C) 2011 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 Commit Points - * - * Synopsis - * hwcCommit [options] graphicFormat ... - * options: - * -s [width, height] - Starting dimension - * -v - Verbose - * - * graphic formats: - * RGBA8888 (reference frame default) - * RGBX8888 - * RGB888 - * RGB565 - * BGRA8888 - * RGBA5551 - * RGBA4444 - * YV12 - * - * Description - * The Hardware Composer (HWC) Commit test is a benchmark that - * discovers the points at which the HWC will commit to rendering an - * overlay(s). Before rendering a set of overlays, the HWC is shown - * the list through a prepare call. During the prepare call the HWC - * is able to examine the list and specify which overlays it is able - * to handle. The overlays that it can't handle are typically composited - * by a higher level (e.g. Surface Flinger) and then the original list - * plus a composit of what HWC passed on are provided back to the HWC - * for rendering. - * - * Once an implementation of the HWC has been shipped, a regression would - * likely occur if a latter implementation started passing on conditions - * that it used to commit to. The primary purpose of this benchmark - * is the automated discovery of the commit points, where an implementation - * is on the edge between committing and not committing. These are commonly - * referred to as commit points. Between implementations changes to the - * commit points are allowed, as long as they improve what the HWC commits - * to. Once an implementation of the HWC is shipped, the commit points are - * not allowed to regress in future implementations. - * - * This benchmark takes a sampling and then adjusts until it finds a - * commit point. It doesn't exhaustively check all possible conditions, - * which do to the number of combinations would be impossible. Instead - * it starts its search from a starting dimension, that can be changed - * via the -s option. The search is also bounded by a set of search - * limits, that are hard-coded into a structure of constants named - * searchLimits. Results that happen to reach a searchLimit are prefixed - * with >=, so that it is known that the value could possibly be larger. - * - * Measurements are made for each of the graphic formats specified as - * positional parameters on the command-line. If no graphic formats - * are specified on the command line, then by default measurements are - * made and reported for each of the known graphic format. - */ - -#include <algorithm> -#include <assert.h> -#include <cerrno> -#include <cmath> -#include <cstdlib> -#include <ctime> -#include <iomanip> -#include <istream> -#include <libgen.h> -#include <list> -#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 "hwcCommitTest" -#include <utils/Log.h> -#include <testUtil.h> - -#include <hardware/hwcomposer.h> - -#include <glTestLib.h> -#include "hwcTestLib.h" - -using namespace std; -using namespace android; - -// Defaults -const HwcTestDim defaultStartDim = HwcTestDim(100, 100); -const bool defaultVerbose = false; - -const uint32_t defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888; -const int32_t defaultTransform = 0; -const uint32_t defaultBlend = HWC_BLENDING_NONE; -const ColorFract defaultColor(0.5, 0.5, 0.5); -const float defaultAlpha = 1.0; // Opaque -const HwcTestDim defaultSourceDim(1, 1); -const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1}; -const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100}; - -// Global Constants -const uint32_t printFieldWidth = 2; -const struct searchLimits { - uint32_t numOverlays; - HwcTestDim sourceCrop; -} searchLimits = { - 10, - HwcTestDim(3000, 2000), -}; -const struct transformType { - const char *desc; - uint32_t id; -} transformType[] = { - {"fliph", HWC_TRANSFORM_FLIP_H}, - {"flipv", HWC_TRANSFORM_FLIP_V}, - {"rot90", HWC_TRANSFORM_ROT_90}, - {"rot180", HWC_TRANSFORM_ROT_180}, - {"rot270", HWC_TRANSFORM_ROT_270}, -}; -const struct blendType { - const char *desc; - uint32_t id; -} blendType[] = { - {"none", HWC_BLENDING_NONE}, - {"premult", HWC_BLENDING_PREMULT}, - {"coverage", HWC_BLENDING_COVERAGE}, -}; - -// Defines -#define MAXCMD 200 -#define CMD_STOP_FRAMEWORK "stop 2>&1" -#define CMD_START_FRAMEWORK "start 2>&1" - -// Macros -#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array - -// Local types -class Rectangle { -public: - Rectangle(uint32_t graphicFormat = defaultFormat, - HwcTestDim dfDim = HwcTestDim(1, 1), - HwcTestDim sDim = HwcTestDim(1, 1)); - void setSourceDim(HwcTestDim dim); - - uint32_t format; - uint32_t transform; - int32_t blend; - ColorFract color; - float alpha; - HwcTestDim sourceDim; - struct hwc_rect sourceCrop; - struct hwc_rect displayFrame; -}; - -class Range { -public: - Range(void) : _l(0), _u(0) {} - Range(uint32_t lower, uint32_t upper) : _l(lower), _u(upper) {} - uint32_t lower(void) { return _l; } - uint32_t upper(void) { return _u; } - - operator string(); - -private: - uint32_t _l; // lower - uint32_t _u; // upper -}; - -Range::operator string() -{ - ostringstream out; - - out << '[' << _l << ", " << _u << ']'; - - return out.str(); -} - -class Rational { -public: - Rational(void) : _n(0), _d(1) {} - Rational(uint32_t n, uint32_t d) : _n(n), _d(d) {} - uint32_t numerator(void) { return _n; } - uint32_t denominator(void) { return _d; } - void setNumerator(uint32_t numerator) { _n = numerator; } - - bool operator==(const Rational& other) const; - bool operator!=(const Rational& other) const { return !(*this == other); } - bool operator<(const Rational& other) const; - bool operator>(const Rational& other) const { - return (!(*this == other) && !(*this < other)); - } - static void double2Rational(double f, Range nRange, Range dRange, - Rational& lower, Rational& upper); - - operator string() const; - operator double() const { return (double) _n / (double) _d; } - - -private: - uint32_t _n; - uint32_t _d; -}; - -// 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 size_t maxHeadingLen; -static vector<string> formats; - -// Measurements -struct meas { - uint32_t format; - uint32_t startDimOverlays; - uint32_t maxNonOverlapping; - uint32_t maxOverlapping; - list<uint32_t> transforms; - list<uint32_t> blends; - struct displayFrame { - uint32_t minWidth; - uint32_t minHeight; - HwcTestDim minDim; - uint32_t maxWidth; - uint32_t maxHeight; - HwcTestDim maxDim; - } df; - struct sourceCrop { - uint32_t minWidth; - uint32_t minHeight; - HwcTestDim minDim; - uint32_t maxWidth; - uint32_t maxHeight; - HwcTestDim maxDim; - Rational hScale; - HwcTestDim hScaleBestDf; - HwcTestDim hScaleBestSc; - Rational vScale; - HwcTestDim vScaleBestDf; - HwcTestDim vScaleBestSc; - } sc; - vector<uint32_t> overlapBlendNone; - vector<uint32_t> overlapBlendPremult; - vector<uint32_t> overlapBlendCoverage; -}; -vector<meas> measurements; - -// Function prototypes -uint32_t numOverlays(list<Rectangle>& rectList); -uint32_t maxOverlays(uint32_t format, bool allowOverlap); -list<uint32_t> supportedTransforms(uint32_t format); -list<uint32_t> supportedBlends(uint32_t format); -uint32_t dfMinWidth(uint32_t format); -uint32_t dfMinHeight(uint32_t format); -uint32_t dfMaxWidth(uint32_t format); -uint32_t dfMaxHeight(uint32_t format); -HwcTestDim dfMinDim(uint32_t format); -HwcTestDim dfMaxDim(uint32_t format); -uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim); -uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim); -uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim); -uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim); -HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim); -HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim); -Rational scHScale(uint32_t format, - const HwcTestDim& dfMin, const HwcTestDim& dfMax, - const HwcTestDim& scMin, const HwcTestDim& scMax, - HwcTestDim& outBestDf, HwcTestDim& outBestSc); -Rational scVScale(uint32_t format, - const HwcTestDim& dfMin, const HwcTestDim& dfMax, - const HwcTestDim& scMin, const HwcTestDim& scMax, - HwcTestDim& outBestDf, HwcTestDim& outBestSc); -uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat, - uint32_t backgroundBlend, uint32_t foregroundBlend); -string transformList2str(const list<uint32_t>& transformList); -string blendList2str(const list<uint32_t>& blendList); -void init(void); -void printFormatHeadings(size_t indent); -void printOverlapLine(size_t indent, const string formatStr, - const vector<uint32_t>& results); -void printSyntax(const char *cmd); - -// Command-line option settings -static bool verbose = defaultVerbose; -static HwcTestDim startDim = defaultStartDim; - -/* - * Main - * - * Performs the following high-level sequence of operations: - * - * 1. Command-line parsing - * - * 2. Form a list of command-line specified graphic formats. If - * no formats are specified, then form a list of all known formats. - * - * 3. Stop framework - * Only one user at a time is allowed to use the HWC. Surface - * Flinger uses the HWC and is part of the framework. Need to - * stop the framework so that Surface Flinger will stop using - * the HWC. - * - * 4. Initialization - * - * 5. For each graphic format in the previously formed list perform - * measurements on that format and report the results. - * - * 6. Start framework - */ -int -main(int argc, char *argv[]) -{ - int rv, opt; - char *chptr; - bool error; - string str; - char cmd[MAXCMD]; - list<Rectangle> rectList; - - testSetLogCatTag(LOG_TAG); - - // Parse command line arguments - while ((opt = getopt(argc, argv, "s:v?h")) != -1) { - switch (opt) { - - case 's': // Start Dimension - // Use arguments until next starts with a dash - // or current ends with a > or ] - str = optarg; - while (optind < argc) { - if (*argv[optind] == '-') { break; } - char endChar = (str.length() > 1) ? str[str.length() - 1] : 0; - if ((endChar == '>') || (endChar == ']')) { break; } - str += " " + string(argv[optind++]); - } - { - istringstream in(str); - startDim = hwcTestParseDim(in, error); - // Any parse error or characters not used by parser - if (error - || (((unsigned int) in.tellg() != in.str().length()) - && (in.tellg() != (streampos) -1))) { - testPrintE("Invalid command-line specified start " - "dimension of: %s", str.c_str()); - exit(8); - } - } - break; - - case 'v': // Verbose - verbose = true; - break; - - case 'h': // Help - case '?': - default: - printSyntax(basename(argv[0])); - exit(((optopt == 0) || (optopt == '?')) ? 0 : 11); - } - } - - // Positional parameters - // Positional parameters provide the names of graphic formats that - // measurements are to be made on. Measurements are made on all - // known graphic formats when no positional parameters are provided. - if (optind == argc) { - // No command-line specified graphic formats - // Add all graphic formats to the list of formats to be measured - for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) { - formats.push_back(hwcTestGraphicFormat[n1].desc); - } - } else { - // Add names of command-line specified graphic formats to the - // list of formats to be tested - for (; argv[optind] != NULL; optind++) { - formats.push_back(argv[optind]); - } - } - - // Determine length of longest specified graphic format. - // This value is used for output formating - for (vector<string>::iterator it = formats.begin(); - it != formats.end(); ++it) { - maxHeadingLen = max(maxHeadingLen, it->length()); - } - - // 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 - needs means to query whether asynchronous stop - // framework operation has completed. For now, just wait - // a long time. - - testPrintI("startDim: %s", ((string) startDim).c_str()); - - init(); - - // For each of the graphic formats - for (vector<string>::iterator itFormat = formats.begin(); - itFormat != formats.end(); ++itFormat) { - - // Locate hwcTestLib structure that describes this format - const struct hwcTestGraphicFormat *format; - format = hwcTestGraphicFormatLookup((*itFormat).c_str()); - if (format == NULL) { - testPrintE("Unknown graphic format of: %s", (*itFormat).c_str()); - exit(1); - } - - // Display format header - testPrintI("format: %s", format->desc); - - // Create area to hold the measurements - struct meas meas; - struct meas *measPtr; - meas.format = format->format; - measurements.push_back(meas); - measPtr = &measurements[measurements.size() - 1]; - - // Start dimension num overlays - Rectangle rect(format->format, startDim); - rectList.clear(); - rectList.push_back(rect); - measPtr->startDimOverlays = numOverlays(rectList); - testPrintI(" startDimOverlays: %u", measPtr->startDimOverlays); - - // Skip the rest of the measurements, when the start dimension - // doesn't produce an overlay - if (measPtr->startDimOverlays == 0) { continue; } - - // Max Overlays - measPtr->maxNonOverlapping = maxOverlays(format->format, false); - testPrintI(" max nonOverlapping overlays: %s%u", - (measPtr->maxNonOverlapping == searchLimits.numOverlays) - ? ">= " : "", - measPtr->maxNonOverlapping); - measPtr->maxOverlapping = maxOverlays(format->format, true); - testPrintI(" max Overlapping overlays: %s%u", - (measPtr->maxOverlapping == searchLimits.numOverlays) - ? ">= " : "", - measPtr->maxOverlapping); - - // Transforms and blends - measPtr->transforms = supportedTransforms(format->format); - testPrintI(" transforms: %s", - transformList2str(measPtr->transforms).c_str()); - measPtr->blends = supportedBlends(format->format); - testPrintI(" blends: %s", - blendList2str(measPtr->blends).c_str()); - - // Display frame measurements - measPtr->df.minWidth = dfMinWidth(format->format); - testPrintI(" dfMinWidth: %u", measPtr->df.minWidth); - - measPtr->df.minHeight = dfMinHeight(format->format); - testPrintI(" dfMinHeight: %u", measPtr->df.minHeight); - - measPtr->df.maxWidth = dfMaxWidth(format->format); - testPrintI(" dfMaxWidth: %u", measPtr->df.maxWidth); - - measPtr->df.maxHeight = dfMaxHeight(format->format); - testPrintI(" dfMaxHeight: %u", measPtr->df.maxHeight); - - measPtr->df.minDim = dfMinDim(format->format); - testPrintI(" dfMinDim: %s", ((string) measPtr->df.minDim).c_str()); - - measPtr->df.maxDim = dfMaxDim(format->format); - testPrintI(" dfMaxDim: %s", ((string) measPtr->df.maxDim).c_str()); - - // Source crop measurements - measPtr->sc.minWidth = scMinWidth(format->format, measPtr->df.minDim); - testPrintI(" scMinWidth: %u", measPtr->sc.minWidth); - - measPtr->sc.minHeight = scMinHeight(format->format, measPtr->df.minDim); - testPrintI(" scMinHeight: %u", measPtr->sc.minHeight); - - measPtr->sc.maxWidth = scMaxWidth(format->format, measPtr->df.maxDim); - testPrintI(" scMaxWidth: %s%u", (measPtr->sc.maxWidth - == searchLimits.sourceCrop.width()) ? ">= " : "", - measPtr->sc.maxWidth); - - measPtr->sc.maxHeight = scMaxHeight(format->format, measPtr->df.maxDim); - testPrintI(" scMaxHeight: %s%u", (measPtr->sc.maxHeight - == searchLimits.sourceCrop.height()) ? ">= " : "", - measPtr->sc.maxHeight); - - measPtr->sc.minDim = scMinDim(format->format, measPtr->df.minDim); - testPrintI(" scMinDim: %s", ((string) measPtr->sc.minDim).c_str()); - - measPtr->sc.maxDim = scMaxDim(format->format, measPtr->df.maxDim); - testPrintI(" scMaxDim: %s%s", ((measPtr->sc.maxDim.width() - >= searchLimits.sourceCrop.width()) - || (measPtr->sc.maxDim.width() >= - searchLimits.sourceCrop.height())) ? ">= " : "", - ((string) measPtr->sc.maxDim).c_str()); - - measPtr->sc.hScale = scHScale(format->format, - measPtr->df.minDim, measPtr->df.maxDim, - measPtr->sc.minDim, measPtr->sc.maxDim, - measPtr->sc.hScaleBestDf, - measPtr->sc.hScaleBestSc); - testPrintI(" scHScale: %s%f", - (measPtr->sc.hScale - >= Rational(searchLimits.sourceCrop.width(), - measPtr->df.minDim.width())) ? ">= " : "", - (double) measPtr->sc.hScale); - testPrintI(" HScale Best Display Frame: %s", - ((string) measPtr->sc.hScaleBestDf).c_str()); - testPrintI(" HScale Best Source Crop: %s", - ((string) measPtr->sc.hScaleBestSc).c_str()); - - measPtr->sc.vScale = scVScale(format->format, - measPtr->df.minDim, measPtr->df.maxDim, - measPtr->sc.minDim, measPtr->sc.maxDim, - measPtr->sc.vScaleBestDf, - measPtr->sc.vScaleBestSc); - testPrintI(" scVScale: %s%f", - (measPtr->sc.vScale - >= Rational(searchLimits.sourceCrop.height(), - measPtr->df.minDim.height())) ? ">= " : "", - (double) measPtr->sc.vScale); - testPrintI(" VScale Best Display Frame: %s", - ((string) measPtr->sc.vScaleBestDf).c_str()); - testPrintI(" VScale Best Source Crop: %s", - ((string) measPtr->sc.vScaleBestSc).c_str()); - - // Overlap two graphic formats and different blends - // Results displayed after all overlap measurments with - // current format in the foreground - // TODO: make measurments with background blend other than - // none. All of these measurements are done with a - // background blend of HWC_BLENDING_NONE, with the - // blend type of the foregound being varied. - uint32_t foregroundFormat = format->format; - for (vector<string>::iterator it = formats.begin(); - it != formats.end(); ++it) { - uint32_t num; - - const struct hwcTestGraphicFormat *backgroundFormatPtr - = hwcTestGraphicFormatLookup((*it).c_str()); - uint32_t backgroundFormat = backgroundFormatPtr->format; - - num = numOverlapping(backgroundFormat, foregroundFormat, - HWC_BLENDING_NONE, HWC_BLENDING_NONE); - measPtr->overlapBlendNone.push_back(num); - - num = numOverlapping(backgroundFormat, foregroundFormat, - HWC_BLENDING_NONE, HWC_BLENDING_PREMULT); - measPtr->overlapBlendPremult.push_back(num); - - num = numOverlapping(backgroundFormat, foregroundFormat, - HWC_BLENDING_NONE, HWC_BLENDING_COVERAGE); - measPtr->overlapBlendCoverage.push_back(num); - } - - } - - // Display overlap results - size_t indent = 2; - testPrintI("overlapping blend: none"); - printFormatHeadings(indent); - for (vector<string>::iterator it = formats.begin(); - it != formats.end(); ++it) { - printOverlapLine(indent, *it, measurements[it - - formats.begin()].overlapBlendNone); - } - testPrintI(""); - - testPrintI("overlapping blend: premult"); - printFormatHeadings(indent); - for (vector<string>::iterator it = formats.begin(); - it != formats.end(); ++it) { - printOverlapLine(indent, *it, measurements[it - - formats.begin()].overlapBlendPremult); - } - testPrintI(""); - - testPrintI("overlapping blend: coverage"); - printFormatHeadings(indent); - for (vector<string>::iterator it = formats.begin(); - it != formats.end(); ++it) { - printOverlapLine(indent, *it, measurements[it - - formats.begin()].overlapBlendCoverage); - } - testPrintI(""); - - // 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); - - return 0; -} - -// Determine the maximum number of overlays that are all of the same format -// that the HWC will commit to. If allowOverlap is true, then the rectangles -// are laid out on a diagonal starting from the upper left corner. With -// each rectangle adjust one pixel to the right and one pixel down. -// When allowOverlap is false, the rectangles are tiled in column major -// order. Note, column major ordering is used so that the initial rectangles -// are all on different horizontal scan rows. It is common that hardware -// has limits on the number of objects it can handle on any single row. -uint32_t maxOverlays(uint32_t format, bool allowOverlap) -{ - unsigned int max = 0; - - for (unsigned int numRects = 1; numRects <= searchLimits.numOverlays; - numRects++) { - list<Rectangle> rectList; - - for (unsigned int x = 0; - (x + startDim.width()) < (unsigned int) width; - x += (allowOverlap) ? 1 : startDim.width()) { - for (unsigned int y = 0; - (y + startDim.height()) < (unsigned int) height; - y += (allowOverlap) ? 1 : startDim.height()) { - Rectangle rect(format, startDim, startDim); - rect.displayFrame.left = x; - rect.displayFrame.top = y; - rect.displayFrame.right = x + startDim.width(); - rect.displayFrame.bottom = y + startDim.height(); - - rectList.push_back(rect); - - if (rectList.size() >= numRects) { break; } - } - if (rectList.size() >= numRects) { break; } - } - - uint32_t num = numOverlays(rectList); - if (num > max) { max = num; } - } - - return max; -} - -// Measures what transforms (i.e. flip horizontal, rotate 180) are -// supported by the specified format -list<uint32_t> supportedTransforms(uint32_t format) -{ - list<uint32_t> rv; - list<Rectangle> rectList; - Rectangle rect(format, startDim); - - // For each of the transform types - for (unsigned int idx = 0; idx < NUMA(transformType); idx++) { - unsigned int id = transformType[idx].id; - - rect.transform = id; - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - - if (num == 1) { - rv.push_back(id); - } - } - - return rv; -} - -// Determines which types of blends (i.e. none, premult, coverage) are -// supported by the specified format -list<uint32_t> supportedBlends(uint32_t format) -{ - list<uint32_t> rv; - list<Rectangle> rectList; - Rectangle rect(format, startDim); - - // For each of the blend types - for (unsigned int idx = 0; idx < NUMA(blendType); idx++) { - unsigned int id = blendType[idx].id; - - rect.blend = id; - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - - if (num == 1) { - rv.push_back(id); - } - } - - return rv; -} - -// Determines the minimum width of any display frame of the given format -// that the HWC will commit to. -uint32_t dfMinWidth(uint32_t format) -{ - uint32_t w; - list<Rectangle> rectList; - - for (w = 1; w <= startDim.width(); w++) { - HwcTestDim dim(w, startDim.height()); - Rectangle rect(format, dim); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return w; - } - } - if (w > startDim.width()) { - testPrintE("Failed to locate display frame min width"); - exit(33); - } - - return w; -} - -// Display frame minimum height -uint32_t dfMinHeight(uint32_t format) -{ - uint32_t h; - list<Rectangle> rectList; - - for (h = 1; h <= startDim.height(); h++) { - HwcTestDim dim(startDim.width(), h); - Rectangle rect(format, dim); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return h; - } - } - if (h > startDim.height()) { - testPrintE("Failed to locate display frame min height"); - exit(34); - } - - return h; -} - -// Display frame maximum width -uint32_t dfMaxWidth(uint32_t format) -{ - uint32_t w; - list<Rectangle> rectList; - - for (w = width; w >= startDim.width(); w--) { - HwcTestDim dim(w, startDim.height()); - Rectangle rect(format, dim); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return w; - } - } - if (w < startDim.width()) { - testPrintE("Failed to locate display frame max width"); - exit(35); - } - - return w; -} - -// Display frame maximum height -uint32_t dfMaxHeight(uint32_t format) -{ - uint32_t h; - - for (h = height; h >= startDim.height(); h--) { - HwcTestDim dim(startDim.width(), h); - Rectangle rect(format, dim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return h; - } - } - if (h < startDim.height()) { - testPrintE("Failed to locate display frame max height"); - exit(36); - } - - return h; -} - -// Determine the minimum number of pixels that the HWC will ever commit to. -// Note, this might be different that dfMinWidth * dfMinHeight, in that this -// function adjusts both the width and height from the starting dimension. -HwcTestDim dfMinDim(uint32_t format) -{ - uint64_t bestMinPixels = 0; - HwcTestDim bestDim; - bool bestSet = false; // True when value has been assigned to - // bestMinPixels and bestDim - - bool origVerbose = verbose; // Temporarily turn off verbose - verbose = false; - for (uint32_t w = 1; w <= startDim.width(); w++) { - for (uint32_t h = 1; h <= startDim.height(); h++) { - if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) { - break; - } - - HwcTestDim dim(w, h); - Rectangle rect(format, dim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - uint64_t pixels = dim.width() * dim.height(); - if (!bestSet || (pixels < bestMinPixels)) { - bestMinPixels = pixels; - bestDim = dim; - bestSet = true; - } - } - } - } - verbose = origVerbose; - - if (!bestSet) { - testPrintE("Unable to locate display frame min dimension"); - exit(20); - } - - return bestDim; -} - -// Display frame maximum dimension -HwcTestDim dfMaxDim(uint32_t format) -{ - uint64_t bestMaxPixels = 0; - HwcTestDim bestDim; - bool bestSet = false; // True when value has been assigned to - // bestMaxPixels and bestDim; - - // Potentially increase benchmark performance by first checking - // for the common case of supporting a full display frame. - HwcTestDim dim(width, height); - Rectangle rect(format, dim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num == 1) { return dim; } - - // TODO: Use a binary search - bool origVerbose = verbose; // Temporarily turn off verbose - verbose = false; - for (uint32_t w = startDim.width(); w <= (uint32_t) width; w++) { - for (uint32_t h = startDim.height(); h <= (uint32_t) height; h++) { - if (bestSet && ((w * h) <= bestMaxPixels)) { continue; } - - HwcTestDim dim(w, h); - Rectangle rect(format, dim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - uint64_t pixels = dim.width() * dim.height(); - if (!bestSet || (pixels > bestMaxPixels)) { - bestMaxPixels = pixels; - bestDim = dim; - bestSet = true; - } - } - } - } - verbose = origVerbose; - - if (!bestSet) { - testPrintE("Unable to locate display frame max dimension"); - exit(21); - } - - return bestDim; -} - -// Source crop minimum width -uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim) -{ - uint32_t w; - list<Rectangle> rectList; - - // Source crop frame min width - for (w = 1; w <= dfDim.width(); w++) { - Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height())); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return w; - } - } - testPrintE("Failed to locate source crop min width"); - exit(35); -} - -// Source crop minimum height -uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim) -{ - uint32_t h; - list<Rectangle> rectList; - - for (h = 1; h <= dfDim.height(); h++) { - Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h)); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return h; - } - } - testPrintE("Failed to locate source crop min height"); - exit(36); -} - -// Source crop maximum width -uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim) -{ - uint32_t w; - list<Rectangle> rectList; - - for (w = searchLimits.sourceCrop.width(); w >= dfDim.width(); w--) { - Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height())); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return w; - } - } - testPrintE("Failed to locate source crop max width"); - exit(35); -} - -// Source crop maximum height -uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim) -{ - uint32_t h; - list<Rectangle> rectList; - - for (h = searchLimits.sourceCrop.height(); h >= dfDim.height(); h--) { - Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h)); - rectList.clear(); - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - return h; - } - } - testPrintE("Failed to locate source crop max height"); - exit(36); -} - -// Source crop minimum dimension -// Discovers the source crop with the least number of pixels that the -// HWC will commit to. Note, this may be different from scMinWidth -// * scMinHeight, in that this function searches for a combination of -// width and height. While the other routines always keep one of the -// dimensions equal to the corresponding start dimension. -HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim) -{ - uint64_t bestMinPixels = 0; - HwcTestDim bestDim; - bool bestSet = false; // True when value has been assigned to - // bestMinPixels and bestDim - - bool origVerbose = verbose; // Temporarily turn off verbose - verbose = false; - for (uint32_t w = 1; w <= dfDim.width(); w++) { - for (uint32_t h = 1; h <= dfDim.height(); h++) { - if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) { - break; - } - - HwcTestDim dim(w, h); - Rectangle rect(format, dfDim, HwcTestDim(w, h)); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - uint64_t pixels = dim.width() * dim.height(); - if (!bestSet || (pixels < bestMinPixels)) { - bestMinPixels = pixels; - bestDim = dim; - bestSet = true; - } - } - } - } - verbose = origVerbose; - - if (!bestSet) { - testPrintE("Unable to locate source crop min dimension"); - exit(20); - } - - return bestDim; -} - -// Source crop maximum dimension -HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim) -{ - uint64_t bestMaxPixels = 0; - HwcTestDim bestDim; - bool bestSet = false; // True when value has been assigned to - // bestMaxPixels and bestDim; - - // Potentially increase benchmark performance by first checking - // for the common case of supporting the maximum checked source size - HwcTestDim dim = searchLimits.sourceCrop; - Rectangle rect(format, dfDim, searchLimits.sourceCrop); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num == 1) { return dim; } - - // TODO: Use a binary search - bool origVerbose = verbose; // Temporarily turn off verbose - verbose = false; - for (uint32_t w = dfDim.width(); - w <= searchLimits.sourceCrop.width(); w++) { - for (uint32_t h = dfDim.height(); - h <= searchLimits.sourceCrop.height(); h++) { - if (bestSet && ((w * h) <= bestMaxPixels)) { continue; } - - HwcTestDim dim(w, h); - Rectangle rect(format, dfDim, dim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - if (num > 0) { - uint64_t pixels = dim.width() * dim.height(); - if (!bestSet || (pixels > bestMaxPixels)) { - bestMaxPixels = pixels; - bestDim = dim; - bestSet = true; - } - } - } - } - verbose = origVerbose; - - if (!bestSet) { - testPrintE("Unable to locate source crop max dimension"); - exit(21); - } - - return bestDim; -} - -// Source crop horizontal scale -// Determines the maximum factor by which the source crop can be larger -// that the display frame. The commit point is discovered through a -// binary search of rational numbers. The numerator in each of the -// rational numbers contains the dimension for the source crop, while -// the denominator specifies the dimension for the display frame. On -// each pass of the binary search the mid-point between the greatest -// point committed to (best) and the smallest point in which a commit -// has failed is calculated. This mid-point is then passed to a function -// named double2Rational, which determines the closest rational numbers -// just below and above the mid-point. By default the lower rational -// number is used for the scale factor on the next pass of the binary -// search. The upper value is only used when best is already equal -// to the lower value. This only occurs when the lower value has already -// been tried. -Rational scHScale(uint32_t format, - const HwcTestDim& dfMin, const HwcTestDim& dfMax, - const HwcTestDim& scMin, const HwcTestDim& scMax, - HwcTestDim& outBestDf, HwcTestDim& outBestSc) -{ - HwcTestDim scDim, dfDim; // Source crop and display frame dimension - Rational best(0, 1), minBad; // Current bounds for a binary search - // MinGood is set below the lowest - // possible scale. The value of minBad, - // will be set by the first pass - // of the binary search. - - // Perform the passes of the binary search - bool firstPass = true; - do { - // On first pass try the maximum scale within the search limits - if (firstPass) { - // Try the maximum possible scale, within the search limits - scDim = HwcTestDim(searchLimits.sourceCrop.width(), scMin.height()); - dfDim = dfMin; - } else { - // Subsequent pass - // Halve the difference between best and minBad. - Rational lower, upper, selected; - - // Try the closest ratio halfway between minBood and minBad; - // TODO: Avoid rounding issue by using Rational type for - // midpoint. For now will use double, which should - // have more than sufficient resolution. - double mid = (double) best - + ((double) minBad - (double) best) / 2.0; - Rational::double2Rational(mid, - Range(scMin.width(), scMax.width()), - Range(dfMin.width(), dfMax.width()), - lower, upper); - if (((lower == best) && (upper == minBad))) { - return best; - } - - // Use lower value unless its already been tried - selected = (lower != best) ? lower : upper; - - // Assign the size of the source crop and display frame - // from the selected ratio of source crop to display frame. - scDim = HwcTestDim(selected.numerator(), scMin.height()); - dfDim = HwcTestDim(selected.denominator(), dfMin.height()); - } - - // See if the HWC will commit to this combination - Rectangle rect(format, dfDim, scDim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - - if (verbose) { - testPrintI(" scHscale num: %u scale: %f dfDim: %s scDim: %s", - num, (float) Rational(scDim.width(), dfDim.width()), - ((string) dfDim).c_str(), ((string) scDim).c_str()); - } - if (num == 1) { - // HWC committed to the combination - // This is the best scale factor seen so far. Report the - // dimensions to the caller, in case nothing better is seen. - outBestDf = dfDim; - outBestSc = scDim; - - // Success on the first pass means the largest possible scale - // is supported, in which case no need to search any further. - if (firstPass) { return Rational(scDim.width(), dfDim.width()); } - - // Update the lower bound of the binary search - best = Rational(scDim.width(), dfDim.width()); - } else { - // HWC didn't commit to this combination, so update the - // upper bound of the binary search. - minBad = Rational(scDim.width(), dfDim.width()); - } - - firstPass = false; - } while (best != minBad); - - return best; -} - -// Source crop vertical scale -// Determines the maximum factor by which the source crop can be larger -// that the display frame. The commit point is discovered through a -// binary search of rational numbers. The numerator in each of the -// rational numbers contains the dimension for the source crop, while -// the denominator specifies the dimension for the display frame. On -// each pass of the binary search the mid-point between the greatest -// point committed to (best) and the smallest point in which a commit -// has failed is calculated. This mid-point is then passed to a function -// named double2Rational, which determines the closest rational numbers -// just below and above the mid-point. By default the lower rational -// number is used for the scale factor on the next pass of the binary -// search. The upper value is only used when best is already equal -// to the lower value. This only occurs when the lower value has already -// been tried. -Rational scVScale(uint32_t format, - const HwcTestDim& dfMin, const HwcTestDim& dfMax, - const HwcTestDim& scMin, const HwcTestDim& scMax, - HwcTestDim& outBestDf, HwcTestDim& outBestSc) -{ - HwcTestDim scDim, dfDim; // Source crop and display frame dimension - Rational best(0, 1), minBad; // Current bounds for a binary search - // MinGood is set below the lowest - // possible scale. The value of minBad, - // will be set by the first pass - // of the binary search. - - // Perform the passes of the binary search - bool firstPass = true; - do { - // On first pass try the maximum scale within the search limits - if (firstPass) { - // Try the maximum possible scale, within the search limits - scDim = HwcTestDim(scMin.width(), searchLimits.sourceCrop.height()); - dfDim = dfMin; - } else { - // Subsequent pass - // Halve the difference between best and minBad. - Rational lower, upper, selected; - - // Try the closest ratio halfway between minBood and minBad; - // TODO: Avoid rounding issue by using Rational type for - // midpoint. For now will use double, which should - // have more than sufficient resolution. - double mid = (double) best - + ((double) minBad - (double) best) / 2.0; - Rational::double2Rational(mid, - Range(scMin.height(), scMax.height()), - Range(dfMin.height(), dfMax.height()), - lower, upper); - if (((lower == best) && (upper == minBad))) { - return best; - } - - // Use lower value unless its already been tried - selected = (lower != best) ? lower : upper; - - // Assign the size of the source crop and display frame - // from the selected ratio of source crop to display frame. - scDim = HwcTestDim(scMin.width(), selected.numerator()); - dfDim = HwcTestDim(dfMin.width(), selected.denominator()); - } - - // See if the HWC will commit to this combination - Rectangle rect(format, dfDim, scDim); - list<Rectangle> rectList; - rectList.push_back(rect); - uint32_t num = numOverlays(rectList); - - if (verbose) { - testPrintI(" scHscale num: %u scale: %f dfDim: %s scDim: %s", - num, (float) Rational(scDim.height(), dfDim.height()), - ((string) dfDim).c_str(), ((string) scDim).c_str()); - } - if (num == 1) { - // HWC committed to the combination - // This is the best scale factor seen so far. Report the - // dimensions to the caller, in case nothing better is seen. - outBestDf = dfDim; - outBestSc = scDim; - - // Success on the first pass means the largest possible scale - // is supported, in which case no need to search any further. - if (firstPass) { return Rational(scDim.height(), dfDim.height()); } - - // Update the lower bound of the binary search - best = Rational(scDim.height(), dfDim.height()); - } else { - // HWC didn't commit to this combination, so update the - // upper bound of the binary search. - minBad = Rational(scDim.height(), dfDim.height()); - } - - firstPass = false; - } while (best != minBad); - - return best; -} - -uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat, - uint32_t backgroundBlend, uint32_t foregroundBlend) -{ - list<Rectangle> rectList; - - Rectangle background(backgroundFormat, startDim, startDim); - background.blend = backgroundBlend; - rectList.push_back(background); - - // TODO: Handle cases where startDim is so small that adding 5 - // causes frames not to overlap. - // TODO: Handle cases where startDim is so large that adding 5 - // cause a portion or all of the foreground displayFrame - // to be off the display. - Rectangle foreground(foregroundFormat, startDim, startDim); - foreground.displayFrame.left += 5; - foreground.displayFrame.top += 5; - foreground.displayFrame.right += 5; - foreground.displayFrame.bottom += 5; - background.blend = foregroundBlend; - rectList.push_back(foreground); - - uint32_t num = numOverlays(rectList); - - return num; -} - -Rectangle::Rectangle(uint32_t graphicFormat, HwcTestDim dfDim, - HwcTestDim sDim) : - format(graphicFormat), transform(defaultTransform), - blend(defaultBlend), color(defaultColor), alpha(defaultAlpha), - sourceCrop(sDim), displayFrame(dfDim) -{ - // Set source dimension - // Can't use a base initializer, because the setting of format - // must be done before setting the sourceDimension. - setSourceDim(sDim); -} - -void Rectangle::setSourceDim(HwcTestDim dim) -{ - this->sourceDim = dim; - - const struct hwcTestGraphicFormat *attrib; - attrib = hwcTestGraphicFormatLookup(this->format); - if (attrib != NULL) { - if (sourceDim.width() % attrib->wMod) { - sourceDim.setWidth(sourceDim.width() + attrib->wMod - - (sourceDim.width() % attrib->wMod)); - } - if (sourceDim.height() % attrib->hMod) { - sourceDim.setHeight(sourceDim.height() + attrib->hMod - - (sourceDim.height() % attrib->hMod)); - } - } -} - -// Rational member functions -bool Rational::operator==(const Rational& other) const -{ - if (((uint64_t) _n * other._d) - == ((uint64_t) _d * other._n)) { return true; } - - return false; -} - -bool Rational::operator<(const Rational& other) const -{ - if (((uint64_t) _n * other._d) - < ((uint64_t) _d * other._n)) { return true; } - - return false; -} - -Rational::operator string() const -{ - ostringstream out; - - out << _n << '/' << _d; - - return out.str(); -} - -void Rational::double2Rational(double f, Range nRange, Range dRange, - Rational& lower, Rational& upper) -{ - Rational bestLower(nRange.lower(), dRange.upper()); - Rational bestUpper(nRange.upper(), dRange.lower()); - - // Search for a better solution - for (uint32_t d = dRange.lower(); d <= dRange.upper(); d++) { - Rational val(d * f, d); // Lower, because double to int cast truncates - - if ((val.numerator() < nRange.lower()) - || (val.numerator() > nRange.upper())) { continue; } - - if (((double) val > (double) bestLower) && ((double) val <= f)) { - bestLower = val; - } - - val.setNumerator(val.numerator() + 1); - if (val.numerator() > nRange.upper()) { continue; } - - if (((double) val < (double) bestUpper) && ((double) val >= f)) { - bestUpper = val; - } - } - - lower = bestLower; - upper = bestUpper; -} - -// Local functions - -// Num Overlays -// Given a list of rectangles, determine how many HWC will commit to render -uint32_t numOverlays(list<Rectangle>& rectList) -{ - hwc_layer_list_t *hwcList; - list<sp<GraphicBuffer> > buffers; - - hwcList = hwcTestCreateLayerList(rectList.size()); - if (hwcList == NULL) { - testPrintE("numOverlays create hwcList failed"); - exit(30); - } - - hwc_layer_t *layer = &hwcList->hwLayers[0]; - for (std::list<Rectangle>::iterator it = rectList.begin(); - it != rectList.end(); ++it, ++layer) { - // Allocate the texture for the source frame - // and push it onto the buffers list, so that it - // stays in scope until a return from this function. - sp<GraphicBuffer> texture; - texture = new GraphicBuffer(it->sourceDim.width(), - it->sourceDim.height(), - it->format, texUsage); - buffers.push_back(texture); - - layer->handle = texture->handle; - layer->blending = it->blend; - layer->transform = it->transform; - layer->sourceCrop = it->sourceCrop; - layer->displayFrame = it->displayFrame; - - layer->visibleRegionScreen.numRects = 1; - layer->visibleRegionScreen.rects = &layer->displayFrame; - } - - // Perform prepare operation - if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(hwcList); } - hwcDevice->prepare(hwcDevice, hwcList); - if (verbose) { - testPrintI("Post Prepare:"); - hwcTestDisplayListPrepareModifiable(hwcList); - } - - // Count the number of overlays - uint32_t total = 0; - for (unsigned int n1 = 0; n1 < hwcList->numHwLayers; n1++) { - if (hwcList->hwLayers[n1].compositionType == HWC_OVERLAY) { - total++; - } - } - - // Free the layer list and graphic buffers - hwcTestFreeLayerList(hwcList); - - return total; -} - -string transformList2str(const list<uint32_t>& transformList) -{ - ostringstream out; - - for (list<uint32_t>::const_iterator it = transformList.begin(); - it != transformList.end(); ++it) { - uint32_t id = *it; - - if (it != transformList.begin()) { - out << ", "; - } - out << id; - - for (unsigned int idx = 0; idx < NUMA(transformType); idx++) { - if (id == transformType[idx].id) { - out << " (" << transformType[idx].desc << ')'; - break; - } - } - } - - return out.str(); -} - -string blendList2str(const list<uint32_t>& blendList) -{ - ostringstream out; - - for (list<uint32_t>::const_iterator it = blendList.begin(); - it != blendList.end(); ++it) { - uint32_t id = *it; - - if (it != blendList.begin()) { - out << ", "; - } - out << id; - - for (unsigned int idx = 0; idx < NUMA(blendType); idx++) { - if (id == blendType[idx].id) { - out << " (" << blendType[idx].desc << ')'; - break; - } - } - } - - return out.str(); -} - -void init(void) -{ - srand48(0); - - hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height); - - hwcTestOpenHwc(&hwcDevice); -} - -void printFormatHeadings(size_t indent) -{ - for (size_t row = 0; row <= maxHeadingLen; row++) { - ostringstream line; - for(vector<string>::iterator it = formats.begin(); - it != formats.end(); ++it) { - if ((maxHeadingLen - row) <= it->length()) { - if (row != maxHeadingLen) { - char ch = (*it)[it->length() - (maxHeadingLen - row)]; - line << ' ' << setw(printFieldWidth) << ch; - } else { - line << ' ' << string(printFieldWidth, '-'); - } - } else { - line << ' ' << setw(printFieldWidth) << ""; - } - } - testPrintI("%*s%s", indent + maxHeadingLen, "", - line.str().c_str()); - } -} - -void printOverlapLine(size_t indent, const string formatStr, - const vector<uint32_t>& results) -{ - ostringstream line; - - line << setw(indent + maxHeadingLen - formatStr.length()) << ""; - - line << formatStr; - - for (vector<uint32_t>::const_iterator it = results.begin(); - it != results.end(); ++it) { - line << ' ' << setw(printFieldWidth) << *it; - } - - testPrintI("%s", line.str().c_str()); -} - -void printSyntax(const char *cmd) -{ - testPrintE(" %s [options] [graphicFormat] ...", - cmd); - testPrintE(" options:"); - testPrintE(" -s [width, height] - start dimension"); - testPrintE(" -v - Verbose"); - testPrintE(""); - testPrintE(" graphic formats:"); - for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) { - testPrintE(" %s", hwcTestGraphicFormat[n1].desc); - } -} |
