Home | History | Annotate | Download | only in hwc
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 
     18 /*
     19  * Hardware Composer Commit Points
     20  *
     21  * Synopsis
     22  *   hwcCommit [options] graphicFormat ...
     23  *     options:
     24  *       -s [width, height] - Starting dimension
     25  *       -v - Verbose
     26  *
     27  *      graphic formats:
     28  *        RGBA8888 (reference frame default)
     29  *        RGBX8888
     30  *        RGB888
     31  *        RGB565
     32  *        BGRA8888
     33  *        RGBA5551
     34  *        RGBA4444
     35  *        YV12
     36  *
     37  * Description
     38  *   The Hardware Composer (HWC) Commit test is a benchmark that
     39  *   discovers the points at which the HWC will commit to rendering an
     40  *   overlay(s).  Before rendering a set of overlays, the HWC is shown
     41  *   the list through a prepare call.  During the prepare call the HWC
     42  *   is able to examine the list and specify which overlays it is able
     43  *   to handle.  The overlays that it can't handle are typically composited
     44  *   by a higher level (e.g. Surface Flinger) and then the original list
     45  *   plus a composit of what HWC passed on are provided back to the HWC
     46  *   for rendering.
     47  *
     48  *   Once an implementation of the HWC has been shipped, a regression would
     49  *   likely occur if a latter implementation started passing on conditions
     50  *   that it used to commit to.  The primary purpose of this benchmark
     51  *   is the automated discovery of the commit points, where an implementation
     52  *   is on the edge between committing and not committing.  These are commonly
     53  *   referred to as commit points.  Between implementations changes to the
     54  *   commit points are allowed, as long as they improve what the HWC commits
     55  *   to.  Once an implementation of the HWC is shipped, the commit points are
     56  *   not allowed to regress in future implementations.
     57  *
     58  *   This benchmark takes a sampling and then adjusts until it finds a
     59  *   commit point.  It doesn't exhaustively check all possible conditions,
     60  *   which do to the number of combinations would be impossible.  Instead
     61  *   it starts its search from a starting dimension, that can be changed
     62  *   via the -s option.  The search is also bounded by a set of search
     63  *   limits, that are hard-coded into a structure of constants named
     64  *   searchLimits.  Results that happen to reach a searchLimit are prefixed
     65  *   with >=, so that it is known that the value could possibly be larger.
     66  *
     67  *   Measurements are made for each of the graphic formats specified as
     68  *   positional parameters on the command-line.  If no graphic formats
     69  *   are specified on the command line, then by default measurements are
     70  *   made and reported for each of the known graphic format.
     71  */
     72 
     73 #include <algorithm>
     74 #include <assert.h>
     75 #include <cerrno>
     76 #include <cmath>
     77 #include <cstdlib>
     78 #include <ctime>
     79 #include <iomanip>
     80 #include <istream>
     81 #include <libgen.h>
     82 #include <list>
     83 #include <sched.h>
     84 #include <sstream>
     85 #include <stdint.h>
     86 #include <string.h>
     87 #include <unistd.h>
     88 #include <vector>
     89 
     90 #include <sys/syscall.h>
     91 #include <sys/types.h>
     92 #include <sys/wait.h>
     93 
     94 #include <EGL/egl.h>
     95 #include <EGL/eglext.h>
     96 #include <GLES2/gl2.h>
     97 #include <GLES2/gl2ext.h>
     98 
     99 #include <ui/GraphicBuffer.h>
    100 
    101 #define LOG_TAG "hwcCommitTest"
    102 #include <utils/Log.h>
    103 #include <testUtil.h>
    104 
    105 #include <hardware/hwcomposer.h>
    106 
    107 #include <glTestLib.h>
    108 #include "hwcTestLib.h"
    109 
    110 using namespace std;
    111 using namespace android;
    112 
    113 // Defaults
    114 const HwcTestDim defaultStartDim = HwcTestDim(100, 100);
    115 const bool defaultVerbose = false;
    116 
    117 const uint32_t   defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
    118 const int32_t    defaultTransform = 0;
    119 const uint32_t   defaultBlend = HWC_BLENDING_NONE;
    120 const ColorFract defaultColor(0.5, 0.5, 0.5);
    121 const float      defaultAlpha = 1.0; // Opaque
    122 const HwcTestDim defaultSourceDim(1, 1);
    123 const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
    124 const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
    125 
    126 // Global Constants
    127 const uint32_t printFieldWidth = 2;
    128 const struct searchLimits {
    129     uint32_t   numOverlays;
    130     HwcTestDim sourceCrop;
    131 } searchLimits = {
    132     10,
    133     HwcTestDim(3000, 2000),
    134 };
    135 const struct transformType {
    136     const char *desc;
    137     uint32_t id;
    138 } transformType[] = {
    139     {"fliph",  HWC_TRANSFORM_FLIP_H},
    140     {"flipv",  HWC_TRANSFORM_FLIP_V},
    141     {"rot90",  HWC_TRANSFORM_ROT_90},
    142     {"rot180", HWC_TRANSFORM_ROT_180},
    143     {"rot270", HWC_TRANSFORM_ROT_270},
    144 };
    145 const struct blendType {
    146     const char *desc;
    147     uint32_t id;
    148 } blendType[] = {
    149     {"none", HWC_BLENDING_NONE},
    150     {"premult", HWC_BLENDING_PREMULT},
    151     {"coverage", HWC_BLENDING_COVERAGE},
    152 };
    153 
    154 // Defines
    155 #define MAXCMD               200
    156 #define CMD_STOP_FRAMEWORK   "stop 2>&1"
    157 #define CMD_START_FRAMEWORK  "start 2>&1"
    158 
    159 // Macros
    160 #define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
    161 
    162 // Local types
    163 class Rectangle {
    164 public:
    165     Rectangle(uint32_t graphicFormat = defaultFormat,
    166               HwcTestDim dfDim = HwcTestDim(1, 1),
    167               HwcTestDim sDim = HwcTestDim(1, 1));
    168     void setSourceDim(HwcTestDim dim);
    169 
    170     uint32_t     format;
    171     uint32_t     transform;
    172     int32_t      blend;
    173     ColorFract   color;
    174     float        alpha;
    175     HwcTestDim   sourceDim;
    176     struct hwc_rect   sourceCrop;
    177     struct hwc_rect   displayFrame;
    178 };
    179 
    180 class Range {
    181 public:
    182     Range(void) : _l(0), _u(0) {}
    183     Range(uint32_t lower, uint32_t upper) : _l(lower), _u(upper) {}
    184     uint32_t lower(void) { return _l; }
    185     uint32_t upper(void) { return _u; }
    186 
    187     operator string();
    188 
    189 private:
    190     uint32_t _l; // lower
    191     uint32_t _u; // upper
    192 };
    193 
    194 Range::operator string()
    195 {
    196     ostringstream out;
    197 
    198     out << '[' << _l << ", " << _u << ']';
    199 
    200     return out.str();
    201 }
    202 
    203 class Rational {
    204 public:
    205     Rational(void) : _n(0), _d(1) {}
    206     Rational(uint32_t n, uint32_t d) : _n(n), _d(d) {}
    207     uint32_t numerator(void) { return _n; }
    208     uint32_t denominator(void) { return _d; }
    209     void setNumerator(uint32_t numerator) { _n = numerator; }
    210 
    211     bool operator==(const Rational& other) const;
    212     bool operator!=(const Rational& other) const { return !(*this == other); }
    213     bool operator<(const Rational& other) const;
    214     bool operator>(const Rational& other) const {
    215         return (!(*this == other) && !(*this < other));
    216     }
    217     static void double2Rational(double f, Range nRange, Range dRange,
    218                                Rational& lower, Rational& upper);
    219 
    220     operator string() const;
    221     operator double() const { return (double) _n / (double) _d; }
    222 
    223 
    224 private:
    225     uint32_t _n;
    226     uint32_t _d;
    227 };
    228 
    229 // Globals
    230 static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
    231         GraphicBuffer::USAGE_SW_WRITE_RARELY;
    232 static hwc_composer_device_1_t *hwcDevice;
    233 static EGLDisplay dpy;
    234 static EGLSurface surface;
    235 static EGLint width, height;
    236 static size_t maxHeadingLen;
    237 static vector<string> formats;
    238 
    239 // Measurements
    240 struct meas {
    241     uint32_t format;
    242     uint32_t startDimOverlays;
    243     uint32_t maxNonOverlapping;
    244     uint32_t maxOverlapping;
    245     list<uint32_t> transforms;
    246     list<uint32_t> blends;
    247     struct displayFrame {
    248         uint32_t minWidth;
    249         uint32_t minHeight;
    250         HwcTestDim minDim;
    251         uint32_t maxWidth;
    252         uint32_t maxHeight;
    253         HwcTestDim maxDim;
    254     } df;
    255     struct sourceCrop {
    256         uint32_t minWidth;
    257         uint32_t minHeight;
    258         HwcTestDim minDim;
    259         uint32_t maxWidth;
    260         uint32_t maxHeight;
    261         HwcTestDim maxDim;
    262         Rational hScale;
    263         HwcTestDim hScaleBestDf;
    264         HwcTestDim hScaleBestSc;
    265         Rational vScale;
    266         HwcTestDim vScaleBestDf;
    267         HwcTestDim vScaleBestSc;
    268     } sc;
    269     vector<uint32_t> overlapBlendNone;
    270     vector<uint32_t> overlapBlendPremult;
    271     vector<uint32_t> overlapBlendCoverage;
    272 };
    273 vector<meas> measurements;
    274 
    275 // Function prototypes
    276 uint32_t numOverlays(list<Rectangle>& rectList);
    277 uint32_t maxOverlays(uint32_t format, bool allowOverlap);
    278 list<uint32_t> supportedTransforms(uint32_t format);
    279 list<uint32_t> supportedBlends(uint32_t format);
    280 uint32_t dfMinWidth(uint32_t format);
    281 uint32_t dfMinHeight(uint32_t format);
    282 uint32_t dfMaxWidth(uint32_t format);
    283 uint32_t dfMaxHeight(uint32_t format);
    284 HwcTestDim dfMinDim(uint32_t format);
    285 HwcTestDim dfMaxDim(uint32_t format);
    286 uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim);
    287 uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim);
    288 uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim);
    289 uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim);
    290 HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim);
    291 HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim);
    292 Rational scHScale(uint32_t format,
    293                   const HwcTestDim& dfMin, const HwcTestDim& dfMax,
    294                   const HwcTestDim& scMin, const HwcTestDim& scMax,
    295                   HwcTestDim& outBestDf, HwcTestDim& outBestSc);
    296 Rational scVScale(uint32_t format,
    297                   const HwcTestDim& dfMin, const HwcTestDim& dfMax,
    298                   const HwcTestDim& scMin, const HwcTestDim& scMax,
    299                   HwcTestDim& outBestDf, HwcTestDim& outBestSc);
    300 uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
    301                         uint32_t backgroundBlend, uint32_t foregroundBlend);
    302 string transformList2str(const list<uint32_t>& transformList);
    303 string blendList2str(const list<uint32_t>& blendList);
    304 void init(void);
    305 void printFormatHeadings(size_t indent);
    306 void printOverlapLine(size_t indent, const string formatStr,
    307                       const vector<uint32_t>& results);
    308 void printSyntax(const char *cmd);
    309 
    310 // Command-line option settings
    311 static bool verbose = defaultVerbose;
    312 static HwcTestDim startDim = defaultStartDim;
    313 
    314 /*
    315  * Main
    316  *
    317  * Performs the following high-level sequence of operations:
    318  *
    319  *   1. Command-line parsing
    320  *
    321  *   2. Form a list of command-line specified graphic formats.  If
    322  *      no formats are specified, then form a list of all known formats.
    323  *
    324  *   3. Stop framework
    325  *      Only one user at a time is allowed to use the HWC.  Surface
    326  *      Flinger uses the HWC and is part of the framework.  Need to
    327  *      stop the framework so that Surface Flinger will stop using
    328  *      the HWC.
    329  *
    330  *   4. Initialization
    331  *
    332  *   5. For each graphic format in the previously formed list perform
    333  *      measurements on that format and report the results.
    334  *
    335  *   6. Start framework
    336  */
    337 int
    338 main(int argc, char *argv[])
    339 {
    340     int     rv, opt;
    341     char   *chptr;
    342     bool    error;
    343     string  str;
    344     char cmd[MAXCMD];
    345     list<Rectangle> rectList;
    346 
    347     testSetLogCatTag(LOG_TAG);
    348 
    349     // Parse command line arguments
    350     while ((opt = getopt(argc, argv, "s:v?h")) != -1) {
    351         switch (opt) {
    352 
    353           case 's': // Start Dimension
    354             // Use arguments until next starts with a dash
    355             // or current ends with a > or ]
    356             str = optarg;
    357             while (optind < argc) {
    358                 if (*argv[optind] == '-') { break; }
    359                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
    360                 if ((endChar == '>') || (endChar == ']')) { break; }
    361                 str += " " + string(argv[optind++]);
    362             }
    363             {
    364                 istringstream in(str);
    365                 startDim = hwcTestParseDim(in, error);
    366                 // Any parse error or characters not used by parser
    367                 if (error
    368                     || (((unsigned int) in.tellg() != in.str().length())
    369                         && (in.tellg() != (streampos) -1))) {
    370                     testPrintE("Invalid command-line specified start "
    371                                "dimension of: %s", str.c_str());
    372                     exit(8);
    373                 }
    374             }
    375             break;
    376 
    377           case 'v': // Verbose
    378             verbose = true;
    379             break;
    380 
    381           case 'h': // Help
    382           case '?':
    383           default:
    384             printSyntax(basename(argv[0]));
    385             exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
    386         }
    387     }
    388 
    389     // Positional parameters
    390     // Positional parameters provide the names of graphic formats that
    391     // measurements are to be made on.  Measurements are made on all
    392     // known graphic formats when no positional parameters are provided.
    393     if (optind == argc) {
    394         // No command-line specified graphic formats
    395         // Add all graphic formats to the list of formats to be measured
    396         for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
    397             formats.push_back(hwcTestGraphicFormat[n1].desc);
    398         }
    399     } else {
    400         // Add names of command-line specified graphic formats to the
    401         // list of formats to be tested
    402         for (; argv[optind] != NULL; optind++) {
    403             formats.push_back(argv[optind]);
    404         }
    405     }
    406 
    407     // Determine length of longest specified graphic format.
    408     // This value is used for output formating
    409     for (vector<string>::iterator it = formats.begin();
    410          it != formats.end(); ++it) {
    411          maxHeadingLen = max(maxHeadingLen, it->length());
    412     }
    413 
    414     // Stop framework
    415     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
    416     if (rv >= (signed) sizeof(cmd) - 1) {
    417         testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
    418         exit(14);
    419     }
    420     testExecCmd(cmd);
    421     testDelay(1.0); // TODO - needs means to query whether asynchronous stop
    422                     // framework operation has completed.  For now, just wait
    423                     // a long time.
    424 
    425     testPrintI("startDim: %s", ((string) startDim).c_str());
    426 
    427     init();
    428 
    429     // For each of the graphic formats
    430     for (vector<string>::iterator itFormat = formats.begin();
    431          itFormat != formats.end(); ++itFormat) {
    432 
    433         // Locate hwcTestLib structure that describes this format
    434         const struct hwcTestGraphicFormat *format;
    435         format = hwcTestGraphicFormatLookup((*itFormat).c_str());
    436         if (format == NULL) {
    437             testPrintE("Unknown graphic format of: %s", (*itFormat).c_str());
    438             exit(1);
    439         }
    440 
    441         // Display format header
    442         testPrintI("format: %s", format->desc);
    443 
    444         // Create area to hold the measurements
    445         struct meas meas;
    446         struct meas *measPtr;
    447         meas.format = format->format;
    448         measurements.push_back(meas);
    449         measPtr = &measurements[measurements.size() - 1];
    450 
    451         // Start dimension num overlays
    452         Rectangle rect(format->format, startDim);
    453         rectList.clear();
    454         rectList.push_back(rect);
    455         measPtr->startDimOverlays = numOverlays(rectList);
    456         testPrintI("  startDimOverlays: %u", measPtr->startDimOverlays);
    457 
    458         // Skip the rest of the measurements, when the start dimension
    459         // doesn't produce an overlay
    460         if (measPtr->startDimOverlays == 0) { continue; }
    461 
    462         // Max Overlays
    463         measPtr->maxNonOverlapping = maxOverlays(format->format, false);
    464         testPrintI("  max nonOverlapping overlays: %s%u",
    465                    (measPtr->maxNonOverlapping == searchLimits.numOverlays)
    466                        ? ">= " : "",
    467                    measPtr->maxNonOverlapping);
    468         measPtr->maxOverlapping = maxOverlays(format->format, true);
    469         testPrintI("  max Overlapping overlays: %s%u",
    470                    (measPtr->maxOverlapping == searchLimits.numOverlays)
    471                        ? ">= " : "",
    472                    measPtr->maxOverlapping);
    473 
    474         // Transforms and blends
    475         measPtr->transforms = supportedTransforms(format->format);
    476         testPrintI("  transforms: %s",
    477                    transformList2str(measPtr->transforms).c_str());
    478         measPtr->blends = supportedBlends(format->format);
    479         testPrintI("  blends: %s",
    480                    blendList2str(measPtr->blends).c_str());
    481 
    482         // Display frame measurements
    483         measPtr->df.minWidth = dfMinWidth(format->format);
    484         testPrintI("  dfMinWidth: %u", measPtr->df.minWidth);
    485 
    486         measPtr->df.minHeight = dfMinHeight(format->format);
    487         testPrintI("  dfMinHeight: %u", measPtr->df.minHeight);
    488 
    489         measPtr->df.maxWidth = dfMaxWidth(format->format);
    490         testPrintI("  dfMaxWidth: %u", measPtr->df.maxWidth);
    491 
    492         measPtr->df.maxHeight = dfMaxHeight(format->format);
    493         testPrintI("  dfMaxHeight: %u", measPtr->df.maxHeight);
    494 
    495         measPtr->df.minDim = dfMinDim(format->format);
    496         testPrintI("  dfMinDim: %s", ((string) measPtr->df.minDim).c_str());
    497 
    498         measPtr->df.maxDim = dfMaxDim(format->format);
    499         testPrintI("  dfMaxDim: %s", ((string) measPtr->df.maxDim).c_str());
    500 
    501         // Source crop measurements
    502         measPtr->sc.minWidth = scMinWidth(format->format, measPtr->df.minDim);
    503         testPrintI("  scMinWidth: %u", measPtr->sc.minWidth);
    504 
    505         measPtr->sc.minHeight = scMinHeight(format->format, measPtr->df.minDim);
    506         testPrintI("  scMinHeight: %u", measPtr->sc.minHeight);
    507 
    508         measPtr->sc.maxWidth = scMaxWidth(format->format, measPtr->df.maxDim);
    509         testPrintI("  scMaxWidth: %s%u", (measPtr->sc.maxWidth
    510                    == searchLimits.sourceCrop.width()) ? ">= " : "",
    511                    measPtr->sc.maxWidth);
    512 
    513         measPtr->sc.maxHeight = scMaxHeight(format->format, measPtr->df.maxDim);
    514         testPrintI("  scMaxHeight: %s%u", (measPtr->sc.maxHeight
    515                    == searchLimits.sourceCrop.height()) ? ">= " : "",
    516                    measPtr->sc.maxHeight);
    517 
    518         measPtr->sc.minDim = scMinDim(format->format, measPtr->df.minDim);
    519         testPrintI("  scMinDim: %s", ((string) measPtr->sc.minDim).c_str());
    520 
    521         measPtr->sc.maxDim = scMaxDim(format->format, measPtr->df.maxDim);
    522         testPrintI("  scMaxDim: %s%s", ((measPtr->sc.maxDim.width()
    523                          >= searchLimits.sourceCrop.width())
    524                          || (measPtr->sc.maxDim.width() >=
    525                          searchLimits.sourceCrop.height())) ? ">= " : "",
    526                    ((string) measPtr->sc.maxDim).c_str());
    527 
    528         measPtr->sc.hScale = scHScale(format->format,
    529                                       measPtr->df.minDim, measPtr->df.maxDim,
    530                                       measPtr->sc.minDim, measPtr->sc.maxDim,
    531                                       measPtr->sc.hScaleBestDf,
    532                                       measPtr->sc.hScaleBestSc);
    533         testPrintI("  scHScale: %s%f",
    534                    (measPtr->sc.hScale
    535                        >= Rational(searchLimits.sourceCrop.width(),
    536                                    measPtr->df.minDim.width())) ? ">= " : "",
    537                    (double) measPtr->sc.hScale);
    538         testPrintI("    HScale Best Display Frame: %s",
    539                    ((string) measPtr->sc.hScaleBestDf).c_str());
    540         testPrintI("    HScale Best Source Crop: %s",
    541                    ((string) measPtr->sc.hScaleBestSc).c_str());
    542 
    543         measPtr->sc.vScale = scVScale(format->format,
    544                                       measPtr->df.minDim, measPtr->df.maxDim,
    545                                       measPtr->sc.minDim, measPtr->sc.maxDim,
    546                                       measPtr->sc.vScaleBestDf,
    547                                       measPtr->sc.vScaleBestSc);
    548         testPrintI("  scVScale: %s%f",
    549                    (measPtr->sc.vScale
    550                        >= Rational(searchLimits.sourceCrop.height(),
    551                                    measPtr->df.minDim.height())) ? ">= " : "",
    552                    (double) measPtr->sc.vScale);
    553         testPrintI("    VScale Best Display Frame: %s",
    554                    ((string) measPtr->sc.vScaleBestDf).c_str());
    555         testPrintI("    VScale Best Source Crop: %s",
    556                    ((string) measPtr->sc.vScaleBestSc).c_str());
    557 
    558         // Overlap two graphic formats and different blends
    559         // Results displayed after all overlap measurments with
    560         // current format in the foreground
    561         // TODO: make measurments with background blend other than
    562         //       none.  All of these measurements are done with a
    563         //       background blend of HWC_BLENDING_NONE, with the
    564         //       blend type of the foregound being varied.
    565         uint32_t foregroundFormat = format->format;
    566         for (vector<string>::iterator it = formats.begin();
    567              it != formats.end(); ++it) {
    568             uint32_t num;
    569 
    570             const struct hwcTestGraphicFormat *backgroundFormatPtr
    571                 = hwcTestGraphicFormatLookup((*it).c_str());
    572             uint32_t backgroundFormat = backgroundFormatPtr->format;
    573 
    574             num = numOverlapping(backgroundFormat, foregroundFormat,
    575                                  HWC_BLENDING_NONE, HWC_BLENDING_NONE);
    576             measPtr->overlapBlendNone.push_back(num);
    577 
    578             num = numOverlapping(backgroundFormat, foregroundFormat,
    579                                  HWC_BLENDING_NONE, HWC_BLENDING_PREMULT);
    580             measPtr->overlapBlendPremult.push_back(num);
    581 
    582             num = numOverlapping(backgroundFormat, foregroundFormat,
    583                                  HWC_BLENDING_NONE, HWC_BLENDING_COVERAGE);
    584             measPtr->overlapBlendCoverage.push_back(num);
    585         }
    586 
    587     }
    588 
    589     // Display overlap results
    590     size_t indent = 2;
    591     testPrintI("overlapping blend: none");
    592     printFormatHeadings(indent);
    593     for (vector<string>::iterator it = formats.begin();
    594          it != formats.end(); ++it) {
    595         printOverlapLine(indent, *it, measurements[it
    596                          - formats.begin()].overlapBlendNone);
    597     }
    598     testPrintI("");
    599 
    600     testPrintI("overlapping blend: premult");
    601     printFormatHeadings(indent);
    602     for (vector<string>::iterator it = formats.begin();
    603          it != formats.end(); ++it) {
    604         printOverlapLine(indent, *it, measurements[it
    605                          - formats.begin()].overlapBlendPremult);
    606     }
    607     testPrintI("");
    608 
    609     testPrintI("overlapping blend: coverage");
    610     printFormatHeadings(indent);
    611     for (vector<string>::iterator it = formats.begin();
    612          it != formats.end(); ++it) {
    613         printOverlapLine(indent, *it, measurements[it
    614                          - formats.begin()].overlapBlendCoverage);
    615     }
    616     testPrintI("");
    617 
    618     // Start framework
    619     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
    620     if (rv >= (signed) sizeof(cmd) - 1) {
    621         testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
    622         exit(21);
    623     }
    624     testExecCmd(cmd);
    625 
    626     return 0;
    627 }
    628 
    629 // Determine the maximum number of overlays that are all of the same format
    630 // that the HWC will commit to.  If allowOverlap is true, then the rectangles
    631 // are laid out on a diagonal starting from the upper left corner.  With
    632 // each rectangle adjust one pixel to the right and one pixel down.
    633 // When allowOverlap is false, the rectangles are tiled in column major
    634 // order.  Note, column major ordering is used so that the initial rectangles
    635 // are all on different horizontal scan rows.  It is common that hardware
    636 // has limits on the number of objects it can handle on any single row.
    637 uint32_t maxOverlays(uint32_t format, bool allowOverlap)
    638 {
    639     unsigned int max = 0;
    640 
    641     for (unsigned int numRects = 1; numRects <= searchLimits.numOverlays;
    642          numRects++) {
    643         list<Rectangle> rectList;
    644 
    645         for (unsigned int x = 0;
    646              (x + startDim.width()) < (unsigned int) width;
    647              x += (allowOverlap) ? 1 : startDim.width()) {
    648             for (unsigned int y = 0;
    649                  (y + startDim.height()) < (unsigned int) height;
    650                  y += (allowOverlap) ? 1 : startDim.height()) {
    651                 Rectangle rect(format, startDim, startDim);
    652                 rect.displayFrame.left = x;
    653                 rect.displayFrame.top = y;
    654                 rect.displayFrame.right = x + startDim.width();
    655                 rect.displayFrame.bottom = y + startDim.height();
    656 
    657                 rectList.push_back(rect);
    658 
    659                 if (rectList.size() >= numRects) { break; }
    660             }
    661             if (rectList.size() >= numRects) { break; }
    662         }
    663 
    664         uint32_t num = numOverlays(rectList);
    665         if (num > max) { max = num; }
    666     }
    667 
    668     return max;
    669 }
    670 
    671 // Measures what transforms (i.e. flip horizontal, rotate 180) are
    672 // supported by the specified format
    673 list<uint32_t> supportedTransforms(uint32_t format)
    674 {
    675     list<uint32_t> rv;
    676     list<Rectangle> rectList;
    677     Rectangle rect(format, startDim);
    678 
    679     // For each of the transform types
    680     for (unsigned int idx = 0; idx < NUMA(transformType); idx++) {
    681         unsigned int id = transformType[idx].id;
    682 
    683         rect.transform = id;
    684         rectList.clear();
    685         rectList.push_back(rect);
    686         uint32_t num = numOverlays(rectList);
    687 
    688         if (num == 1) {
    689             rv.push_back(id);
    690         }
    691     }
    692 
    693     return rv;
    694 }
    695 
    696 // Determines which types of blends (i.e. none, premult, coverage) are
    697 // supported by the specified format
    698 list<uint32_t> supportedBlends(uint32_t format)
    699 {
    700     list<uint32_t> rv;
    701     list<Rectangle> rectList;
    702     Rectangle rect(format, startDim);
    703 
    704     // For each of the blend types
    705     for (unsigned int idx = 0; idx < NUMA(blendType); idx++) {
    706         unsigned int id = blendType[idx].id;
    707 
    708         rect.blend = id;
    709         rectList.clear();
    710         rectList.push_back(rect);
    711         uint32_t num = numOverlays(rectList);
    712 
    713         if (num == 1) {
    714             rv.push_back(id);
    715         }
    716     }
    717 
    718     return rv;
    719 }
    720 
    721 // Determines the minimum width of any display frame of the given format
    722 // that the HWC will commit to.
    723 uint32_t dfMinWidth(uint32_t format)
    724 {
    725     uint32_t w;
    726     list<Rectangle> rectList;
    727 
    728     for (w = 1; w <= startDim.width(); w++) {
    729         HwcTestDim dim(w, startDim.height());
    730         Rectangle rect(format, dim);
    731         rectList.clear();
    732         rectList.push_back(rect);
    733         uint32_t num = numOverlays(rectList);
    734         if (num > 0) {
    735             return w;
    736         }
    737     }
    738     if (w > startDim.width()) {
    739         testPrintE("Failed to locate display frame min width");
    740         exit(33);
    741     }
    742 
    743     return w;
    744 }
    745 
    746 // Display frame minimum height
    747 uint32_t dfMinHeight(uint32_t format)
    748 {
    749     uint32_t h;
    750     list<Rectangle> rectList;
    751 
    752     for (h = 1; h <= startDim.height(); h++) {
    753         HwcTestDim dim(startDim.width(), h);
    754         Rectangle rect(format, dim);
    755         rectList.clear();
    756         rectList.push_back(rect);
    757         uint32_t num = numOverlays(rectList);
    758         if (num > 0) {
    759             return h;
    760         }
    761     }
    762     if (h > startDim.height()) {
    763         testPrintE("Failed to locate display frame min height");
    764         exit(34);
    765     }
    766 
    767     return h;
    768 }
    769 
    770 // Display frame maximum width
    771 uint32_t dfMaxWidth(uint32_t format)
    772 {
    773     uint32_t w;
    774     list<Rectangle> rectList;
    775 
    776     for (w = width; w >= startDim.width(); w--) {
    777         HwcTestDim dim(w, startDim.height());
    778         Rectangle rect(format, dim);
    779         rectList.clear();
    780         rectList.push_back(rect);
    781         uint32_t num = numOverlays(rectList);
    782         if (num > 0) {
    783             return w;
    784         }
    785     }
    786     if (w < startDim.width()) {
    787         testPrintE("Failed to locate display frame max width");
    788         exit(35);
    789     }
    790 
    791     return w;
    792 }
    793 
    794 // Display frame maximum height
    795 uint32_t dfMaxHeight(uint32_t format)
    796 {
    797     uint32_t h;
    798 
    799     for (h = height; h >= startDim.height(); h--) {
    800         HwcTestDim dim(startDim.width(), h);
    801         Rectangle rect(format, dim);
    802         list<Rectangle> rectList;
    803         rectList.push_back(rect);
    804         uint32_t num = numOverlays(rectList);
    805         if (num > 0) {
    806             return h;
    807         }
    808     }
    809     if (h < startDim.height()) {
    810         testPrintE("Failed to locate display frame max height");
    811         exit(36);
    812     }
    813 
    814     return h;
    815 }
    816 
    817 // Determine the minimum number of pixels that the HWC will ever commit to.
    818 // Note, this might be different that dfMinWidth * dfMinHeight, in that this
    819 // function adjusts both the width and height from the starting dimension.
    820 HwcTestDim dfMinDim(uint32_t format)
    821 {
    822     uint64_t bestMinPixels = 0;
    823     HwcTestDim bestDim;
    824     bool bestSet = false; // True when value has been assigned to
    825                           // bestMinPixels and bestDim
    826 
    827     bool origVerbose = verbose;  // Temporarily turn off verbose
    828     verbose = false;
    829     for (uint32_t w = 1; w <= startDim.width(); w++) {
    830         for (uint32_t h = 1; h <= startDim.height(); h++) {
    831             if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) {
    832                 break;
    833             }
    834 
    835             HwcTestDim dim(w, h);
    836             Rectangle rect(format, dim);
    837             list<Rectangle> rectList;
    838             rectList.push_back(rect);
    839             uint32_t num = numOverlays(rectList);
    840             if (num > 0) {
    841                 uint64_t pixels = dim.width() * dim.height();
    842                 if (!bestSet || (pixels < bestMinPixels)) {
    843                     bestMinPixels = pixels;
    844                     bestDim = dim;
    845                     bestSet = true;
    846                 }
    847             }
    848         }
    849     }
    850     verbose = origVerbose;
    851 
    852     if (!bestSet) {
    853         testPrintE("Unable to locate display frame min dimension");
    854         exit(20);
    855     }
    856 
    857     return bestDim;
    858 }
    859 
    860 // Display frame maximum dimension
    861 HwcTestDim dfMaxDim(uint32_t format)
    862 {
    863     uint64_t bestMaxPixels = 0;
    864     HwcTestDim bestDim;
    865     bool bestSet = false; // True when value has been assigned to
    866                           // bestMaxPixels and bestDim;
    867 
    868     // Potentially increase benchmark performance by first checking
    869     // for the common case of supporting a full display frame.
    870     HwcTestDim dim(width, height);
    871     Rectangle rect(format, dim);
    872     list<Rectangle> rectList;
    873     rectList.push_back(rect);
    874     uint32_t num = numOverlays(rectList);
    875     if (num == 1) { return dim; }
    876 
    877     // TODO: Use a binary search
    878     bool origVerbose = verbose;  // Temporarily turn off verbose
    879     verbose = false;
    880     for (uint32_t w = startDim.width(); w <= (uint32_t) width; w++) {
    881         for (uint32_t h = startDim.height(); h <= (uint32_t) height; h++) {
    882             if (bestSet && ((w * h) <= bestMaxPixels)) { continue; }
    883 
    884             HwcTestDim dim(w, h);
    885             Rectangle rect(format, dim);
    886             list<Rectangle> rectList;
    887             rectList.push_back(rect);
    888             uint32_t num = numOverlays(rectList);
    889             if (num > 0) {
    890                 uint64_t pixels = dim.width() * dim.height();
    891                 if (!bestSet || (pixels > bestMaxPixels)) {
    892                     bestMaxPixels = pixels;
    893                     bestDim = dim;
    894                     bestSet = true;
    895                 }
    896             }
    897         }
    898     }
    899     verbose = origVerbose;
    900 
    901     if (!bestSet) {
    902         testPrintE("Unable to locate display frame max dimension");
    903         exit(21);
    904     }
    905 
    906     return bestDim;
    907 }
    908 
    909 // Source crop minimum width
    910 uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim)
    911 {
    912     uint32_t w;
    913     list<Rectangle> rectList;
    914 
    915     // Source crop frame min width
    916     for (w = 1; w <= dfDim.width(); w++) {
    917         Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height()));
    918         rectList.clear();
    919         rectList.push_back(rect);
    920         uint32_t num = numOverlays(rectList);
    921         if (num > 0) {
    922             return w;
    923         }
    924     }
    925     testPrintE("Failed to locate source crop min width");
    926     exit(35);
    927 }
    928 
    929 // Source crop minimum height
    930 uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim)
    931 {
    932     uint32_t h;
    933     list<Rectangle> rectList;
    934 
    935     for (h = 1; h <= dfDim.height(); h++) {
    936         Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h));
    937         rectList.clear();
    938         rectList.push_back(rect);
    939         uint32_t num = numOverlays(rectList);
    940         if (num > 0) {
    941             return h;
    942         }
    943     }
    944     testPrintE("Failed to locate source crop min height");
    945     exit(36);
    946 }
    947 
    948 // Source crop maximum width
    949 uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim)
    950 {
    951     uint32_t w;
    952     list<Rectangle> rectList;
    953 
    954     for (w = searchLimits.sourceCrop.width(); w >= dfDim.width(); w--) {
    955         Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height()));
    956         rectList.clear();
    957         rectList.push_back(rect);
    958         uint32_t num = numOverlays(rectList);
    959         if (num > 0) {
    960             return w;
    961         }
    962     }
    963     testPrintE("Failed to locate source crop max width");
    964     exit(35);
    965 }
    966 
    967 // Source crop maximum height
    968 uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim)
    969 {
    970     uint32_t h;
    971     list<Rectangle> rectList;
    972 
    973     for (h = searchLimits.sourceCrop.height(); h >= dfDim.height(); h--) {
    974         Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h));
    975         rectList.clear();
    976         rectList.push_back(rect);
    977         uint32_t num = numOverlays(rectList);
    978         if (num > 0) {
    979             return h;
    980         }
    981     }
    982     testPrintE("Failed to locate source crop max height");
    983     exit(36);
    984 }
    985 
    986 // Source crop minimum dimension
    987 // Discovers the source crop with the least number of pixels that the
    988 // HWC will commit to.  Note, this may be different from scMinWidth
    989 // * scMinHeight, in that this function searches for a combination of
    990 // width and height.  While the other routines always keep one of the
    991 // dimensions equal to the corresponding start dimension.
    992 HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim)
    993 {
    994     uint64_t bestMinPixels = 0;
    995     HwcTestDim bestDim;
    996     bool bestSet = false; // True when value has been assigned to
    997                           // bestMinPixels and bestDim
    998 
    999     bool origVerbose = verbose;  // Temporarily turn off verbose
   1000     verbose = false;
   1001     for (uint32_t w = 1; w <= dfDim.width(); w++) {
   1002         for (uint32_t h = 1; h <= dfDim.height(); h++) {
   1003             if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) {
   1004                 break;
   1005             }
   1006 
   1007             HwcTestDim dim(w, h);
   1008             Rectangle rect(format, dfDim, HwcTestDim(w, h));
   1009             list<Rectangle> rectList;
   1010             rectList.push_back(rect);
   1011             uint32_t num = numOverlays(rectList);
   1012             if (num > 0) {
   1013                 uint64_t pixels = dim.width() * dim.height();
   1014                 if (!bestSet || (pixels < bestMinPixels)) {
   1015                     bestMinPixels = pixels;
   1016                     bestDim = dim;
   1017                     bestSet = true;
   1018                 }
   1019             }
   1020         }
   1021     }
   1022     verbose = origVerbose;
   1023 
   1024     if (!bestSet) {
   1025         testPrintE("Unable to locate source crop min dimension");
   1026         exit(20);
   1027     }
   1028 
   1029     return bestDim;
   1030 }
   1031 
   1032 // Source crop maximum dimension
   1033 HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim)
   1034 {
   1035     uint64_t bestMaxPixels = 0;
   1036     HwcTestDim bestDim;
   1037     bool bestSet = false; // True when value has been assigned to
   1038                           // bestMaxPixels and bestDim;
   1039 
   1040     // Potentially increase benchmark performance by first checking
   1041     // for the common case of supporting the maximum checked source size
   1042     HwcTestDim dim = searchLimits.sourceCrop;
   1043     Rectangle rect(format, dfDim, searchLimits.sourceCrop);
   1044     list<Rectangle> rectList;
   1045     rectList.push_back(rect);
   1046     uint32_t num = numOverlays(rectList);
   1047     if (num == 1) { return dim; }
   1048 
   1049     // TODO: Use a binary search
   1050     bool origVerbose = verbose;  // Temporarily turn off verbose
   1051     verbose = false;
   1052     for (uint32_t w = dfDim.width();
   1053          w <= searchLimits.sourceCrop.width(); w++) {
   1054         for (uint32_t h = dfDim.height();
   1055              h <= searchLimits.sourceCrop.height(); h++) {
   1056             if (bestSet && ((w * h) <= bestMaxPixels)) { continue; }
   1057 
   1058             HwcTestDim dim(w, h);
   1059             Rectangle rect(format, dfDim, dim);
   1060             list<Rectangle> rectList;
   1061             rectList.push_back(rect);
   1062             uint32_t num = numOverlays(rectList);
   1063             if (num > 0) {
   1064                 uint64_t pixels = dim.width() * dim.height();
   1065                 if (!bestSet || (pixels > bestMaxPixels)) {
   1066                     bestMaxPixels = pixels;
   1067                     bestDim = dim;
   1068                     bestSet = true;
   1069                 }
   1070             }
   1071         }
   1072     }
   1073     verbose = origVerbose;
   1074 
   1075     if (!bestSet) {
   1076         testPrintE("Unable to locate source crop max dimension");
   1077         exit(21);
   1078     }
   1079 
   1080     return bestDim;
   1081 }
   1082 
   1083 // Source crop horizontal scale
   1084 // Determines the maximum factor by which the source crop can be larger
   1085 // that the display frame.  The commit point is discovered through a
   1086 // binary search of rational numbers.  The numerator in each of the
   1087 // rational numbers contains the dimension for the source crop, while
   1088 // the denominator specifies the dimension for the display frame.  On
   1089 // each pass of the binary search the mid-point between the greatest
   1090 // point committed to (best) and the smallest point in which a commit
   1091 // has failed is calculated.  This mid-point is then passed to a function
   1092 // named double2Rational, which determines the closest rational numbers
   1093 // just below and above the mid-point.  By default the lower rational
   1094 // number is used for the scale factor on the next pass of the binary
   1095 // search.  The upper value is only used when best is already equal
   1096 // to the lower value.  This only occurs when the lower value has already
   1097 // been tried.
   1098 Rational scHScale(uint32_t format,
   1099                       const HwcTestDim& dfMin, const HwcTestDim& dfMax,
   1100                       const HwcTestDim& scMin, const HwcTestDim& scMax,
   1101                       HwcTestDim& outBestDf, HwcTestDim& outBestSc)
   1102 {
   1103     HwcTestDim scDim, dfDim; // Source crop and display frame dimension
   1104     Rational best(0, 1), minBad;  // Current bounds for a binary search
   1105                                   // MinGood is set below the lowest
   1106                                   // possible scale.  The value of minBad,
   1107                                   // will be set by the first pass
   1108                                   // of the binary search.
   1109 
   1110     // Perform the passes of the binary search
   1111     bool firstPass = true;
   1112     do {
   1113         // On first pass try the maximum scale within the search limits
   1114         if (firstPass) {
   1115             // Try the maximum possible scale, within the search limits
   1116             scDim = HwcTestDim(searchLimits.sourceCrop.width(), scMin.height());
   1117             dfDim = dfMin;
   1118         } else {
   1119             // Subsequent pass
   1120             // Halve the difference between best and minBad.
   1121             Rational lower, upper, selected;
   1122 
   1123             // Try the closest ratio halfway between minBood and minBad;
   1124             // TODO: Avoid rounding issue by using Rational type for
   1125             //       midpoint.  For now will use double, which should
   1126             //       have more than sufficient resolution.
   1127             double mid = (double) best
   1128                          + ((double) minBad - (double) best) / 2.0;
   1129             Rational::double2Rational(mid,
   1130                             Range(scMin.width(), scMax.width()),
   1131                             Range(dfMin.width(), dfMax.width()),
   1132                             lower, upper);
   1133             if (((lower == best) && (upper == minBad))) {
   1134                 return best;
   1135             }
   1136 
   1137             // Use lower value unless its already been tried
   1138             selected = (lower != best) ? lower : upper;
   1139 
   1140             // Assign the size of the source crop and display frame
   1141             // from the selected ratio of source crop to display frame.
   1142             scDim = HwcTestDim(selected.numerator(), scMin.height());
   1143             dfDim = HwcTestDim(selected.denominator(), dfMin.height());
   1144         }
   1145 
   1146         // See if the HWC will commit to this combination
   1147         Rectangle rect(format, dfDim, scDim);
   1148         list<Rectangle> rectList;
   1149         rectList.push_back(rect);
   1150         uint32_t num = numOverlays(rectList);
   1151 
   1152         if (verbose) {
   1153             testPrintI("  scHscale num: %u scale: %f dfDim: %s scDim: %s",
   1154                        num, (float) Rational(scDim.width(), dfDim.width()),
   1155                        ((string) dfDim).c_str(), ((string) scDim).c_str());
   1156         }
   1157         if (num == 1) {
   1158             // HWC committed to the combination
   1159             // This is the best scale factor seen so far.  Report the
   1160             // dimensions to the caller, in case nothing better is seen.
   1161             outBestDf = dfDim;
   1162             outBestSc = scDim;
   1163 
   1164             // Success on the first pass means the largest possible scale
   1165             // is supported, in which case no need to search any further.
   1166             if (firstPass) { return Rational(scDim.width(), dfDim.width()); }
   1167 
   1168             // Update the lower bound of the binary search
   1169             best = Rational(scDim.width(), dfDim.width());
   1170         } else {
   1171             // HWC didn't commit to this combination, so update the
   1172             // upper bound of the binary search.
   1173             minBad = Rational(scDim.width(), dfDim.width());
   1174         }
   1175 
   1176         firstPass = false;
   1177     } while (best != minBad);
   1178 
   1179     return best;
   1180 }
   1181 
   1182 // Source crop vertical scale
   1183 // Determines the maximum factor by which the source crop can be larger
   1184 // that the display frame.  The commit point is discovered through a
   1185 // binary search of rational numbers.  The numerator in each of the
   1186 // rational numbers contains the dimension for the source crop, while
   1187 // the denominator specifies the dimension for the display frame.  On
   1188 // each pass of the binary search the mid-point between the greatest
   1189 // point committed to (best) and the smallest point in which a commit
   1190 // has failed is calculated.  This mid-point is then passed to a function
   1191 // named double2Rational, which determines the closest rational numbers
   1192 // just below and above the mid-point.  By default the lower rational
   1193 // number is used for the scale factor on the next pass of the binary
   1194 // search.  The upper value is only used when best is already equal
   1195 // to the lower value.  This only occurs when the lower value has already
   1196 // been tried.
   1197 Rational scVScale(uint32_t format,
   1198                       const HwcTestDim& dfMin, const HwcTestDim& dfMax,
   1199                       const HwcTestDim& scMin, const HwcTestDim& scMax,
   1200                       HwcTestDim& outBestDf, HwcTestDim& outBestSc)
   1201 {
   1202     HwcTestDim scDim, dfDim; // Source crop and display frame dimension
   1203     Rational best(0, 1), minBad;  // Current bounds for a binary search
   1204                                   // MinGood is set below the lowest
   1205                                   // possible scale.  The value of minBad,
   1206                                   // will be set by the first pass
   1207                                   // of the binary search.
   1208 
   1209     // Perform the passes of the binary search
   1210     bool firstPass = true;
   1211     do {
   1212         // On first pass try the maximum scale within the search limits
   1213         if (firstPass) {
   1214             // Try the maximum possible scale, within the search limits
   1215             scDim = HwcTestDim(scMin.width(), searchLimits.sourceCrop.height());
   1216             dfDim = dfMin;
   1217         } else {
   1218             // Subsequent pass
   1219             // Halve the difference between best and minBad.
   1220             Rational lower, upper, selected;
   1221 
   1222             // Try the closest ratio halfway between minBood and minBad;
   1223             // TODO: Avoid rounding issue by using Rational type for
   1224             //       midpoint.  For now will use double, which should
   1225             //       have more than sufficient resolution.
   1226             double mid = (double) best
   1227                          + ((double) minBad - (double) best) / 2.0;
   1228             Rational::double2Rational(mid,
   1229                             Range(scMin.height(), scMax.height()),
   1230                             Range(dfMin.height(), dfMax.height()),
   1231                             lower, upper);
   1232             if (((lower == best) && (upper == minBad))) {
   1233                 return best;
   1234             }
   1235 
   1236             // Use lower value unless its already been tried
   1237             selected = (lower != best) ? lower : upper;
   1238 
   1239             // Assign the size of the source crop and display frame
   1240             // from the selected ratio of source crop to display frame.
   1241             scDim = HwcTestDim(scMin.width(), selected.numerator());
   1242             dfDim = HwcTestDim(dfMin.width(), selected.denominator());
   1243         }
   1244 
   1245         // See if the HWC will commit to this combination
   1246         Rectangle rect(format, dfDim, scDim);
   1247         list<Rectangle> rectList;
   1248         rectList.push_back(rect);
   1249         uint32_t num = numOverlays(rectList);
   1250 
   1251         if (verbose) {
   1252             testPrintI("  scHscale num: %u scale: %f dfDim: %s scDim: %s",
   1253                        num, (float) Rational(scDim.height(), dfDim.height()),
   1254                        ((string) dfDim).c_str(), ((string) scDim).c_str());
   1255         }
   1256         if (num == 1) {
   1257             // HWC committed to the combination
   1258             // This is the best scale factor seen so far.  Report the
   1259             // dimensions to the caller, in case nothing better is seen.
   1260             outBestDf = dfDim;
   1261             outBestSc = scDim;
   1262 
   1263             // Success on the first pass means the largest possible scale
   1264             // is supported, in which case no need to search any further.
   1265             if (firstPass) { return Rational(scDim.height(), dfDim.height()); }
   1266 
   1267             // Update the lower bound of the binary search
   1268             best = Rational(scDim.height(), dfDim.height());
   1269         } else {
   1270             // HWC didn't commit to this combination, so update the
   1271             // upper bound of the binary search.
   1272             minBad = Rational(scDim.height(), dfDim.height());
   1273         }
   1274 
   1275         firstPass = false;
   1276     } while (best != minBad);
   1277 
   1278     return best;
   1279 }
   1280 
   1281 uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
   1282                         uint32_t backgroundBlend, uint32_t foregroundBlend)
   1283 {
   1284     list<Rectangle> rectList;
   1285 
   1286     Rectangle background(backgroundFormat, startDim, startDim);
   1287     background.blend = backgroundBlend;
   1288     rectList.push_back(background);
   1289 
   1290     // TODO: Handle cases where startDim is so small that adding 5
   1291     //       causes frames not to overlap.
   1292     // TODO: Handle cases where startDim is so large that adding 5
   1293     //       cause a portion or all of the foreground displayFrame
   1294     //       to be off the display.
   1295     Rectangle foreground(foregroundFormat, startDim, startDim);
   1296     foreground.displayFrame.left += 5;
   1297     foreground.displayFrame.top += 5;
   1298     foreground.displayFrame.right += 5;
   1299     foreground.displayFrame.bottom += 5;
   1300     background.blend = foregroundBlend;
   1301     rectList.push_back(foreground);
   1302 
   1303     uint32_t num = numOverlays(rectList);
   1304 
   1305     return num;
   1306 }
   1307 
   1308 Rectangle::Rectangle(uint32_t graphicFormat, HwcTestDim dfDim,
   1309                      HwcTestDim sDim) :
   1310     format(graphicFormat), transform(defaultTransform),
   1311     blend(defaultBlend), color(defaultColor), alpha(defaultAlpha),
   1312     sourceCrop(sDim), displayFrame(dfDim)
   1313 {
   1314     // Set source dimension
   1315     // Can't use a base initializer, because the setting of format
   1316     // must be done before setting the sourceDimension.
   1317     setSourceDim(sDim);
   1318 }
   1319 
   1320 void Rectangle::setSourceDim(HwcTestDim dim)
   1321 {
   1322     this->sourceDim = dim;
   1323 
   1324     const struct hwcTestGraphicFormat *attrib;
   1325     attrib = hwcTestGraphicFormatLookup(this->format);
   1326     if (attrib != NULL) {
   1327         if (sourceDim.width() % attrib->wMod) {
   1328             sourceDim.setWidth(sourceDim.width() + attrib->wMod
   1329             - (sourceDim.width() % attrib->wMod));
   1330         }
   1331         if (sourceDim.height() % attrib->hMod) {
   1332             sourceDim.setHeight(sourceDim.height() + attrib->hMod
   1333             - (sourceDim.height() % attrib->hMod));
   1334         }
   1335     }
   1336 }
   1337 
   1338 // Rational member functions
   1339 bool Rational::operator==(const Rational& other) const
   1340 {
   1341     if (((uint64_t) _n * other._d)
   1342         == ((uint64_t) _d * other._n)) { return true; }
   1343 
   1344     return false;
   1345 }
   1346 
   1347 bool Rational::operator<(const Rational& other) const
   1348 {
   1349     if (((uint64_t) _n * other._d)
   1350         < ((uint64_t) _d * other._n)) { return true; }
   1351 
   1352     return false;
   1353 }
   1354 
   1355 Rational::operator string() const
   1356 {
   1357     ostringstream out;
   1358 
   1359     out << _n << '/' << _d;
   1360 
   1361     return out.str();
   1362 }
   1363 
   1364 void Rational::double2Rational(double f, Range nRange, Range dRange,
   1365                     Rational& lower, Rational& upper)
   1366 {
   1367     Rational bestLower(nRange.lower(), dRange.upper());
   1368     Rational bestUpper(nRange.upper(), dRange.lower());
   1369 
   1370     // Search for a better solution
   1371     for (uint32_t d = dRange.lower(); d <= dRange.upper(); d++) {
   1372         Rational val(d * f, d);  // Lower, because double to int cast truncates
   1373 
   1374         if ((val.numerator() < nRange.lower())
   1375             || (val.numerator() > nRange.upper())) { continue; }
   1376 
   1377         if (((double) val > (double) bestLower) && ((double) val <= f)) {
   1378             bestLower = val;
   1379         }
   1380 
   1381         val.setNumerator(val.numerator() + 1);
   1382         if (val.numerator() > nRange.upper()) { continue; }
   1383 
   1384         if (((double) val < (double) bestUpper) && ((double) val >= f)) {
   1385             bestUpper = val;
   1386         }
   1387     }
   1388 
   1389     lower = bestLower;
   1390     upper = bestUpper;
   1391 }
   1392 
   1393 // Local functions
   1394 
   1395 // Num Overlays
   1396 // Given a list of rectangles, determine how many HWC will commit to render
   1397 uint32_t numOverlays(list<Rectangle>& rectList)
   1398 {
   1399     hwc_display_contents_1_t *hwcList;
   1400     list<sp<GraphicBuffer> > buffers;
   1401 
   1402     hwcList = hwcTestCreateLayerList(rectList.size());
   1403     if (hwcList == NULL) {
   1404         testPrintE("numOverlays create hwcList failed");
   1405         exit(30);
   1406     }
   1407 
   1408     hwc_layer_1_t *layer = &hwcList->hwLayers[0];
   1409     for (std::list<Rectangle>::iterator it = rectList.begin();
   1410          it != rectList.end(); ++it, ++layer) {
   1411         // Allocate the texture for the source frame
   1412         // and push it onto the buffers list, so that it
   1413         // stays in scope until a return from this function.
   1414         sp<GraphicBuffer> texture;
   1415         texture  = new GraphicBuffer(it->sourceDim.width(),
   1416                                      it->sourceDim.height(),
   1417                                      it->format, texUsage);
   1418         buffers.push_back(texture);
   1419 
   1420         layer->handle = texture->handle;
   1421         layer->blending = it->blend;
   1422         layer->transform = it->transform;
   1423         layer->sourceCrop = it->sourceCrop;
   1424         layer->displayFrame = it->displayFrame;
   1425 
   1426         layer->visibleRegionScreen.numRects = 1;
   1427         layer->visibleRegionScreen.rects = &layer->displayFrame;
   1428     }
   1429 
   1430     // Perform prepare operation
   1431     if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(hwcList); }
   1432     hwcDevice->prepare(hwcDevice, 1, &hwcList);
   1433     if (verbose) {
   1434         testPrintI("Post Prepare:");
   1435         hwcTestDisplayListPrepareModifiable(hwcList);
   1436     }
   1437 
   1438     // Count the number of overlays
   1439     uint32_t total = 0;
   1440     for (unsigned int n1 = 0; n1 < hwcList->numHwLayers; n1++) {
   1441         if (hwcList->hwLayers[n1].compositionType == HWC_OVERLAY) {
   1442             total++;
   1443         }
   1444     }
   1445 
   1446     // Free the layer list and graphic buffers
   1447     hwcTestFreeLayerList(hwcList);
   1448 
   1449     return total;
   1450 }
   1451 
   1452 string transformList2str(const list<uint32_t>& transformList)
   1453 {
   1454     ostringstream out;
   1455 
   1456     for (list<uint32_t>::const_iterator it = transformList.begin();
   1457          it != transformList.end(); ++it) {
   1458         uint32_t id = *it;
   1459 
   1460         if (it != transformList.begin()) {
   1461             out << ", ";
   1462         }
   1463         out << id;
   1464 
   1465         for (unsigned int idx = 0; idx < NUMA(transformType); idx++) {
   1466             if (id == transformType[idx].id) {
   1467                 out << " (" << transformType[idx].desc << ')';
   1468                 break;
   1469             }
   1470         }
   1471     }
   1472 
   1473     return out.str();
   1474 }
   1475 
   1476 string blendList2str(const list<uint32_t>& blendList)
   1477 {
   1478     ostringstream out;
   1479 
   1480     for (list<uint32_t>::const_iterator it = blendList.begin();
   1481          it != blendList.end(); ++it) {
   1482         uint32_t id = *it;
   1483 
   1484         if (it != blendList.begin()) {
   1485             out << ", ";
   1486         }
   1487         out << id;
   1488 
   1489         for (unsigned int idx = 0; idx < NUMA(blendType); idx++) {
   1490             if (id == blendType[idx].id) {
   1491                 out << " (" << blendType[idx].desc << ')';
   1492                 break;
   1493             }
   1494         }
   1495     }
   1496 
   1497     return out.str();
   1498 }
   1499 
   1500 void init(void)
   1501 {
   1502     srand48(0);
   1503 
   1504     hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
   1505 
   1506     hwcTestOpenHwc(&hwcDevice);
   1507 }
   1508 
   1509 void printFormatHeadings(size_t indent)
   1510 {
   1511     for (size_t row = 0; row <= maxHeadingLen; row++) {
   1512         ostringstream line;
   1513         for(vector<string>::iterator it = formats.begin();
   1514             it != formats.end(); ++it) {
   1515             if ((maxHeadingLen - row) <= it->length()) {
   1516                 if (row != maxHeadingLen) {
   1517                     char ch = (*it)[it->length() - (maxHeadingLen - row)];
   1518                     line << ' ' << setw(printFieldWidth) << ch;
   1519                 } else {
   1520                     line << ' ' << string(printFieldWidth, '-');
   1521                 }
   1522             } else {
   1523                line << ' ' << setw(printFieldWidth) << "";
   1524             }
   1525         }
   1526         testPrintI("%*s%s", indent + maxHeadingLen, "",
   1527                    line.str().c_str());
   1528     }
   1529 }
   1530 
   1531 void printOverlapLine(size_t indent, const string formatStr,
   1532                         const vector<uint32_t>& results)
   1533 {
   1534     ostringstream line;
   1535 
   1536     line << setw(indent + maxHeadingLen - formatStr.length()) << "";
   1537 
   1538     line << formatStr;
   1539 
   1540     for (vector<uint32_t>::const_iterator it = results.begin();
   1541          it != results.end(); ++it) {
   1542         line << ' ' << setw(printFieldWidth) << *it;
   1543     }
   1544 
   1545     testPrintI("%s", line.str().c_str());
   1546 }
   1547 
   1548 void printSyntax(const char *cmd)
   1549 {
   1550     testPrintE("  %s [options] [graphicFormat] ...",
   1551                cmd);
   1552     testPrintE("    options:");
   1553     testPrintE("      -s [width, height] - start dimension");
   1554     testPrintE("      -v - Verbose");
   1555     testPrintE("");
   1556     testPrintE("    graphic formats:");
   1557     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
   1558         testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
   1559     }
   1560 }
   1561