1 /*
2 * Copyright (C) 2015 Advanced Driver Information Technology Joint Venture GmbH
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/stat.h>
28 #include <sys/time.h>
29 #include <pthread.h>
30 #include <getopt.h>
31
32 #include "ilm_control.h"
33
34 t_ilm_uint screenWidth;
35 t_ilm_uint screenHeight;
36 static t_ilm_uint layer = 0;
37 pthread_mutex_t mutex;
38 static pthread_cond_t waiterVariable = PTHREAD_COND_INITIALIZER;
39 static int number_of_surfaces = 0;
40 char display_name[256] = {0};
41
configure_ilm_surface(t_ilm_uint id,t_ilm_uint width,t_ilm_uint height)42 static void configure_ilm_surface(t_ilm_uint id, t_ilm_uint width, t_ilm_uint height)
43 {
44 ilm_surfaceSetDestinationRectangle(id, 0, 0, width, height);
45 ilm_surfaceSetSourceRectangle(id, 0, 0, width, height);
46 ilm_surfaceSetVisibility(id, ILM_TRUE);
47 ilm_layerAddSurface(layer,id);
48 ilm_surfaceRemoveNotification(id);
49
50 ilm_commitChanges();
51 pthread_cond_signal( &waiterVariable );
52
53 printf("layer-add-surfaces: surface (%u) configured with:\n"
54 " dst region: x:0 y:0 w:%u h:%u\n"
55 " src region: x:0 y:0 w:%u h:%u\n"
56 " visibility: TRUE\n"
57 " added to layer (%u)\n", id, width, height, width, height,layer);
58 }
59
surfaceCallbackFunction(t_ilm_uint id,struct ilmSurfaceProperties * sp,t_ilm_notification_mask m)60 static void surfaceCallbackFunction(t_ilm_uint id, struct ilmSurfaceProperties* sp, t_ilm_notification_mask m)
61 {
62 if ((unsigned)m & ILM_NOTIFICATION_CONFIGURED)
63 {
64 configure_ilm_surface(id, sp->origSourceWidth, sp->origSourceHeight);
65 }
66 }
67
callbackFunction(ilmObjectType object,t_ilm_uint id,t_ilm_bool created,void * user_data)68 static void callbackFunction(ilmObjectType object, t_ilm_uint id, t_ilm_bool created, void *user_data)
69 {
70 (void)user_data;
71 struct ilmSurfaceProperties sp;
72
73 if (object == ILM_SURFACE) {
74 if (created) {
75 if (number_of_surfaces > 0) {
76 number_of_surfaces--;
77 printf("layer-add-surfaces: surface (%d) created\n",id);
78 // always get configured event to follow the surface changings
79 ilm_surfaceAddNotification(id,&surfaceCallbackFunction);
80 ilm_commitChanges();
81 ilm_getPropertiesOfSurface(id, &sp);
82
83 if ((sp.origSourceWidth != 0) && (sp.origSourceHeight !=0))
84 { // surface is already configured
85 configure_ilm_surface(id, sp.origSourceWidth, sp.origSourceHeight);
86 }
87 }
88 }
89 else if(!created)
90 printf("layer-add-surfaces: surface (%u) destroyed\n",id);
91 } else if (object == ILM_LAYER) {
92 if (created)
93 printf("layer-add-surfaces: layer (%u) created\n",id);
94 else if(!created)
95 printf("layer-add-surfaces: layer (%u) destroyed\n",id);
96 }
97 }
98
shutdownCallbackFunction(t_ilm_shutdown_error_type error_type,int errornum,void * user_data)99 static void shutdownCallbackFunction(t_ilm_shutdown_error_type error_type,
100 int errornum,
101 void *user_data)
102 {
103 (void) user_data;
104
105 switch (error_type) {
106 case ILM_ERROR_WAYLAND:
107 {
108 printf("layer-add-surfaces: exit, ilm shutdown due to wayland error: %s\n",
109 strerror(errornum));
110 break;
111 }
112 case ILM_ERROR_POLL:
113 {
114 printf("layer-add-surfaces: exit, ilm shutdown due to poll error: %s\n",
115 strerror(errornum));
116 break;
117 }
118 default:
119 {
120 printf("layer-add-surfaces: exit, ilm shutdown due to unknown reason: %s\n",
121 strerror(errornum));
122 }
123 }
124
125 exit(1);
126 }
127
128 /* Choose the display with the largest resolution.*/
choose_screen(void)129 static t_ilm_uint choose_screen(void)
130 {
131 struct ilmScreenProperties screenProperties;
132 t_ilm_uint* screen_IDs = NULL;
133 t_ilm_uint screen_ID = 0;
134 t_ilm_uint screen_count = 0;
135 t_ilm_uint choosen_width = 0;
136 t_ilm_uint choosen_height = 0;
137 t_ilm_uint i;
138
139 ilm_getScreenIDs(&screen_count, &screen_IDs);
140
141 for (i = 0; i<screen_count; i++)
142 {
143 ilm_getPropertiesOfScreen(screen_IDs[i], &screenProperties);
144 if (!strcmp(screenProperties.connectorName, display_name)) {
145 choosen_width = screenProperties.screenWidth;
146 choosen_height = screenProperties.screenHeight;
147 screen_ID = screen_IDs[i];
148 break;
149 }
150 else if (screenProperties.screenWidth > choosen_width) {
151 choosen_width = screenProperties.screenWidth;
152 choosen_height = screenProperties.screenHeight;
153 screen_ID = screen_IDs[i];
154 }
155 }
156
157 screenWidth = choosen_width;
158 screenHeight = choosen_height;
159
160 free(screen_IDs);
161
162 return screen_ID;
163 }
164
165 static int
usage(int ret)166 usage(int ret)
167 {
168 fprintf(stderr, " -h, --help display this help and exit.\n"
169 " -d, --display-name name of the display which will be used,\n"
170 " e.g.: HDMI-A-1, LVDS1\n"
171 " If it is not set, display with highest resolution is used.\n"
172 " -l, --layer-id id of the used ILM layer. It has to be set\n"
173 " -s, --surface-count number of surfaces which will be added to\n"
174 " the layer. It has to be set\n");
175 exit(ret);
176 }
177
parse_options(int argc,char * argv[])178 void parse_options(int argc, char *argv[])
179 {
180 int opt;
181 static const struct option options[] = {
182 { "help", no_argument, NULL, 'h' },
183 { "layer-id", required_argument, 0, 'l' },
184 { "surface-count", required_argument, 0, 's' },
185 { "display-name", required_argument, NULL, 'd' },
186 { 0, 0, NULL, 0 }
187 };
188
189 while (1) {
190 opt = getopt_long(argc, argv, "hl:s:d:", options, NULL);
191
192 if (opt == -1)
193 break;
194
195 switch (opt) {
196 case 'h':
197 usage(0);
198 break;
199 case 'l':
200 layer = atoi(optarg);
201 break;
202 case 's':
203 number_of_surfaces = atoi(optarg);
204 break;
205 case 'd':
206 strcpy(display_name, optarg);
207 break;
208 default:
209 usage(-1);
210 break;
211 }
212 }
213
214 printf("layer-add-surfaces: layer (%u) on display (%s) created, waiting for %d surfaces ...\n",
215 layer,
216 display_name,
217 number_of_surfaces);
218 }
219
main(int argc,char * argv[])220 int main (int argc, char *argv[])
221 {
222 // Get command-line options
223 if ( argc < 3) {
224 usage(-1);
225 }
226
227 // Check the first character of the first parameter
228 if (!strncmp(argv[1], "-", 1)) {
229 parse_options(argc, argv);
230 } else {
231 layer = strtol(argv[1], NULL, 0);
232 number_of_surfaces = strtol(argv[2], NULL, 0);
233 }
234
235 if (!number_of_surfaces || !layer)
236 usage(-1);
237
238 pthread_mutexattr_t a;
239 if (pthread_mutexattr_init(&a) != 0)
240 {
241 return -1;
242 }
243
244 if (pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE) != 0)
245 {
246 pthread_mutexattr_destroy(&a);
247 return -1;
248 }
249
250 if (pthread_mutex_init(&mutex, &a) != 0)
251 {
252 pthread_mutexattr_destroy(&a);
253 fprintf(stderr, "layer-add-surfaces: failed to initialize pthread_mutex\n");
254 return -1;
255 }
256
257 pthread_mutexattr_destroy(&a);
258
259 t_ilm_layer renderOrder[1];
260 t_ilm_uint screen_ID;
261 renderOrder[0] = layer;
262 if (ilm_init() == ILM_FAILED) {
263 fprintf(stderr, "layer-add-surfaces: ilm_init failed\n");
264 return -1;
265 }
266
267 ilm_registerShutdownNotification(shutdownCallbackFunction, NULL);
268
269 screen_ID = choose_screen();
270 ilm_layerCreateWithDimension(&layer, screenWidth, screenHeight);
271 printf("layer-add-surfaces: layer (%d) destination region: x:0 y:0 w:%u h:%u\n", layer, screenWidth, screenHeight);
272 ilm_layerSetVisibility(layer,ILM_TRUE);
273 printf("layer-add-surfaces: layer (%d) visibility TRUE\n", layer);
274 ilm_displaySetRenderOrder(screen_ID, renderOrder, 1);
275 ilm_commitChanges();
276 ilm_registerNotification(callbackFunction, NULL);
277
278 while (number_of_surfaces > 0) {
279 pthread_mutex_lock(&mutex);
280 pthread_cond_wait( &waiterVariable, &mutex);
281 }
282
283 ilm_unregisterNotification();
284 ilm_destroy();
285
286 return 0;
287 }
288