summaryrefslogtreecommitdiff
path: root/ivi-layermanagement-examples
diff options
context:
space:
mode:
authorNobuhiko Tanibata <ntanibata@jp.adit-jv.com>2015-09-02 16:10:55 +0900
committerNobuhiko Tanibata <nobuhiko_tanibata@xddp.denso.co.jp>2015-09-30 16:20:11 +0900
commit0770a892fa4a00870f24d37285a1a6cb02371a43 (patch)
tree0be60fe2ad26f162ed46efabc504d19e445a0c3c /ivi-layermanagement-examples
parent88de528f8f6cbda3589b0e026bfd244b4fa7fd7e (diff)
downloadwayland-ivi-extension-0770a892fa4a00870f24d37285a1a6cb02371a43.tar.gz
multi-touch-viewer: an example to receive multi touch and display them as
points. This example provides us how to receive multi touch and handle them for own application. This shows multi touch as points with differenct color. Signed-off-by: Nobihiko Tanibata <ntanibata@jp.adit-jv.com>
Diffstat (limited to 'ivi-layermanagement-examples')
-rw-r--r--ivi-layermanagement-examples/CMakeLists.txt1
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt92
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/include/multi-touch-viewer.h61
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/include/util.h77
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/include/window.h140
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c657
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/src/util.c91
-rw-r--r--ivi-layermanagement-examples/multi-touch-viewer/src/window.c683
8 files changed, 1802 insertions, 0 deletions
diff --git a/ivi-layermanagement-examples/CMakeLists.txt b/ivi-layermanagement-examples/CMakeLists.txt
index 43957ae..6595d8f 100644
--- a/ivi-layermanagement-examples/CMakeLists.txt
+++ b/ivi-layermanagement-examples/CMakeLists.txt
@@ -27,3 +27,4 @@ add_subdirectory(LayerManagerControl)
add_subdirectory(EGLWLMockNavigation)
add_subdirectory(EGLWLInputEventExample)
add_subdirectory(layer-add-surfaces)
+add_subdirectory(multi-touch-viewer)
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt b/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt
new file mode 100644
index 0000000..4ef33cc
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt
@@ -0,0 +1,92 @@
+############################################################################
+#
+# \copyright (c) 2012, 2013 Advanced Driver Information Technology.
+# This code is developed by Advanced Driver Information Technology.
+# Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+############################################################################
+
+cmake_minimum_required (VERSION 2.6)
+
+project (generate-protocol-src)
+
+find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner)
+
+add_custom_command(
+ OUTPUT ivi-application-protocol.c
+ COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code
+ < ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml
+ > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-protocol.c
+ DEPENDS ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml
+)
+
+################################################################
+
+project (multi-touch-viewer)
+
+find_package(PkgConfig)
+pkg_check_modules(GLESv2 glesv2 REQUIRED)
+pkg_check_modules(EGL egl REQUIRED)
+pkg_check_modules(WAYLAND_EGL wayland-egl REQUIRED)
+pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED)
+
+GET_TARGET_PROPERTY(IVI_EXTENSION_PROTOCOL_DIRS ivi-extension-protocol INCLUDE_DIRECTORIES)
+
+include_directories(
+ include
+ ${IVI_EXTENSION_PROTOCOL_DIRS}
+ ${GLESv2_INCLUDE_DIRS}
+ ${EGL_INCLUDE_DIRS}
+ ${WAYLAND_CLIENT_INCLUDE_DIR}
+)
+
+link_directories(
+ ${GLESv2_LIBRARY_DIRS}
+ ${EGL_LIBRARY_DIRS}
+ ${WAYLAND_CLIENT_LIBRARY_DIRS}
+)
+
+SET(LIBS
+ ${LIBS}
+ ${GLESv2_LIBRARIES}
+ ${WAYLAND_CLIENT_LIBRARIES}
+ ${WAYLAND_EGL_LIBRARIES}
+ ${EGL_LIBRARIES}
+ m
+)
+
+SET(SRC_FILES
+ src/multi-touch-viewer.c
+ src/util.c
+ src/window.c
+)
+
+set(HEADER_FILES
+ include/multi-touch-viewer.h
+ include/util.h
+ include/window.h
+)
+
+add_executable(${PROJECT_NAME}
+ ${SRC_FILES}
+ ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-protocol.c
+)
+
+add_dependencies(${PROJECT_NAME} ${LIBS})
+
+target_link_libraries(${PROJECT_NAME} ${LIBS})
+
+install (TARGETS ${PROJECT_NAME} DESTINATION bin)
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/include/multi-touch-viewer.h b/ivi-layermanagement-examples/multi-touch-viewer/include/multi-touch-viewer.h
new file mode 100644
index 0000000..60c5bc8
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/include/multi-touch-viewer.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *
+ * Copyright (c) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+ * All rights reserved.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#ifndef MULTI_TOUCH_TEST_H
+#define MULTI_TOUCH_TEST_H
+
+#include "window.h"
+#include "util.h"
+
+struct touch_point_params
+{
+ struct wl_list link;
+ int display;
+ int id;
+ float x, y;
+ float r;
+ int32_t n_vtx;
+ GLfloat *p_vertices;
+ GLfloat color[3];
+};
+
+struct touch_event_test_params
+{
+ struct WaylandDisplay *p_display;
+ struct WaylandEglWindow *p_window;
+ struct wl_seat *p_seat;
+ struct wl_touch *p_touch;
+ struct wl_list touch_point_list;
+ struct event_log_array log_array;
+ char *p_logfile;
+ int n_fail;
+
+ struct {
+ GLuint pos;
+ GLuint loc_col;
+ GLuint loc_x;
+ GLuint loc_y;
+ GLuint loc_w;
+ GLuint loc_h;
+ } gl;
+};
+
+#endif /* MULTI_TOUCH_TEST_H */
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/include/util.h b/ivi-layermanagement-examples/multi-touch-viewer/include/util.h
new file mode 100644
index 0000000..b61adea
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/include/util.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ *
+ * Copyright (c) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+ * All rights reserved.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdint.h>
+
+/* Log Macro */
+#ifndef LOG_ERROR
+#define LOG_ERROR(...) { \
+ fprintf(stderr, "ERROR : " __VA_ARGS__); \
+}
+#endif
+
+#ifndef LOG_INFO
+#define LOG_INFO(...) { \
+ fprintf(stderr, "INFO : " __VA_ARGS__); \
+}
+#endif
+
+#ifndef LOG_WARNING
+#define LOG_WARNING(...) { \
+ fprintf(stderr, "WARN : " __VA_ARGS__); \
+}
+#endif
+
+enum
+{
+ TOUCH_DOWN = (1 << 0),
+ TOUCH_MOTION = (1 << 1),
+ TOUCH_UP = (1 << 2),
+ TOUCH_FRAME = (1 << 3),
+ TOUCH_CANCEL = (1 << 4)
+};
+
+struct event_log
+{
+ uint32_t event;
+ int32_t id;
+ float x;
+ float y;
+ uint32_t time;
+ char dmy[4];
+};
+
+struct event_log_array
+{
+ size_t n_log;
+ size_t n_alloc;
+ struct event_log *p_logs;
+};
+
+void* allocate(uint32_t alloc_size, int clear);
+void log_array_init(struct event_log_array *p_array, int n_alloc);
+void log_array_release(struct event_log_array *p_array);
+void log_array_add(struct event_log_array *p_array, struct event_log *p_log);
+
+#endif /* UTIL_H */
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/include/window.h b/ivi-layermanagement-examples/multi-touch-viewer/include/window.h
new file mode 100644
index 0000000..40e2925
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/include/window.h
@@ -0,0 +1,140 @@
+/***************************************************************************
+ *
+ * Copyright (c) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+ * All rights reserved.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <wayland-client.h>
+#include <wayland-egl.h>
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include "ivi-application-client-protocol.h"
+
+#define _UNUSED_(arg) (void)arg;
+
+struct WaylandDisplay;
+struct WaylandEglWindow;
+
+typedef void (*window_redraw_handler_t)
+ (struct WaylandEglWindow *p_window, void *p_data);
+
+typedef void (*display_global_handler_t)
+ (struct WaylandDisplay *p_display, uint32_t name, const char *p_interface,
+ uint32_t version, void *p_data);
+
+struct Task
+{
+ void (*run)(struct Task *p_task, uint32_t events);
+ struct wl_list link;
+};
+
+struct WaylandDisplay
+{
+ struct Task display_task;
+ struct wl_display *p_display;
+ struct wl_registry *p_registry;
+ struct wl_compositor *p_compositor;
+ struct wl_shell *p_shell;
+ struct ivi_application *p_ivi_application;
+ EGLDisplay egldisplay;
+ EGLConfig eglconfig;
+ EGLContext eglcontext;
+
+ int running;
+ int epoll_fd;
+ int display_fd;
+ uint32_t display_fd_events;
+
+ display_global_handler_t global_handler;
+
+ struct wl_list global_list;
+ struct wl_list surface_list;
+ struct wl_list deferred_list;
+
+ void *p_user_data;
+};
+
+struct WaylandEglWindow
+{
+ struct Task redraw_task;
+ struct wl_list link;
+ struct WaylandDisplay *p_display;
+ struct wl_surface *p_surface;
+ struct wl_shell_surface *p_shell_surface;
+ struct ivi_surface *p_ivi_surface;
+ struct wl_egl_window *p_egl_window;
+ struct wl_callback *p_frame_cb;
+ EGLSurface eglsurface;
+ struct {
+ GLuint rotation_uniform;
+ GLuint pos;
+ GLuint col;
+ } gl;
+ struct {
+ int width;
+ int height;
+ } geometry;
+ int configured;
+ int redraw_scheduled;
+ int redraw_needed;
+ window_redraw_handler_t redraw_handler;
+ uint32_t time;
+ int type;
+ void *p_user_data;
+};
+
+struct WaylandDisplay*
+CreateDisplay(int argc, char **argv);
+
+void
+DestroyDisplay(struct WaylandDisplay *p_display);
+
+struct WaylandEglWindow*
+CreateEglWindow(struct WaylandDisplay *p_display, const char *p_window_title,
+ uint32_t surface_id);
+
+void
+WindowScheduleRedraw(struct WaylandEglWindow *p_window);
+
+void
+WindowScheduleResize(struct WaylandEglWindow *p_window, int width, int height);
+
+void
+DisplayRun(struct WaylandDisplay *p_display);
+
+void
+DisplayExit(struct WaylandDisplay *p_display);
+
+int
+DisplayAcquireWindowSurface(struct WaylandDisplay *p_display,
+ struct WaylandEglWindow *p_window);
+
+void
+DisplaySetGlobalHandler(struct WaylandDisplay *p_display,
+ display_global_handler_t handler);
+
+void
+DisplaySetUserData(struct WaylandDisplay *p_display, void *p_data);
+
+void
+WindowCreateSurface(struct WaylandEglWindow *p_window);
+
+#endif
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c b/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c
new file mode 100644
index 0000000..0b88ca3
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c
@@ -0,0 +1,657 @@
+/***************************************************************************
+ *
+ * Copyright (c) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+ * All rights reserved.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <wayland-client-protocol.h>
+#include "multi-touch-viewer.h"
+
+#define WINDOW_TITLE "multi_touch_viewer"
+#define WINDOW_WIDTH 1080
+#define WINDOW_HEIGHT 1920
+#define SURFACE_ID 4000
+#define LAYER_ID 4000
+
+#ifndef _UNUSED_
+# define _UNUSED_(x) (void)x
+#endif
+
+static const char *gp_vert_shader_text =
+ "uniform mediump float uX; \n"
+ "uniform mediump float uY; \n"
+ "uniform mediump float uWidth; \n"
+ "uniform mediump float uHeight; \n"
+ "uniform vec3 uColor; \n"
+ "attribute vec4 pos; \n"
+ "varying vec4 v_color; \n"
+ "void main() { \n"
+ " mediump vec4 position; \n"
+ " position.xy = vec2(uX + uWidth * pos.x, \n"
+ " uY + uHeight * pos.y); \n"
+ " position.xy = 2.0 * position.xy - 1.0; \n"
+ " position.zw = vec2(0.0, 1.0); \n"
+ " gl_Position = position; \n"
+ " v_color = vec4(uColor, 1.0); \n"
+ "} \n";
+
+static const char *gp_frag_shader_text =
+ "precision mediump float; \n"
+ "varying vec4 v_color; \n"
+ "void main() { \n"
+ " gl_FragColor = v_color; \n"
+ "} \n";
+
+static struct touch_event_test_params *gp_test_params = NULL;
+
+static int g_is_print_log = 0;
+
+/******************************************************************************/
+
+static void frame_callback(void *, struct wl_callback *, uint32_t);
+
+static void
+update_touch_point(struct touch_event_test_params *p_params, int ev,
+ float x, float y, int32_t id, uint32_t time)
+{
+ struct touch_point_params *p_point_params;
+ struct event_log elog;
+
+ if (NULL == p_params)
+ {
+ return;
+ }
+
+ wl_list_for_each(p_point_params, &p_params->touch_point_list, link)
+ {
+ if (p_point_params->id != id)
+ continue;
+
+ switch (ev) {
+ case TOUCH_DOWN:
+ case TOUCH_MOTION:
+ p_point_params->display = 1;
+ p_point_params->x = x;
+ p_point_params->y = y;
+ break;
+ case TOUCH_UP:
+ p_point_params->display = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (g_is_print_log)
+ {
+ printf("[%d] %8.2f %8.2f (%s)\n", id, x, y,
+ (ev == TOUCH_MOTION) ? "MOTION":
+ (ev == TOUCH_DOWN) ? "DOWN" : "UP");
+ }
+
+ /* store event log */
+ elog.event = ev;
+ elog.x = x;
+ elog.y = y;
+ elog.id = id;
+ elog.time = time;
+ log_array_add(&p_params->log_array, &elog);
+}
+
+/******************************************************************************/
+
+static void
+frame_callback(void *p_data, struct wl_callback *p_cb, uint32_t time)
+{
+ _UNUSED_(time);
+
+ WindowScheduleRedraw((struct WaylandEglWindow*)p_data);
+
+ if (NULL != p_cb)
+ wl_callback_destroy(p_cb);
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_callback
+};
+
+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)
+{
+ _UNUSED_(p_touch);
+ _UNUSED_(serial);
+ _UNUSED_(p_surface);
+
+ update_touch_point((struct touch_event_test_params*)p_data,
+ TOUCH_DOWN,
+ (float)wl_fixed_to_double(x_w),
+ (float)wl_fixed_to_double(y_w),
+ id, time);
+}
+
+static void
+touch_handle_up(void *p_data, struct wl_touch *p_touch, uint32_t serial,
+ uint32_t time, int32_t id)
+{
+ _UNUSED_(p_touch);
+ _UNUSED_(serial);
+
+ update_touch_point((struct touch_event_test_params*)p_data,
+ TOUCH_UP,
+ 0,
+ 0,
+ id, time);
+}
+
+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)
+{
+ _UNUSED_(p_touch);
+
+ update_touch_point((struct touch_event_test_params*)p_data,
+ TOUCH_MOTION,
+ (float)wl_fixed_to_double(x_w),
+ (float)wl_fixed_to_double(y_w),
+ id, time);
+}
+
+static void
+touch_handle_frame(void *p_data, struct wl_touch *p_touch)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_touch);
+
+ update_touch_point(NULL, TOUCH_FRAME, 0, 0, 0, 0);
+}
+
+static void
+touch_handle_cancel(void *p_data, struct wl_touch *p_touch)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_touch);
+
+ update_touch_point(NULL, TOUCH_CANCEL, 0, 0, 0, 0);
+}
+
+static const struct wl_touch_listener touch_listener = {
+ touch_handle_down,
+ touch_handle_up,
+ touch_handle_motion,
+ touch_handle_frame,
+ touch_handle_cancel
+};
+
+static void
+seat_capabilities(void *p_data, struct wl_seat *p_seat, uint32_t caps)
+{
+ struct touch_event_test_params *p_params =
+ (struct touch_event_test_params*)p_data;
+
+ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !p_params->p_touch)
+ {
+ p_params->p_touch = wl_seat_get_touch(p_seat);
+ wl_touch_add_listener(p_params->p_touch, &touch_listener, p_data);
+ }
+ else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && p_params->p_touch)
+ {
+ wl_touch_destroy(p_params->p_touch);
+ p_params->p_touch = NULL;
+ }
+}
+
+static const struct wl_seat_listener seat_listener = {
+ seat_capabilities,
+ NULL /* name: since version 2 */
+};
+
+static void
+display_global_handler(struct WaylandDisplay *p_display, uint32_t name,
+ const char *p_interface, uint32_t version, void *p_data)
+{
+ _UNUSED_(version);
+ struct touch_event_test_params *p_params =
+ (struct touch_event_test_params*)p_data;
+
+ if (0 == strcmp(p_interface, "wl_seat"))
+ {
+ p_params->p_seat = wl_registry_bind(p_display->p_registry,
+ name, &wl_seat_interface, 1);
+ wl_seat_add_listener(p_params->p_seat, &seat_listener, p_data);
+ }
+}
+
+/******************************************************************************/
+
+static void
+draw_grid(int direction, GLfloat width, GLfloat height, float step,
+ struct touch_event_test_params *p_params)
+{
+ GLfloat coord = step;
+ GLfloat uX = 0.0f;
+ GLfloat uY = 0.0f;
+ GLfloat dest_width = 0.0f;
+ GLfloat dest_height = 0.0f;
+ GLfloat dest_coord;
+
+ GLfloat vertices[2][2] = {
+ {0.0f, 0.0f},
+ {0.0f, 0.0f}
+ };
+#if 0
+ GLfloat line_color[3] = {0.25f, 0.28f, 0.80f};
+#else
+ GLfloat line_color[3] = {0.1, 0.1, 0.1};
+#endif
+
+ switch (direction)
+ {
+ case 0: /* verticality */
+ vertices[1][1] = 1.0f;
+ dest_coord = width;
+ break;
+ case 1: /* horizontality */
+ vertices[1][0] = 1.0f;
+ dest_coord = height;
+ break;
+ default:
+ return;
+ }
+
+ glLineWidth(2.0f);
+
+ coord = step;
+ while (coord < dest_coord)
+ {
+ if (direction == 0)
+ {
+ uX = coord / width;
+ dest_height = height;
+ }
+ else
+ {
+ uY = 1.0f - coord / height;
+ dest_width = width;
+ }
+
+ glUniform1fv(p_params->gl.loc_x, 1, &uX);
+ glUniform1fv(p_params->gl.loc_y, 1, &uY);
+ glUniform1fv(p_params->gl.loc_w, 1, &dest_width);
+ glUniform1fv(p_params->gl.loc_h, 1, &dest_height);
+ glUniform3fv(p_params->gl.loc_col, 1, line_color);
+
+ glVertexAttribPointer(p_params->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+
+ glDrawArrays(GL_LINES, 0, 2);
+
+ coord += step;
+ }
+}
+
+static void
+redraw_handler(struct WaylandEglWindow *p_window, void *p_data)
+{
+ GLfloat w, h, uX, uY;
+ GLfloat view_width, view_height;
+ GLfloat dest_width, dest_height;
+ struct touch_event_test_params *p_params = (struct touch_event_test_params*)p_data;
+ struct touch_point_params *p_point_params;
+
+ DisplayAcquireWindowSurface(p_window->p_display, p_window);
+
+ view_width = p_window->geometry.width;
+ view_height = p_window->geometry.height;
+
+ glViewport(0, 0, (int)view_width, (int)view_height);
+
+#if 0
+ glClearColor(0.60, 0.84, 0.91, 1.0);
+#else
+ glClearColor(0.7, 0.7, 0.7, 1.0);
+#endif
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnableVertexAttribArray(p_params->gl.pos);
+
+ /* readraw touch areas */
+ draw_grid(0, view_width, view_height, 100.0f, p_params);
+ draw_grid(1, view_width, view_height, 100.0f, p_params);
+
+ /* redraw pointer circles */
+ wl_list_for_each(p_point_params, &p_params->touch_point_list, link)
+ {
+ if (0 == p_point_params->display)
+ continue;
+
+ w = h = p_point_params->r * 2.0;
+
+ uX = (p_point_params->x - p_point_params->r)/ view_width;
+ uY = 1.0f - (p_point_params->y + p_point_params->r) / view_height;
+
+ dest_width = w / view_width;
+ dest_height = h / view_height;
+
+ glUniform1fv(p_params->gl.loc_x, 1, &uX);
+ glUniform1fv(p_params->gl.loc_y, 1, &uY);
+ glUniform1fv(p_params->gl.loc_w, 1, &dest_width);
+ glUniform1fv(p_params->gl.loc_h, 1, &dest_height);
+ glUniform3fv(p_params->gl.loc_col, 1, p_point_params->color);
+
+ glVertexAttribPointer(p_params->gl.pos, 2,
+ GL_FLOAT, GL_FALSE, 0, p_point_params->p_vertices);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, p_point_params->n_vtx);
+ }
+
+ glDisableVertexAttribArray(p_params->gl.pos);
+
+ struct wl_callback *p_cb = wl_surface_frame(p_window->p_surface);
+ wl_callback_add_listener(p_cb, &frame_listener, p_window);
+}
+
+/******************************************************************************/
+
+static GLuint
+create_shader(const char *p_source, GLenum shader_type)
+{
+ GLuint shader;
+ GLint status;
+
+ shader = glCreateShader(shader_type);
+ assert(shader != 0);
+
+ glShaderSource(shader, 1, (const char**)&p_source, NULL);
+ glCompileShader(shader);
+
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (0 == status)
+ {
+ char gllog[1000];
+ GLsizei len;
+ glGetShaderInfoLog(shader, sizeof(gllog), &len, gllog);
+ LOG_ERROR("Shader Compiling Failed (%s):\n%*s\n",
+ shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", len, gllog);
+ exit(-1);
+ }
+
+ return shader;
+}
+
+static void
+init_gl(struct touch_event_test_params *p_params)
+{
+ GLuint vert, frag;
+ GLuint program;
+ GLint status;
+
+ vert = create_shader(gp_vert_shader_text, GL_VERTEX_SHADER);
+ frag = create_shader(gp_frag_shader_text, GL_FRAGMENT_SHADER);
+
+ program = glCreateProgram();
+ glAttachShader(program, frag);
+ glAttachShader(program, vert);
+ glLinkProgram(program);
+
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (0 == status)
+ {
+ char gllog[1000];
+ GLsizei len;
+ glGetProgramInfoLog(program, sizeof(gllog), &len, gllog);
+ LOG_ERROR("Shader Linking Failed:\n%*s\n", len, gllog);
+ exit(-1);
+ }
+
+ glUseProgram(program);
+
+ p_params->gl.pos = 0;
+
+ glBindAttribLocation(program, p_params->gl.pos, "pos");
+
+ p_params->gl.loc_x = glGetUniformLocation(program, "uX");
+ p_params->gl.loc_y = glGetUniformLocation(program, "uY");
+ p_params->gl.loc_w = glGetUniformLocation(program, "uWidth");
+ p_params->gl.loc_h = glGetUniformLocation(program, "uHeight");
+ p_params->gl.loc_col = glGetUniformLocation(program, "uColor");
+}
+
+#define NUM_OF_TOUCH_POINT_COLOR 5
+
+static int
+setup_point_params(struct touch_event_test_params *p_params)
+{
+ struct touch_point_params *p_point_params;
+ int i, j;
+ int n_vtx = 13;
+ float rad = 0.0;
+ float cx = 0.5;
+ float cy = 0.5;
+ float step = (float)(M_PI / 6.0);
+ GLfloat colors[NUM_OF_TOUCH_POINT_COLOR][3] = {
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f},
+ {1.0f, 0.0f, 1.0f},
+ {1.0f, 1.0f, 0.0f}
+ };
+
+ for (i = 0; i < NUM_OF_TOUCH_POINT_COLOR; ++i)
+ {
+ p_point_params =
+ (struct touch_point_params*)allocate(sizeof *p_point_params, 1);
+ if (NULL == p_point_params)
+ {
+ LOG_ERROR("Memory allocation failed\n");
+ return -1;
+ }
+
+ p_point_params->display = 0;
+ p_point_params->id = i;
+ p_point_params->x = 0.0;
+ p_point_params->y = 0.0;
+ p_point_params->r = 15.0;
+ p_point_params->n_vtx = n_vtx;
+ p_point_params->p_vertices = (GLfloat*)allocate(sizeof(GLfloat) * n_vtx * 2, 0);
+ assert(NULL != p_point_params->p_vertices);
+
+ for (j = 0; j < (n_vtx - 1); ++j)
+ {
+ p_point_params->p_vertices[j*2 ] = cx + (float)(0.5 * cos(rad));
+ p_point_params->p_vertices[j*2+1] = cy + (float)(0.5 * sin(rad));
+ rad += step;
+ }
+ p_point_params->p_vertices[j*2 ] = p_point_params->p_vertices[0];
+ p_point_params->p_vertices[j*2+1] = p_point_params->p_vertices[1];
+
+ int idx = (i % NUM_OF_TOUCH_POINT_COLOR);
+ memcpy(p_point_params->color, colors[idx], sizeof(GLfloat) * 3);
+
+ wl_list_insert(p_params->touch_point_list.prev, &p_point_params->link);
+ }
+
+ return 0;
+}
+
+static int
+setup_touch_event_test(struct touch_event_test_params *p_params)
+{
+ if (0 > setup_point_params(p_params))
+ {
+ return -1;
+ }
+
+ init_gl(p_params);
+ return 0;
+}
+
+/******************************************************************************/
+
+static void
+signal_handler(int signum)
+{
+ switch (signum) {
+ case SIGINT:
+ LOG_INFO("Caught SIGINT - Interrupt\n");
+ LOG_INFO("Recieved touch event information:\n");
+ {
+ int n_down = 0, n_up = 0, n_motion = 0;
+ size_t i;
+ for (i = 0; i < gp_test_params->log_array.n_log; ++i)
+ {
+ switch (gp_test_params->log_array.p_logs[i].event)
+ {
+ case TOUCH_DOWN:
+ ++n_down;
+ break;
+ case TOUCH_MOTION:
+ ++n_motion;
+ break;
+ case TOUCH_UP:
+ ++n_up;
+ break;
+ }
+ }
+ LOG_INFO(" - DOWN event %d\n", n_down);
+ LOG_INFO(" - MOTION event %d\n", n_motion);
+ LOG_INFO(" - UP event %d\n", n_up);
+ }
+ break;
+ default:
+ LOG_INFO("Caught unknown signal(%d), exit\n", signum);
+ break;
+ }
+
+ DisplayExit(gp_test_params->p_display);
+}
+
+static void
+setup_signal()
+{
+ struct sigaction sigact;
+
+ sigact.sa_handler = signal_handler;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ sigaction(SIGINT, &sigact, NULL);
+}
+
+/******************************************************************************/
+
+int
+touch_event_test_main(struct touch_event_test_params *p_params)
+{
+ struct WaylandDisplay *p_display;
+ struct WaylandEglWindow *p_window;
+
+ setup_signal();
+
+ p_display = CreateDisplay(0, NULL);
+ if (NULL == p_display)
+ {
+ LOG_ERROR("Failed to create display\n");
+ return -1;
+ }
+ p_params->p_display = p_display;
+
+ DisplaySetUserData(p_display, p_params);
+ DisplaySetGlobalHandler(p_display, display_global_handler);
+
+ p_window = CreateEglWindow(p_display, WINDOW_TITLE, SURFACE_ID);
+ if (NULL == p_window)
+ {
+ LOG_ERROR("Failed to create EGL window\n");
+ DestroyDisplay(p_display);
+ return -1;
+ }
+ p_params->p_window = p_window;
+
+ /**
+ * TODO: Create setter function to window.c
+ */
+ p_window->redraw_handler = redraw_handler;
+ p_window->p_user_data = p_params;
+
+ WindowScheduleResize(p_window, WINDOW_WIDTH, WINDOW_HEIGHT);
+ WindowCreateSurface(p_window);
+
+ if (0 > setup_touch_event_test(p_params))
+ {
+ LOG_ERROR("Failed to setup this viewer\n");
+ DestroyDisplay(p_display);
+ return -1;
+ }
+
+ DisplayRun(p_display);
+
+ /* Print event information */
+ LOG_INFO("Number of events: %d\n", p_params->log_array.n_log);
+
+ log_array_release(&p_params->log_array);
+
+ return 0;
+}
+
+void
+usage(int status)
+{
+ printf("usage: multi-touch-viewer [OPTION]\n");
+ printf(" -p : print received touch point\n");
+ exit(status);
+}
+
+int
+main(int argc, char **argv)
+{
+ _UNUSED_(argc);
+ _UNUSED_(argv);
+ struct touch_event_test_params params;
+
+ memset(&params, 0x00, sizeof params);
+
+ if (argc == 2)
+ {
+ if (0 == strcmp(argv[1], "-p"))
+ {
+ g_is_print_log = 1;
+ }
+ else
+ {
+ usage(EXIT_SUCCESS);
+ }
+ }
+
+ gp_test_params = &params;
+
+ wl_list_init(&params.touch_point_list);
+
+ log_array_init(&params.log_array, 500);
+
+ return touch_event_test_main(&params);
+}
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/src/util.c b/ivi-layermanagement-examples/multi-touch-viewer/src/util.c
new file mode 100644
index 0000000..fa4acb1
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/src/util.c
@@ -0,0 +1,91 @@
+/***************************************************************************
+ *
+ * Copyright (c) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+ * All rights reserved.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "util.h"
+
+void*
+allocate(uint32_t alloc_size, int clear)
+{
+ if (0 == alloc_size)
+ return NULL;
+
+ return (0 == clear) ? malloc(alloc_size)
+ : calloc(1, alloc_size);
+}
+
+void
+log_array_init(struct event_log_array *p_array, int n_alloc)
+{
+ if (NULL != p_array)
+ {
+ memset(p_array, 0x00, sizeof *p_array);
+ if (0 < n_alloc)
+ {
+ p_array->p_logs =
+ (struct event_log*)malloc(sizeof(struct event_log) * n_alloc);
+ if (NULL == p_array->p_logs)
+ {
+ LOG_ERROR("Memory allocation for logs failed\n");
+ exit(-1);
+ }
+ p_array->n_alloc = n_alloc;
+ }
+ }
+}
+
+void
+log_array_release(struct event_log_array *p_array)
+{
+ if (NULL != p_array)
+ {
+ if ((0 < p_array->n_alloc) && (NULL != p_array->p_logs))
+ {
+ free(p_array->p_logs);
+ }
+ memset(p_array, 0x00, sizeof *p_array);
+ }
+}
+
+void
+log_array_add(struct event_log_array *p_array, struct event_log *p_log)
+{
+ if ((NULL != p_array) && (NULL != p_log))
+ {
+ if ((p_array->n_log + 1) > p_array->n_alloc)
+ {
+ p_array->n_alloc += 500;
+ p_array->p_logs = (struct event_log*)
+ realloc(p_array->p_logs,
+ sizeof(struct event_log) * p_array->n_alloc);
+ if (NULL == p_array->p_logs)
+ {
+ LOG_ERROR("Memory allocation for logs failed\n");
+ exit(-1);
+ }
+ }
+
+ p_array->p_logs[p_array->n_log] = *p_log;
+ ++(p_array->n_log);
+ }
+}
diff --git a/ivi-layermanagement-examples/multi-touch-viewer/src/window.c b/ivi-layermanagement-examples/multi-touch-viewer/src/window.c
new file mode 100644
index 0000000..41b02a9
--- /dev/null
+++ b/ivi-layermanagement-examples/multi-touch-viewer/src/window.c
@@ -0,0 +1,683 @@
+/***************************************************************************
+ *
+ * Copyright (c) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch, and DENSO.
+ * All rights reserved.
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <wayland-client-protocol.h>
+#include "window.h"
+#include "util.h"
+
+#ifndef ARRAY_LENGTH
+# define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
+#endif
+
+struct Global
+{
+ uint32_t name;
+ char *p_interface;
+ uint32_t version;
+ struct wl_list link;
+};
+
+enum {
+ TYPE_NONE,
+ TYPE_TOPLEVEL
+#if 0 /* not use */
+ TYPE_FULLSCREEN,
+ TYPE_MAXIMIZED,
+ TYPE_TRANSIENT
+#endif
+};
+
+/*** Event handlers ***********************************************************/
+
+/**
+ * wl_registry event handlers
+ */
+static void
+registry_handle_global(void *p_data, struct wl_registry *p_registry,
+ uint32_t id, const char *p_interface, uint32_t version)
+{
+ struct WaylandDisplay *p_display = (struct WaylandDisplay*)p_data;
+ struct Global *p_global;
+
+ p_global = (struct Global*)allocate(sizeof(struct Global), 0);
+ if (NULL != p_global)
+ {
+ p_global->name = id;
+ p_global->p_interface = strdup(p_interface);
+ p_global->version = version;
+ wl_list_insert(p_display->global_list.prev, &p_global->link);
+ }
+
+ if (0 == strcmp(p_interface, "wl_compositor"))
+ {
+ p_display->p_compositor = wl_registry_bind(p_registry, id,
+ &wl_compositor_interface, 1);
+ }
+ else if (0 == strcmp(p_interface, "wl_shell"))
+ {
+ p_display->p_shell = wl_registry_bind(p_registry, id,
+ &wl_shell_interface, 1);
+ }
+ else if (0 == strcmp(p_interface, "ivi_application"))
+ {
+ p_display->p_ivi_application = wl_registry_bind(p_registry, id,
+ &ivi_application_interface, 1);
+ }
+
+ if (p_display->global_handler)
+ {
+ p_display->global_handler(p_display, id, p_interface, version,
+ p_display->p_user_data);
+ }
+}
+
+static void
+registry_handle_remove(void *p_data, struct wl_registry *p_registry,
+ uint32_t id)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_registry);
+ _UNUSED_(id);
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ registry_handle_remove
+};
+
+/**
+ * wl_surface event handlers
+ */
+static void
+surface_enter(void *p_data, struct wl_surface *p_surface,
+ struct wl_output *p_output)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_surface);
+ _UNUSED_(p_output);
+}
+
+static void
+surface_leave(void *p_data, struct wl_surface *p_surface,
+ struct wl_output *p_output)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_surface);
+ _UNUSED_(p_output);
+}
+
+static const struct wl_surface_listener surface_listener = {
+ surface_enter,
+ surface_leave
+};
+
+/**
+ * wl_shell_surface event handlers
+ */
+static void
+shell_surface_handle_ping(void *p_data,
+ struct wl_shell_surface *p_shell_surface, uint32_t serial)
+{
+ _UNUSED_(p_data);
+
+ wl_shell_surface_pong(p_shell_surface, serial);
+}
+
+static void
+shell_surface_handle_configure(void *p_data,
+ struct wl_shell_surface *p_shell_surface, uint32_t edges,
+ int32_t width, int32_t height)
+{
+ _UNUSED_(p_shell_surface);
+ _UNUSED_(edges);
+
+ WindowScheduleResize((struct WaylandEglWindow*)p_data, width, height);
+}
+
+static void
+shell_surface_handle_popup_done(void *p_data,
+ struct wl_shell_surface *p_shell_surface)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_shell_surface);
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+ shell_surface_handle_ping,
+ shell_surface_handle_configure,
+ shell_surface_handle_popup_done
+};
+
+/**
+ * wl_callback event handler
+ */
+static void
+frame_callback(void *p_data, struct wl_callback *p_cb, uint32_t time)
+{
+ struct WaylandEglWindow *p_window = (struct WaylandEglWindow*)p_data;
+
+ assert(p_cb == p_window->p_frame_cb);
+
+ wl_callback_destroy(p_cb);
+
+ p_window->p_frame_cb = NULL;
+ p_window->redraw_scheduled = 0;
+ p_window->time = time;
+
+ if (0 != p_window->redraw_needed)
+ {
+ WindowScheduleRedraw(p_window);
+ }
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_callback
+};
+
+static void
+ivi_surface_configure(void *p_data, struct ivi_surface *p_ivi_surface,
+ int32_t width, int32_t height)
+{
+ _UNUSED_(p_data);
+ _UNUSED_(p_ivi_surface);
+ _UNUSED_(width);
+ _UNUSED_(height);
+}
+
+static const struct ivi_surface_listener ivi_surface_event_listener = {
+ ivi_surface_configure
+};
+
+/*** Static functions *********************************************************/
+static int
+set_cloexec_or_close(int fd)
+{
+ long flags;
+
+ if (fd == -1)
+ return -1;
+
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1)
+ goto err;
+
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+ goto err;
+
+ return fd;
+
+err:
+ close(fd);
+ return -1;
+}
+
+int
+os_epoll_create_cloexec()
+{
+ int fd = epoll_create1(EPOLL_CLOEXEC);
+
+ if (fd >= 0)
+ {
+ return fd;
+ }
+
+ if (errno != EINVAL)
+ {
+ return -1;
+ }
+
+ fd = epoll_create(1);
+ return set_cloexec_or_close(fd);
+}
+
+static void
+handle_display_data(struct Task *p_task, uint32_t events)
+{
+ struct WaylandDisplay *p_display = (struct WaylandDisplay*)p_task;
+ struct epoll_event ep;
+ int ret;
+
+ p_display->display_fd_events = events;
+
+ if ((events & EPOLLERR) || (events & EPOLLHUP))
+ {
+ DisplayExit(p_display);
+ return;
+ }
+
+ if (events & EPOLLIN)
+ {
+ ret = wl_display_dispatch(p_display->p_display);
+ if (ret == -1)
+ {
+ DisplayExit(p_display);
+ return;
+ }
+ }
+
+ if (events & EPOLLOUT)
+ {
+ ret = wl_display_flush(p_display->p_display);
+ if (ret == 0)
+ {
+ ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
+ ep.data.ptr = &p_display->display_task;
+ epoll_ctl(p_display->epoll_fd,
+ EPOLL_CTL_MOD, p_display->display_fd, &ep);
+ }
+ else if (ret == -1 && errno != EAGAIN)
+ {
+ DisplayExit(p_display);
+ return;
+ }
+ }
+}
+
+void
+display_watch_fd(struct WaylandDisplay *p_display, int fd, uint32_t events,
+ struct Task *p_task)
+{
+ struct epoll_event ep;
+
+ ep.events = events;
+ ep.data.ptr = p_task;
+ epoll_ctl(p_display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
+}
+
+static int
+init_egl(struct WaylandDisplay *p_display)
+{
+ EGLint iMajor, iMinor;
+ EGLint n;
+
+ static const EGLint argb_config_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, 1,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
+ static const EGLint context_attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ p_display->egldisplay = eglGetDisplay(p_display->p_display);
+
+ if (!eglInitialize(p_display->egldisplay, &iMajor, &iMinor))
+ {
+ fprintf(stderr, "failed to initialize EGL\n");
+ return -1;
+ }
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API))
+ {
+ fprintf(stderr, "failed to bind EGL client API\n");
+ return -1;
+ }
+
+ if (!eglChooseConfig(p_display->egldisplay, argb_config_attribs,
+ &p_display->eglconfig, 1, &n))
+ {
+ fprintf(stderr, "failed to choose argb EGL config\n");
+ return -1;
+ }
+
+ p_display->eglcontext = eglCreateContext(p_display->egldisplay,
+ p_display->eglconfig, EGL_NO_CONTEXT, context_attribs);
+ if (NULL == p_display->eglcontext)
+ {
+ fprintf(stderr, "failed to create EGL context\n");
+ return -1;
+ }
+#if 0
+ if (!eglMakeCurrent(p_display->egldisplay, NULL, NULL,
+ p_display->eglcontext))
+ {
+ fprintf(stderr, "failed to make EGL context current\n");
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static void
+finish_egl(struct WaylandDisplay *p_display)
+{
+ eglMakeCurrent(p_display->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+
+ eglTerminate(p_display->egldisplay);
+ eglReleaseThread();
+}
+
+static void
+window_create_surface(struct WaylandEglWindow *p_window)
+{
+ if (NULL != p_window->p_egl_window)
+ {
+ return;
+ }
+
+ p_window->p_egl_window = wl_egl_window_create(p_window->p_surface,
+ p_window->geometry.width, p_window->geometry.height);
+
+ p_window->eglsurface = eglCreateWindowSurface(
+ p_window->p_display->egldisplay, p_window->p_display->eglconfig,
+ p_window->p_egl_window, NULL);
+
+ eglMakeCurrent(p_window->p_display->egldisplay, p_window->eglsurface,
+ p_window->eglsurface, p_window->p_display->eglcontext);
+}
+
+static void
+idle_redraw(struct Task *p_task, uint32_t events)
+{
+ struct WaylandEglWindow *p_window = (struct WaylandEglWindow*)p_task;
+
+ _UNUSED_(events);
+
+ window_create_surface(p_window);
+
+ if (NULL != p_window->redraw_handler)
+ {
+ p_window->redraw_handler(p_window, p_window->p_user_data);
+ }
+
+ p_window->redraw_needed = 0;
+ wl_list_init(&p_window->redraw_task.link);
+
+ if (p_window->type == TYPE_NONE)
+ {
+ p_window->type = TYPE_TOPLEVEL;
+ if (NULL != p_window->p_shell_surface)
+ {
+ wl_shell_surface_set_toplevel(p_window->p_shell_surface);
+ }
+ }
+
+ p_window->p_frame_cb = wl_surface_frame(p_window->p_surface);
+ wl_callback_add_listener(p_window->p_frame_cb, &frame_listener,
+ p_window);
+
+ eglSwapBuffers(p_window->p_display->egldisplay, p_window->eglsurface);
+}
+
+/*** Public functions *********************************************************/
+
+void
+WindowCreateSurface(struct WaylandEglWindow *p_window)
+{
+ window_create_surface(p_window);
+}
+
+void
+DisplaySetGlobalHandler(struct WaylandDisplay *p_display,
+ display_global_handler_t handler)
+{
+ struct Global *p_global;
+
+ p_display->global_handler = handler;
+ if (NULL == handler)
+ {
+ return;
+ }
+
+ wl_list_for_each(p_global, &p_display->global_list, link)
+ {
+ p_display->global_handler(p_display, p_global->name,
+ p_global->p_interface, p_global->version, p_display->p_user_data);
+ }
+}
+
+void
+DisplaySetUserData(struct WaylandDisplay *p_display, void *p_data)
+{
+ p_display->p_user_data = p_data;
+}
+
+void
+WindowScheduleRedraw(struct WaylandEglWindow *p_window)
+{
+ p_window->redraw_needed = 1;
+ if (0 == p_window->redraw_scheduled)
+ {
+ p_window->redraw_task.run = idle_redraw;
+ wl_list_insert(&p_window->p_display->deferred_list, &p_window->redraw_task.link);
+ p_window->redraw_scheduled = 1;
+ }
+}
+
+void
+WindowScheduleResize(struct WaylandEglWindow *p_window, int width, int height)
+{
+ p_window->geometry.width = width;
+ p_window->geometry.height = height;
+
+ WindowScheduleRedraw(p_window);
+}
+
+int
+DisplayAcquireWindowSurface(struct WaylandDisplay *p_display,
+ struct WaylandEglWindow *p_window)
+{
+ if (!eglMakeCurrent(p_display->egldisplay, p_window->eglsurface,
+ p_window->eglsurface, p_display->eglcontext))
+ {
+ fprintf(stderr, "[ERR] failed to make surface current\n");
+ }
+
+ return 0;
+}
+
+struct WaylandDisplay *
+CreateDisplay(int argc, char **argv)
+{
+ struct WaylandDisplay *p_display;
+
+ _UNUSED_(argc);
+ _UNUSED_(argv);
+
+ p_display = (struct WaylandDisplay*)malloc(sizeof(struct WaylandDisplay));
+ if (NULL == p_display)
+ {
+ return NULL;
+ }
+
+ p_display->p_display = wl_display_connect(NULL);
+ if (NULL == p_display->p_display)
+ {
+ fprintf(stderr, "[ERR] failed to connect to wayland: %m\n");
+ free(p_display);
+ return NULL;
+ }
+
+ p_display->epoll_fd = os_epoll_create_cloexec();
+ p_display->display_fd = wl_display_get_fd(p_display->p_display);
+ p_display->display_task.run = handle_display_data;
+ display_watch_fd(p_display, p_display->display_fd,
+ EPOLLIN | EPOLLERR | EPOLLHUP, &p_display->display_task);
+
+ wl_list_init(&p_display->global_list);
+ wl_list_init(&p_display->surface_list);
+ wl_list_init(&p_display->deferred_list);
+
+ p_display->p_registry = wl_display_get_registry(p_display->p_display);
+ wl_registry_add_listener(p_display->p_registry, &registry_listener,
+ p_display);
+
+ if (0 > wl_display_dispatch(p_display->p_display))
+ {
+ fprintf(stderr, "[ERR] failed to process wayland connection: %m\n");
+ free(p_display);
+ return NULL;
+ }
+
+ if (0 > init_egl(p_display))
+ {
+ fprintf(stderr, "[ERR] EGL does not seem to work\n");
+ free(p_display);
+ return NULL;
+ }
+
+ return p_display;
+}
+
+void
+DestroyDisplay(struct WaylandDisplay *p_display)
+{
+ finish_egl(p_display);
+
+ if (NULL != p_display->p_shell)
+ wl_shell_destroy(p_display->p_shell);
+
+ if (NULL != p_display->p_ivi_application)
+ ivi_application_destroy(p_display->p_ivi_application);
+
+ if (NULL != p_display->p_compositor)
+ wl_compositor_destroy(p_display->p_compositor);
+
+ if (NULL != p_display->p_registry)
+ wl_registry_destroy(p_display->p_registry);
+
+ if (NULL != p_display->p_display)
+ wl_display_disconnect(p_display->p_display);
+
+ free(p_display);
+}
+
+struct WaylandEglWindow *
+CreateEglWindow(struct WaylandDisplay *p_display, const char *p_window_title,
+ uint32_t surface_id)
+{
+ struct WaylandEglWindow *p_window;
+
+ p_window =
+ (struct WaylandEglWindow*)malloc(sizeof(struct WaylandEglWindow));
+ if (NULL == p_window)
+ {
+ return NULL;
+ }
+ memset(p_window, 0x00, sizeof(struct WaylandEglWindow));
+
+ p_window->p_display = p_display;
+ p_window->p_surface = wl_compositor_create_surface(p_display->p_compositor);
+
+ wl_surface_add_listener(p_window->p_surface, &surface_listener, p_window);
+
+ if (NULL != p_display->p_shell)
+ {
+ p_window->p_shell_surface =
+ wl_shell_get_shell_surface(p_display->p_shell, p_window->p_surface);
+
+ wl_shell_surface_set_user_data(p_window->p_shell_surface, p_window);
+
+ wl_shell_surface_add_listener(p_window->p_shell_surface,
+ &shell_surface_listener, p_window);
+
+ wl_shell_surface_set_title(p_window->p_shell_surface, p_window_title);
+ }
+
+ if (NULL != p_display->p_ivi_application)
+ {
+ /* force sync to compositor */
+ wl_display_roundtrip(p_display->p_display);
+ p_window->p_ivi_surface =
+ ivi_application_surface_create(p_display->p_ivi_application,
+ surface_id,
+ p_window->p_surface);
+ ivi_surface_add_listener(p_window->p_ivi_surface,
+ &ivi_surface_event_listener, p_window);
+ }
+
+ wl_list_insert(p_display->surface_list.prev, &p_window->link);
+
+ return p_window;
+}
+
+void
+DisplayRun(struct WaylandDisplay *p_display)
+{
+ struct Task *p_task;
+ struct epoll_event ep[16];
+ int i, count, ret;
+
+ p_display->running = 1;
+ while (1)
+ {
+ while (0 == wl_list_empty(&p_display->deferred_list))
+ {
+ /* avoid lint warning */
+ const __typeof__(((struct Task*)0)->link) *p_ptr = p_display->deferred_list.prev;
+ p_task = (struct Task*)((unsigned long)p_ptr - offsetof(struct Task, link));
+
+ wl_list_remove(&p_task->link);
+ p_task->run(p_task, 0);
+ }
+
+ wl_display_dispatch_pending(p_display->p_display);
+
+ if (0 == p_display->running)
+ {
+ break;
+ }
+
+ ret = wl_display_flush(p_display->p_display);
+ if (0 > ret && EAGAIN == errno)
+ {
+ ep[0].events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP;
+ ep[0].data.ptr = &p_display->display_task;
+ epoll_ctl(p_display->epoll_fd, EPOLL_CTL_MOD,
+ p_display->display_fd, &ep[0]);
+ }
+ else if (0 > ret)
+ {
+ break;
+ }
+
+ count = epoll_wait(p_display->epoll_fd, ep, ARRAY_LENGTH(ep), 1);
+ for (i = 0; i < count; ++i)
+ {
+ p_task = ep[i].data.ptr;
+ p_task->run(p_task, ep[i].events);
+ }
+ }
+}
+
+void
+DisplayExit(struct WaylandDisplay *p_display)
+{
+ if (NULL != p_display)
+ {
+ p_display->running = 0;
+ }
+}