blob: 580eb830cd6ddc2fc46dff59173b008f83a92e10 [file] [log] [blame]
Louis Huemiller365b2c62010-11-22 18:05:30 -08001/*
2 * Copyright (C) 2010 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 stress test
20 *
21 * Performs a pseudo-random (prandom) sequence of operations to the
22 * Hardware Composer (HWC), for a specified number of passes or for
23 * a specified period of time. By default the period of time is FLT_MAX,
24 * so that the number of passes will take precedence.
25 *
26 * The passes are grouped together, where (pass / passesPerGroup) specifies
27 * which group a particular pass is in. This causes every passesPerGroup
28 * worth of sequential passes to be within the same group. Computationally
29 * intensive operations are performed just once at the beginning of a group
30 * of passes and then used by all the passes in that group. This is done
31 * so as to increase both the average and peak rate of graphic operations,
32 * by moving computationally intensive operations to the beginning of a group.
33 * In particular, at the start of each group of passes a set of
34 * graphic buffers are created, then used by the first and remaining
35 * passes of that group of passes.
36 *
37 * The per-group initialization of the graphic buffers is performed
38 * by a function called initFrames. This function creates an array
39 * of smart pointers to the graphic buffers, in the form of a vector
40 * of vectors. The array is accessed in row major order, so each
41 * row is a vector of smart pointers. All the pointers of a single
42 * row point to graphic buffers which use the same pixel format and
43 * have the same dimension, although it is likely that each one is
44 * filled with a different color. This is done so that after doing
45 * the first HWC prepare then set call, subsequent set calls can
46 * be made with each of the layer handles changed to a different
47 * graphic buffer within the same row. Since the graphic buffers
48 * in a particular row have the same pixel format and dimension,
49 * additional HWC set calls can be made, without having to perform
50 * an HWC prepare call.
51 *
52 * This test supports the following command-line options:
53 *
54 * -v Verbose
55 * -s num Starting pass
56 * -e num Ending pass
57 * -p num Execute the single pass specified by num
58 * -n num Number of set operations to perform after each prepare operation
59 * -t float Maximum time in seconds to execute the test
60 * -d float Delay in seconds performed after each set operation
61 * -D float Delay in seconds performed after the last pass is executed
62 *
63 * Typically the test is executed for a large range of passes. By default
64 * passes 0 through 99999 (100,000 passes) are executed. Although this test
65 * does not validate the generated image, at times it is useful to reexecute
66 * a particular pass and leave the displayed image on the screen for an
67 * extended period of time. This can be done either by setting the -s
68 * and -e options to the desired pass, along with a large value for -D.
69 * This can also be done via the -p option, again with a large value for
70 * the -D options.
71 *
72 * So far this test only contains code to create graphic buffers with
73 * a continuous solid color. Although this test is unable to validate the
74 * image produced, any image that contains other than rectangles of a solid
75 * color are incorrect. Note that the rectangles may use a transparent
76 * color and have a blending operation that causes the color in overlapping
77 * rectangles to be mixed. In such cases the overlapping portions may have
78 * a different color from the rest of the rectangle.
79 */
80
81#include <algorithm>
82#include <assert.h>
83#include <cerrno>
84#include <cmath>
85#include <cstdlib>
86#include <ctime>
87#include <libgen.h>
88#include <sched.h>
89#include <sstream>
90#include <stdint.h>
91#include <string.h>
92#include <unistd.h>
93#include <vector>
94
95#include <arpa/inet.h> // For ntohl() and htonl()
96
97#include <sys/syscall.h>
98#include <sys/types.h>
99#include <sys/wait.h>
100
101#include <EGL/egl.h>
102#include <EGL/eglext.h>
103#include <GLES2/gl2.h>
104#include <GLES2/gl2ext.h>
105
106#include <ui/FramebufferNativeWindow.h>
107#include <ui/GraphicBuffer.h>
108#include <ui/EGLUtils.h>
109
110#define LOG_TAG "hwcStressTest"
111#include <utils/Log.h>
112#include <testUtil.h>
113
114#include <hardware/hwcomposer.h>
115
116using namespace std;
117using namespace android;
118
119const float maxSizeRatio = 1.3; // Graphic buffers can be upto this munch
120 // larger than the default screen size
121const unsigned int passesPerGroup = 10; // A group of passes all use the same
122 // graphic buffers
Louis Huemillerb5265942010-12-12 23:05:31 -0800123
124// Ratios at which rare and frequent conditions should be produced
125const float rareRatio = 0.1;
126const float freqRatio = 0.9;
Louis Huemiller365b2c62010-11-22 18:05:30 -0800127
128// Defaults for command-line options
129const bool defaultVerbose = false;
130const unsigned int defaultStartPass = 0;
131const unsigned int defaultEndPass = 99999;
132const unsigned int defaultPerPassNumSet = 10;
Louis Huemillerb5265942010-12-12 23:05:31 -0800133const float defaultPerSetDelay = 0.0; // Default delay after each set
134 // operation. Default delay of
135 // zero used so as to perform the
136 // the set operations as quickly
137 // as possible.
Louis Huemiller365b2c62010-11-22 18:05:30 -0800138const float defaultEndDelay = 2.0; // Default delay between completion of
139 // final pass and restart of framework
140const float defaultDuration = FLT_MAX; // A fairly long time, so that
141 // range of passes will have
142 // precedence
143
144// Command-line option settings
145static bool verbose = defaultVerbose;
146static unsigned int startPass = defaultStartPass;
147static unsigned int endPass = defaultEndPass;
148static unsigned int numSet = defaultPerPassNumSet;
Louis Huemillerb5265942010-12-12 23:05:31 -0800149static float perSetDelay = defaultPerSetDelay;
Louis Huemiller365b2c62010-11-22 18:05:30 -0800150static float endDelay = defaultEndDelay;
151static float duration = defaultDuration;
152
153// Command-line mutual exclusion detection flags.
154// Corresponding flag set true once an option is used.
155bool eFlag, sFlag, pFlag;
156
157#define MAXSTR 100
158#define MAXCMD 200
159#define BITSPERBYTE 8 // TODO: Obtain from <values.h>, once
160 // it has been added
161
162#define CMD_STOP_FRAMEWORK "stop 2>&1"
163#define CMD_START_FRAMEWORK "start 2>&1"
164
165#define NUMA(a) (sizeof(a) / sizeof(a [0]))
166#define MEMCLR(addr, size) do { \
167 memset((addr), 0, (size)); \
168 } while (0)
169
170// Represent RGB color as fraction of color components.
171// Each of the color components are expected in the range [0.0, 1.0]
172class RGBColor {
173 public:
174 RGBColor(): _r(0.0), _g(0.0), _b(0.0) {};
175 RGBColor(float f): _r(f), _g(f), _b(f) {}; // Gray
176 RGBColor(float r, float g, float b): _r(r), _g(g), _b(b) {};
177 float r(void) const { return _r; }
178 float g(void) const { return _g; }
179 float b(void) const { return _b; }
180
181 private:
182 float _r;
183 float _g;
184 float _b;
185};
186
187// Represent YUV color as fraction of color components.
188// Each of the color components are expected in the range [0.0, 1.0]
189class YUVColor {
190 public:
191 YUVColor(): _y(0.0), _u(0.0), _v(0.0) {};
192 YUVColor(float f): _y(f), _u(0.0), _v(0.0) {}; // Gray
193 YUVColor(float y, float u, float v): _y(y), _u(u), _v(v) {};
194 float y(void) const { return _y; }
195 float u(void) const { return _u; }
196 float v(void) const { return _v; }
197
198 private:
199 float _y;
200 float _u;
201 float _v;
202};
203
204// File scope constants
Louis Huemiller5d86b532010-12-14 10:22:42 -0800205static const struct graphicFormat {
Louis Huemiller365b2c62010-11-22 18:05:30 -0800206 unsigned int format;
207 const char *desc;
Louis Huemiller5d86b532010-12-14 10:22:42 -0800208 unsigned int wMod, hMod; // Width/height mod this value must equal zero
Louis Huemiller365b2c62010-11-22 18:05:30 -0800209} graphicFormat[] = {
Louis Huemiller5d86b532010-12-14 10:22:42 -0800210 {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
211 {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
212 {HAL_PIXEL_FORMAT_RGB_888, "RGB888", 1, 1},
213 {HAL_PIXEL_FORMAT_RGB_565, "RGB565", 1, 1},
214 {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
215 {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
216 {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
217 {HAL_PIXEL_FORMAT_YV12, "YV12", 2, 2},
Louis Huemiller365b2c62010-11-22 18:05:30 -0800218};
219const unsigned int blendingOps[] = {
220 HWC_BLENDING_NONE,
221 HWC_BLENDING_PREMULT,
222 HWC_BLENDING_COVERAGE,
223};
224const unsigned int layerFlags[] = {
225 HWC_SKIP_LAYER,
226};
227const vector<unsigned int> vecLayerFlags(layerFlags,
228 layerFlags + NUMA(layerFlags));
229
230const unsigned int transformFlags[] = {
231 HWC_TRANSFORM_FLIP_H,
232 HWC_TRANSFORM_FLIP_V,
233 HWC_TRANSFORM_ROT_90,
234 // ROT_180 & ROT_270 intentionally not listed, because they
235 // they are formed from combinations of the flags already listed.
236};
237const vector<unsigned int> vecTransformFlags(transformFlags,
238 transformFlags + NUMA(transformFlags));
239
240// File scope globals
241static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
242 GraphicBuffer::USAGE_SW_WRITE_RARELY;
243static hw_module_t const *hwcModule;
244static hwc_composer_device_t *hwcDevice;
245static vector <vector <sp<GraphicBuffer> > > frames;
246static EGLDisplay dpy;
247static EGLContext context;
248static EGLSurface surface;
249static EGLint width, height;
250
251// File scope prototypes
252static void execCmd(const char *cmd);
253static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
254static void checkGlError(const char* op);
255static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
256static void printGLString(const char *name, GLenum s);
257static hwc_layer_list_t *createLayerList(size_t numLayers);
258static void freeLayerList(hwc_layer_list_t *list);
259static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans);
260static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans);
261void init(void);
262void initFrames(unsigned int seed);
263void displayList(hwc_layer_list_t *list);
264void displayListPrepareModifiable(hwc_layer_list_t *list);
265void displayListHandles(hwc_layer_list_t *list);
266const char *graphicFormat2str(unsigned int format);
267template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num);
268template <class T> T vectorOr(const vector<T>& vec);
269
270/*
271 * Main
272 *
273 * Performs the following high-level sequence of operations:
274 *
275 * 1. Command-line parsing
276 *
277 * 2. Initialization
278 *
279 * 3. For each pass:
280 *
281 * a. If pass is first pass or in a different group from the
282 * previous pass, initialize the array of graphic buffers.
283 *
284 * b. Create a HWC list with room to specify a prandomly
285 * selected number of layers.
286 *
287 * c. Select a subset of the rows from the graphic buffer array,
288 * such that there is a unique row to be used for each
289 * of the layers in the HWC list.
290 *
291 * d. Prandomly fill in the HWC list with handles
292 * selected from any of the columns of the selected row.
293 *
294 * e. Pass the populated list to the HWC prepare call.
295 *
296 * f. Pass the populated list to the HWC set call.
297 *
298 * g. If additional set calls are to be made, then for each
299 * additional set call, select a new set of handles and
300 * perform the set call.
301 */
302int
303main(int argc, char *argv[])
304{
305 int rv, opt;
306 char *chptr;
307 unsigned int pass;
308 char cmd[MAXCMD];
309 struct timeval startTime, currentTime, delta;
310
311 testSetLogCatTag(LOG_TAG);
312
313 // Parse command line arguments
314 while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) {
315 switch (opt) {
316 case 'd': // Delay after each set operation
317 perSetDelay = strtod(optarg, &chptr);
318 if ((*chptr != '\0') || (perSetDelay < 0.0)) {
319 testPrintE("Invalid command-line specified per pass delay of: "
320 "%s", optarg);
321 exit(1);
322 }
323 break;
324
325 case 'D': // End of test delay
326 // Delay between completion of final pass and restart
327 // of framework
328 endDelay = strtod(optarg, &chptr);
329 if ((*chptr != '\0') || (endDelay < 0.0)) {
330 testPrintE("Invalid command-line specified end of test delay "
331 "of: %s", optarg);
332 exit(2);
333 }
334 break;
335
336 case 't': // Duration
337 duration = strtod(optarg, &chptr);
338 if ((*chptr != '\0') || (duration < 0.0)) {
339 testPrintE("Invalid command-line specified duration of: %s",
340 optarg);
341 exit(3);
342 }
343 break;
344
345 case 'n': // Num set operations per pass
346 numSet = strtoul(optarg, &chptr, 10);
347 if (*chptr != '\0') {
348 testPrintE("Invalid command-line specified num set per pass "
349 "of: %s", optarg);
350 exit(4);
351 }
352 break;
353
354 case 's': // Starting Pass
355 sFlag = true;
356 if (pFlag) {
357 testPrintE("Invalid combination of command-line options.");
358 testPrintE(" The -p option is mutually exclusive from the");
359 testPrintE(" -s and -e options.");
360 exit(5);
361 }
362 startPass = strtoul(optarg, &chptr, 10);
363 if (*chptr != '\0') {
364 testPrintE("Invalid command-line specified starting pass "
365 "of: %s", optarg);
366 exit(6);
367 }
368 break;
369
370 case 'e': // Ending Pass
371 eFlag = true;
372 if (pFlag) {
373 testPrintE("Invalid combination of command-line options.");
374 testPrintE(" The -p option is mutually exclusive from the");
375 testPrintE(" -s and -e options.");
376 exit(7);
377 }
378 endPass = strtoul(optarg, &chptr, 10);
379 if (*chptr != '\0') {
380 testPrintE("Invalid command-line specified ending pass "
381 "of: %s", optarg);
382 exit(8);
383 }
384 break;
385
386 case 'p': // Run a single specified pass
387 pFlag = true;
388 if (sFlag || eFlag) {
389 testPrintE("Invalid combination of command-line options.");
390 testPrintE(" The -p option is mutually exclusive from the");
391 testPrintE(" -s and -e options.");
392 exit(9);
393 }
394 startPass = endPass = strtoul(optarg, &chptr, 10);
395 if (*chptr != '\0') {
396 testPrintE("Invalid command-line specified pass of: %s",
397 optarg);
398 exit(10);
399 }
400 break;
401
402 case 'v': // Verbose
403 verbose = true;
404 break;
405
406 case 'h': // Help
407 case '?':
408 default:
409 testPrintE(" %s [options]", basename(argv[0]));
410 testPrintE(" options:");
411 testPrintE(" -p Execute specified pass");
412 testPrintE(" -s Starting pass");
413 testPrintE(" -e Ending pass");
414 testPrintE(" -t Duration");
415 testPrintE(" -d Delay after each set operation");
416 testPrintE(" -D End of test delay");
417 testPrintE(" -n Num set operations per pass");
418 testPrintE(" -v Verbose");
419 exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
420 }
421 }
422 if (endPass < startPass) {
423 testPrintE("Unexpected ending pass before starting pass");
424 testPrintE(" startPass: %u endPass: %u", startPass, endPass);
425 exit(12);
426 }
427 if (argc != optind) {
428 testPrintE("Unexpected command-line postional argument");
429 testPrintE(" %s [-s start_pass] [-e end_pass] [-t duration]",
430 basename(argv[0]));
431 exit(13);
432 }
433 testPrintI("duration: %g", duration);
434 testPrintI("startPass: %u", startPass);
435 testPrintI("endPass: %u", endPass);
436 testPrintI("numSet: %u", numSet);
437
438 // Stop framework
439 rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
440 if (rv >= (signed) sizeof(cmd) - 1) {
441 testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
442 exit(14);
443 }
444 execCmd(cmd);
445 testDelay(1.0); // TODO - needs means to query whether asyncronous stop
446 // framework operation has completed. For now, just wait
447 // a long time.
448
449 init();
450
451 // For each pass
452 gettimeofday(&startTime, NULL);
453 for (pass = startPass; pass <= endPass; pass++) {
454 // Stop if duration of work has already been performed
455 gettimeofday(&currentTime, NULL);
456 delta = tvDelta(&startTime, &currentTime);
457 if (tv2double(&delta) > duration) { break; }
458
459 // Regenerate a new set of test frames when this pass is
460 // either the first pass or is in a different group then
461 // the previous pass. A group of passes are passes that
462 // all have the same quotient when their pass number is
463 // divided by passesPerGroup.
464 if ((pass == startPass)
465 || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) {
466 initFrames(pass / passesPerGroup);
467 }
468
469 testPrintI("==== Starting pass: %u", pass);
470
471 // Cause deterministic sequence of prandom numbers to be
472 // generated for this pass.
473 srand48(pass);
474
475 hwc_layer_list_t *list;
476 list = createLayerList(testRandMod(frames.size()) + 1);
477 if (list == NULL) {
478 testPrintE("createLayerList failed");
479 exit(20);
480 }
481
Louis Huemiller5d86b532010-12-14 10:22:42 -0800482 // Prandomly select a subset of frames to be used by this pass.
Louis Huemiller365b2c62010-11-22 18:05:30 -0800483 vector <vector <sp<GraphicBuffer> > > selectedFrames;
484 selectedFrames = vectorRandSelect(frames, list->numHwLayers);
485
486 // Any transform tends to create a layer that the hardware
487 // composer is unable to support and thus has to leave for
488 // SurfaceFlinger. Place heavy bias on specifying no transforms.
489 bool noTransform = testRandFract() > rareRatio;
490
491 for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
492 unsigned int idx = testRandMod(selectedFrames[n1].size());
493 sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
494 hwc_layer_t *layer = &list->hwLayers[n1];
495 layer->handle = gBuf->handle;
496
497 layer->blending = blendingOps[testRandMod(NUMA(blendingOps))];
498 layer->flags = (testRandFract() > rareRatio) ? 0
499 : vectorOr(vectorRandSelect(vecLayerFlags,
500 testRandMod(vecLayerFlags.size() + 1)));
501 layer->transform = (noTransform || testRandFract() > rareRatio) ? 0
502 : vectorOr(vectorRandSelect(vecTransformFlags,
503 testRandMod(vecTransformFlags.size() + 1)));
504 layer->sourceCrop.left = testRandMod(gBuf->getWidth());
505 layer->sourceCrop.top = testRandMod(gBuf->getHeight());
506 layer->sourceCrop.right = layer->sourceCrop.left
507 + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1;
508 layer->sourceCrop.bottom = layer->sourceCrop.top
509 + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1;
510 layer->displayFrame.left = testRandMod(width);
511 layer->displayFrame.top = testRandMod(height);
512 layer->displayFrame.right = layer->displayFrame.left
513 + testRandMod(width - layer->displayFrame.left) + 1;
514 layer->displayFrame.bottom = layer->displayFrame.top
515 + testRandMod(height - layer->displayFrame.top) + 1;
Louis Huemillerb5265942010-12-12 23:05:31 -0800516
517 // Increase the frequency that a scale factor of 1.0 from
518 // the sourceCrop to displayFrame occurs. This is the
519 // most common scale factor used by applications and would
520 // be rarely produced by this stress test without this
521 // logic.
522 if (testRandFract() <= freqRatio) {
523 // Only change to scale factor to 1.0 if both the
524 // width and height will fit.
525 int sourceWidth = layer->sourceCrop.right
526 - layer->sourceCrop.left;
527 int sourceHeight = layer->sourceCrop.bottom
528 - layer->sourceCrop.top;
529 if (((layer->displayFrame.left + sourceWidth) <= width)
530 && ((layer->displayFrame.top + sourceHeight) <= height)) {
531 layer->displayFrame.right = layer->displayFrame.left
532 + sourceWidth;
533 layer->displayFrame.bottom = layer->displayFrame.top
534 + sourceHeight;
535 }
536 }
537
Louis Huemiller365b2c62010-11-22 18:05:30 -0800538 layer->visibleRegionScreen.numRects = 1;
539 layer->visibleRegionScreen.rects = &layer->displayFrame;
540 }
541
542 // Perform prepare operation
543 if (verbose) { testPrintI("Prepare:"); displayList(list); }
544 hwcDevice->prepare(hwcDevice, list);
545 if (verbose) {
546 testPrintI("Post Prepare:");
547 displayListPrepareModifiable(list);
548 }
549
550 // Turn off the geometry changed flag
551 list->flags &= ~HWC_GEOMETRY_CHANGED;
552
553 // Perform the set operation(s)
554 if (verbose) {testPrintI("Set:"); }
555 for (unsigned int n1 = 0; n1 < numSet; n1++) {
556 if (verbose) {displayListHandles(list); }
557 hwcDevice->set(hwcDevice, dpy, surface, list);
558
559 // Prandomly select a new set of handles
560 for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
561 unsigned int idx = testRandMod(selectedFrames[n1].size());
562 sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
563 hwc_layer_t *layer = &list->hwLayers[n1];
564 layer->handle = (native_handle_t *) gBuf->handle;
565 }
566
567 testDelay(perSetDelay);
568 }
569
570
571 freeLayerList(list);
572 testPrintI("==== Completed pass: %u", pass);
573 }
574
575 testDelay(endDelay);
576
577 // Start framework
578 rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
579 if (rv >= (signed) sizeof(cmd) - 1) {
580 testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
581 exit(21);
582 }
583 execCmd(cmd);
584
585 testPrintI("Successfully completed %u passes", pass - startPass);
586
587 return 0;
588}
589
590/*
591 * Execute Command
592 *
593 * Executes the command pointed to by cmd. Output from the
594 * executed command is captured and sent to LogCat Info. Once
595 * the command has finished execution, it's exit status is captured
596 * and checked for an exit status of zero. Any other exit status
597 * causes diagnostic information to be printed and an immediate
598 * testcase failure.
599 */
600static void execCmd(const char *cmd)
601{
602 FILE *fp;
603 int rv;
604 int status;
605 char str[MAXSTR];
606
607 // Display command to be executed
608 testPrintI("cmd: %s", cmd);
609
610 // Execute the command
611 fflush(stdout);
612 if ((fp = popen(cmd, "r")) == NULL) {
613 testPrintE("execCmd popen failed, errno: %i", errno);
614 exit(30);
615 }
616
617 // Obtain and display each line of output from the executed command
618 while (fgets(str, sizeof(str), fp) != NULL) {
619 if ((strlen(str) > 1) && (str[strlen(str) - 1] == '\n')) {
620 str[strlen(str) - 1] = '\0';
621 }
622 testPrintI(" out: %s", str);
623 }
624
625 // Obtain and check return status of executed command.
626 // Fail on non-zero exit status
627 status = pclose(fp);
628 if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
629 testPrintE("Unexpected command failure");
630 testPrintE(" status: %#x", status);
631 if (WIFEXITED(status)) {
632 testPrintE("WEXITSTATUS: %i", WEXITSTATUS(status));
633 }
634 if (WIFSIGNALED(status)) {
635 testPrintE("WTERMSIG: %i", WTERMSIG(status));
636 }
637 exit(31);
638 }
639}
640
641static void checkEglError(const char* op, EGLBoolean returnVal) {
642 if (returnVal != EGL_TRUE) {
643 testPrintE("%s() returned %d", op, returnVal);
644 }
645
646 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
647 = eglGetError()) {
648 testPrintE("after %s() eglError %s (0x%x)",
649 op, EGLUtils::strerror(error), error);
650 }
651}
652
653static void checkGlError(const char* op) {
654 for (GLint error = glGetError(); error; error
655 = glGetError()) {
656 testPrintE("after %s() glError (0x%x)", op, error);
657 }
658}
659
660static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
661
662#define X(VAL) {VAL, #VAL}
663 struct {EGLint attribute; const char* name;} names[] = {
664 X(EGL_BUFFER_SIZE),
665 X(EGL_ALPHA_SIZE),
666 X(EGL_BLUE_SIZE),
667 X(EGL_GREEN_SIZE),
668 X(EGL_RED_SIZE),
669 X(EGL_DEPTH_SIZE),
670 X(EGL_STENCIL_SIZE),
671 X(EGL_CONFIG_CAVEAT),
672 X(EGL_CONFIG_ID),
673 X(EGL_LEVEL),
674 X(EGL_MAX_PBUFFER_HEIGHT),
675 X(EGL_MAX_PBUFFER_PIXELS),
676 X(EGL_MAX_PBUFFER_WIDTH),
677 X(EGL_NATIVE_RENDERABLE),
678 X(EGL_NATIVE_VISUAL_ID),
679 X(EGL_NATIVE_VISUAL_TYPE),
680 X(EGL_SAMPLES),
681 X(EGL_SAMPLE_BUFFERS),
682 X(EGL_SURFACE_TYPE),
683 X(EGL_TRANSPARENT_TYPE),
684 X(EGL_TRANSPARENT_RED_VALUE),
685 X(EGL_TRANSPARENT_GREEN_VALUE),
686 X(EGL_TRANSPARENT_BLUE_VALUE),
687 X(EGL_BIND_TO_TEXTURE_RGB),
688 X(EGL_BIND_TO_TEXTURE_RGBA),
689 X(EGL_MIN_SWAP_INTERVAL),
690 X(EGL_MAX_SWAP_INTERVAL),
691 X(EGL_LUMINANCE_SIZE),
692 X(EGL_ALPHA_MASK_SIZE),
693 X(EGL_COLOR_BUFFER_TYPE),
694 X(EGL_RENDERABLE_TYPE),
695 X(EGL_CONFORMANT),
696 };
697#undef X
698
699 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
700 EGLint value = -1;
701 EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
702 EGLint error = eglGetError();
703 if (returnVal && error == EGL_SUCCESS) {
704 testPrintI(" %s: %d (%#x)", names[j].name, value, value);
705 }
706 }
707 testPrintI("");
708}
709
710static void printGLString(const char *name, GLenum s)
711{
712 const char *v = (const char *) glGetString(s);
713
714 if (v == NULL) {
715 testPrintI("GL %s unknown", name);
716 } else {
717 testPrintI("GL %s = %s", name, v);
718 }
719}
720
721/*
722 * createLayerList
723 * dynamically creates layer list with numLayers worth
724 * of hwLayers entries.
725 */
726static hwc_layer_list_t *createLayerList(size_t numLayers)
727{
728 hwc_layer_list_t *list;
729
730 size_t size = sizeof(hwc_layer_list) + numLayers * sizeof(hwc_layer_t);
731 if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
732 return NULL;
733 }
734 list->flags = HWC_GEOMETRY_CHANGED;
735 list->numHwLayers = numLayers;
736
737 return list;
738}
739
740/*
741 * freeLayerList
742 * Frees memory previous allocated via createLayerList().
743 */
744static void freeLayerList(hwc_layer_list_t *list)
745{
746 free(list);
747}
748
749static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans)
750{
751 unsigned char* buf = NULL;
752 status_t err;
Louis Huemiller365b2c62010-11-22 18:05:30 -0800753 uint32_t pixel;
754
755 // RGB 2 YUV conversion ratios
756 const struct rgb2yuvRatios {
757 int format;
758 float weightRed;
759 float weightBlu;
760 float weightGrn;
761 } rgb2yuvRatios[] = {
762 { HAL_PIXEL_FORMAT_YV12, 0.299, 0.114, 0.587 },
763 };
764
765 const struct rgbAttrib {
766 int format;
767 bool hostByteOrder;
768 size_t bytes;
769 size_t rOffset;
770 size_t rSize;
771 size_t gOffset;
772 size_t gSize;
773 size_t bOffset;
774 size_t bSize;
775 size_t aOffset;
776 size_t aSize;
777 } rgbAttributes[] = {
778 {HAL_PIXEL_FORMAT_RGBA_8888, false, 4, 0, 8, 8, 8, 16, 8, 24, 8},
779 {HAL_PIXEL_FORMAT_RGBX_8888, false, 4, 0, 8, 8, 8, 16, 8, 0, 0},
780 {HAL_PIXEL_FORMAT_RGB_888, false, 3, 0, 8, 8, 8, 16, 8, 0, 0},
781 {HAL_PIXEL_FORMAT_RGB_565, true, 2, 0, 5, 5, 6, 11, 5, 0, 0},
782 {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8, 8, 8, 0, 8, 24, 8},
783 {HAL_PIXEL_FORMAT_RGBA_5551, true , 2, 0, 5, 5, 5, 10, 5, 15, 1},
784 {HAL_PIXEL_FORMAT_RGBA_4444, false, 2, 12, 4, 0, 4, 4, 4, 8, 4},
785 };
786
787 // If YUV format, convert color and pass work to YUV color fill
788 for (unsigned int n1 = 0; n1 < NUMA(rgb2yuvRatios); n1++) {
789 if (gBuf->getPixelFormat() == rgb2yuvRatios[n1].format) {
790 float wr = rgb2yuvRatios[n1].weightRed;
791 float wb = rgb2yuvRatios[n1].weightBlu;
792 float wg = rgb2yuvRatios[n1].weightGrn;
793 float y = wr * color.r() + wb * color.b() + wg * color.g();
794 float u = 0.5 * ((color.b() - y) / (1 - wb)) + 0.5;
795 float v = 0.5 * ((color.r() - y) / (1 - wr)) + 0.5;
796 YUVColor yuvColor(y, u, v);
797 fillColor(gBuf, yuvColor, trans);
798 return;
799 }
800 }
801
802 const struct rgbAttrib *attrib;
803 for (attrib = rgbAttributes; attrib < rgbAttributes + NUMA(rgbAttributes);
804 attrib++) {
805 if (attrib->format == gBuf->getPixelFormat()) { break; }
806 }
807 if (attrib >= rgbAttributes + NUMA(rgbAttributes)) {
808 testPrintE("fillColor rgb unsupported format of: %u",
809 gBuf->getPixelFormat());
810 exit(50);
811 }
812
813 pixel = htonl((uint32_t) (((1 << attrib->rSize) - 1) * color.r())
814 << ((sizeof(pixel) * BITSPERBYTE)
815 - (attrib->rOffset + attrib->rSize)));
816 pixel |= htonl((uint32_t) (((1 << attrib->gSize) - 1) * color.g())
817 << ((sizeof(pixel) * BITSPERBYTE)
818 - (attrib->gOffset + attrib->gSize)));
819 pixel |= htonl((uint32_t) (((1 << attrib->bSize) - 1) * color.b())
820 << ((sizeof(pixel) * BITSPERBYTE)
821 - (attrib->bOffset + attrib->bSize)));
822 if (attrib->aSize) {
823 pixel |= htonl((uint32_t) (((1 << attrib->aSize) - 1) * trans)
824 << ((sizeof(pixel) * BITSPERBYTE)
825 - (attrib->aOffset + attrib->aSize)));
826 }
827 if (attrib->hostByteOrder) {
828 pixel = ntohl(pixel);
829 pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
830 }
831
832 err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
833 if (err != 0) {
834 testPrintE("fillColor rgb lock failed: %d", err);
835 exit(51);
836 }
837
Louis Huemiller5d86b532010-12-14 10:22:42 -0800838 for (unsigned int row = 0; row < gBuf->getHeight(); row++) {
839 for (unsigned int col = 0; col < gBuf->getWidth(); col++) {
840 memmove(buf, &pixel, attrib->bytes);
841 buf += attrib->bytes;
842 }
843 for (unsigned int pad = 0;
844 pad < (gBuf->getStride() - gBuf->getWidth()) * attrib->bytes;
845 pad++) {
846 *buf++ = testRandMod(256);
847 }
Louis Huemiller365b2c62010-11-22 18:05:30 -0800848 }
849
850 err = gBuf->unlock();
851 if (err != 0) {
852 testPrintE("fillColor rgb unlock failed: %d", err);
853 exit(52);
854 }
855}
856
857static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans)
858{
859 unsigned char* buf = NULL;
860 status_t err;
861 unsigned int width = gBuf->getWidth();
862 unsigned int height = gBuf->getHeight();
863
864 const struct yuvAttrib {
865 int format;
Louis Huemiller365b2c62010-11-22 18:05:30 -0800866 bool planar;
867 unsigned int uSubSampX;
868 unsigned int uSubSampY;
869 unsigned int vSubSampX;
870 unsigned int vSubSampY;
871 } yuvAttributes[] = {
Louis Huemiller5d86b532010-12-14 10:22:42 -0800872 { HAL_PIXEL_FORMAT_YV12, true, 2, 2, 2, 2},
Louis Huemiller365b2c62010-11-22 18:05:30 -0800873 };
874
875 const struct yuvAttrib *attrib;
876 for (attrib = yuvAttributes; attrib < yuvAttributes + NUMA(yuvAttributes);
877 attrib++) {
878 if (attrib->format == gBuf->getPixelFormat()) { break; }
879 }
880 if (attrib >= yuvAttributes + NUMA(yuvAttributes)) {
881 testPrintE("fillColor yuv unsupported format of: %u",
882 gBuf->getPixelFormat());
883 exit(60);
884 }
885
886 assert(attrib->planar == true); // So far, only know how to handle planar
887
Louis Huemiller365b2c62010-11-22 18:05:30 -0800888 err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
889 if (err != 0) {
890 testPrintE("fillColor lock failed: %d", err);
891 exit(61);
892 }
893
894 // Fill in Y component
Louis Huemiller5d86b532010-12-14 10:22:42 -0800895 for (unsigned int row = 0; row < height; row++) {
896 for (unsigned int col = 0; col < width; col++) {
897 *buf++ = 255 * color.y();
898 }
899 for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
900 pad++) {
901 *buf++ = testRandMod(256);
Louis Huemiller365b2c62010-11-22 18:05:30 -0800902 }
903 }
904
905 // Fill in U component
Louis Huemiller5d86b532010-12-14 10:22:42 -0800906 for (unsigned int row = 0; row < height; row += attrib->uSubSampY) {
907 for (unsigned int col = 0; col < width; col += attrib->uSubSampX) {
908 *buf++ = 255 * color.u();
909 }
910 for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
911 pad += attrib->uSubSampX) {
912 *buf++ = testRandMod(256);
Louis Huemiller365b2c62010-11-22 18:05:30 -0800913 }
914 }
915
916 // Fill in V component
Louis Huemiller5d86b532010-12-14 10:22:42 -0800917 for (unsigned int row = 0; row < height; row += attrib->vSubSampY) {
918 for (unsigned int col = 0; col < width; col += attrib->vSubSampX) {
919 *buf++ = 255 * color.v();
920 }
921 for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
922 pad += attrib->vSubSampX) {
923 *buf++ = testRandMod(256);
Louis Huemiller365b2c62010-11-22 18:05:30 -0800924 }
925 }
926
927 err = gBuf->unlock();
928 if (err != 0) {
929 testPrintE("fillColor unlock failed: %d", err);
930 exit(62);
931 }
932}
933
934void init(void)
935{
936 int rv;
937
938 EGLBoolean returnValue;
939 EGLConfig myConfig = {0};
940 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
941 EGLint sConfigAttribs[] = {
942 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
943 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
944 EGL_NONE };
945 EGLint majorVersion, minorVersion;
946
947 checkEglError("<init>");
948 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
949 checkEglError("eglGetDisplay");
950 if (dpy == EGL_NO_DISPLAY) {
951 testPrintE("eglGetDisplay returned EGL_NO_DISPLAY");
952 exit(70);
953 }
954
955 returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
956 checkEglError("eglInitialize", returnValue);
957 testPrintI("EGL version %d.%d", majorVersion, minorVersion);
958 if (returnValue != EGL_TRUE) {
959 testPrintE("eglInitialize failed");
960 exit(71);
961 }
962
963 EGLNativeWindowType window = android_createDisplaySurface();
964 if (window == NULL) {
965 testPrintE("android_createDisplaySurface failed");
966 exit(72);
967 }
968 returnValue = EGLUtils::selectConfigForNativeWindow(dpy,
969 sConfigAttribs, window, &myConfig);
970 if (returnValue) {
971 testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
972 returnValue);
973 exit(73);
974 }
975 checkEglError("EGLUtils::selectConfigForNativeWindow");
976
977 testPrintI("Chose this configuration:");
978 printEGLConfiguration(dpy, myConfig);
979
980 surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
981 checkEglError("eglCreateWindowSurface");
982 if (surface == EGL_NO_SURFACE) {
983 testPrintE("gelCreateWindowSurface failed.");
984 exit(74);
985 }
986
987 context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
988 checkEglError("eglCreateContext");
989 if (context == EGL_NO_CONTEXT) {
990 testPrintE("eglCreateContext failed");
991 exit(75);
992 }
993 returnValue = eglMakeCurrent(dpy, surface, surface, context);
994 checkEglError("eglMakeCurrent", returnValue);
995 if (returnValue != EGL_TRUE) {
996 testPrintE("eglMakeCurrent failed");
997 exit(76);
998 }
999 eglQuerySurface(dpy, surface, EGL_WIDTH, &width);
1000 checkEglError("eglQuerySurface");
1001 eglQuerySurface(dpy, surface, EGL_HEIGHT, &height);
1002 checkEglError("eglQuerySurface");
1003
Louis Huemiller5d86b532010-12-14 10:22:42 -08001004 testPrintI("Window dimensions: %d x %d", width, height);
Louis Huemiller365b2c62010-11-22 18:05:30 -08001005
1006 printGLString("Version", GL_VERSION);
1007 printGLString("Vendor", GL_VENDOR);
1008 printGLString("Renderer", GL_RENDERER);
1009 printGLString("Extensions", GL_EXTENSIONS);
1010
1011 if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
1012 testPrintE("hw_get_module failed, rv: %i", rv);
1013 errno = -rv;
1014 perror(NULL);
1015 exit(77);
1016 }
1017 if ((rv = hwc_open(hwcModule, &hwcDevice)) != 0) {
1018 testPrintE("hwc_open failed, rv: %i", rv);
1019 errno = -rv;
1020 perror(NULL);
1021 exit(78);
1022 }
1023
1024 testPrintI("");
1025}
1026
1027/*
1028 * Initialize Frames
1029 *
1030 * Creates an array of graphic buffers, within the global variable
1031 * named frames. The graphic buffers are contained within a vector of
Louis Huemiller5d86b532010-12-14 10:22:42 -08001032 * vectors. All the graphic buffers in a particular row are of the same
Louis Huemiller365b2c62010-11-22 18:05:30 -08001033 * format and dimension. Each graphic buffer is uniformly filled with a
1034 * prandomly selected color. It is likely that each buffer, even
1035 * in the same row, will be filled with a unique color.
1036 */
1037void initFrames(unsigned int seed)
1038{
Louis Huemillerb5265942010-12-12 23:05:31 -08001039 int rv;
Louis Huemiller365b2c62010-11-22 18:05:30 -08001040 const size_t maxRows = 5;
1041 const size_t minCols = 2; // Need at least double buffering
1042 const size_t maxCols = 4; // One more than triple buffering
1043
1044 if (verbose) { testPrintI("initFrames seed: %u", seed); }
1045 srand48(seed);
1046 size_t rows = testRandMod(maxRows) + 1;
1047
1048 frames.clear();
1049 frames.resize(rows);
1050
1051 for (unsigned int row = 0; row < rows; row++) {
1052 // All frames within a row have to have the same format and
1053 // dimensions. Width and height need to be >= 1.
Louis Huemiller5d86b532010-12-14 10:22:42 -08001054 unsigned int formatIdx = testRandMod(NUMA(graphicFormat));
1055 const struct graphicFormat *formatPtr = &graphicFormat[formatIdx];
1056 int format = formatPtr->format;
1057
1058 // Pick width and height, which must be >= 1 and the size
1059 // mod the wMod/hMod value must be equal to 0.
Louis Huemiller365b2c62010-11-22 18:05:30 -08001060 size_t w = (width * maxSizeRatio) * testRandFract();
1061 size_t h = (height * maxSizeRatio) * testRandFract();
1062 w = max(1u, w);
1063 h = max(1u, h);
Louis Huemiller5d86b532010-12-14 10:22:42 -08001064 if ((w % formatPtr->wMod) != 0) {
1065 w += formatPtr->wMod - (w % formatPtr->wMod);
1066 }
1067 if ((h % formatPtr->hMod) != 0) {
1068 h += formatPtr->hMod - (h % formatPtr->hMod);
1069 }
Louis Huemiller1812cfd2010-12-14 14:58:55 -08001070 if (verbose) {
1071 testPrintI(" frame %u width: %u height: %u format: %u %s",
1072 row, w, h, format, graphicFormat2str(format));
1073 }
Louis Huemiller365b2c62010-11-22 18:05:30 -08001074
1075 size_t cols = testRandMod((maxCols + 1) - minCols) + minCols;
1076 frames[row].resize(cols);
1077 for (unsigned int col = 0; col < cols; col++) {
1078 RGBColor color(testRandFract(), testRandFract(), testRandFract());
1079 float transp = testRandFract();
1080
1081 frames[row][col] = new GraphicBuffer(w, h, format, texUsage);
Louis Huemillerb5265942010-12-12 23:05:31 -08001082 if ((rv = frames[row][col]->initCheck()) != NO_ERROR) {
1083 testPrintE("GraphicBuffer initCheck failed, rv: %i", rv);
1084 testPrintE(" frame %u width: %u height: %u format: %u %s",
1085 row, w, h, format, graphicFormat2str(format));
1086 exit(80);
1087 }
1088
Louis Huemiller365b2c62010-11-22 18:05:30 -08001089 fillColor(frames[row][col].get(), color, transp);
1090 if (verbose) {
1091 testPrintI(" buf: %p handle: %p color: <%f, %f, %f> "
1092 "transp: %f",
1093 frames[row][col].get(), frames[row][col]->handle,
1094 color.r(), color.g(), color.b(), transp);
1095 }
1096 }
1097 }
1098}
1099
1100void displayList(hwc_layer_list_t *list)
1101{
1102 testPrintI(" flags: %#x%s", list->flags,
1103 (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
1104 testPrintI(" numHwLayers: %u", list->numHwLayers);
1105
1106 for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
1107 testPrintI(" layer %u compositionType: %#x%s%s", layer,
1108 list->hwLayers[layer].compositionType,
1109 (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
1110 ? " FRAMEBUFFER" : "",
1111 (list->hwLayers[layer].compositionType == HWC_OVERLAY)
1112 ? " OVERLAY" : "");
1113
1114 testPrintI(" hints: %#x",
1115 list->hwLayers[layer].hints,
1116 (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
1117 ? " TRIPLE_BUFFER" : "",
1118 (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
1119 ? " CLEAR_FB" : "");
1120
1121 testPrintI(" flags: %#x%s",
1122 list->hwLayers[layer].flags,
1123 (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
1124 ? " SKIP_LAYER" : "");
1125
1126 testPrintI(" handle: %p",
1127 list->hwLayers[layer].handle);
1128
1129 // Intentionally skipped display of ROT_180 & ROT_270,
1130 // which are formed from combinations of the other flags.
1131 testPrintI(" transform: %#x%s%s%s",
1132 list->hwLayers[layer].transform,
1133 (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
1134 ? " FLIP_H" : "",
1135 (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
1136 ? " FLIP_V" : "",
1137 (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
1138 ? " ROT_90" : "");
1139
1140 testPrintI(" blending: %#x",
1141 list->hwLayers[layer].blending,
1142 (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
1143 ? " NONE" : "",
1144 (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
1145 ? " PREMULT" : "",
1146 (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
1147 ? " COVERAGE" : "");
1148
1149 testPrintI(" sourceCrop: [%i, %i, %i, %i]",
1150 list->hwLayers[layer].sourceCrop.left,
1151 list->hwLayers[layer].sourceCrop.top,
1152 list->hwLayers[layer].sourceCrop.right,
1153 list->hwLayers[layer].sourceCrop.bottom);
1154
1155 testPrintI(" displayFrame: [%i, %i, %i, %i]",
1156 list->hwLayers[layer].displayFrame.left,
1157 list->hwLayers[layer].displayFrame.top,
1158 list->hwLayers[layer].displayFrame.right,
1159 list->hwLayers[layer].displayFrame.bottom);
Louis Huemillerb5265942010-12-12 23:05:31 -08001160 testPrintI(" scaleFactor: [%f %f]",
1161 (float) (list->hwLayers[layer].displayFrame.right
1162 - list->hwLayers[layer].displayFrame.left)
1163 / (float) (list->hwLayers[layer].sourceCrop.right
1164 - list->hwLayers[layer].sourceCrop.left),
1165 (float) (list->hwLayers[layer].displayFrame.bottom
1166 - list->hwLayers[layer].displayFrame.top)
1167 / (float) (list->hwLayers[layer].sourceCrop.bottom
1168 - list->hwLayers[layer].sourceCrop.top));
Louis Huemiller365b2c62010-11-22 18:05:30 -08001169 }
1170}
1171
1172/*
1173 * Display List Prepare Modifiable
1174 *
1175 * Displays the portions of a list that are meant to be modified by
1176 * a prepare call.
1177 */
1178void displayListPrepareModifiable(hwc_layer_list_t *list)
1179{
1180 for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
1181 testPrintI(" layer %u compositionType: %#x%s%s", layer,
1182 list->hwLayers[layer].compositionType,
1183 (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
1184 ? " FRAMEBUFFER" : "",
1185 (list->hwLayers[layer].compositionType == HWC_OVERLAY)
1186 ? " OVERLAY" : "");
1187 testPrintI(" hints: %#x%s%s",
1188 list->hwLayers[layer].hints,
1189 (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
1190 ? " TRIPLE_BUFFER" : "",
1191 (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
1192 ? " CLEAR_FB" : "");
1193 }
1194}
1195
1196/*
1197 * Display List Handles
1198 *
1199 * Displays the handles of all the graphic buffers in the list.
1200 */
1201void displayListHandles(hwc_layer_list_t *list)
1202{
1203 const unsigned int maxLayersPerLine = 6;
1204
1205 ostringstream str(" layers:");
1206 for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
1207 str << ' ' << list->hwLayers[layer].handle;
1208 if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
1209 && (layer != list->numHwLayers - 1)) {
1210 testPrintI("%s", str.str().c_str());
1211 str.str(" ");
1212 }
1213 }
1214 testPrintI("%s", str.str().c_str());
1215}
1216
1217const char *graphicFormat2str(unsigned int format)
1218{
1219 const static char *unknown = "unknown";
1220
1221 for (unsigned int n1 = 0; n1 < NUMA(graphicFormat); n1++) {
1222 if (format == graphicFormat[n1].format) {
1223 return graphicFormat[n1].desc;
1224 }
1225 }
1226
1227 return unknown;
1228}
1229
1230/*
1231 * Vector Random Select
1232 *
1233 * Prandomly selects and returns num elements from vec.
1234 */
1235template <class T>
1236vector<T> vectorRandSelect(const vector<T>& vec, size_t num)
1237{
1238 vector<T> rv = vec;
1239
1240 while (rv.size() > num) {
1241 rv.erase(rv.begin() + testRandMod(rv.size()));
1242 }
1243
1244 return rv;
1245}
1246
1247/*
1248 * Vector Or
1249 *
1250 * Or's togethen the values of each element of vec and returns the result.
1251 */
1252template <class T>
1253T vectorOr(const vector<T>& vec)
1254{
1255 T rv = 0;
1256
1257 for (size_t n1 = 0; n1 < vec.size(); n1++) {
1258 rv |= vec[n1];
1259 }
1260
1261 return rv;
1262}