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