123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560 |
- /*
- * 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/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_1_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;
- 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_display_contents_1_t *hwcList;
- list<sp<GraphicBuffer> > buffers;
- hwcList = hwcTestCreateLayerList(rectList.size());
- if (hwcList == NULL) {
- testPrintE("numOverlays create hwcList failed");
- exit(30);
- }
- hwc_layer_1_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, 1, &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);
- }
- }
|