• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *
3  * Copyright (c) 2015 Advanced Driver Information Technology.
4  * This code is developed by Advanced Driver Information Technology.
5  * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
6  * All rights reserved.
7  *
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *        http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  ****************************************************************************/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <math.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <wayland-client-protocol.h>
32 #include "multi-touch-viewer.h"
33 
34 #define WINDOW_TITLE "multi_touch_viewer"
35 #define WINDOW_WIDTH  1080
36 #define WINDOW_HEIGHT 1920
37 #define SURFACE_ID    4000
38 #define LAYER_ID      4000
39 
40 #ifndef _UNUSED_
41 #    define _UNUSED_(x) (void)x
42 #endif
43 
44 static const char *gp_vert_shader_text =
45     "uniform mediump float uX;                     \n"
46     "uniform mediump float uY;                     \n"
47     "uniform mediump float uWidth;                 \n"
48     "uniform mediump float uHeight;                \n"
49     "uniform vec3 uColor;                          \n"
50     "attribute vec4 pos;                           \n"
51     "varying vec4 v_color;                         \n"
52     "void main() {                                 \n"
53     "    mediump vec4 position;                    \n"
54     "    position.xy = vec2(uX + uWidth  * pos.x,  \n"
55     "                       uY + uHeight * pos.y); \n"
56     "    position.xy = 2.0 * position.xy - 1.0;    \n"
57     "    position.zw = vec2(0.0, 1.0);             \n"
58     "    gl_Position = position;                   \n"
59     "    v_color = vec4(uColor, 1.0);              \n"
60     "}                                             \n";
61 
62 static const char *gp_frag_shader_text =
63     "precision mediump float;        \n"
64     "varying vec4 v_color;           \n"
65     "void main() {                   \n"
66     "    gl_FragColor = v_color;     \n"
67     "}                               \n";
68 
69 static struct touch_event_test_params *gp_test_params = NULL;
70 
71 static int g_is_print_log = 0;
72 
73 /******************************************************************************/
74 
75 static void frame_callback(void *, struct wl_callback *, uint32_t);
76 
77 static void
update_touch_point(struct touch_event_test_params * p_params,int ev,float x,float y,int32_t id,uint32_t time)78 update_touch_point(struct touch_event_test_params *p_params, int ev,
79                    float x, float y, int32_t id, uint32_t time)
80 {
81     struct touch_point_params *p_point_params;
82     struct event_log elog;
83 
84     if (NULL == p_params)
85     {
86         return;
87     }
88 
89     wl_list_for_each(p_point_params, &p_params->touch_point_list, link)
90     {
91         if (p_point_params->id != id)
92             continue;
93 
94         switch (ev) {
95         case TOUCH_DOWN:
96         case TOUCH_MOTION:
97             p_point_params->display = 1;
98             p_point_params->x = x;
99             p_point_params->y = y;
100             break;
101         case TOUCH_UP:
102             p_point_params->display = 0;
103             break;
104         default:
105             break;
106         }
107         break;
108     }
109 
110     if (g_is_print_log)
111     {
112         printf("[%d] %8.2f %8.2f (%s)\n", id, x, y,
113                (ev == TOUCH_MOTION) ? "MOTION":
114                (ev == TOUCH_DOWN)   ? "DOWN"  : "UP");
115     }
116 
117     /* store event log */
118     elog.event = ev;
119     elog.x     = x;
120     elog.y     = y;
121     elog.id    = id;
122     elog.time  = time;
123     log_array_add(&p_params->log_array, &elog);
124 }
125 
126 /******************************************************************************/
127 
128 static void
frame_callback(void * p_data,struct wl_callback * p_cb,uint32_t time)129 frame_callback(void *p_data, struct wl_callback *p_cb, uint32_t time)
130 {
131     _UNUSED_(time);
132 
133     WindowScheduleRedraw((struct WaylandEglWindow*)p_data);
134 
135     if (NULL != p_cb)
136         wl_callback_destroy(p_cb);
137 }
138 
139 static const struct wl_callback_listener frame_listener = {
140     frame_callback
141 };
142 
143 static void
touch_handle_down(void * p_data,struct wl_touch * p_touch,uint32_t serial,uint32_t time,struct wl_surface * p_surface,int32_t id,wl_fixed_t x_w,wl_fixed_t y_w)144 touch_handle_down(void *p_data, struct wl_touch *p_touch, uint32_t serial,
145                   uint32_t time, struct wl_surface *p_surface, int32_t id,
146                   wl_fixed_t x_w, wl_fixed_t y_w)
147 {
148     _UNUSED_(p_touch);
149     _UNUSED_(serial);
150     _UNUSED_(p_surface);
151 
152     update_touch_point((struct touch_event_test_params*)p_data,
153                        TOUCH_DOWN,
154                        (float)wl_fixed_to_double(x_w),
155                        (float)wl_fixed_to_double(y_w),
156                        id, time);
157 }
158 
159 static void
touch_handle_up(void * p_data,struct wl_touch * p_touch,uint32_t serial,uint32_t time,int32_t id)160 touch_handle_up(void *p_data, struct wl_touch *p_touch, uint32_t serial,
161                 uint32_t time, int32_t id)
162 {
163     _UNUSED_(p_touch);
164     _UNUSED_(serial);
165 
166     update_touch_point((struct touch_event_test_params*)p_data,
167                        TOUCH_UP,
168                        0,
169                        0,
170                        id, time);
171 }
172 
173 static void
touch_handle_motion(void * p_data,struct wl_touch * p_touch,uint32_t time,int32_t id,wl_fixed_t x_w,wl_fixed_t y_w)174 touch_handle_motion(void *p_data, struct wl_touch *p_touch, uint32_t time,
175                     int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
176 {
177     _UNUSED_(p_touch);
178 
179     update_touch_point((struct touch_event_test_params*)p_data,
180                        TOUCH_MOTION,
181                        (float)wl_fixed_to_double(x_w),
182                        (float)wl_fixed_to_double(y_w),
183                        id, time);
184 }
185 
186 static void
touch_handle_frame(void * p_data,struct wl_touch * p_touch)187 touch_handle_frame(void *p_data, struct wl_touch *p_touch)
188 {
189     _UNUSED_(p_data);
190     _UNUSED_(p_touch);
191 
192     update_touch_point(NULL, TOUCH_FRAME, 0, 0, 0, 0);
193 }
194 
195 static void
touch_handle_cancel(void * p_data,struct wl_touch * p_touch)196 touch_handle_cancel(void *p_data, struct wl_touch *p_touch)
197 {
198     _UNUSED_(p_data);
199     _UNUSED_(p_touch);
200 
201     update_touch_point(NULL, TOUCH_CANCEL, 0, 0, 0, 0);
202 }
203 
204 static void
touch_handle_shape(void * p_data,struct wl_touch * p_touch,int32_t id,wl_fixed_t major,wl_fixed_t minor)205 touch_handle_shape(void *p_data, struct wl_touch *p_touch,
206                    int32_t id, wl_fixed_t major, wl_fixed_t minor)
207 {
208     _UNUSED_(p_data);
209     _UNUSED_(p_touch);
210     _UNUSED_(id);
211     _UNUSED_(major);
212     _UNUSED_(minor);
213 }
214 
215 static void
touch_handle_orientation(void * p_data,struct wl_touch * p_touch,int32_t id,wl_fixed_t orientation)216 touch_handle_orientation(void *p_data, struct wl_touch *p_touch,
217                          int32_t id, wl_fixed_t orientation)
218 {
219     _UNUSED_(p_data);
220     _UNUSED_(p_touch);
221     _UNUSED_(id);
222     _UNUSED_(orientation);
223 }
224 
225 static const struct wl_touch_listener touch_listener = {
226     touch_handle_down,
227     touch_handle_up,
228     touch_handle_motion,
229     touch_handle_frame,
230     touch_handle_cancel,
231     touch_handle_shape,
232     touch_handle_orientation
233 };
234 
235 static void
seat_capabilities(void * p_data,struct wl_seat * p_seat,uint32_t caps)236 seat_capabilities(void *p_data, struct wl_seat *p_seat, uint32_t caps)
237 {
238     struct touch_event_test_params *p_params =
239         (struct touch_event_test_params*)p_data;
240 
241     if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !p_params->p_touch)
242     {
243         p_params->p_touch = wl_seat_get_touch(p_seat);
244         wl_touch_add_listener(p_params->p_touch, &touch_listener, p_data);
245     }
246     else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && p_params->p_touch)
247     {
248         wl_touch_destroy(p_params->p_touch);
249         p_params->p_touch = NULL;
250     }
251 }
252 
253 static const struct wl_seat_listener seat_listener = {
254     seat_capabilities,
255     NULL /* name: since version 2 */
256 };
257 
258 static void
display_global_handler(struct WaylandDisplay * p_display,uint32_t name,const char * p_interface,uint32_t version,void * p_data)259 display_global_handler(struct WaylandDisplay *p_display, uint32_t name,
260                        const char *p_interface, uint32_t version, void *p_data)
261 {
262     _UNUSED_(version);
263     struct touch_event_test_params *p_params =
264         (struct touch_event_test_params*)p_data;
265 
266     if (0 == strcmp(p_interface, "wl_seat"))
267     {
268         p_params->p_seat = wl_registry_bind(p_display->p_registry,
269                                             name, &wl_seat_interface, 1);
270         wl_seat_add_listener(p_params->p_seat, &seat_listener, p_data);
271     }
272 }
273 
274 /******************************************************************************/
275 
276 static void
draw_grid(int direction,GLfloat width,GLfloat height,float step,struct touch_event_test_params * p_params)277 draw_grid(int direction, GLfloat width, GLfloat height, float step,
278           struct touch_event_test_params *p_params)
279 {
280     GLfloat coord       = step;
281     GLfloat uX          = 0.0f;
282     GLfloat uY          = 0.0f;
283     GLfloat dest_width  = 0.0f;
284     GLfloat dest_height = 0.0f;
285     GLfloat dest_coord;
286 
287     GLfloat vertices[2][2] = {
288         {0.0f, 0.0f},
289         {0.0f, 0.0f}
290     };
291 #if 0
292     GLfloat line_color[3] = {0.25f, 0.28f, 0.80f};
293 #else
294     GLfloat line_color[3] = {0.1, 0.1, 0.1};
295 #endif
296 
297     switch (direction)
298     {
299     case 0: /* verticality   */
300         vertices[1][1] = 1.0f;
301         dest_coord = width;
302         break;
303     case 1: /* horizontality */
304         vertices[1][0] = 1.0f;
305         dest_coord = height;
306         break;
307     default:
308         return;
309     }
310 
311     glLineWidth(2.0f);
312 
313     coord = step;
314     while (coord < dest_coord)
315     {
316         if (direction == 0)
317         {
318             uX          = coord / width;
319             dest_height = height;
320         }
321         else
322         {
323             uY         = 1.0f - coord / height;
324             dest_width = width;
325         }
326 
327         glUniform1fv(p_params->gl.loc_x, 1, &uX);
328         glUniform1fv(p_params->gl.loc_y, 1, &uY);
329         glUniform1fv(p_params->gl.loc_w, 1, &dest_width);
330         glUniform1fv(p_params->gl.loc_h, 1, &dest_height);
331         glUniform3fv(p_params->gl.loc_col, 1, line_color);
332 
333         glVertexAttribPointer(p_params->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
334 
335         glDrawArrays(GL_LINES, 0, 2);
336 
337         coord += step;
338     }
339 }
340 
341 static void
redraw_handler(struct WaylandEglWindow * p_window,void * p_data)342 redraw_handler(struct WaylandEglWindow *p_window, void *p_data)
343 {
344     GLfloat w, h, uX, uY;
345     GLfloat view_width, view_height;
346     GLfloat dest_width, dest_height;
347     struct touch_event_test_params *p_params = (struct touch_event_test_params*)p_data;
348     struct touch_point_params *p_point_params;
349 
350     DisplayAcquireWindowSurface(p_window->p_display, p_window);
351 
352     view_width  = p_window->geometry.width;
353     view_height = p_window->geometry.height;
354 
355     glViewport(0, 0, (int)view_width, (int)view_height);
356 
357 #if 0
358     glClearColor(0.60, 0.84, 0.91, 1.0);
359 #else
360     glClearColor(0.7, 0.7, 0.7, 1.0);
361 #endif
362     glClear(GL_COLOR_BUFFER_BIT);
363 
364     glEnableVertexAttribArray(p_params->gl.pos);
365 
366     /* readraw touch areas */
367     draw_grid(0, view_width, view_height, 100.0f, p_params);
368     draw_grid(1, view_width, view_height, 100.0f, p_params);
369 
370     /* redraw pointer circles */
371     wl_list_for_each(p_point_params, &p_params->touch_point_list, link)
372     {
373         if (0 == p_point_params->display)
374             continue;
375 
376         w = h = p_point_params->r * 2.0;
377 
378         uX = (p_point_params->x - p_point_params->r)/ view_width;
379         uY = 1.0f - (p_point_params->y + p_point_params->r) / view_height;
380 
381         dest_width  = w / view_width;
382         dest_height = h / view_height;
383 
384         glUniform1fv(p_params->gl.loc_x, 1, &uX);
385         glUniform1fv(p_params->gl.loc_y, 1, &uY);
386         glUniform1fv(p_params->gl.loc_w, 1, &dest_width);
387         glUniform1fv(p_params->gl.loc_h, 1, &dest_height);
388         glUniform3fv(p_params->gl.loc_col, 1, p_point_params->color);
389 
390         glVertexAttribPointer(p_params->gl.pos, 2,
391             GL_FLOAT, GL_FALSE, 0, p_point_params->p_vertices);
392 
393         glDrawArrays(GL_TRIANGLE_FAN, 0, p_point_params->n_vtx);
394     }
395 
396     glDisableVertexAttribArray(p_params->gl.pos);
397 
398     struct wl_callback *p_cb = wl_surface_frame(p_window->p_surface);
399     wl_callback_add_listener(p_cb, &frame_listener, p_window);
400 }
401 
402 /******************************************************************************/
403 
404 static GLuint
create_shader(const char * p_source,GLenum shader_type)405 create_shader(const char *p_source, GLenum shader_type)
406 {
407     GLuint shader;
408     GLint status;
409 
410     shader = glCreateShader(shader_type);
411     assert(shader != 0);
412 
413     glShaderSource(shader, 1, (const char**)&p_source, NULL);
414     glCompileShader(shader);
415 
416     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
417     if (0 == status)
418     {
419         char gllog[1000];
420         GLsizei len;
421         glGetShaderInfoLog(shader, sizeof(gllog), &len, gllog);
422         LOG_ERROR("Shader Compiling Failed (%s):\n%*s\n",
423             shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", len, gllog);
424         exit(-1);
425     }
426 
427     return shader;
428 }
429 
430 static void
init_gl(struct touch_event_test_params * p_params)431 init_gl(struct touch_event_test_params *p_params)
432 {
433     GLuint vert, frag;
434     GLuint program;
435     GLint status;
436 
437     vert = create_shader(gp_vert_shader_text, GL_VERTEX_SHADER);
438     frag = create_shader(gp_frag_shader_text, GL_FRAGMENT_SHADER);
439 
440     program = glCreateProgram();
441     glAttachShader(program, frag);
442     glAttachShader(program, vert);
443     glLinkProgram(program);
444 
445     glGetProgramiv(program, GL_LINK_STATUS, &status);
446     if (0 == status)
447     {
448         char gllog[1000];
449         GLsizei len;
450         glGetProgramInfoLog(program, sizeof(gllog), &len, gllog);
451         LOG_ERROR("Shader Linking Failed:\n%*s\n", len, gllog);
452         exit(-1);
453     }
454 
455     glUseProgram(program);
456 
457     p_params->gl.pos = 0;
458 
459     glBindAttribLocation(program, p_params->gl.pos, "pos");
460 
461     p_params->gl.loc_x   = glGetUniformLocation(program, "uX");
462     p_params->gl.loc_y   = glGetUniformLocation(program, "uY");
463     p_params->gl.loc_w   = glGetUniformLocation(program, "uWidth");
464     p_params->gl.loc_h   = glGetUniformLocation(program, "uHeight");
465     p_params->gl.loc_col = glGetUniformLocation(program, "uColor");
466 }
467 
468 #define NUM_OF_TOUCH_POINT_COLOR 5
469 
470 static int
setup_point_params(struct touch_event_test_params * p_params)471 setup_point_params(struct touch_event_test_params *p_params)
472 {
473     struct touch_point_params *p_point_params;
474     int i, j;
475     int n_vtx = 13;
476     float rad = 0.0;
477     float cx  = 0.5;
478     float cy  = 0.5;
479     float step = (float)(M_PI / 6.0);
480     GLfloat colors[NUM_OF_TOUCH_POINT_COLOR][3] = {
481         {1.0f, 0.0f, 0.0f},
482         {0.0f, 1.0f, 0.0f},
483         {0.0f, 0.0f, 1.0f},
484         {1.0f, 0.0f, 1.0f},
485         {1.0f, 1.0f, 0.0f}
486     };
487 
488     for (i = 0; i < NUM_OF_TOUCH_POINT_COLOR; ++i)
489     {
490         p_point_params =
491             (struct touch_point_params*)allocate(sizeof *p_point_params, 1);
492         if (NULL == p_point_params)
493         {
494             LOG_ERROR("Memory allocation failed\n");
495             return -1;
496         }
497 
498         p_point_params->display = 0;
499         p_point_params->id = i;
500         p_point_params->x  = 0.0;
501         p_point_params->y  = 0.0;
502         p_point_params->r  = 15.0;
503         p_point_params->n_vtx = n_vtx;
504         p_point_params->p_vertices = (GLfloat*)allocate(sizeof(GLfloat) * n_vtx * 2, 0);
505         assert(NULL != p_point_params->p_vertices);
506 
507         for (j = 0; j < (n_vtx - 1); ++j)
508         {
509             p_point_params->p_vertices[j*2  ] = cx + (float)(0.5 * cos(rad));
510             p_point_params->p_vertices[j*2+1] = cy + (float)(0.5 * sin(rad));
511             rad += step;
512         }
513         p_point_params->p_vertices[j*2  ] = p_point_params->p_vertices[0];
514         p_point_params->p_vertices[j*2+1] = p_point_params->p_vertices[1];
515 
516         int idx = (i % NUM_OF_TOUCH_POINT_COLOR);
517         memcpy(p_point_params->color, colors[idx], sizeof(GLfloat) * 3);
518 
519         wl_list_insert(p_params->touch_point_list.prev, &p_point_params->link);
520     }
521 
522     return 0;
523 }
524 
525 static int
setup_touch_event_test(struct touch_event_test_params * p_params)526 setup_touch_event_test(struct touch_event_test_params *p_params)
527 {
528     if (0 > setup_point_params(p_params))
529     {
530         return -1;
531     }
532 
533     init_gl(p_params);
534     return 0;
535 }
536 
537 /******************************************************************************/
538 
539 static void
signal_handler(int signum)540 signal_handler(int signum)
541 {
542     switch (signum) {
543     case SIGINT:
544         LOG_INFO("Caught SIGINT - Interrupt\n");
545         LOG_INFO("Recieved touch event information:\n");
546         {
547             int n_down = 0, n_up = 0, n_motion = 0;
548             size_t i;
549             for (i = 0; i < gp_test_params->log_array.n_log; ++i)
550             {
551                 switch (gp_test_params->log_array.p_logs[i].event)
552                 {
553                 case TOUCH_DOWN:
554                     ++n_down;
555                     break;
556                 case TOUCH_MOTION:
557                     ++n_motion;
558                     break;
559                 case TOUCH_UP:
560                     ++n_up;
561                     break;
562                 }
563             }
564             LOG_INFO(" - DOWN   event  %d\n", n_down);
565             LOG_INFO(" - MOTION event  %d\n", n_motion);
566             LOG_INFO(" - UP     event  %d\n", n_up);
567         }
568         break;
569     default:
570         LOG_INFO("Caught unknown signal(%d), exit\n", signum);
571         break;
572     }
573 
574     DisplayExit(gp_test_params->p_display);
575 }
576 
577 static void
setup_signal()578 setup_signal()
579 {
580     struct sigaction sigact;
581 
582     sigact.sa_handler = signal_handler;
583     sigemptyset(&sigact.sa_mask);
584     sigact.sa_flags = 0;
585     sigaction(SIGINT, &sigact, NULL);
586 }
587 
588 /******************************************************************************/
589 
590 int
touch_event_test_main(struct touch_event_test_params * p_params)591 touch_event_test_main(struct touch_event_test_params *p_params)
592 {
593     struct WaylandDisplay   *p_display;
594     struct WaylandEglWindow *p_window;
595 
596     setup_signal();
597 
598     p_display = CreateDisplay(0, NULL);
599     if (NULL == p_display)
600     {
601         LOG_ERROR("Failed to create display\n");
602         return -1;
603     }
604     p_params->p_display = p_display;
605 
606     DisplaySetUserData(p_display, p_params);
607     DisplaySetGlobalHandler(p_display, display_global_handler);
608 
609     p_window = CreateEglWindow(p_display, WINDOW_TITLE, SURFACE_ID);
610     if (NULL == p_window)
611     {
612         LOG_ERROR("Failed to create EGL window\n");
613         DestroyDisplay(p_display);
614         return -1;
615     }
616     p_params->p_window = p_window;
617 
618     /**
619      * TODO: Create setter function to window.c
620      */
621     p_window->redraw_handler = redraw_handler;
622     p_window->p_user_data = p_params;
623 
624     WindowScheduleResize(p_window, WINDOW_WIDTH, WINDOW_HEIGHT);
625     WindowCreateSurface(p_window);
626 
627     if (0 > setup_touch_event_test(p_params))
628     {
629         LOG_ERROR("Failed to setup this viewer\n");
630         DestroyDisplay(p_display);
631         return -1;
632     }
633 
634     DisplayRun(p_display);
635 
636     /* Print event information */
637     LOG_INFO("Number of events: %lu\n", p_params->log_array.n_log);
638 
639     log_array_release(&p_params->log_array);
640 
641     return 0;
642 }
643 
644 void
usage(int status)645 usage(int status)
646 {
647     printf("usage: multi-touch-viewer [OPTION]\n");
648     printf("  -p : print received touch point\n");
649     exit(status);
650 }
651 
652 int
main(int argc,char ** argv)653 main(int argc, char **argv)
654 {
655     _UNUSED_(argc);
656     _UNUSED_(argv);
657     struct touch_event_test_params params;
658 
659     memset(&params, 0x00, sizeof params);
660 
661     if (argc == 2)
662     {
663         if (0 == strcmp(argv[1], "-p"))
664         {
665             g_is_print_log = 1;
666         }
667         else
668         {
669             usage(EXIT_SUCCESS);
670         }
671     }
672 
673     gp_test_params = &params;
674 
675     wl_list_init(&params.touch_point_list);
676 
677     log_array_init(&params.log_array, 500);
678 
679     return touch_event_test_main(&params);
680 }
681