xref: /aosp_15_r20/frameworks/native/opengl/tests/hwc/hwcRects.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker /*
18*38e8c45fSAndroid Build Coastguard Worker  * Hardware Composer Rectangles
19*38e8c45fSAndroid Build Coastguard Worker  *
20*38e8c45fSAndroid Build Coastguard Worker  * Synopsis
21*38e8c45fSAndroid Build Coastguard Worker  *   hwcRects [options] (graphicFormat displayFrame [attributes],)...
22*38e8c45fSAndroid Build Coastguard Worker  *     options:
23*38e8c45fSAndroid Build Coastguard Worker  *       -D #.## - End of test delay
24*38e8c45fSAndroid Build Coastguard Worker  *       -v - Verbose
25*38e8c45fSAndroid Build Coastguard Worker  *
26*38e8c45fSAndroid Build Coastguard Worker  *      graphic formats:
27*38e8c45fSAndroid Build Coastguard Worker  *        RGBA8888 (reference frame default)
28*38e8c45fSAndroid Build Coastguard Worker  *        RGBX8888
29*38e8c45fSAndroid Build Coastguard Worker  *        RGB888
30*38e8c45fSAndroid Build Coastguard Worker  *        RGB565
31*38e8c45fSAndroid Build Coastguard Worker  *        BGRA8888
32*38e8c45fSAndroid Build Coastguard Worker  *        RGBA5551
33*38e8c45fSAndroid Build Coastguard Worker  *        RGBA4444
34*38e8c45fSAndroid Build Coastguard Worker  *        YV12
35*38e8c45fSAndroid Build Coastguard Worker  *
36*38e8c45fSAndroid Build Coastguard Worker  *      displayFrame
37*38e8c45fSAndroid Build Coastguard Worker  *        [left, top, right, bottom]
38*38e8c45fSAndroid Build Coastguard Worker  *
39*38e8c45fSAndroid Build Coastguard Worker  *      attributes:
40*38e8c45fSAndroid Build Coastguard Worker  *        transform: none | fliph | flipv | rot90 | rot180 | rot270
41*38e8c45fSAndroid Build Coastguard Worker  *        blend: none | premult | coverage
42*38e8c45fSAndroid Build Coastguard Worker  *        color: [0.##, 0.##, 0.##]
43*38e8c45fSAndroid Build Coastguard Worker  *        alpha: 0.##
44*38e8c45fSAndroid Build Coastguard Worker  *        sourceDim: [width, height]
45*38e8c45fSAndroid Build Coastguard Worker  *        sourceCrop: [left, top, right, bottom]
46*38e8c45fSAndroid Build Coastguard Worker  *
47*38e8c45fSAndroid Build Coastguard Worker  *      Example:
48*38e8c45fSAndroid Build Coastguard Worker  *        # White YV12 rectangle, with overlapping turquoise
49*38e8c45fSAndroid Build Coastguard Worker  *        #  RGBA8888 rectangle at 30%% (alpha: 0.7) transparency
50*38e8c45fSAndroid Build Coastguard Worker  *        hwcRects -v -D 30.0 \
51*38e8c45fSAndroid Build Coastguard Worker  *          YV12 [50, 80, 200, 300] transform: none \
52*38e8c45fSAndroid Build Coastguard Worker  *            color: [1.0, 0.5, 0.5], \
53*38e8c45fSAndroid Build Coastguard Worker  *          RGBA8888 [100, 150, 300, 400] blend: coverage \
54*38e8c45fSAndroid Build Coastguard Worker  *            color: [0.251, 0.878, 0.816] alpha: 0.7 \
55*38e8c45fSAndroid Build Coastguard Worker  *            sourceDim: [50, 60] sourceCrop: [5, 8, 12, 15]
56*38e8c45fSAndroid Build Coastguard Worker  *
57*38e8c45fSAndroid Build Coastguard Worker  * Description
58*38e8c45fSAndroid Build Coastguard Worker  *   Constructs a Hardware Composer (HWC) list of frames from
59*38e8c45fSAndroid Build Coastguard Worker  *   command-line specified parameters.  Then sends it to the HWC
60*38e8c45fSAndroid Build Coastguard Worker  *   be rendered.  The intended purpose of this tool is as a means to
61*38e8c45fSAndroid Build Coastguard Worker  *   reproduce and succinctly specify an observed HWC operation, with
62*38e8c45fSAndroid Build Coastguard Worker  *   no need to modify/compile a program.
63*38e8c45fSAndroid Build Coastguard Worker  *
64*38e8c45fSAndroid Build Coastguard Worker  *   The command-line syntax consists of a few standard command-line
65*38e8c45fSAndroid Build Coastguard Worker  *   options and then a description of one or more frames.  The frame
66*38e8c45fSAndroid Build Coastguard Worker  *   descriptions are separated from one another via a comma.  The
67*38e8c45fSAndroid Build Coastguard Worker  *   beginning of a frame description requires the specification
68*38e8c45fSAndroid Build Coastguard Worker  *   of the graphic format and then the display frame rectangle where
69*38e8c45fSAndroid Build Coastguard Worker  *   the frame will be displayed.  The display frame rectangle is
70*38e8c45fSAndroid Build Coastguard Worker  *   specified as follows, with the right and bottom coordinates being
71*38e8c45fSAndroid Build Coastguard Worker  *   exclusive values:
72*38e8c45fSAndroid Build Coastguard Worker  *
73*38e8c45fSAndroid Build Coastguard Worker  *     [left, top, right, bottom]
74*38e8c45fSAndroid Build Coastguard Worker  *
75*38e8c45fSAndroid Build Coastguard Worker  *   After these two required parameters each frame description can
76*38e8c45fSAndroid Build Coastguard Worker  *   specify 1 or more optional attributes.  The name of each optional
77*38e8c45fSAndroid Build Coastguard Worker  *   attribute is preceded by a colon.  The current implementation
78*38e8c45fSAndroid Build Coastguard Worker  *   then requires white space after the colon and then the value of
79*38e8c45fSAndroid Build Coastguard Worker  *   the attribute is specified.  See the synopsis section above for
80*38e8c45fSAndroid Build Coastguard Worker  *   a list of attributes and the format of their expected value.
81*38e8c45fSAndroid Build Coastguard Worker  */
82*38e8c45fSAndroid Build Coastguard Worker 
83*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "hwcRectsTest"
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker #include <algorithm>
86*38e8c45fSAndroid Build Coastguard Worker #include <assert.h>
87*38e8c45fSAndroid Build Coastguard Worker #include <cerrno>
88*38e8c45fSAndroid Build Coastguard Worker #include <cmath>
89*38e8c45fSAndroid Build Coastguard Worker #include <cstdlib>
90*38e8c45fSAndroid Build Coastguard Worker #include <ctime>
91*38e8c45fSAndroid Build Coastguard Worker #include <istream>
92*38e8c45fSAndroid Build Coastguard Worker #include <libgen.h>
93*38e8c45fSAndroid Build Coastguard Worker #include <list>
94*38e8c45fSAndroid Build Coastguard Worker #include <sched.h>
95*38e8c45fSAndroid Build Coastguard Worker #include <sstream>
96*38e8c45fSAndroid Build Coastguard Worker #include <stdint.h>
97*38e8c45fSAndroid Build Coastguard Worker #include <string.h>
98*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
99*38e8c45fSAndroid Build Coastguard Worker 
100*38e8c45fSAndroid Build Coastguard Worker #include <sys/syscall.h>
101*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
102*38e8c45fSAndroid Build Coastguard Worker #include <sys/wait.h>
103*38e8c45fSAndroid Build Coastguard Worker 
104*38e8c45fSAndroid Build Coastguard Worker #include <EGL/egl.h>
105*38e8c45fSAndroid Build Coastguard Worker #include <EGL/eglext.h>
106*38e8c45fSAndroid Build Coastguard Worker #include <GLES2/gl2.h>
107*38e8c45fSAndroid Build Coastguard Worker #include <GLES2/gl2ext.h>
108*38e8c45fSAndroid Build Coastguard Worker 
109*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicBuffer.h>
110*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
111*38e8c45fSAndroid Build Coastguard Worker #include <testUtil.h>
112*38e8c45fSAndroid Build Coastguard Worker 
113*38e8c45fSAndroid Build Coastguard Worker #include <hardware/hwcomposer.h>
114*38e8c45fSAndroid Build Coastguard Worker 
115*38e8c45fSAndroid Build Coastguard Worker #include <glTestLib.h>
116*38e8c45fSAndroid Build Coastguard Worker #include "hwcTestLib.h"
117*38e8c45fSAndroid Build Coastguard Worker 
118*38e8c45fSAndroid Build Coastguard Worker using namespace std;
119*38e8c45fSAndroid Build Coastguard Worker using namespace android;
120*38e8c45fSAndroid Build Coastguard Worker 
121*38e8c45fSAndroid Build Coastguard Worker // Defaults
122*38e8c45fSAndroid Build Coastguard Worker const bool defaultVerbose = false;
123*38e8c45fSAndroid Build Coastguard Worker const float defaultEndDelay = 2.0; // Default delay after rendering graphics
124*38e8c45fSAndroid Build Coastguard Worker 
125*38e8c45fSAndroid Build Coastguard Worker const uint32_t   defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
126*38e8c45fSAndroid Build Coastguard Worker const int32_t    defaultTransform = 0;
127*38e8c45fSAndroid Build Coastguard Worker const uint32_t   defaultBlend = HWC_BLENDING_NONE;
128*38e8c45fSAndroid Build Coastguard Worker const ColorFract defaultColor(0.5, 0.5, 0.5);
129*38e8c45fSAndroid Build Coastguard Worker const float      defaultAlpha = 1.0; // Opaque
130*38e8c45fSAndroid Build Coastguard Worker const HwcTestDim defaultSourceDim(1, 1);
131*38e8c45fSAndroid Build Coastguard Worker const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
132*38e8c45fSAndroid Build Coastguard Worker const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
133*38e8c45fSAndroid Build Coastguard Worker 
134*38e8c45fSAndroid Build Coastguard Worker // Defines
135*38e8c45fSAndroid Build Coastguard Worker #define MAXCMD               200
136*38e8c45fSAndroid Build Coastguard Worker #define CMD_STOP_FRAMEWORK   "stop 2>&1"
137*38e8c45fSAndroid Build Coastguard Worker #define CMD_START_FRAMEWORK  "start 2>&1"
138*38e8c45fSAndroid Build Coastguard Worker 
139*38e8c45fSAndroid Build Coastguard Worker // Macros
140*38e8c45fSAndroid Build Coastguard Worker #define NUMA(a) (sizeof(a) / sizeof((a)[0])) // Num elements in an array
141*38e8c45fSAndroid Build Coastguard Worker 
142*38e8c45fSAndroid Build Coastguard Worker // Local types
143*38e8c45fSAndroid Build Coastguard Worker class Rectangle {
144*38e8c45fSAndroid Build Coastguard Worker public:
Rectangle()145*38e8c45fSAndroid Build Coastguard Worker     Rectangle() : format(defaultFormat), transform(defaultTransform),
146*38e8c45fSAndroid Build Coastguard Worker                   blend(defaultBlend), color(defaultColor),
147*38e8c45fSAndroid Build Coastguard Worker                   alpha(defaultAlpha), sourceDim(defaultSourceDim),
148*38e8c45fSAndroid Build Coastguard Worker                   sourceCrop(defaultSourceCrop),
149*38e8c45fSAndroid Build Coastguard Worker                   displayFrame(defaultDisplayFrame) {};
150*38e8c45fSAndroid Build Coastguard Worker 
151*38e8c45fSAndroid Build Coastguard Worker     uint32_t     format;
152*38e8c45fSAndroid Build Coastguard Worker     uint32_t     transform;
153*38e8c45fSAndroid Build Coastguard Worker     int32_t      blend;
154*38e8c45fSAndroid Build Coastguard Worker     ColorFract   color;
155*38e8c45fSAndroid Build Coastguard Worker     float        alpha;
156*38e8c45fSAndroid Build Coastguard Worker     HwcTestDim   sourceDim;
157*38e8c45fSAndroid Build Coastguard Worker     struct hwc_rect   sourceCrop;
158*38e8c45fSAndroid Build Coastguard Worker     struct hwc_rect   displayFrame;
159*38e8c45fSAndroid Build Coastguard Worker 
160*38e8c45fSAndroid Build Coastguard Worker     sp<GraphicBuffer> texture;
161*38e8c45fSAndroid Build Coastguard Worker };
162*38e8c45fSAndroid Build Coastguard Worker 
163*38e8c45fSAndroid Build Coastguard Worker // Globals
164*38e8c45fSAndroid Build Coastguard Worker list<Rectangle> rectangle;
165*38e8c45fSAndroid Build Coastguard Worker static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
166*38e8c45fSAndroid Build Coastguard Worker         GraphicBuffer::USAGE_SW_WRITE_RARELY;
167*38e8c45fSAndroid Build Coastguard Worker static hwc_composer_device_1_t *hwcDevice;
168*38e8c45fSAndroid Build Coastguard Worker static EGLDisplay dpy;
169*38e8c45fSAndroid Build Coastguard Worker static EGLSurface surface;
170*38e8c45fSAndroid Build Coastguard Worker static EGLint width, height;
171*38e8c45fSAndroid Build Coastguard Worker 
172*38e8c45fSAndroid Build Coastguard Worker // Function prototypes
173*38e8c45fSAndroid Build Coastguard Worker static Rectangle parseRect(const string& rectStr);
174*38e8c45fSAndroid Build Coastguard Worker void init(void);
175*38e8c45fSAndroid Build Coastguard Worker void printSyntax(const char *cmd);
176*38e8c45fSAndroid Build Coastguard Worker 
177*38e8c45fSAndroid Build Coastguard Worker // Command-line option settings
178*38e8c45fSAndroid Build Coastguard Worker static bool verbose = defaultVerbose;
179*38e8c45fSAndroid Build Coastguard Worker static float endDelay = defaultEndDelay;
180*38e8c45fSAndroid Build Coastguard Worker 
181*38e8c45fSAndroid Build Coastguard Worker /*
182*38e8c45fSAndroid Build Coastguard Worker  * Main
183*38e8c45fSAndroid Build Coastguard Worker  *
184*38e8c45fSAndroid Build Coastguard Worker  * Performs the following high-level sequence of operations:
185*38e8c45fSAndroid Build Coastguard Worker  *
186*38e8c45fSAndroid Build Coastguard Worker  *   1. Parse command-line options
187*38e8c45fSAndroid Build Coastguard Worker  *
188*38e8c45fSAndroid Build Coastguard Worker  *   2. Stop framework
189*38e8c45fSAndroid Build Coastguard Worker  *
190*38e8c45fSAndroid Build Coastguard Worker  *   3. Initialization
191*38e8c45fSAndroid Build Coastguard Worker  *
192*38e8c45fSAndroid Build Coastguard Worker  *   4. Parse frame descriptions
193*38e8c45fSAndroid Build Coastguard Worker  *
194*38e8c45fSAndroid Build Coastguard Worker  *   5. Create HWC list from frame descriptions
195*38e8c45fSAndroid Build Coastguard Worker  *
196*38e8c45fSAndroid Build Coastguard Worker  *   6. Have HWC render the list description of the frames
197*38e8c45fSAndroid Build Coastguard Worker  *
198*38e8c45fSAndroid Build Coastguard Worker  *   7. Delay for amount of time given by endDelay
199*38e8c45fSAndroid Build Coastguard Worker  *
200*38e8c45fSAndroid Build Coastguard Worker  *   8. Start framework
201*38e8c45fSAndroid Build Coastguard Worker  */
202*38e8c45fSAndroid Build Coastguard Worker int
main(int argc,char * argv[])203*38e8c45fSAndroid Build Coastguard Worker main(int argc, char *argv[])
204*38e8c45fSAndroid Build Coastguard Worker {
205*38e8c45fSAndroid Build Coastguard Worker     int     rv, opt;
206*38e8c45fSAndroid Build Coastguard Worker     char   *chptr;
207*38e8c45fSAndroid Build Coastguard Worker     string  str;
208*38e8c45fSAndroid Build Coastguard Worker     char cmd[MAXCMD];
209*38e8c45fSAndroid Build Coastguard Worker 
210*38e8c45fSAndroid Build Coastguard Worker     testSetLogCatTag(LOG_TAG);
211*38e8c45fSAndroid Build Coastguard Worker 
212*38e8c45fSAndroid Build Coastguard Worker     // Parse command line arguments
213*38e8c45fSAndroid Build Coastguard Worker     while ((opt = getopt(argc, argv, "D:v?h")) != -1) {
214*38e8c45fSAndroid Build Coastguard Worker         switch (opt) {
215*38e8c45fSAndroid Build Coastguard Worker           case 'D': // End of test delay
216*38e8c45fSAndroid Build Coastguard Worker             endDelay = strtod(optarg, &chptr);
217*38e8c45fSAndroid Build Coastguard Worker             if ((*chptr != '\0') || (endDelay < 0.0)) {
218*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Invalid command-line specified end of test delay "
219*38e8c45fSAndroid Build Coastguard Worker                            "of: %s", optarg);
220*38e8c45fSAndroid Build Coastguard Worker                 exit(1);
221*38e8c45fSAndroid Build Coastguard Worker             }
222*38e8c45fSAndroid Build Coastguard Worker             break;
223*38e8c45fSAndroid Build Coastguard Worker 
224*38e8c45fSAndroid Build Coastguard Worker           case 'v': // Verbose
225*38e8c45fSAndroid Build Coastguard Worker             verbose = true;
226*38e8c45fSAndroid Build Coastguard Worker             break;
227*38e8c45fSAndroid Build Coastguard Worker 
228*38e8c45fSAndroid Build Coastguard Worker           case 'h': // Help
229*38e8c45fSAndroid Build Coastguard Worker           case '?':
230*38e8c45fSAndroid Build Coastguard Worker           default:
231*38e8c45fSAndroid Build Coastguard Worker             printSyntax(basename(argv[0]));
232*38e8c45fSAndroid Build Coastguard Worker             exit(((optopt == 0) || (optopt == '?')) ? 0 : 2);
233*38e8c45fSAndroid Build Coastguard Worker         }
234*38e8c45fSAndroid Build Coastguard Worker     }
235*38e8c45fSAndroid Build Coastguard Worker 
236*38e8c45fSAndroid Build Coastguard Worker     // Stop framework
237*38e8c45fSAndroid Build Coastguard Worker     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
238*38e8c45fSAndroid Build Coastguard Worker     if (rv >= (signed) sizeof(cmd) - 1) {
239*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
240*38e8c45fSAndroid Build Coastguard Worker         exit(3);
241*38e8c45fSAndroid Build Coastguard Worker     }
242*38e8c45fSAndroid Build Coastguard Worker     testExecCmd(cmd);
243*38e8c45fSAndroid Build Coastguard Worker     testDelay(1.0); // TODO - needs means to query whether asyncronous stop
244*38e8c45fSAndroid Build Coastguard Worker                     // framework operation has completed.  For now, just wait
245*38e8c45fSAndroid Build Coastguard Worker                     // a long time.
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker     init();
248*38e8c45fSAndroid Build Coastguard Worker 
249*38e8c45fSAndroid Build Coastguard Worker     // Parse rectangle descriptions
250*38e8c45fSAndroid Build Coastguard Worker     int numOpen = 0; // Current number of unmatched <[
251*38e8c45fSAndroid Build Coastguard Worker     string rectDesc(""); // String description of a single rectangle
252*38e8c45fSAndroid Build Coastguard Worker     while (optind < argc) {
253*38e8c45fSAndroid Build Coastguard Worker         string argNext = string(argv[optind++]);
254*38e8c45fSAndroid Build Coastguard Worker 
255*38e8c45fSAndroid Build Coastguard Worker         if (rectDesc.length()) { rectDesc += ' '; }
256*38e8c45fSAndroid Build Coastguard Worker         rectDesc += argNext;
257*38e8c45fSAndroid Build Coastguard Worker 
258*38e8c45fSAndroid Build Coastguard Worker         // Count number of opening <[ and matching >]
259*38e8c45fSAndroid Build Coastguard Worker         // At this point not worried about an opening character being
260*38e8c45fSAndroid Build Coastguard Worker         // matched by it's corresponding closing character.  For example,
261*38e8c45fSAndroid Build Coastguard Worker         // "<1.0, 2.0]" is incorrect because the opening < should be matched
262*38e8c45fSAndroid Build Coastguard Worker         // with a closing >, instead of the closing ].  Such errors are
263*38e8c45fSAndroid Build Coastguard Worker         // detected when the actual value is parsed.
264*38e8c45fSAndroid Build Coastguard Worker         for (unsigned int n1 = 0; n1 < argNext.length(); n1++) {
265*38e8c45fSAndroid Build Coastguard Worker             switch(argNext[n1]) {
266*38e8c45fSAndroid Build Coastguard Worker               case '[':
267*38e8c45fSAndroid Build Coastguard Worker               case '<':
268*38e8c45fSAndroid Build Coastguard Worker                 numOpen++;
269*38e8c45fSAndroid Build Coastguard Worker                 break;
270*38e8c45fSAndroid Build Coastguard Worker 
271*38e8c45fSAndroid Build Coastguard Worker               case ']':
272*38e8c45fSAndroid Build Coastguard Worker               case '>':
273*38e8c45fSAndroid Build Coastguard Worker                 numOpen--;
274*38e8c45fSAndroid Build Coastguard Worker                 break;
275*38e8c45fSAndroid Build Coastguard Worker             }
276*38e8c45fSAndroid Build Coastguard Worker 
277*38e8c45fSAndroid Build Coastguard Worker             // Error anytime there is more closing then opening characters
278*38e8c45fSAndroid Build Coastguard Worker             if (numOpen < 0) {
279*38e8c45fSAndroid Build Coastguard Worker                 testPrintI("Mismatched number of opening <[ with "
280*38e8c45fSAndroid Build Coastguard Worker                            "closing >] in: %s", rectDesc.c_str());
281*38e8c45fSAndroid Build Coastguard Worker                 exit(4);
282*38e8c45fSAndroid Build Coastguard Worker             }
283*38e8c45fSAndroid Build Coastguard Worker         }
284*38e8c45fSAndroid Build Coastguard Worker 
285*38e8c45fSAndroid Build Coastguard Worker         // Description of a rectangle is complete when all opening
286*38e8c45fSAndroid Build Coastguard Worker         // <[ are closed with >] and the string ends with a comma or
287*38e8c45fSAndroid Build Coastguard Worker         // there are no more args.
288*38e8c45fSAndroid Build Coastguard Worker         if ((numOpen == 0) && rectDesc.length()
289*38e8c45fSAndroid Build Coastguard Worker             && ((rectDesc[rectDesc.length() - 1] == ',')
290*38e8c45fSAndroid Build Coastguard Worker                 || (optind == argc))) {
291*38e8c45fSAndroid Build Coastguard Worker             // Remove trailing comma if it is present
292*38e8c45fSAndroid Build Coastguard Worker             if (rectDesc[rectDesc.length() - 1] == ',') {
293*38e8c45fSAndroid Build Coastguard Worker                 rectDesc.erase(rectDesc.length() - 1);
294*38e8c45fSAndroid Build Coastguard Worker             }
295*38e8c45fSAndroid Build Coastguard Worker 
296*38e8c45fSAndroid Build Coastguard Worker             // Parse string description of rectangle
297*38e8c45fSAndroid Build Coastguard Worker             Rectangle rect = parseRect(rectDesc);
298*38e8c45fSAndroid Build Coastguard Worker 
299*38e8c45fSAndroid Build Coastguard Worker             // Add to the list of rectangles
300*38e8c45fSAndroid Build Coastguard Worker             rectangle.push_back(rect);
301*38e8c45fSAndroid Build Coastguard Worker 
302*38e8c45fSAndroid Build Coastguard Worker             // Prepare for description of another rectangle
303*38e8c45fSAndroid Build Coastguard Worker             rectDesc = string("");
304*38e8c45fSAndroid Build Coastguard Worker         }
305*38e8c45fSAndroid Build Coastguard Worker     }
306*38e8c45fSAndroid Build Coastguard Worker 
307*38e8c45fSAndroid Build Coastguard Worker     // Create list of frames
308*38e8c45fSAndroid Build Coastguard Worker     hwc_display_contents_1_t *list;
309*38e8c45fSAndroid Build Coastguard Worker     list = hwcTestCreateLayerList(rectangle.size());
310*38e8c45fSAndroid Build Coastguard Worker     if (list == NULL) {
311*38e8c45fSAndroid Build Coastguard Worker         testPrintE("hwcTestCreateLayerList failed");
312*38e8c45fSAndroid Build Coastguard Worker         exit(5);
313*38e8c45fSAndroid Build Coastguard Worker     }
314*38e8c45fSAndroid Build Coastguard Worker 
315*38e8c45fSAndroid Build Coastguard Worker     hwc_layer_1_t *layer = &list->hwLayers[0];
316*38e8c45fSAndroid Build Coastguard Worker     for (std::list<Rectangle>::iterator it = rectangle.begin();
317*38e8c45fSAndroid Build Coastguard Worker          it != rectangle.end(); ++it, ++layer) {
318*38e8c45fSAndroid Build Coastguard Worker         layer->handle = it->texture->handle;
319*38e8c45fSAndroid Build Coastguard Worker         layer->blending = it->blend;
320*38e8c45fSAndroid Build Coastguard Worker         layer->transform = it->transform;
321*38e8c45fSAndroid Build Coastguard Worker         layer->sourceCrop = it->sourceCrop;
322*38e8c45fSAndroid Build Coastguard Worker         layer->displayFrame = it->displayFrame;
323*38e8c45fSAndroid Build Coastguard Worker 
324*38e8c45fSAndroid Build Coastguard Worker         layer->visibleRegionScreen.numRects = 1;
325*38e8c45fSAndroid Build Coastguard Worker         layer->visibleRegionScreen.rects = &layer->displayFrame;
326*38e8c45fSAndroid Build Coastguard Worker     }
327*38e8c45fSAndroid Build Coastguard Worker 
328*38e8c45fSAndroid Build Coastguard Worker     // Perform prepare operation
329*38e8c45fSAndroid Build Coastguard Worker     if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
330*38e8c45fSAndroid Build Coastguard Worker     hwcDevice->prepare(hwcDevice, 1, &list);
331*38e8c45fSAndroid Build Coastguard Worker     if (verbose) {
332*38e8c45fSAndroid Build Coastguard Worker         testPrintI("Post Prepare:");
333*38e8c45fSAndroid Build Coastguard Worker         hwcTestDisplayListPrepareModifiable(list);
334*38e8c45fSAndroid Build Coastguard Worker     }
335*38e8c45fSAndroid Build Coastguard Worker 
336*38e8c45fSAndroid Build Coastguard Worker     // Turn off the geometry changed flag
337*38e8c45fSAndroid Build Coastguard Worker     list->flags &= ~HWC_GEOMETRY_CHANGED;
338*38e8c45fSAndroid Build Coastguard Worker 
339*38e8c45fSAndroid Build Coastguard Worker     // Perform the set operation(s)
340*38e8c45fSAndroid Build Coastguard Worker     if (verbose) {testPrintI("Set:"); }
341*38e8c45fSAndroid Build Coastguard Worker     if (verbose) { hwcTestDisplayListHandles(list); }
342*38e8c45fSAndroid Build Coastguard Worker     list->dpy = dpy;
343*38e8c45fSAndroid Build Coastguard Worker     list->sur = surface;
344*38e8c45fSAndroid Build Coastguard Worker     hwcDevice->set(hwcDevice, 1, &list);
345*38e8c45fSAndroid Build Coastguard Worker 
346*38e8c45fSAndroid Build Coastguard Worker     testDelay(endDelay);
347*38e8c45fSAndroid Build Coastguard Worker 
348*38e8c45fSAndroid Build Coastguard Worker     // Start framework
349*38e8c45fSAndroid Build Coastguard Worker     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
350*38e8c45fSAndroid Build Coastguard Worker     if (rv >= (signed) sizeof(cmd) - 1) {
351*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
352*38e8c45fSAndroid Build Coastguard Worker         exit(6);
353*38e8c45fSAndroid Build Coastguard Worker     }
354*38e8c45fSAndroid Build Coastguard Worker     testExecCmd(cmd);
355*38e8c45fSAndroid Build Coastguard Worker 
356*38e8c45fSAndroid Build Coastguard Worker     return 0;
357*38e8c45fSAndroid Build Coastguard Worker }
358*38e8c45fSAndroid Build Coastguard Worker 
359*38e8c45fSAndroid Build Coastguard Worker // Parse string description of rectangle and add it to list of rectangles
360*38e8c45fSAndroid Build Coastguard Worker // to be rendered.
parseRect(const string & rectStr)361*38e8c45fSAndroid Build Coastguard Worker static Rectangle parseRect(const string& rectStr)
362*38e8c45fSAndroid Build Coastguard Worker {
363*38e8c45fSAndroid Build Coastguard Worker     int rv;
364*38e8c45fSAndroid Build Coastguard Worker     string str;
365*38e8c45fSAndroid Build Coastguard Worker     bool   error;
366*38e8c45fSAndroid Build Coastguard Worker     istringstream in(rectStr);
367*38e8c45fSAndroid Build Coastguard Worker     const struct hwcTestGraphicFormat *format;
368*38e8c45fSAndroid Build Coastguard Worker     Rectangle rect;
369*38e8c45fSAndroid Build Coastguard Worker 
370*38e8c45fSAndroid Build Coastguard Worker     // Graphic Format
371*38e8c45fSAndroid Build Coastguard Worker     in >> str;
372*38e8c45fSAndroid Build Coastguard Worker     if (!in) {
373*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Error parsing format from: %s", rectStr.c_str());
374*38e8c45fSAndroid Build Coastguard Worker         exit(20);
375*38e8c45fSAndroid Build Coastguard Worker     }
376*38e8c45fSAndroid Build Coastguard Worker     format = hwcTestGraphicFormatLookup(str.c_str());
377*38e8c45fSAndroid Build Coastguard Worker     if (format == NULL) {
378*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Unknown graphic format in: %s", rectStr.c_str());
379*38e8c45fSAndroid Build Coastguard Worker         exit(21);
380*38e8c45fSAndroid Build Coastguard Worker     }
381*38e8c45fSAndroid Build Coastguard Worker     rect.format = format->format;
382*38e8c45fSAndroid Build Coastguard Worker 
383*38e8c45fSAndroid Build Coastguard Worker     // Display Frame
384*38e8c45fSAndroid Build Coastguard Worker     rect.displayFrame = hwcTestParseHwcRect(in, error);
385*38e8c45fSAndroid Build Coastguard Worker     if (error) {
386*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Invalid display frame in: %s", rectStr.c_str());
387*38e8c45fSAndroid Build Coastguard Worker         exit(22);
388*38e8c45fSAndroid Build Coastguard Worker     }
389*38e8c45fSAndroid Build Coastguard Worker 
390*38e8c45fSAndroid Build Coastguard Worker     // Set default sourceDim and sourceCrop based on size of display frame.
391*38e8c45fSAndroid Build Coastguard Worker     // Default is source size equal to the size of the display frame, with
392*38e8c45fSAndroid Build Coastguard Worker     // the source crop being the entire size of the source frame.
393*38e8c45fSAndroid Build Coastguard Worker     rect.sourceDim = HwcTestDim(rect.displayFrame.right
394*38e8c45fSAndroid Build Coastguard Worker                                      - rect.displayFrame.left,
395*38e8c45fSAndroid Build Coastguard Worker                                  rect.displayFrame.bottom
396*38e8c45fSAndroid Build Coastguard Worker                                      - rect.displayFrame.top);
397*38e8c45fSAndroid Build Coastguard Worker     rect.sourceCrop.left = 0;
398*38e8c45fSAndroid Build Coastguard Worker     rect.sourceCrop.top = 0;
399*38e8c45fSAndroid Build Coastguard Worker     rect.sourceCrop.right = rect.sourceDim.width();
400*38e8c45fSAndroid Build Coastguard Worker     rect.sourceCrop.bottom = rect.sourceDim.height();
401*38e8c45fSAndroid Build Coastguard Worker 
402*38e8c45fSAndroid Build Coastguard Worker     // Optional settings
403*38e8c45fSAndroid Build Coastguard Worker     while ((in.tellg() < (streampos) in.str().length())
404*38e8c45fSAndroid Build Coastguard Worker            && (in.tellg() != (streampos) -1)) {
405*38e8c45fSAndroid Build Coastguard Worker         string attrName;
406*38e8c45fSAndroid Build Coastguard Worker 
407*38e8c45fSAndroid Build Coastguard Worker         in >> attrName;
408*38e8c45fSAndroid Build Coastguard Worker         if (in.eof()) { break; }
409*38e8c45fSAndroid Build Coastguard Worker         if (!in) {
410*38e8c45fSAndroid Build Coastguard Worker             testPrintE("Error reading attribute name in: %s",
411*38e8c45fSAndroid Build Coastguard Worker                        rectStr.c_str());
412*38e8c45fSAndroid Build Coastguard Worker             exit(23);
413*38e8c45fSAndroid Build Coastguard Worker         }
414*38e8c45fSAndroid Build Coastguard Worker 
415*38e8c45fSAndroid Build Coastguard Worker         // Transform
416*38e8c45fSAndroid Build Coastguard Worker         if (attrName == "transform:") { // Transform
417*38e8c45fSAndroid Build Coastguard Worker             string str;
418*38e8c45fSAndroid Build Coastguard Worker 
419*38e8c45fSAndroid Build Coastguard Worker             in >> str;
420*38e8c45fSAndroid Build Coastguard Worker             if (str == "none") {
421*38e8c45fSAndroid Build Coastguard Worker                 rect.transform = 0;
422*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "fliph") {
423*38e8c45fSAndroid Build Coastguard Worker                 rect.transform = HWC_TRANSFORM_FLIP_H;
424*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "flipv") {
425*38e8c45fSAndroid Build Coastguard Worker                 rect.transform = HWC_TRANSFORM_FLIP_V;
426*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "rot90") {
427*38e8c45fSAndroid Build Coastguard Worker                 rect.transform = HWC_TRANSFORM_ROT_90;
428*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "rot180") {
429*38e8c45fSAndroid Build Coastguard Worker                 rect.transform = HWC_TRANSFORM_ROT_180;
430*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "rot270") {
431*38e8c45fSAndroid Build Coastguard Worker                 rect.transform = HWC_TRANSFORM_ROT_270;
432*38e8c45fSAndroid Build Coastguard Worker             } else {
433*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Unknown transform of \"%s\" in: %s", str.c_str(),
434*38e8c45fSAndroid Build Coastguard Worker                            rectStr.c_str());
435*38e8c45fSAndroid Build Coastguard Worker                 exit(24);
436*38e8c45fSAndroid Build Coastguard Worker             }
437*38e8c45fSAndroid Build Coastguard Worker         } else if (attrName == "blend:") { // Blend
438*38e8c45fSAndroid Build Coastguard Worker             string str;
439*38e8c45fSAndroid Build Coastguard Worker 
440*38e8c45fSAndroid Build Coastguard Worker             in >> str;
441*38e8c45fSAndroid Build Coastguard Worker             if (str == string("none")) {
442*38e8c45fSAndroid Build Coastguard Worker                 rect.blend = HWC_BLENDING_NONE;
443*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "premult") {
444*38e8c45fSAndroid Build Coastguard Worker                 rect.blend = HWC_BLENDING_PREMULT;
445*38e8c45fSAndroid Build Coastguard Worker             } else if (str == "coverage") {
446*38e8c45fSAndroid Build Coastguard Worker                 rect.blend = HWC_BLENDING_COVERAGE;
447*38e8c45fSAndroid Build Coastguard Worker             } else {
448*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Unknown blend of \"%s\" in: %s", str.c_str(),
449*38e8c45fSAndroid Build Coastguard Worker                            rectStr.c_str());
450*38e8c45fSAndroid Build Coastguard Worker                 exit(25);
451*38e8c45fSAndroid Build Coastguard Worker             }
452*38e8c45fSAndroid Build Coastguard Worker         } else if (attrName == "color:") { // Color
453*38e8c45fSAndroid Build Coastguard Worker             rect.color = hwcTestParseColor(in, error);
454*38e8c45fSAndroid Build Coastguard Worker             if (error) {
455*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Error parsing color in: %s", rectStr.c_str());
456*38e8c45fSAndroid Build Coastguard Worker                 exit(26);
457*38e8c45fSAndroid Build Coastguard Worker             }
458*38e8c45fSAndroid Build Coastguard Worker         } else if (attrName == "alpha:") { // Alpha
459*38e8c45fSAndroid Build Coastguard Worker             in >> rect.alpha;
460*38e8c45fSAndroid Build Coastguard Worker             if (!in) {
461*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Error parsing value for alpha attribute in: %s",
462*38e8c45fSAndroid Build Coastguard Worker                            rectStr.c_str());
463*38e8c45fSAndroid Build Coastguard Worker                 exit(27);
464*38e8c45fSAndroid Build Coastguard Worker             }
465*38e8c45fSAndroid Build Coastguard Worker         } else if (attrName == "sourceDim:") { // Source Dimension
466*38e8c45fSAndroid Build Coastguard Worker            rect.sourceDim = hwcTestParseDim(in, error);
467*38e8c45fSAndroid Build Coastguard Worker             if (error) {
468*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Error parsing source dimenision in: %s",
469*38e8c45fSAndroid Build Coastguard Worker                            rectStr.c_str());
470*38e8c45fSAndroid Build Coastguard Worker                 exit(28);
471*38e8c45fSAndroid Build Coastguard Worker             }
472*38e8c45fSAndroid Build Coastguard Worker         } else if (attrName == "sourceCrop:") { // Source Crop
473*38e8c45fSAndroid Build Coastguard Worker             rect.sourceCrop = hwcTestParseHwcRect(in, error);
474*38e8c45fSAndroid Build Coastguard Worker             if (error) {
475*38e8c45fSAndroid Build Coastguard Worker                 testPrintE("Error parsing source crop in: %s",
476*38e8c45fSAndroid Build Coastguard Worker                            rectStr.c_str());
477*38e8c45fSAndroid Build Coastguard Worker                 exit(29);
478*38e8c45fSAndroid Build Coastguard Worker             }
479*38e8c45fSAndroid Build Coastguard Worker         } else { // Unknown attribute
480*38e8c45fSAndroid Build Coastguard Worker             testPrintE("Unknown attribute of \"%s\" in: %s", attrName.c_str(),
481*38e8c45fSAndroid Build Coastguard Worker                        rectStr.c_str());
482*38e8c45fSAndroid Build Coastguard Worker             exit(30);
483*38e8c45fSAndroid Build Coastguard Worker         }
484*38e8c45fSAndroid Build Coastguard Worker     }
485*38e8c45fSAndroid Build Coastguard Worker 
486*38e8c45fSAndroid Build Coastguard Worker     // Validate
487*38e8c45fSAndroid Build Coastguard Worker     if (((uint32_t) rect.sourceCrop.left >= rect.sourceDim.width())
488*38e8c45fSAndroid Build Coastguard Worker         || ((uint32_t) rect.sourceCrop.right > rect.sourceDim.width())
489*38e8c45fSAndroid Build Coastguard Worker         || ((uint32_t) rect.sourceCrop.top >= rect.sourceDim.height())
490*38e8c45fSAndroid Build Coastguard Worker         || ((uint32_t) rect.sourceCrop.bottom > rect.sourceDim.height())) {
491*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Invalid source crop in: %s", rectStr.c_str());
492*38e8c45fSAndroid Build Coastguard Worker         exit(31);
493*38e8c45fSAndroid Build Coastguard Worker     }
494*38e8c45fSAndroid Build Coastguard Worker     if ((rect.displayFrame.left >= width)
495*38e8c45fSAndroid Build Coastguard Worker         || (rect.displayFrame.right > width)
496*38e8c45fSAndroid Build Coastguard Worker         || (rect.displayFrame.top >= height)
497*38e8c45fSAndroid Build Coastguard Worker         || (rect.displayFrame.bottom > height)) {
498*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Invalid display frame in: %s", rectStr.c_str());
499*38e8c45fSAndroid Build Coastguard Worker         exit(32);
500*38e8c45fSAndroid Build Coastguard Worker     }
501*38e8c45fSAndroid Build Coastguard Worker     if ((rect.alpha < 0.0) || (rect.alpha > 1.0)) {
502*38e8c45fSAndroid Build Coastguard Worker         testPrintE("Invalid alpha in: %s", rectStr.c_str());
503*38e8c45fSAndroid Build Coastguard Worker         exit(33);
504*38e8c45fSAndroid Build Coastguard Worker     }
505*38e8c45fSAndroid Build Coastguard Worker 
506*38e8c45fSAndroid Build Coastguard Worker     // Create source texture
507*38e8c45fSAndroid Build Coastguard Worker     rect.texture = new GraphicBuffer(rect.sourceDim.width(),
508*38e8c45fSAndroid Build Coastguard Worker                                      rect.sourceDim.height(),
509*38e8c45fSAndroid Build Coastguard Worker                                      rect.format, texUsage);
510*38e8c45fSAndroid Build Coastguard Worker     if ((rv = rect.texture->initCheck()) != NO_ERROR) {
511*38e8c45fSAndroid Build Coastguard Worker         testPrintE("source texture initCheck failed, rv: %i", rv);
512*38e8c45fSAndroid Build Coastguard Worker         testPrintE("  %s", rectStr.c_str());
513*38e8c45fSAndroid Build Coastguard Worker 
514*38e8c45fSAndroid Build Coastguard Worker     }
515*38e8c45fSAndroid Build Coastguard Worker 
516*38e8c45fSAndroid Build Coastguard Worker     // Fill with uniform color
517*38e8c45fSAndroid Build Coastguard Worker     hwcTestFillColor(rect.texture.get(), rect.color, rect.alpha);
518*38e8c45fSAndroid Build Coastguard Worker     if (verbose) {
519*38e8c45fSAndroid Build Coastguard Worker         testPrintI("    buf: %p handle: %p format: %s width: %u height: %u "
520*38e8c45fSAndroid Build Coastguard Worker                    "color: %s alpha: %f",
521*38e8c45fSAndroid Build Coastguard Worker                    rect.texture.get(), rect.texture->handle, format->desc,
522*38e8c45fSAndroid Build Coastguard Worker                    rect.sourceDim.width(), rect.sourceDim.height(),
523*38e8c45fSAndroid Build Coastguard Worker                    string(rect.color).c_str(), rect.alpha);
524*38e8c45fSAndroid Build Coastguard Worker     }
525*38e8c45fSAndroid Build Coastguard Worker 
526*38e8c45fSAndroid Build Coastguard Worker     return rect;
527*38e8c45fSAndroid Build Coastguard Worker }
528*38e8c45fSAndroid Build Coastguard Worker 
init(void)529*38e8c45fSAndroid Build Coastguard Worker void init(void)
530*38e8c45fSAndroid Build Coastguard Worker {
531*38e8c45fSAndroid Build Coastguard Worker     // Seed pseudo random number generator
532*38e8c45fSAndroid Build Coastguard Worker     // Needed so that the pad areas of frames are filled with a deterministic
533*38e8c45fSAndroid Build Coastguard Worker     // pseudo random value.
534*38e8c45fSAndroid Build Coastguard Worker     srand48(0);
535*38e8c45fSAndroid Build Coastguard Worker 
536*38e8c45fSAndroid Build Coastguard Worker     hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
537*38e8c45fSAndroid Build Coastguard Worker 
538*38e8c45fSAndroid Build Coastguard Worker     hwcTestOpenHwc(&hwcDevice);
539*38e8c45fSAndroid Build Coastguard Worker }
540*38e8c45fSAndroid Build Coastguard Worker 
printSyntax(const char * cmd)541*38e8c45fSAndroid Build Coastguard Worker void printSyntax(const char *cmd)
542*38e8c45fSAndroid Build Coastguard Worker {
543*38e8c45fSAndroid Build Coastguard Worker     testPrintE("  %s [options] (graphicFormat displayFrame [attributes],)...",
544*38e8c45fSAndroid Build Coastguard Worker                cmd);
545*38e8c45fSAndroid Build Coastguard Worker     testPrintE("    options:");
546*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      -D End of test delay");
547*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      -v Verbose");
548*38e8c45fSAndroid Build Coastguard Worker     testPrintE("");
549*38e8c45fSAndroid Build Coastguard Worker     testPrintE("    graphic formats:");
550*38e8c45fSAndroid Build Coastguard Worker     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
551*38e8c45fSAndroid Build Coastguard Worker         testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
552*38e8c45fSAndroid Build Coastguard Worker     }
553*38e8c45fSAndroid Build Coastguard Worker     testPrintE("");
554*38e8c45fSAndroid Build Coastguard Worker     testPrintE("    displayFrame");
555*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      [left, top, right, bottom]");
556*38e8c45fSAndroid Build Coastguard Worker     testPrintE("");
557*38e8c45fSAndroid Build Coastguard Worker     testPrintE("    attributes:");
558*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      transform: none | fliph | flipv | rot90 | rot180 "
559*38e8c45fSAndroid Build Coastguard Worker                " | rot270");
560*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      blend: none | premult | coverage");
561*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      color: [0.##, 0.##, 0.##]");
562*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      alpha: 0.##");
563*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      sourceDim: [width, height]");
564*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      sourceCrop: [left, top, right, bottom]");
565*38e8c45fSAndroid Build Coastguard Worker     testPrintE("");
566*38e8c45fSAndroid Build Coastguard Worker     testPrintE("    Example:");
567*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      # White YV12 rectangle, with overlapping turquoise ");
568*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      #  RGBA8888 rectangle at 30%% (alpha: 0.7) transparency");
569*38e8c45fSAndroid Build Coastguard Worker     testPrintE("      %s -v -D 30.0 \\", cmd);
570*38e8c45fSAndroid Build Coastguard Worker     testPrintE("        YV12 [50, 80, 200, 300] transform: none \\");
571*38e8c45fSAndroid Build Coastguard Worker     testPrintE("          color: [1.0, 0.5, 0.5], \\");
572*38e8c45fSAndroid Build Coastguard Worker     testPrintE("        RGBA8888 [100, 150, 300, 400] blend: coverage \\");
573*38e8c45fSAndroid Build Coastguard Worker     testPrintE("          color: [0.251, 0.878, 0.816] alpha: 0.7 \\");
574*38e8c45fSAndroid Build Coastguard Worker     testPrintE("          sourceDim: [50, 60] sourceCrop: [5, 8, 12, 15]");
575*38e8c45fSAndroid Build Coastguard Worker }
576