hwcCommit.cpp 53 KB

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