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