blob: 66ccdae709d9c038145e0da22fc981533e7640a3 [file] [log] [blame]
Louis Huemiller585cd4f2011-01-09 10:59:31 -08001/*
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>
Louis Huemiller35ad62762011-01-10 17:21:15 -080079#include <iomanip>
Louis Huemiller585cd4f2011-01-09 10:59:31 -080080#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
112using namespace std;
113using namespace android;
114
115// Defaults
116const HwcTestDim defaultStartDim = HwcTestDim(100, 100);
117const bool defaultVerbose = false;
118
119const uint32_t defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
120const int32_t defaultTransform = 0;
121const uint32_t defaultBlend = HWC_BLENDING_NONE;
122const ColorFract defaultColor(0.5, 0.5, 0.5);
123const float defaultAlpha = 1.0; // Opaque
124const HwcTestDim defaultSourceDim(1, 1);
125const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
126const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
127
128// Global Constants
Louis Huemiller35ad62762011-01-10 17:21:15 -0800129const uint32_t printFieldWidth = 2;
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800130const struct searchLimits {
131 uint32_t numOverlays;
132 HwcTestDim sourceCrop;
133} searchLimits = {
134 10,
135 HwcTestDim(3000, 2000),
136};
137const 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};
147const 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
165class Rectangle {
166public:
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
182class Range {
183public:
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
191private:
192 uint32_t _l; // lower
193 uint32_t _u; // upper
194};
195
196Range::operator string()
197{
198 ostringstream out;
199
200 out << '[' << _l << ", " << _u << ']';
201
202 return out.str();
203}
204
205class Rational {
206public:
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
226private:
227 uint32_t _n;
228 uint32_t _d;
229};
230
231// Globals
232static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
233 GraphicBuffer::USAGE_SW_WRITE_RARELY;
234static hwc_composer_device_t *hwcDevice;
235static EGLDisplay dpy;
236static EGLSurface surface;
237static EGLint width, height;
Louis Huemiller35ad62762011-01-10 17:21:15 -0800238static size_t maxHeadingLen;
239static vector<string> formats;
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800240
241// Measurements
242struct 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;
Louis Huemiller35ad62762011-01-10 17:21:15 -0800271 vector<uint32_t> overlapBlendNone;
272 vector<uint32_t> overlapBlendPremult;
273 vector<uint32_t> overlapBlendCoverage;
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800274};
275vector<meas> measurements;
276
277// Function prototypes
278uint32_t numOverlays(list<Rectangle>& rectList);
279uint32_t maxOverlays(uint32_t format, bool allowOverlap);
280list<uint32_t> supportedTransforms(uint32_t format);
281list<uint32_t> supportedBlends(uint32_t format);
282uint32_t dfMinWidth(uint32_t format);
283uint32_t dfMinHeight(uint32_t format);
284uint32_t dfMaxWidth(uint32_t format);
285uint32_t dfMaxHeight(uint32_t format);
286HwcTestDim dfMinDim(uint32_t format);
287HwcTestDim dfMaxDim(uint32_t format);
288uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim);
289uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim);
290uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim);
291uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim);
292HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim);
293HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim);
294Rational scHScale(uint32_t format,
295 const HwcTestDim& dfMin, const HwcTestDim& dfMax,
296 const HwcTestDim& scMin, const HwcTestDim& scMax,
297 HwcTestDim& outBestDf, HwcTestDim& outBestSc);
298Rational scVScale(uint32_t format,
299 const HwcTestDim& dfMin, const HwcTestDim& dfMax,
300 const HwcTestDim& scMin, const HwcTestDim& scMax,
301 HwcTestDim& outBestDf, HwcTestDim& outBestSc);
Louis Huemiller35ad62762011-01-10 17:21:15 -0800302uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
303 uint32_t backgroundBlend, uint32_t foregroundBlend);
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800304string transformList2str(const list<uint32_t>& transformList);
305string blendList2str(const list<uint32_t>& blendList);
306void init(void);
Louis Huemiller35ad62762011-01-10 17:21:15 -0800307void printFormatHeadings(size_t indent);
308void printOverlapLine(size_t indent, const string formatStr,
309 const vector<uint32_t>& results);
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800310void printSyntax(const char *cmd);
311
312// Command-line option settings
313static bool verbose = defaultVerbose;
314static 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 */
339int
340main(int argc, char *argv[])
341{
342 int rv, opt;
343 char *chptr;
344 bool error;
345 string str;
346 char cmd[MAXCMD];
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800347 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
Louis Huemiller35ad62762011-01-10 17:21:15 -0800409 // 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
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800416 // 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
Louis Huemiller35ad62762011-01-10 17:21:15 -0800432 for (vector<string>::iterator itFormat = formats.begin();
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800433 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
Louis Huemiller35ad62762011-01-10 17:21:15 -0800560 // 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
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800589 }
590
Louis Huemiller35ad62762011-01-10 17:21:15 -0800591 // 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
Louis Huemiller585cd4f2011-01-09 10:59:31 -0800620 // 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.
639uint32_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
675list<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
700list<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.
725uint32_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
749uint32_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
773uint32_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
797uint32_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.
822HwcTestDim 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
863HwcTestDim 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
912uint32_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
932uint32_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
951uint32_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
970uint32_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.
994HwcTestDim 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
1035HwcTestDim 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.
1100Rational 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.
1199Rational 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
Louis Huemiller35ad62762011-01-10 17:21:15 -08001283uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
1284 uint32_t backgroundBlend, uint32_t foregroundBlend)
1285{
1286 list<Rectangle> rectList;
Louis Huemiller67669362011-01-10 18:03:05 -08001287
Louis Huemiller35ad62762011-01-10 17:21:15 -08001288 Rectangle background(backgroundFormat, startDim, startDim);
Louis Huemiller67669362011-01-10 18:03:05 -08001289 background.blend = backgroundBlend;
1290 rectList.push_back(background);
Louis Huemiller35ad62762011-01-10 17:21:15 -08001291
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.
Louis Huemiller67669362011-01-10 18:03:05 -08001297 Rectangle foreground(foregroundFormat, startDim, startDim);
Louis Huemiller35ad62762011-01-10 17:21:15 -08001298 foreground.displayFrame.left += 5;
1299 foreground.displayFrame.top += 5;
1300 foreground.displayFrame.right += 5;
1301 foreground.displayFrame.bottom += 5;
Louis Huemiller67669362011-01-10 18:03:05 -08001302 background.blend = foregroundBlend;
Louis Huemiller35ad62762011-01-10 17:21:15 -08001303 rectList.push_back(foreground);
Louis Huemiller67669362011-01-10 18:03:05 -08001304
Louis Huemiller35ad62762011-01-10 17:21:15 -08001305 uint32_t num = numOverlays(rectList);
1306
1307 return num;
1308}
1309
Louis Huemiller585cd4f2011-01-09 10:59:31 -08001310Rectangle::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
1322void 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
1341bool 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
1349bool 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
1357Rational::operator string() const
1358{
1359 ostringstream out;
1360
1361 out << _n << '/' << _d;
1362
1363 return out.str();
1364}
1365
1366void 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
1399uint32_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
1454string 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
1478string 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
1502void init(void)
1503{
1504 srand48(0);
1505
1506 hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
1507
1508 hwcTestOpenHwc(&hwcDevice);
1509}
1510
Louis Huemiller35ad62762011-01-10 17:21:15 -08001511void 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
1533void 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
Louis Huemiller585cd4f2011-01-09 10:59:31 -08001550void 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}