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