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