From 110215ad40cd0c24ed5ae70430e45304d5c60fe1 Mon Sep 17 00:00:00 2001 From: zheng_wenlong Date: Wed, 14 Nov 2018 12:49:40 +0900 Subject: Add waltham server for horizontal mode. Add waltham server for horizontal mode. This application is used for receive video from waltham transmitter. Change-Id: I794abf014eb014a4f0b42175093bf5c898e261f5 Signed-off-by: zheng_wenlong --- .../waltham-server/orig/src/utils/bitmap.c | 107 ++ .../orig/src/utils/os-compatibility.c | 204 ++++ .../waltham-server/orig/src/wth-server-gst.c | 1151 +++++++++++++++++++ .../waltham-server/orig/src/wth-server-main.c | 344 ++++++ .../orig/src/wth-server-waltham-comm.c | 1179 ++++++++++++++++++++ .../waltham-server/orig/src/wth-server-weston.c | 811 ++++++++++++++ 6 files changed, 3796 insertions(+) create mode 100644 demo3/horizontal/waltham-server/orig/src/utils/bitmap.c create mode 100644 demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-gst.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-main.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-weston.c (limited to 'demo3/horizontal/waltham-server/orig/src') diff --git a/demo3/horizontal/waltham-server/orig/src/utils/bitmap.c b/demo3/horizontal/waltham-server/orig/src/utils/bitmap.c new file mode 100644 index 0000000..2c7fdb5 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/utils/bitmap.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "bitmap.h" +#include + +struct __attribute__ ((__packed__)) BITMAPFILEHEADER { + char bfType[2]; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +}; + +struct __attribute__ ((__packed__)) BITMAPINFOHEADER { + uint32_t biSize; + uint32_t biWidth; + uint32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPixPerMeter; + uint32_t biYPixPerMeter; + uint32_t biClrUsed; + uint32_t biClrImporant; +}; + +static void +create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size) +{ + file_header->bfType[0] = 'B'; + file_header->bfType[1] = 'M'; + file_header->bfSize = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER) + + image_size; + file_header->bfOffBits = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER); +} + +static void +create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp) +{ + info_header->biSize = sizeof(struct BITMAPINFOHEADER); + info_header->biWidth = width; + info_header->biHeight = height; + info_header->biPlanes = 1; + info_header->biBitCount = bpp; + info_header->biSizeImage = image_size; +} + +static int +write_bitmap(const char *filename, + const struct BITMAPFILEHEADER *file_header, + const struct BITMAPINFOHEADER *info_header, + const char *buffer) +{ + FILE *fp = fopen(filename, "w"); + if (fp == NULL) { + return -1; + } + + fwrite(file_header, sizeof(struct BITMAPFILEHEADER), 1, fp); + fwrite(info_header, sizeof(struct BITMAPINFOHEADER), 1, fp); + fwrite(buffer, info_header->biSizeImage, 1, fp); + + fclose(fp); + return 0; +} + +int +save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp) +{ + if ((filename == NULL) || (buffer == NULL)) { + return -1; + } + + struct BITMAPFILEHEADER file_header = {}; + struct BITMAPINFOHEADER info_header = {}; + + create_file_header(&file_header, image_size); + create_info_header(&info_header, image_size, width, height, bpp); + return write_bitmap(filename, &file_header, &info_header, buffer); +} diff --git a/demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c b/demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c new file mode 100644 index 0000000..d9502e5 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os-compatibility.h" + +int +os_fd_set_cloexec(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + return -1; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + return -1; + + return 0; +} + +static int +set_cloexec_or_close(int fd) +{ + if (os_fd_set_cloexec(fd) != 0) { + close(fd); + return -1; + } + return fd; +} + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (ret == 0 || errno != EINVAL) + return ret; +#endif + + ret = socketpair(domain, type, protocol, sv); + if (ret < 0) + return ret; + + sv[0] = set_cloexec_or_close(sv[0]); + sv[1] = set_cloexec_or_close(sv[1]); + + if (sv[0] != -1 && sv[1] != -1) + return 0; + + close(sv[0]); + close(sv[1]); + return -1; +} + +int +os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficent, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +int +os_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + return (char *)s; +} +#endif diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-gst.c b/demo3/horizontal/waltham-server/orig/src/wth-server-gst.c new file mode 100644 index 0000000..572a04d --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-gst.c @@ -0,0 +1,1151 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* + ** ** + ** SRC-MODULE: ** + ** ** + ** TARGET : linux ** + ** ** + ** PROJECT : waltham-server ** + ** ** + ** AUTHOR : ** + ** ** + ** ** + ** ** + ** PURPOSE : This file is acts as interface to weston compositor at server ** + ** side ** + ** ** + ** REMARKS : ** + ** ** + ** PLATFORM DEPENDANT [yes/no]: yes ** + ** ** + ** TO BE CHANGED BY USER [yes/no]: no ** + ** ** + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "wth-server-waltham-comm.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" + +static int running = 1; +extern bool get_verbosity(void); +extern int verbose; + +typedef struct _GstAppContext +{ + GMainLoop *loop; + GstBus *bus; + GstElement *pipeline; + GstElement *sink; + GstSample *sample; + GstBuffer *gstbuffer; + GstVideoMeta *vmeta; + + int dma_fd[2]; + + struct display *display; + struct window *window; + + pthread_mutex_t mutex; + pthread_cond_t cond; + int wait; + + GstVideoInfo info; + uint32_t format; + bool no_dma_buf; +}GstAppContext; + +static const gchar *vertex_shader_str = +"attribute vec4 a_position; \n" +"attribute vec2 a_texCoord; \n" +"varying vec2 v_texCoord; \n" +"void main() \n" +"{ \n" +" gl_Position = a_position; \n" +" v_texCoord = a_texCoord; \n" +"} \n"; + +static const gchar *fragment_shader_str = +"#ifdef GL_ES \n" +"precision mediump float; \n" +"#endif \n" +"varying vec2 v_texCoord; \n" +"uniform sampler2D tex; \n" +"void main() \n" +"{ \n" +"vec2 uv; \n" +"uv = v_texCoord.xy; \n" +"vec4 c = texture2D(tex, uv); \n" +"gl_FragColor = c; \n" +"} \n"; + +/* + * pointer callbcak functions + */ + static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +static int +drm_fourcc_from_gst_format(GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + return DRM_FORMAT_RGB565; + + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + return DRM_FORMAT_BGR888; + + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_AYUV: + return DRM_FORMAT_ARGB8888; + + case GST_VIDEO_FORMAT_GRAY8: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + return DRM_FORMAT_GR88; + + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_NV12: + return DRM_FORMAT_NV12; + + default: + return -1; + } +} + +gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) +{ + GstAppContext *gstctx = p; + + fprintf(stderr, "mesage: %s\n", GST_MESSAGE_TYPE_NAME(message)); + + switch( GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: + { + GError *err; + gchar *debug; + + gst_message_parse_error(message, &err, &debug); + g_print("ERROR: %s\n", err->message); + + g_error_free(err); + g_free(debug); + g_main_loop_quit(gstctx->loop); + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldstate, newstate; + + gst_message_parse_state_changed(message, &oldstate, &newstate, NULL); + fprintf(stderr, "#%s state changed\n", GST_MESSAGE_SRC_NAME(message)); + switch (newstate){ + case GST_STATE_NULL: + fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_READY: + fprintf(stderr, "%s: state is READY\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PAUSED: + fprintf(stderr, "%s: state is PAUSED\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PLAYING: + fprintf(stderr, "%s: state is PLAYING\n", GST_MESSAGE_SRC_NAME(message)); + break; + } + break; + } + default: + fprintf(stderr, "Unhandled message\n"); + break; + } + fprintf(stderr, "-----------------\n"); +} + +EGLImageKHR create_eglImage(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + + uint32_t n_planes = vmeta->n_planes; + EGLint attribs[30]; + int fourcc; + int atti = 0; + + fourcc = drm_fourcc_from_gst_format(vmeta->format); + + n_planes = GST_VIDEO_INFO_N_PLANES(&(gstctx->info)); + + int width = GST_VIDEO_INFO_WIDTH(&(gstctx->info)); + int height = GST_VIDEO_INFO_HEIGHT(&(gstctx->info)); + + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = vmeta->width; + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = vmeta->height; + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = fourcc; + + /* + * Offset value for both the planes i.e Y and UV is "0" + * The omxdec gives the output is 2 different memory blocks, + * One for Y -> dmafd[0] and other for UV -> dmafd[1] + */ + + if (n_planes > 0) { + attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[atti++] = gstctx->dma_fd[0]; + attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[atti++] = vmeta->stride[0]; + } + + if (n_planes > 1) { + attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; + attribs[atti++] = gstctx->dma_fd[1]; + attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; + attribs[atti++] = vmeta->stride[1]; + } + + attribs[atti++] = EGL_NONE; + + return display->egl.create_image(display->egl.dpy, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, + attribs); +} + +static int +redraw(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + struct window *window = display->window; + GLfloat vVertices[] = { -1.0f, 1.0f, 1.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -1.0f, -1.0f, 1.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 1.0f, -1.0f, 1.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 1.0f, 1.0f, 1.0f, // Position 3, skewed a bit + 1.0f, 0.0f // TexCoord 3 + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + glViewport(0,0,vmeta->width,vmeta->height); + wl_egl_window_resize(window->native,vmeta->width,vmeta->height,0,0); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(display->gl.program_object); + + /* Load the vertex position */ + GLint positionLoc = glGetAttribLocation(display->gl.program_object, "a_position"); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + /* Load the texture coordinate */ + GLint texCoordLoc = glGetAttribLocation(display->gl.program_object, "a_texCoord"); + glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + glEnableVertexAttribArray(positionLoc); + glEnableVertexAttribArray(texCoordLoc); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, display->gl.texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + if(gstctx->no_dma_buf == false && window->egl_img != NULL ) + { + display->egl.image_texture_2d(GL_TEXTURE_2D, window->egl_img); + } + else + { + GstMapInfo map; + gst_buffer_map(gstctx->gstbuffer, &map, GST_MAP_READ); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, vmeta->width, vmeta->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)map.data); + gst_buffer_unmap(gstctx->gstbuffer, &map); + } + + /* Set the texture sampler to texture unit 0 */ + GLint tex = glGetUniformLocation(display->gl.program_object, "tex"); + glUniform1i(tex, 0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); +} + +static GstFlowReturn +appsink_callback(GstElement *object, gpointer *data) +{ + wth_verbose("%s >>> \n",__func__); + int ret; + GstAppContext *gstctx = (struct gstApplContext *)data; + GstSample *sample; + GstBuffer *gstbuffer; + GstMemory *mem; + int i; + int n_mem; + + sample = gst_app_sink_pull_sample((GstAppSink*)((void*)object)); + if(sample == NULL) { + wth_error("No frame received\n"); + return -1; + } + else { + wth_verbose("Frame received\n"); + } + + /* get dmabuf fd from gstbuffer */ + gstbuffer = gst_sample_get_buffer(sample); + if(!gstbuffer){ + wth_error("Cannot get buffer from sample\n"); + } + gstctx->vmeta = gst_buffer_get_video_meta(gstbuffer); + if(gstctx->vmeta==NULL){ + wth_error("no metadata on buffer\n"); + } + + n_mem = gst_buffer_n_memory(gstbuffer); + if (n_mem < 1) { + wth_error("Buffer with no mem!\n"); + } + + for (i = 0; i < n_mem; i++) { + /* get dmabuf fd from gstbuffer */ + mem = gst_buffer_peek_memory (gstbuffer, i); + if (!gst_is_dmabuf_memory(mem)) { + wth_verbose("Memory is not of dmabuf type \n"); + gstctx->no_dma_buf = true; + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; + } + gstctx->dma_fd[i] = gst_dmabuf_memory_get_fd(mem); + } + + if (gstctx->dma_fd[0] < 0 || gstctx->dma_fd[1] < 0 ) { + wth_error("dma fd is null \n"); + return GST_FLOW_ERROR; + } + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + /* stub */ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + /* stub */ +} +void +wth_server_weston_shm_damage(struct window *window) +{ + /* stub */ +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + /* stub */ +} + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +init_egl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint major, minor, count; + EGLBoolean ret; + + display->egl.dpy = eglGetDisplay(display->display); + assert(display->egl.dpy); + + ret = eglInitialize(display->egl.dpy, &major, &minor); + assert(ret == EGL_TRUE); + ret = eglBindAPI(EGL_OPENGL_ES_API); + assert(ret == EGL_TRUE); + + ret = eglChooseConfig(display->egl.dpy, config_attribs, + &display->egl.conf, 1, &count); + assert(ret && count >= 1); + + display->egl.ctx = eglCreateContext(display->egl.dpy, + display->egl.conf, + EGL_NO_CONTEXT, context_attribs); + assert(display->egl.ctx); + + eglSwapInterval(display->egl.dpy, 1); + + display->egl.create_image = + (void *) eglGetProcAddress("eglCreateImageKHR"); + assert(display->egl.create_image); + + display->egl.image_texture_2d = + (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); + assert(display->egl.image_texture_2d); + + display->egl.destroy_image = + (void *) eglGetProcAddress("eglDestroyImageKHR"); + assert(display->egl.destroy_image); +} + +GLuint load_shader(GLenum type, const char *shaderSrc) +{ + wth_verbose("%s >>> \n",__func__); + GLuint shader; + GLint compiled; + + /* Create the shader object */ + shader = glCreateShader(type); + if (shader == 0) + { + printf("\n Failed to create shader \n"); + return 0; + } + /* Load the shader source */ + glShaderSource(shader, 1, &shaderSrc, NULL); + /* Compile the shader */ + glCompileShader(shader); + /* Check the compile status */ + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc (sizeof(char) * infoLen ); + glGetShaderInfoLog(shader, infoLen, NULL, infoLog); + fprintf(stderr, "Error compiling shader:%s\n",infoLog); + free(infoLog); + } + glDeleteShader(shader); + return 0; + } + return shader; +} + +void init_gl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + GLint linked; + + /* load vertext/fragment shader */ + display->gl.vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_shader_str); + display->gl.fragment_shader = load_shader(GL_FRAGMENT_SHADER, fragment_shader_str); + + /* Create the program object */ + display->gl.program_object = glCreateProgram(); + if (display->gl.program_object == 0) + { + fprintf(stderr, "error program object\n"); + return; + } + + glAttachShader(display->gl.program_object, display->gl.vertex_shader); + glAttachShader(display->gl.program_object, display->gl.fragment_shader); + /* Bind vPosition to attribute 0 */ + glBindAttribLocation(display->gl.program_object, 0, "a_position"); + /* Link the program */ + glLinkProgram(display->gl.program_object); + /* Check the link status */ + glGetProgramiv(display->gl.program_object, GL_LINK_STATUS, &linked); + if (!linked) + { + GLint infoLen = 0; + glGetProgramiv(display->gl.program_object, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc(sizeof(char) * infoLen); + glGetProgramInfoLog(display->gl.program_object, infoLen, NULL, infoLog); + fprintf(stderr, "Error linking program:%s\n", infoLog); + free(infoLog); + } + glDeleteProgram(display->gl.program_object); + } + + glGenTextures(1, &display->gl.texture); + + return; +} + +static void +create_surface(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct display *display = window->display; + int ret; + + window->surface = wl_compositor_create_surface(display->compositor); + assert(window->surface); + + window->native = wl_egl_window_create(window->surface, + window->width, window->height); + assert(window->native); + + window->egl_surface = eglCreateWindowSurface(display->egl.dpy, + display->egl.conf, + (NativeWindowType)window->native, NULL); + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + } else { + assert(0); + } + ret = eglMakeCurrent(display->egl.dpy, window->egl_surface, + window->egl_surface, display->egl.ctx); + assert(ret == EGL_TRUE); + + glClearColor(0.5, 0.5, 0.5, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + + window->display = display; + window->width = width; + window->height = height; + window->window_frames = 0; + window->window_benchmark_time = 0; + + create_surface(window); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +void *stream_thread(void *data) +{ + wth_verbose("%s >>> \n",__func__); + GMainLoop *loop = data; + g_main_loop_run(loop); + wth_verbose(" <<< %s \n",__func__); +} + + + +static GstPadProbeReturn +pad_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + wth_verbose("%s >>> \n",__func__); + GstAppContext *dec = user_data; + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); + GstCaps *caps; + + (void)pad; + + if (GST_EVENT_TYPE(event) != GST_EVENT_CAPS) + return GST_PAD_PROBE_OK; + + gst_event_parse_caps(event, &caps); + + if (!caps) { + GST_ERROR("caps event without caps"); + return GST_PAD_PROBE_OK; + } + + if (!gst_video_info_from_caps(&dec->info, caps)) { + GST_ERROR("caps event with invalid video caps"); + return GST_PAD_PROBE_OK; + } + + switch (GST_VIDEO_INFO_FORMAT(&(dec->info))) { + case GST_VIDEO_FORMAT_I420: + dec->format = DRM_FORMAT_YUV420; + break; + case GST_VIDEO_FORMAT_NV12: + dec->format = DRM_FORMAT_NV12; + break; + case GST_VIDEO_FORMAT_YUY2: + dec->format = DRM_FORMAT_YUYV; + break; + default: + GST_ERROR("unknown format\n"); + return GST_PAD_PROBE_OK; + } + wth_verbose(" <<< %s \n",__func__); + return GST_PAD_PROBE_OK; +} + +/** + * wth_server_weston_main + * + * This is the main function which will handle connection to the compositor at server side + * + * @param names void *data + * @param value struct window data + * @return 0 on success, -1 on error + */ +int +wth_server_weston_main(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct sigaction sigint; + pthread_t pthread; + GstAppContext gstctx; + int ret = 0; + GError *gerror = NULL; + char * pipe = NULL; + FILE *pFile; + long lSize; + size_t res; + + memset(&gstctx, 0, sizeof(gstctx)); + /* Initialization for window creation */ + gstctx.display = create_display(); + init_egl(gstctx.display); + /* ToDo: fix the hardcoded value of width, height */ + create_window(window, gstctx.display,1920,1080); + init_gl(gstctx.display); + gstctx.window = window; + + gstctx.display->window = window; + + wth_verbose("display %p\n", gstctx.display); + wth_verbose("display->window %p\n", gstctx.display->window); + wth_verbose("window %p\n", window); + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* create gstreamer pipeline */ + gst_init(NULL, NULL); + gstctx.loop = g_main_loop_new(NULL, FALSE); + + /* Read pipeline from file */ + pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); + if (pFile==NULL){ + fprintf(stderr, "failed to open file\n"); + return -1; + } + + /* obtain file size */ + fseek (pFile , 0 , SEEK_END); + lSize = ftell (pFile); + rewind (pFile); + + /* allocate memory to contain the whole file */ + pipe = (char*) zalloc (sizeof(char)*lSize); + if (pipe == NULL){ + fprintf(stderr,"Cannot allocate memory\n"); + return -1; + } + + /* copy the file into the buffer */ + res = fread (pipe,1,lSize,pFile); + if (res != lSize){ + fprintf(stderr,"File read error\n"); + return -1; + } + + wth_verbose("Gst Pipeline=%s",pipe); + /* close file */ + fclose (pFile); + + /* parse the pipeline */ + gstctx.pipeline = gst_parse_launch(pipe, &gerror); + + if(!gstctx.pipeline) + fprintf(stderr,"Could not create gstreamer pipeline.\n"); + free(pipe); + + gstctx.bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx.pipeline)); + gst_bus_add_watch(gstctx.bus, bus_message, &gstctx); + fprintf(stderr, "registered bus signal\n"); + + gstctx.sink = gst_bin_get_by_name(GST_BIN(gstctx.pipeline), "sink"); + g_object_set(G_OBJECT(gstctx.sink), "emit-signals", TRUE, NULL); + g_signal_connect(gstctx.sink, "new-sample", G_CALLBACK(appsink_callback), &gstctx); + g_object_set(G_OBJECT(gstctx.sink), "drop", TRUE, "max-buffers",-1, NULL); + gst_pad_add_probe(gst_element_get_static_pad(gstctx.sink, "sink"), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + pad_probe, &gstctx, NULL); + + fprintf(stderr, "set state as playing\n"); + gst_element_set_state((GstElement*)((void*)gstctx.pipeline), GST_STATE_PLAYING); + + pthread_mutex_init(&gstctx.mutex, NULL); + pthread_cond_init(&gstctx.cond, NULL); + + pthread_create(&pthread, NULL, &stream_thread, gstctx.loop); + + fprintf(stderr, "rendering part\n"); + + gstctx.wait = 1; + pthread_mutex_lock(&gstctx.mutex); + + while (running && ret != -1) { + wth_verbose("in render loop\n"); + ret = wl_display_dispatch(gstctx.display->display); + if(gstctx.wait == 1) { + wth_verbose("cond wait\n"); + pthread_cond_wait(&gstctx.cond, &gstctx.mutex); + } + + if(gstctx.no_dma_buf == false) + { + wth_verbose("create egl image\n"); + window->egl_img = create_eglImage(&gstctx); + } + + wth_verbose("redraw\n"); + redraw(&gstctx); + wth_verbose("fin redraw\n"); + gstctx.display->egl.destroy_image(gstctx.display->egl.dpy, window->egl_img); + gst_buffer_unref(gstctx.gstbuffer); + gst_sample_unref(gstctx.sample); + gstctx.wait = 1; + } + pthread_mutex_unlock(&gstctx.mutex); + + wth_verbose("wth_server_gst_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(gstctx.display); + + wth_verbose(" <<< %s \n",__func__); + + return 0; +} diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-main.c b/demo3/horizontal/waltham-server/orig/src/wth-server-main.c new file mode 100644 index 0000000..4bbf399 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-main.c @@ -0,0 +1,344 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file handles connection with remote-client ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +#include "wth-server-waltham-comm.h" + +#define MAX_EPOLL_WATCHES 2 + +int verbose=0; +uint16_t tcp_port; + + + +/** get verbosity + */ +bool +get_verbosity() +{ + if (verbose == 1) + { + return true; + } + else + { + return false; + } +} + +/** Print out the application help + */ +static void usage(void) +{ + printf("Usage: waltham server [options]\n"); + printf("Options:\n"); + printf(" -p --port number TCP port number\n"); + printf(" -h --help Usage\n"); + printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity()); +} + +static struct option long_options[] = { + {"port", required_argument, 0, 'p'}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} +}; + +/** + * parse_args + * + * Parses the application arguments + * The arguments are parsed and saved in static structure for future use. + * + * @param argc The amount of arguments + * @param argv The table of arguments + * + * @return 0 on success, -1 otherwise + */ +static int parse_args(int argc, char *argv[]) +{ + int c = -1; + int long_index = 0; + + while ((c = getopt_long(argc, + argv, + "p:vh", + long_options, + &long_index)) != -1) + { + switch (c) + { + case 'p': + tcp_port = atoi(optarg); + break; + case 'v': + verbose=1; + break; + case 'h': + usage(); + return -1; + default: + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + } + + if (tcp_port == 0) + { + wth_error("TCP port not set \n"); + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + + return 0; +} + +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +/** +* listen_socket_handle_data +* +* Handles all incoming events on socket +* +* @param names struct watch *w ,uint32_t events +* @param value pointer to watch connection it holds server information, Incoming events information +* @return none +*/ +static void +listen_socket_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct server *srv = container_of(w, struct server, listen_watch); + + if (events & EPOLLERR) { + wth_error("Listening socket errored out.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLHUP) { + wth_error("Listening socket hung up.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLIN) + { + wth_verbose("EPOLLIN evnet received. \n"); + server_accept_client(srv); + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_mainloop +* +* This is the main loop, which will flush all pending clients requests and +* listen to input events from socket +* +* @param names void *data +* @param value pointer to server struct - +* struct holds the client connection information +* @return none +*/ +static void +server_mainloop(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + + struct epoll_event ee[MAX_EPOLL_WATCHES]; + struct watch *w; + int count; + int i; + + srv->running = true; + + while (srv->running) { + /* Run any idle tasks at this point. */ + + server_flush_clients(srv); + + /* Wait for events or signals */ + count = epoll_wait(srv->epoll_fd, + ee, ARRAY_LENGTH(ee), -1); + if (count < 0 && errno != EINTR) { + perror("Error with epoll_wait"); + break; + } + + /* Handle all fds, both the listening socket + * (see listen_socket_handle_data()) and clients + * (see connection_handle_data()). + */ + for (i = 0; i < count; i++) { + w = ee[i].data.ptr; + w->cb(w, ee[i].events); + } + } + wth_verbose(" <<< %s \n",__func__); +} + +static int +server_listen(uint16_t tcp_port) +{ + wth_verbose("%s >>> \n",__func__); + int fd; + int reuse = 1; + struct sockaddr_in addr; + + fd = socket(AF_INET, SOCK_STREAM, 0); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(tcp_port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse); + + if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) { + wth_error("Failed to bind to port %d", tcp_port); + close(fd); + return -1; + } + + if (listen(fd, 1024) < 0) { + wth_error("Failed to listen to port %d", tcp_port); + close (fd); + return -1; + } + + wth_verbose(" <<< %s \n",__func__); + return fd; +} + +static bool *signal_int_handler_run_flag; + +static void +signal_int_handler(int signum) +{ + wth_verbose("%s >>> \n",__func__); + if (!*signal_int_handler_run_flag) + abort(); + + *signal_int_handler_run_flag = false; + wth_verbose(" <<< %s \n",__func__); +} + +static void +set_sigint_handler(bool *running) +{ + wth_verbose("%s >>> \n",__func__); + struct sigaction sigint; + + signal_int_handler_run_flag = running; + sigint.sa_handler = signal_int_handler; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* main +* +* waltham server main function, it accepts tcp port number as argument. +* Establishes connection on the port and listen to port for incoming connection +* request from waltham clients +* +* @param names argv - argument list and argc -argument count +* @param value tcp port number as argument +* @return 0 on success, -1 on error +*/ +int +main(int argc, char *argv[]) +{ + struct server srv = { 0 }; + struct client *c; + + wth_verbose("%s >>> \n",__func__); + + /* Get command line arguments */ + if (parse_args(argc, argv) != 0) + { + return -1; + } + + set_sigint_handler(&srv.running); + + wl_list_init(&srv.client_list); + + srv.epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (srv.epoll_fd == -1) { + perror("Error on epoll_create1"); + exit(1); + } + + srv.listen_fd = server_listen(tcp_port); + if (srv.listen_fd < 0) { + perror("Error setting up listening socket"); + exit(1); + } + + srv.listen_watch.server = &srv; + srv.listen_watch.cb = listen_socket_handle_data; + srv.listen_watch.fd = srv.listen_fd; + if (watch_ctl(&srv.listen_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + perror("Error setting up listen polling"); + exit(1); + } + + wth_verbose("Waltham server listening on TCP port %u...\n",tcp_port); + + + server_mainloop(&srv); + + /* destroy all things */ + wl_list_last_until_empty(c, &srv.client_list, link) + client_destroy(c); + + close(srv.listen_fd); + close(srv.epoll_fd); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c b/demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c new file mode 100644 index 0000000..bcd2cd4 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c @@ -0,0 +1,1179 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file acts as interface to waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include "wth-server-waltham-comm.h" + +extern int wth_server_weston_main(struct window *); + +extern void wth_server_weston_shm_attach(struct window *, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); +extern void wth_server_weston_shm_damage(struct window *); +extern void wth_server_weston_shm_commit(struct window *); + +extern bool get_verbosity(void); +extern int verbose; + +/* + * utility functions + */ +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +static void +client_post_out_of_memory(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct wth_display *disp; + + disp = wth_connection_get_display(c->connection); + wth_object_post_error((struct wth_object *)disp, 1, + "out of memory"); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham surface implementation + */ +static void +surface_destroy(struct surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("surface %p destroy\n", surface->obj); + + wthp_surface_free(surface->obj); + wl_list_remove(&surface->link); + free(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_destroy(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + + assert(wthp_surface == surface->obj); + + surface_destroy(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_attach(struct wthp_surface *wthp_surface, + struct wthp_buffer *wthp_buffer, int32_t x, int32_t y) +{ + wth_verbose("%s >>> \n",__func__); + struct buffer *buffr = wth_object_get_user_data((struct wth_object *)wthp_buffer); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + struct buffer *buf = NULL; + + buf = container_of(wthp_buffer, struct buffer, obj); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_attach(surf->shm_window, + buf->data_sz, + buf->data, + buf->width, + buf->height, + buf->stride, + buf->format); + + wthp_buffer_send_complete(wthp_buffer, 0); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_damage(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("surface %p damage(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_damage(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_frame(struct wthp_surface *wthp_surface, + struct wthp_callback *callback) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("surface %p callback(%p)\n",wthp_surface, callback); + + surf->cb = callback; + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_opaque_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_opaque_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_set_input_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_input_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_commit(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("commit %p\n",wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_commit(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_buffer_transform(struct wthp_surface *wthp_surface, + int32_t transform) +{ + wth_verbose("surface %p et_buffer_transform(%d)\n", + wthp_surface, transform); +} + +static void +surface_handle_set_buffer_scale(struct wthp_surface *wthp_surface, + int32_t scale) +{ + wth_verbose("surface %p set_buffer_scale(%d)\n", + wthp_surface, scale); +} + +static void +surface_handle_damage_buffer(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("surface %p damage_buffer(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); +} + +static const struct wthp_surface_interface surface_implementation = { + surface_handle_destroy, + surface_handle_attach, + surface_handle_damage, + surface_handle_frame, + surface_handle_set_opaque_region, + surface_handle_set_input_region, + surface_handle_commit, + surface_handle_set_buffer_transform, + surface_handle_set_buffer_scale, + surface_handle_damage_buffer +}; + + +/* BEGIN wthp_region implementation */ + +static void +buffer_handle_destroy(struct wthp_buffer *wthp_buffer) +{ + struct buffer *buf = wth_object_get_user_data((struct wth_object *)wthp_buffer); + + wthp_buffer_free(wthp_buffer); + wl_list_remove(&buf->link); + free(buf); +} + +static const struct wthp_buffer_interface buffer_implementation = { + buffer_handle_destroy +}; + +/* END wthp_region implementation */ + +/* BEGIN wthp_blob_factory implementation */ + +static void +blob_factory_create_buffer(struct wthp_blob_factory *blob_factory, + struct wthp_buffer *wthp_buffer, uint32_t data_sz, void *data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + struct blob_factory *blob = wth_object_get_user_data((struct wth_object *)blob_factory); + struct buffer *buffer; + + + wth_verbose("wthp_blob_factory %p create_buffer(%p, %d, %p, %d, %d, %d, %d)\n", + blob_factory, wthp_buffer, data_sz, data, width, height, stride, format); + + buffer = zalloc(sizeof *buffer); + if (!buffer) { + client_post_out_of_memory(blob->client); + return; + } + + wl_list_insert(&blob->client->buffer_list, &buffer->link); + + buffer->data_sz = data_sz; + buffer->data = data; + buffer->width = width; + buffer->height = height; + buffer->stride = stride; + buffer->format = format; + buffer->obj = wthp_buffer; + + wthp_buffer_set_interface(wthp_buffer, &buffer_implementation, buffer); +} + +static const struct wthp_blob_factory_interface blob_factory_implementation = { + blob_factory_create_buffer +}; + +static void +client_bind_blob_factory(struct client *c, struct wthp_blob_factory *obj) +{ + struct blob_factory *blob; + + blob = zalloc(sizeof *blob); + if (!blob) { + client_post_out_of_memory(c); + return; + } + + blob->obj = obj; + blob->client = c; + wl_list_insert(&c->compositor_list, &blob->link); + + wthp_blob_factory_set_interface(obj, &blob_factory_implementation, + blob); + fprintf(stderr, "client %p bound wthp_blob_factory\n", c); +} + +/* + * waltam ivi surface implementation + */ +static void +wthp_ivi_surface_destroy(struct wthp_ivi_surface * ivi_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct ivisurface *ivisurf = wth_object_get_user_data((struct wth_object *)ivi_surface); + free(ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_surface_interface wthp_ivi_surface_implementation = { + wthp_ivi_surface_destroy, +}; + + +/* + * waltham ivi application implementation + */ +static void +wthp_ivi_application_surface_create(struct wthp_ivi_application * ivi_application, uint32_t ivi_id, + struct wthp_surface * wthp_surface, struct wthp_ivi_surface *obj) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("ivi_application %p surface_create(%d, %p, %p)\n", + ivi_application, ivi_id, wthp_surface, obj); + struct application *app = wth_object_get_user_data((struct wth_object *)ivi_application); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("----------------------------------\n\n\n"); + wth_verbose("surface [%p]\n", surface); + wth_verbose("shm_window [%p]\n\n\n", surface->shm_window); + wth_verbose("----------------------------------\n"); + + surface->ivi_id = ivi_id + 100; + surface->shm_window->id_ivisurf = surface->ivi_id; + struct ivisurface *ivisurf; + + ivisurf = zalloc(sizeof *ivisurf); + if (!ivisurf) { + return; + } + + ivisurf->obj = obj; + ivisurf->surf = surface; + + wth_server_weston_main(surface->shm_window); + + while (!surface->shm_window->ready) + usleep(1); + + wthp_ivi_surface_set_interface(obj, &wthp_ivi_surface_implementation, + ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_application_interface wthp_ivi_application_implementation = { + wthp_ivi_application_surface_create, +}; + +static void +client_bind_wthp_ivi_application(struct client *c, struct wthp_ivi_application *obj) +{ + wth_verbose("%s >>> \n",__func__); + + struct application *app; + + app = zalloc(sizeof *app); + if (!app) { + client_post_out_of_memory(c); + return; + } + + app->obj = obj; + app->client = c; + wl_list_insert(&c->compositor_list, &app->link); + + wthp_ivi_application_set_interface(obj, &wthp_ivi_application_implementation, + app); + wth_verbose("client %p bound wthp_ivi_application\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * APIs to send pointer events to waltham client + */ + +void +waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_enter [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_enter (pointer->obj, serial, surface->obj, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_leave(struct window *window, uint32_t serial) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_leave [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_leave (pointer->obj, serial, surface->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_motion (pointer->obj, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_button (pointer->obj, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_axis (pointer->obj, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham pointer implementation + */ +static void +pointer_set_cursor(struct wthp_pointer *wthp_pointer, int32_t serial, struct wthp_surface *surface, + int32_t hotspot_x, int32_t hotspot_y) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p (%d, %p, %d, %d)\n", + wthp_pointer, serial, surface, hotspot_x, hotspot_y); + +} + +static void +pointer_release(struct wthp_pointer *wthp_pointer) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p\n",wthp_pointer); +} + +static const struct wthp_pointer_interface pointer_implementation = { + pointer_set_cursor, + pointer_release +}; + +/* + * APIs to send touch events to waltham client + */ + +void +waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wth_verbose("touch_handle_down surface [%d]\n", surface->ivi_id); + wthp_touch_send_down(touch->obj, serial, time, surface->obj, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_up(touch->obj, serial, time, id); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_motion(touch->obj, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_frame(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_frame(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_cancel(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_cancel(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham touch implementation + */ +static void +touch_release(struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + struct touch *touch = wth_object_get_user_data((struct wth_object *)wthp_touch); + + wth_verbose("%p\n",wthp_touch); +} + +static const struct wthp_touch_interface touch_implementation = { + touch_release, +}; + +/* + * waltham seat implementation + */ +static void +seat_get_pointer(struct wthp_seat *wthp_seat, struct wthp_pointer *wthp_pointer) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("wthp_seat %p get_pointer(%p)\n", + wthp_seat, wthp_pointer); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct pointer *pointer; + + pointer = zalloc(sizeof *pointer); + if (!pointer) { + client_post_out_of_memory(seat->client); + return; + } + + pointer->obj = wthp_pointer; + pointer->seat = seat; + seat->pointer = pointer; + wl_list_insert(&seat->client->pointer_list, &pointer->link); + + wthp_pointer_set_interface(wthp_pointer, &pointer_implementation, pointer); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_get_touch(struct wthp_seat *wthp_seat, struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("wthp_seat %p get_touch(%p)\n", + wthp_seat, wthp_touch); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct touch *touch; + + touch = zalloc(sizeof *touch); + if (!touch) { + client_post_out_of_memory(seat->client); + return; + } + + touch->obj = wthp_touch; + touch->seat = seat; + seat->touch = touch; + wl_list_insert(&seat->client->touch_list, &touch->link); + + wthp_touch_set_interface(wthp_touch, &touch_implementation, touch); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_release(struct wthp_seat *wthp_seat) +{ +} + +static const struct wthp_seat_interface seat_implementation = { + seat_get_pointer, + NULL, + seat_get_touch, + seat_release, + NULL +}; + +static void +seat_send_updated_caps(struct seat *seat) +{ + wth_verbose("%s >>> \n",__func__); + enum wthp_seat_capability caps = 0; + + caps |= WTHP_SEAT_CAPABILITY_POINTER; + wth_verbose("WTHP_SEAT_CAPABILITY_POINTER %d\n", caps); + + caps |= WTHP_SEAT_CAPABILITY_TOUCH; + wth_verbose("WTHP_SEAT_CAPABILITY_TOUCH %d\n", caps); + + wthp_seat_send_capabilities(seat->obj, caps); + wth_verbose(" <<< %s \n",__func__); +} + +static void +client_bind_seat(struct client *c, struct wthp_seat *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat; + + seat = zalloc(sizeof *seat); + if (!seat) { + client_post_out_of_memory(c); + return; + } + + seat->obj = obj; + seat->client = c; + wl_list_insert(&c->seat_list, &seat->link); + wth_verbose("wthp_seat object=%p and seat=%p\n",obj,seat); + wthp_seat_set_interface(obj, &seat_implementation, + seat); + wth_verbose("client %p bound wthp_seat\n", c); + seat_send_updated_caps(seat); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham region implementation + */ + +static void +region_destroy(struct region *region) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("region %p destroy\n", region->obj); + + wthp_region_free(region->obj); + wl_list_remove(®ion->link); + free(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_destroy(struct wthp_region *wthp_region) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region = wth_object_get_user_data((struct wth_object *)wthp_region); + + assert(wthp_region == region->obj); + + region_destroy(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_add(struct wthp_region *wthp_region, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("region %p add(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static void +region_handle_subtract(struct wthp_region *wthp_region, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + wth_verbose("region %p subtract(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static const struct wthp_region_interface region_implementation = { + region_handle_destroy, + region_handle_add, + region_handle_subtract +}; + +/* + * waltham compositor implementation + */ +static void +compositor_destroy(struct compositor *comp) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, comp->obj); + + wthp_compositor_free(comp->obj); + wl_list_remove(&comp->link); + free(comp); + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_surface(struct wthp_compositor *compositor, + struct wthp_surface *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct client *client = comp->client; + struct surface *surface; + struct seat *seat, *tmp; + + wth_verbose("client %p create surface %p\n", + comp->client, id); + + surface = zalloc(sizeof *surface); + if (!surface) { + client_post_out_of_memory(comp->client); + return; + } + + surface->obj = id; + wl_list_insert(&comp->client->surface_list, &surface->link); + + wthp_surface_set_interface(id, &surface_implementation, surface); + + surface->shm_window = calloc(1, sizeof *surface->shm_window); + if (!surface->shm_window) + return; + + surface->shm_window->server_surf = surface; + surface->shm_window->ready = false; + surface->ivi_id = 0; + + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + surface->shm_window->server_seat = seat; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_region(struct wthp_compositor *compositor, + struct wthp_region *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct region *region; + + wth_verbose("client %p create region %p\n", + comp->client, id); + + region = zalloc(sizeof *region); + if (!region) { + client_post_out_of_memory(comp->client); + return; + } + + region->obj = id; + wl_list_insert(&comp->client->region_list, ®ion->link); + + wthp_region_set_interface(id, ®ion_implementation, region); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_compositor_interface compositor_implementation = { + compositor_handle_create_surface, + compositor_handle_create_region +}; + +static void +client_bind_compositor(struct client *c, struct wthp_compositor *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp; + + comp = zalloc(sizeof *comp); + if (!comp) { + client_post_out_of_memory(c); + return; + } + + comp->obj = obj; + comp->client = c; + wl_list_insert(&c->compositor_list, &comp->link); + + wthp_compositor_set_interface(obj, &compositor_implementation, + comp); + wth_verbose("client %p bound wthp_compositor\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham registry implementation + */ +static void +registry_destroy(struct registry *reg) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, reg->obj); + + wthp_registry_free(reg->obj); + wl_list_remove(®->link); + free(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_destroy(struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + + registry_destroy(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_bind(struct wthp_registry *registry, + uint32_t name, + struct wth_object *id, + const char *interface, + uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + wth_verbose("Recieved registry : %s\n", interface); + + if (strcmp(interface, "wthp_compositor") == 0) { + client_bind_compositor(reg->client, (struct wthp_compositor *)id); + } else if (strcmp(interface, "wthp_blob_factory") == 0) { + client_bind_blob_factory(reg->client, (struct wthp_blob_factory *)id); + struct client *client = reg->client; + struct seat *seat, *tmp,*get_seat; + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + get_seat = seat; + } + wth_verbose("get_seat : %p\n", get_seat); + seat_send_updated_caps(get_seat); + } else if (strcmp(interface, "wthp_ivi_application") == 0) { + client_bind_wthp_ivi_application(reg->client, (struct wthp_ivi_application *)id); + } else if (strcmp(interface, "wthp_seat") == 0) { + client_bind_seat(reg->client, (struct wthp_seat *)id); + } else { + wth_object_post_error((struct wth_object *)registry, 0, + "%s: unknown name %u", __func__, name); + wth_object_delete(id); + } + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_registry_interface registry_implementation = { + registry_handle_destroy, + registry_handle_bind +}; + +/* + * waltham display implementation + */ + +static void +display_handle_client_version(struct wth_display *wth_display, + uint32_t client_version) +{ + wth_verbose("%s >>> \n",__func__); + wth_object_post_error((struct wth_object *)wth_display, 0, + "unimplemented: %s", __func__); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_sync(struct wth_display * wth_display, struct wthp_callback * callback) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + + wth_verbose("Client %p requested wth_display.sync\n", c); + wthp_callback_send_done(callback, 0); + wthp_callback_free(callback); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_get_registry(struct wth_display *wth_display, + struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + struct registry *reg; + + reg = zalloc(sizeof *reg); + if (!reg) { + client_post_out_of_memory(c); + return; + } + + reg->obj = registry; + reg->client = c; + wl_list_insert(&c->registry_list, ®->link); + wthp_registry_set_interface(registry, + ®istry_implementation, reg); + + wthp_registry_send_global(registry, 1, "wthp_compositor", 4); + wthp_registry_send_global(registry, 1, "wthp_ivi_application", 1); + wthp_registry_send_global(registry, 1, "wthp_seat", 4); + wthp_registry_send_global(registry, 1, "wthp_blob_factory", 4); + wth_verbose(" <<< %s \n",__func__); +} + +const struct wth_display_interface display_implementation = { + display_handle_client_version, + display_handle_sync, + display_handle_get_registry +}; + +/* + * functions to handle waltham client connections + */ +static void +connection_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = container_of(w, struct client, conn_watch); + int ret; + + if (events & EPOLLERR) { + wth_error("Client %p errored out.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLHUP) { + wth_error("Client %p hung up.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLOUT) { + ret = wth_connection_flush(c->connection); + if (ret == 0) + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN); + else if (ret < 0 && errno != EAGAIN){ + wth_error("Client %p flush error.\n", c); + client_destroy(c); + + return; + } + } + + if (events & EPOLLIN) { + ret = wth_connection_read(c->connection); + if (ret < 0) { + wth_error("Client %p read error.\n", c); + client_destroy(c); + + return; + } + + ret = wth_connection_dispatch(c->connection); + if (ret < 0 && errno != EPROTO) { + wth_error("Client %p dispatch error.\n", c); + client_destroy(c); + + return; + } + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* client_create +* +* Create new client connection +* +* @param srv Server structure +* @param wth_connection Waltham connection handle +* @return Pointer to client structure +*/ +static struct client * +client_create(struct server *srv, struct wth_connection *conn) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c; + struct wth_display *disp; + + c = zalloc(sizeof *c); + if (!c) + return NULL; + + c->server = srv; + c->connection = conn; + + c->conn_watch.server = srv; + c->conn_watch.fd = wth_connection_get_fd(conn); + c->conn_watch.cb = connection_handle_data; + if (watch_ctl(&c->conn_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + free(c); + return NULL; + } + + wth_verbose("Client %p connected.\n", c); + + wl_list_insert(&srv->client_list, &c->link); + + wl_list_init(&c->registry_list); + wl_list_init(&c->compositor_list); + wl_list_init(&c->seat_list); + wl_list_init(&c->pointer_list); + wl_list_init(&c->touch_list); + wl_list_init(&c->region_list); + wl_list_init(&c->surface_list); + wl_list_init(&c->buffer_list); + + disp = wth_connection_get_display(c->connection); + wth_display_set_interface(disp, &display_implementation, c); + + wth_verbose(" <<< %s \n",__func__); + return c; +} + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void +client_destroy(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region; + struct compositor *comp; + struct registry *reg; + struct surface *surface; + + wth_verbose("Client %p disconnected.\n", c); + + /* clean up remaining client resources in case the client + * did not. + */ + wl_list_last_until_empty(region, &c->region_list, link) + region_destroy(region); + + wl_list_last_until_empty(comp, &c->compositor_list, link) + compositor_destroy(comp); + + wl_list_last_until_empty(reg, &c->registry_list, link) + registry_destroy(reg); + + wl_list_last_until_empty(surface, &c->surface_list, link) + surface_destroy(surface); + + wl_list_remove(&c->link); + watch_ctl(&c->conn_watch, EPOLL_CTL_DEL, 0); + wth_connection_destroy(c->connection); + free(c); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_flush_clients(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c, *tmp; + int ret; + + wl_list_for_each_safe(c, tmp, &srv->client_list, link) { + /* Flush out buffered requests. If the Waltham socket is + * full, poll it for writable too. + */ + ret = wth_connection_flush(c->connection); + if (ret < 0 && errno == EAGAIN) { + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN | EPOLLOUT); + } else if (ret < 0) { + perror("Connection flush failed"); + client_destroy(c); + return; + } + } + + wth_verbose(" <<< %s \n",__func__); + +} + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_accept_client(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *client; + struct wth_connection *conn; + struct sockaddr_in addr; + socklen_t len; + + len = sizeof addr; + conn = wth_accept(srv->listen_fd, (struct sockaddr *)&addr, &len); + if (!conn) { + wth_error("Failed to accept a connection.\n"); + return; + } + + client = client_create(srv, conn); + if (!client) { + wth_error("Failed client_create().\n"); + return; + } + wth_verbose(" <<< %s \n",__func__); +} diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-weston.c b/demo3/horizontal/waltham-server/orig/src/wth-server-weston.c new file mode 100644 index 0000000..6cc309c --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-weston.c @@ -0,0 +1,811 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file is acts as interface to weston compositor at server ** +** side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +#include +#include + +#include "wth-server-weston.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" + + +static int running = 1; +extern bool get_verbosity(void); +extern int verbose; +/* + * buffer callback + */ +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct shm_buffer *mybuf = data; + + wth_verbose("%s >>> \n",__func__); + + mybuf->busy = 0; + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_shm_buffer(struct display *display, struct shm_buffer *buffer, + int width, int height, uint32_t format) +{ + struct wl_shm_pool *pool; + int fd, size, stride; + void *data; + + wth_verbose("%s >>> \n",__func__); + stride = width * 4; + size = stride * height; + + fd = os_create_anonymous_file(size); + if (fd < 0) { + wth_error("creating a buffer file for %d B failed: %m\n", + size); + return -1; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + wth_error("mmap failed: %m\n"); + close(fd); + return -1; + } + + pool = wl_shm_create_pool(display->shm, fd, size); + buffer->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, + stride, format); + wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); + wl_shm_pool_destroy(pool); + close(fd); + + buffer->shm_data = data; + + wth_verbose(" <<< %s \n",__func__); + return 0; +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->surface = wl_compositor_create_surface(display->compositor); + window->window_frames = 0; + window->window_benchmark_time = 0; + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + + } else { + assert(0); + } + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static struct shm_buffer * +window_next_buffer(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct shm_buffer *buffer; + int ret = 0; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + else { + window->buffers[0].busy = 0; + window->buffers[0].busy = 1; + buffer = &window->buffers[0]; + } + + if (!buffer->buffer) { + ret = create_shm_buffer(window->display, buffer, + window->width, window->height, + WL_SHM_FORMAT_XRGB8888); + + if (ret < 0) + return NULL; + + /* paint the padding */ + memset(buffer->shm_data, 0xff, + window->width * window->height * 4); + } + + wth_verbose(" <<< %s \n",__func__); + return buffer; +} + +static void +paint_pixels(void *image, int padding, int width, int height, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + const int halfh = padding + (height - padding * 2) / 2; + const int halfw = padding + (width - padding * 2) / 2; + int ir, or; + uint32_t *pixel = image; + int y; + + /* squared radii thresholds */ + or = (halfw < halfh ? halfw : halfh) - 8; + ir = or - 32; + or *= or; + ir *= ir; + + pixel += padding * width; + for (y = padding; y < height - padding; y++) { + int x; + int y2 = (y - halfh) * (y - halfh); + + pixel += padding; + for (x = padding; x < width - padding; x++) { + uint32_t v; + + /* squared distance from center */ + int r2 = (x - halfw) * (x - halfw) + y2; + + if (r2 < ir) + v = (r2 / 32 + time / 64) * 0x0080401; + else if (r2 < or) + v = (y + time / 32) * 0x0080401; + else + v = (x + time / 16) * 0x0080401; + v &= 0x00ffffff; + + /* cross if compositor uses X from XRGB as alpha */ + if (abs(x - y) > 6 && abs(x + y - height) > 6) + v |= 0xff000000; + + *pixel++ = v; + } + + pixel += padding; + } + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct timeval tv; + uint32_t time; + struct shm_buffer *buffer; + static int ss_count = 0; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + buffer = window_next_buffer(window); + if (!buffer) { + wth_error("Both buffers busy at redraw().\n"); + return; + } + + char *bitmap; + bitmap = getenv("BITMAP"); + if (bitmap) { + if (!strcmp(bitmap, "1")) { + int len; + const char *path = "/tmp/bitmap"; + len = strlen(path); + char *filename; + filename = (char *)malloc(len + 10); + sprintf(filename, "%s%d.bmp", path, ss_count); + wth_verbose("%s\n", filename); + + save_as_bitmap(filename, data, data_sz, width, height, format); + ss_count++; + free(filename); + } + } + buffer->shm_data = data; + window->width = width; + window->height = height; + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_damage(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + wl_surface_damage(window->surface, + 0, 0, window->width, window->height); + + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + static const uint32_t benchmark_interval = 5; + struct timeval tv; + uint32_t time; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (window->window_frames == 0) + window->window_benchmark_time = time; + if (time - window->window_benchmark_time > (benchmark_interval * 1000)) { + wth_verbose("-------------------------------%d frames in %d seconds: %f fps\n", + window->window_frames, + benchmark_interval, + (float) window->window_frames / benchmark_interval); + + window->window_benchmark_time = time; + window->window_frames = 0; + } + + wl_surface_commit(window->surface); + + wl_display_flush(window->display->display); + + if (window->wait) + window->wait = 0; + + window->window_frames++; + wth_verbose(" <<< %s \n",__func__); +} + +/* + * frame callback function - this function will display buffer to surface + */ + +static const struct wl_callback_listener frame_listener; +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = data; + struct shm_buffer *buffer; + + buffer = window_next_buffer(window); + if (!buffer) { + if(!callback) + { + wth_error("Failed to create the first buffer.\n"); + } + else + { + wth_error("Both buffers busy at redraw(). Server bug?\n"); + } + abort(); + } + + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + wl_surface_damage(window->surface, + 20, 20, window->width - 40, window->height - 40); + + if (callback) + wl_callback_destroy(callback); + + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +/* + * shm callbcak function + */ + +static void +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (format == WL_SHM_FORMAT_XRGB8888) + d->has_xrgb = true; + + wth_verbose(" <<< %s \n",__func__); +} + +struct wl_shm_listener shm_listener = { + shm_format +}; + +/* + * pointer callbcak functions + */ +static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + if (display->shm == NULL) { + wth_error("No wl_shm global\n"); + exit(1); + } + + wl_display_roundtrip(display->display); + + if (!display->has_xrgb) { + wth_error("WL_SHM_FORMAT_XRGB32 not available\n"); + exit(1); + } + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->shm) + wl_shm_destroy(display->shm); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int +wth_server_weston_main(void *data) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = (struct window *) data; + struct sigaction sigint; + struct display *display; + int ret = 0; + + display = create_display(); + create_window(window, display, 400, 400); + if (!window) + return -1; + wl_display_roundtrip(display->display); + wth_verbose("data %p\n", data); + wth_verbose("window %p\n", window); + + display->window = window; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* Initialise damage to full surface, so the padding gets painted */ + wl_surface_damage(window->surface, 0, 0, + window->width, window->height); + + redraw(window, NULL, 0); + + window->wait = 1; + window->ready = true; + while (window->wait) + { + ret = wl_display_dispatch(display->display); + usleep(1); + } + wth_verbose("debug\n"); + while (running && ret != -1) + ret = wl_display_dispatch(display->display); + + wth_verbose("wth_server_weston_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(display); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} -- cgit 1.2.3-korg