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