blob: 35ec67a4c3a1f70629ef1ed30423b01ff73854bb [file] [log] [blame]
From 62628502047672c190fadc3f98caf427df25dfe6 Mon Sep 17 00:00:00 2001
From: Qian Hu <Qian.Hu@mediatek.com>
Date: Tue, 24 Sep 2019 14:31:26 +0800
Subject: [PATCH 7/8] [PATCH] weston: add mtk test client
add mtk test client
Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
---
Makefile.am | 14 +
clients/simple-configure-mtk.c | 1247 ++++++++++++++++++++++++++++++++++++++++
configure.ac | 1 +
3 files changed, 1262 insertions(+)
create mode 100644 clients/simple-configure-mtk.c
diff --git a/Makefile.am b/Makefile.am
index a9e48f8..7efa5a0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -668,6 +668,20 @@ nodist_weston_simple_screenshooter_mtk_SOURCES = \
weston_simple_screenshooter_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
weston_simple_screenshooter_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
+if BUILD_SIMPLE_CONFIGURE_MTK_CLIENT
+demo_clients += weston-simple-configure-mtk
+weston_simple_configure_mtk_SOURCES = clients/simple-configure-mtk.c
+nodist_weston_simple_configure_mtk_SOURCES = \
+ protocol/xdg-shell-unstable-v6-protocol.c \
+ protocol/xdg-shell-unstable-v6-client-protocol.h \
+ protocol/fullscreen-shell-unstable-v1-protocol.c \
+ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
+ protocol/linux-dmabuf-unstable-v1-protocol.c \
+ protocol/linux-dmabuf-unstable-v1-client-protocol.h
+weston_simple_configure_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+weston_simple_configure_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
+BUILT_SOURCES += protocol/linux-dmabuf-unstable-v1-client-protocol.h
+endif
noinst_LTLIBRARIES += libtoytoolkit.la
diff --git a/clients/simple-configure-mtk.c b/clients/simple-configure-mtk.c
new file mode 100644
index 0000000..8b146ff
--- /dev/null
+++ b/clients/simple-configure-mtk.c
@@ -0,0 +1,1245 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <math.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/input.h>
+
+#include <wayland-client.h>
+#include <wayland-cursor.h>
+
+#include <drm_fourcc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+//#include "ivi-application-client-protocol.h"
+#include "xdg-shell-unstable-v6-client-protocol.h"
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
+#include "fullscreen-shell-unstable-v1-client-protocol.h"
+#include "weston-configure-mtk-client-protocol.h"
+
+#include <shared/platform.h>
+
+//#define IVI_SURFACE_ID 9000
+#define MAX_IMAGE 16
+#define ALIGN(X,bit) ((X + bit-1) & (~(bit-1)))
+#define MAX_DMABUF_PLANES 4
+#define RES_NUM 4
+#define MAX_LEN 60
+
+struct window;
+struct seat;
+
+struct display {
+ struct wl_display *display;
+ struct wl_registry *registry;
+ struct wl_compositor *compositor;
+ struct zxdg_shell_v6 *shell;
+ struct zwp_fullscreen_shell_v1 *fshell;
+ //struct ivi_application *ivi_application;
+ struct wl_seat *seat;
+ struct wl_pointer *pointer;
+ struct wl_touch *touch;
+ struct wl_keyboard *keyboard;
+ struct wl_shm *shm;
+ struct zwp_linux_dmabuf_v1 *dmabuf;
+ struct wl_list output_list; /* struct output_unit::link */
+ struct wl_cursor_theme *cursor_theme;
+ struct wl_cursor *default_cursor;
+ struct wl_surface *cursor_surface;
+ struct window *window;
+ struct config_switch *config_switch;
+};
+
+struct geometry {
+ int width, height;
+};
+
+struct buffer {
+ struct wl_buffer *buffer;
+ void *dma_map;
+ int busy;
+};
+
+struct file_arg{
+ char filename[MAX_LEN];
+ int width;
+ int height;
+ int format;
+};
+
+struct window {
+ struct display *display;
+ struct geometry geometry, window_size;
+ bool wait_for_configure;
+ struct {
+ struct file_arg fProp;
+ struct buffer out_bufs[RES_NUM];
+ } image;
+ struct img_texture *tex;
+ uint32_t benchmark_time, frames;
+ struct wl_surface *surface;
+ struct zxdg_surface_v6 *xdg_surface;
+ struct zxdg_toplevel_v6 *xdg_toplevel;
+ //struct ivi_surface *ivi_surface;
+ struct wl_callback *callback;
+ int fullscreen, opaque, buffer_size, overlay, format;
+ enum wl_output_transform transform;
+ int drm_card_fd;
+ struct config_switch_set *switch_set;
+};
+
+struct img_texture {
+ struct context *ctx;
+
+ /* input */
+ int width;
+ int height;
+ int drm_format;
+ int bpp;
+ int plane_nums;
+
+ int pitch[MAX_DMABUF_PLANES];
+ int offset[MAX_DMABUF_PLANES];
+ int fds[MAX_DMABUF_PLANES];
+ int handle[MAX_DMABUF_PLANES];
+
+ void *texbuf;
+ int size;
+};
+
+typedef enum _IMG_FORMAT_E {
+ IMG_FORMAT_RGB565 = 0,
+ IMG_FORMAT_XRGB8888,
+ IMG_FORMAT_ARGB8888,
+ IMG_FORMAT_YUYV,
+ IMG_FORMAT_NV12,
+ IMG_FORMAT_NV16,
+ IMG_FORMAT_YUV420,
+ IMG_FORMAT_YVU420,
+ IMG_FORMAT_LAST,
+} IMG_FORMAT_T;
+
+struct drm_fourcc_info {
+ unsigned int drm_format;
+ int plane_cnt;
+ int bpp;
+};
+
+static struct drm_fourcc_info fourcc_tbl[] = {
+ {DRM_FORMAT_RGB565, 1, 16},
+ {DRM_FORMAT_RGBA5551, 1, 16},
+ {DRM_FORMAT_RGBA4444, 1, 16},
+ {DRM_FORMAT_XRGB8888, 1, 32},
+ {DRM_FORMAT_XBGR8888, 1, 32},
+ {DRM_FORMAT_RGBX8888, 1, 32},
+ {DRM_FORMAT_BGRX8888, 1, 32},
+ {DRM_FORMAT_ARGB8888, 1, 32},
+ {DRM_FORMAT_ABGR8888, 1, 32},
+ {DRM_FORMAT_RGBA8888, 1, 32},
+ {DRM_FORMAT_BGRA8888, 1, 32},
+ {DRM_FORMAT_YUYV, 1, 16},
+ {DRM_FORMAT_VYUY, 1, 16},
+ {DRM_FORMAT_NV12, 2, 12},
+ {DRM_FORMAT_NV21, 2, 12},
+ {DRM_FORMAT_NV16, 2, 16},
+ {DRM_FORMAT_NV61, 2, 16},
+ {DRM_FORMAT_YUV420, 3, 12},
+ {DRM_FORMAT_YVU420, 3, 12},
+ {0, 0, 0},
+};
+
+static int running = 1;
+static int debug = 0;
+
+static void
+redraw(void *data, struct wl_callback *callback, uint32_t time);
+
+static int _format_transfer(int format, int *drm_format)
+{
+ int new_format;
+
+ if (!drm_format)
+ return -1;
+
+ switch (format) {
+ case IMG_FORMAT_RGB565:
+ new_format = DRM_FORMAT_RGB565;
+ break;
+ case IMG_FORMAT_XRGB8888:
+ new_format = DRM_FORMAT_XRGB8888;
+ break;
+ case IMG_FORMAT_ARGB8888:
+ new_format = DRM_FORMAT_ARGB8888;
+ break;
+ case IMG_FORMAT_YUYV:
+ new_format = DRM_FORMAT_YUYV;
+ break;
+ case IMG_FORMAT_NV12:
+ new_format = DRM_FORMAT_NV12;
+ break;
+ case IMG_FORMAT_NV16:
+ new_format = DRM_FORMAT_NV16;
+ break;
+ case IMG_FORMAT_YUV420:
+ new_format = DRM_FORMAT_YUV420;
+ break;
+ case IMG_FORMAT_YVU420:
+ new_format = DRM_FORMAT_YVU420;
+ break;
+ default:
+ return -2;
+ }
+ *drm_format = new_format;
+
+ return 0;
+}
+
+static struct drm_fourcc_info *
+get_drm_format_info(unsigned int format)
+{
+ int i;
+
+ for (i = 0; ; i++) {
+ if ( format == fourcc_tbl[i].drm_format){
+ return &fourcc_tbl[i];
+ }
+ if ( fourcc_tbl[i].drm_format == 0)
+ break;
+ }
+ return NULL;
+}
+
+static char *
+_get_tex_resource(int drifd, struct img_texture *tex)
+{
+ void *map = NULL;
+ struct drm_mode_create_dumb create_arg;
+ struct drm_mode_map_dumb map_arg;
+ struct drm_prime_handle prime_arg;
+ struct drm_fourcc_info *format_info;
+ int i, ret;
+ unsigned int alloc_size;
+
+ memset(&create_arg, 0, sizeof(create_arg));
+ memset(&map_arg, 0, sizeof(map_arg));
+ memset(&prime_arg, 0, sizeof(prime_arg));
+
+ for(i = 0; i < MAX_DMABUF_PLANES; i ++ )
+ tex->fds[i] = -1;
+
+ format_info = get_drm_format_info(tex->drm_format);
+ if (format_info == NULL)
+ return NULL;
+
+ tex->bpp = format_info->bpp;
+ if (format_info->plane_cnt == 3) {
+ if (format_info->bpp == 12) {
+ tex->pitch[0] = ALIGN(tex->width, 16);
+ tex->pitch[1] = tex->pitch[0] / 2;
+ tex->pitch[2] = tex->pitch[0] / 2;
+ tex->offset[0] = 0;
+ tex->offset[1] = tex->pitch[0] * tex->height;
+ tex->offset[2] = tex->offset[1] + tex->pitch[1] * tex->height / 2;
+ alloc_size = tex->offset[2] + tex->pitch[2] * tex->height / 2;
+ } else {
+ fprintf(stderr,"debug: please add new format 0x%x\n", tex->drm_format);
+ return NULL;
+ }
+ } else if (format_info->plane_cnt == 2) {
+ tex->pitch[0] = ALIGN(tex->width, 16);
+ tex->offset[0] = 0;
+ if (format_info->bpp == 16) {
+ tex->pitch[1] = tex->pitch[0];
+ tex->offset[1] = tex->pitch[0] * tex->height;
+ alloc_size = tex->offset[1] + tex->pitch[1] * tex->height;
+ fprintf(stderr,"debug: %s %d alloc_size = %d o/p [%d %d]\n",
+ __FUNCTION__, __LINE__, alloc_size, tex->offset[1], tex->pitch[1]);
+ }
+ else if (format_info->bpp == 12) {
+ tex->pitch[1] = tex->pitch[0] / 2;
+ tex->offset[1] = tex->pitch[0] * tex->height;
+ alloc_size = tex->offset[1] + tex->pitch[1] * tex->height;
+ } else {
+ fprintf(stderr,"debug: please add new format 0x%x\n", tex->drm_format);
+ return NULL;
+ }
+ } else {
+ tex->pitch[0] = ALIGN(tex->width * tex->bpp / 8, 16);
+ tex->offset[0] = 0;
+ alloc_size = tex->pitch[0] * tex->height;
+ }
+
+ create_arg.bpp = 8;
+ create_arg.width = alloc_size;
+ create_arg.height = 1;
+
+ ret = drmIoctl(drifd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
+ if (ret) {
+ fprintf(stderr,"error: drmIoctl %d DRM_IOCTL_MODE_CREATE_DUMB fail %d\n", drifd, ret);
+ return NULL;
+ }
+
+ map_arg.handle = create_arg.handle;
+
+ ret = drmIoctl(drifd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
+ if (ret) {
+ fprintf(stderr,"error: drmIoctl DRM_IOCTL_MODE_MAP_DUMB fail %d\n", ret);
+ return NULL;
+ }
+
+ map = mmap(0, create_arg.size, PROT_WRITE|PROT_READ , MAP_SHARED, drifd, map_arg.offset);
+ if (map == MAP_FAILED) {
+ fprintf(stderr,"error: mmap fail : %p\n", map);
+ return NULL;
+ }
+
+ prime_arg.handle = create_arg.handle;
+ prime_arg.flags = DRM_CLOEXEC;
+ ret = drmIoctl(drifd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_arg);
+ if (ret || prime_arg.fd == -1) {
+ fprintf(stderr,"error: drmIoctl DRM_IOCTL_PRIME_HANDLE_TO_FD fail %d fd=%d\n",ret,prime_arg.fd);
+ return NULL;
+ }
+
+ for (i = 0; i < format_info->plane_cnt; i++) {
+ tex->fds[i] = prime_arg.fd;
+ tex->handle[i] = create_arg.handle;
+ }
+ tex->plane_nums = format_info->plane_cnt;
+ tex->texbuf = map;
+ tex->size = create_arg.size;
+
+ return map;
+}
+
+static int
+init_img_texture(struct window *window)
+{
+ int ret;
+ struct img_texture *tex;
+ tex = malloc(sizeof *tex);
+ if (tex == NULL)
+ return -1;
+
+ ret = _format_transfer(window->image.fProp.format, &(tex->drm_format));
+ if (ret < 0)
+ return -1;
+
+ tex->width = window->image.fProp.width;
+ tex->height= window->image.fProp.height;
+
+ window->tex = tex;
+ return 0;
+}
+
+static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+ struct buffer *mybuf = data;
+
+ mybuf->busy = 0;
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+ buffer_release
+};
+
+static void
+create_succeeded(void *data,
+ struct zwp_linux_buffer_params_v1 *params,
+ struct wl_buffer *new_buffer)
+{
+ struct buffer *buffer = data;
+
+ buffer->buffer = new_buffer;
+ wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
+
+ zwp_linux_buffer_params_v1_destroy(params);
+}
+
+static void
+create_failed(void *data, struct zwp_linux_buffer_params_v1 *params)
+{
+ struct buffer *buffer = data;
+
+ buffer->buffer = NULL;
+
+ zwp_linux_buffer_params_v1_destroy(params);
+
+ running = false;
+
+ fprintf(stderr, "Error: zwp_linux_buffer_params.create failed.\n");
+}
+
+static const struct zwp_linux_buffer_params_v1_listener params_listener = {
+ create_succeeded,
+ create_failed
+};
+
+static int
+create_dmabuf_buffer(struct display *display, struct buffer *buffer)
+{
+ struct zwp_linux_buffer_params_v1 *params;
+ struct img_texture *cbtex = display->window->tex;
+ uint64_t modifier;
+ uint32_t flags;
+ int i;
+ /* output */
+ buffer->dma_map = _get_tex_resource(display->window->drm_card_fd, cbtex);
+
+ if (buffer->dma_map == NULL) {
+ fprintf(stderr, "error: _get_tex_resource failed\n");
+ return -1;
+ }
+
+ modifier = 0;
+ params = zwp_linux_dmabuf_v1_create_params(display->dmabuf);
+
+ for(i = 0; i < cbtex->plane_nums; i ++)
+ {
+ zwp_linux_buffer_params_v1_add(params,
+ cbtex->fds[i],
+ i, /* plane_idx */
+ cbtex->offset[i],/* offset */
+ cbtex->pitch[i],
+ modifier >> 32,
+ modifier & 0xffffffff);
+ }
+ zwp_linux_buffer_params_v1_add_listener(params, &params_listener, buffer);
+ zwp_linux_buffer_params_v1_create(params,
+ cbtex->width,
+ cbtex->height,
+ cbtex->drm_format,
+ flags);
+
+ /* params is destroyed by the event handlers */
+ wl_display_roundtrip(display->display);
+ if (buffer->buffer == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+_load_file(void *buf, int len, const char *file_name)
+{
+ int ret, nread = 0;
+
+ FILE *fp = fopen(file_name, "rb");
+ if (!fp)
+ {
+ fprintf(stderr,"debug: file %s open failed\n", file_name);
+ return -1;
+ }
+
+ while (nread < len) {
+ ret = fread(buf + nread, 1, len - nread, fp);
+ if (!ret)
+ break;
+ nread += ret;
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+static int
+_kms_device_fd(void)
+{
+ int i;
+ bool has_conn = false;
+ for (i = 0; i < 8; ++i) {
+ char path[99];
+ sprintf(path, "/dev/dri/card%d", i);
+ fprintf(stderr, "debug: trying %s\n", path);
+ int fd = open(path, O_RDWR | O_CLOEXEC);
+ if (fd >= 0) {
+ drmModeResPtr mr = drmModeGetResources(fd);
+ if (mr) {
+ has_conn = mr->count_connectors > 0;
+ drmModeFreeResources(mr);
+ }
+ if (has_conn) {
+ fprintf(stderr, "debug: using %s\n", path);
+ return fd;
+ }
+ close(fd);
+ }
+ }
+ return -1;
+}
+
+static void
+handle_xdg_surface_configure(void *data, struct zxdg_surface_v6 *surface,
+ uint32_t serial)
+{
+ struct window *window = data;
+ fprintf(stderr, "handle_xdg_surface_configure\n");
+
+ zxdg_surface_v6_ack_configure(surface, serial);
+
+ if (window->wait_for_configure) {
+ redraw(window, NULL, 0);
+ window->wait_for_configure = false;
+ }
+}
+
+static const struct zxdg_surface_v6_listener xdg_surface_listener = {
+ handle_xdg_surface_configure,
+};
+
+
+static void
+handle_toplevel_configure(void *data, struct zxdg_toplevel_v6 *toplevel,
+ int32_t width, int32_t height,
+ struct wl_array *states)
+{
+ struct window *window = data;
+ uint32_t *p;
+
+ window->fullscreen = 0;
+ wl_array_for_each(p, states) {
+ uint32_t state = *p;
+ switch (state) {
+ case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
+ window->fullscreen = 1;
+ break;
+ }
+ }
+
+ if (width > 0 && height > 0) {
+ if (!window->fullscreen) {
+ window->window_size.width = width;
+ window->window_size.height = height;
+ }
+ window->geometry.width = width;
+ window->geometry.height = height;
+ } else if (!window->fullscreen) {
+ window->geometry = window->window_size;
+ }
+
+ /*if (window->native)
+ wl_egl_window_resize(window->native,
+ window->geometry.width,
+ window->geometry.height, 0, 0);*/
+}
+
+static void
+handle_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel)
+{
+ running = 0;
+}
+
+static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
+ handle_toplevel_configure,
+ handle_toplevel_close,
+};
+/*
+static void
+handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
+ int32_t width, int32_t height)
+{
+
+}
+
+static const struct ivi_surface_listener ivi_surface_listener = {
+ handle_ivi_surface_configure,
+};
+*/
+static struct buffer *
+window_next_buffer(struct window *window)
+{
+ struct buffer *buffer = NULL;
+ int i, ret = 0;
+
+ for(i = 0; i < RES_NUM; i++) {
+ if (!window->image.out_bufs[i].busy) {
+ buffer = &window->image.out_bufs[i];
+ break;
+ }
+ }
+
+ if (!buffer)
+ return NULL;
+
+ if (!buffer->buffer) {
+ ret = create_dmabuf_buffer(window->display, buffer);
+ if (ret < 0)
+ return NULL;
+ if(i%2)
+ _load_file(buffer->dma_map, window->tex->size, window->image.fProp.filename);
+ else
+ memset(buffer->dma_map, 0, window->tex->size);
+ }
+
+ return buffer;
+}
+
+static void
+create_surface(struct window *window)
+{
+ struct display *display = window->display;
+
+ window->surface = wl_compositor_create_surface(display->compositor);
+ display->cursor_surface =
+ wl_compositor_create_surface(display->compositor);
+
+ window->switch_set = config_switch_connect(display->config_switch, window->surface);
+
+ if (display->shell) {
+ window->xdg_surface =
+ zxdg_shell_v6_get_xdg_surface(display->shell,
+ window->surface);
+
+ assert(window->xdg_surface);
+
+ zxdg_surface_v6_add_listener(window->xdg_surface,
+ &xdg_surface_listener, window);
+
+ window->xdg_toplevel =
+ zxdg_surface_v6_get_toplevel(window->xdg_surface);
+ zxdg_toplevel_v6_add_listener(window->xdg_toplevel,
+ &xdg_toplevel_listener, window);
+
+ zxdg_toplevel_v6_set_title(window->xdg_toplevel, "simple-configure-mtk");
+ window->wait_for_configure = true;
+ wl_surface_commit(window->surface);
+ } else if (display->fshell) {
+ zwp_fullscreen_shell_v1_present_surface(display->fshell,
+ window->surface,
+ ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT,
+ NULL);
+ //} else if (display->ivi_application ) {
+ // uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
+ // window->ivi_surface =
+ // ivi_application_surface_create(display->ivi_application,
+ // id_ivisurf, window->surface);
+ // if (window->ivi_surface == NULL) {
+ // fprintf(stderr, "Failed to create ivi_client_surface\n");
+ // abort();
+ // }
+//
+ // ivi_surface_add_listener(window->ivi_surface,
+ // &ivi_surface_listener, window);
+
+ } else {
+ assert(0);
+ }
+
+}
+
+static void
+destroy_surface(struct window *window)
+{
+ if (window->xdg_toplevel)
+ zxdg_toplevel_v6_destroy(window->xdg_toplevel);
+ if (window->xdg_surface)
+ zxdg_surface_v6_destroy(window->xdg_surface);
+ //if (window->display->ivi_application)
+ // ivi_surface_destroy(window->ivi_surface);
+ if (window->display->fshell)
+ zwp_fullscreen_shell_v1_release(window->display->fshell);
+ wl_surface_destroy(window->surface);
+
+ if (window->callback)
+ wl_callback_destroy(window->callback);
+
+ if (window->image.out_bufs[0].buffer)
+ wl_buffer_destroy(window->image.out_bufs[0].buffer);
+ if (window->image.out_bufs[1].buffer)
+ wl_buffer_destroy(window->image.out_bufs[1].buffer);
+ if (window->image.out_bufs[2].buffer)
+ wl_buffer_destroy(window->image.out_bufs[2].buffer);
+}
+
+static const struct wl_callback_listener frame_listener;
+
+static void
+redraw(void *data, struct wl_callback *callback, uint32_t time)
+{
+ struct window *window = data;
+ struct buffer *buffer;
+ char filename[MAX_LEN] = {0};
+ static const uint32_t benchmark_interval = 5;
+ struct wl_region *region;
+ struct timeval tv;
+ int tmp;
+
+ buffer = window_next_buffer(window);
+ if (!buffer) {
+ fprintf(stderr,
+ !callback ? "error: Failed to create the first buffer.\n" :
+ "error: Both buffers busy at redraw(). Server bug?\n");
+ abort();
+ }
+
+ gettimeofday(&tv, NULL);
+ time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ if (window->frames == 0)
+ window->benchmark_time = time;
+ if (time - window->benchmark_time > (benchmark_interval * 1000)) {
+ printf("debug: %d frames in %d seconds: %f fps\n",
+ window->frames,
+ benchmark_interval,
+ (float) window->frames / benchmark_interval);
+ window->benchmark_time = time;
+ window->frames = 0;
+ }
+
+ if (window->opaque || window->fullscreen) {
+ region = wl_compositor_create_region(window->display->compositor);
+ wl_region_add(region, 0, 0,
+ window->geometry.width,
+ window->geometry.height);
+ wl_surface_set_opaque_region(window->surface, region);
+ wl_region_destroy(region);
+ } else {
+ wl_surface_set_opaque_region(window->surface, NULL);
+ }
+
+ wl_surface_attach(window->surface, buffer->buffer, 0, 0);
+ wl_surface_set_buffer_transform(window->surface,
+ window->transform);
+ wl_surface_damage(window->surface,
+ 0, 0, window->geometry.width, window->geometry.height);
+
+ 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;
+
+ window->frames++;
+}
+
+static const struct wl_callback_listener frame_listener = {
+ redraw
+};
+
+static void
+pointer_handle_enter(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t sx, wl_fixed_t sy)
+{
+ struct display *display = data;
+ struct wl_buffer *buffer;
+ struct wl_cursor *cursor = display->default_cursor;
+ struct wl_cursor_image *image;
+
+ if (display->window->fullscreen)
+ wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
+ else if (cursor) {
+ image = display->default_cursor->images[0];
+ buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer)
+ return;
+ wl_pointer_set_cursor(pointer, serial,
+ display->cursor_surface,
+ image->hotspot_x,
+ image->hotspot_y);
+ wl_surface_attach(display->cursor_surface, buffer, 0, 0);
+ wl_surface_damage(display->cursor_surface, 0, 0,
+ image->width, image->height);
+ wl_surface_commit(display->cursor_surface);
+ }
+
+}
+
+static void
+pointer_handle_leave(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface)
+{
+}
+
+static void
+pointer_handle_motion(void *data, struct wl_pointer *pointer,
+ uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
+{
+
+}
+
+static void
+pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
+ uint32_t serial, uint32_t time, uint32_t button,
+ uint32_t state)
+{
+ struct display *display = data;
+
+ if (!display->window->xdg_surface)
+ return;
+
+ if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
+ zxdg_toplevel_v6_move(display->window->xdg_toplevel,
+ display->seat, serial);
+}
+
+static void
+pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
+ uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+ pointer_handle_enter,
+ pointer_handle_leave,
+ pointer_handle_motion,
+ pointer_handle_button,
+ pointer_handle_axis,
+};
+
+static void
+touch_handle_down(void *data, struct wl_touch *wl_touch,
+ uint32_t serial, uint32_t time, struct wl_surface *surface,
+ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+ struct display *d = (struct display *)data;
+
+ if (!d->shell)
+ return;
+
+ zxdg_toplevel_v6_move(d->window->xdg_toplevel, d->seat, serial);
+}
+
+static void
+touch_handle_up(void *data, struct wl_touch *wl_touch,
+ uint32_t serial, uint32_t time, int32_t id)
+{
+}
+
+static void
+touch_handle_motion(void *data, struct wl_touch *wl_touch,
+ uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+}
+
+static void
+touch_handle_frame(void *data, struct wl_touch *wl_touch)
+{
+}
+
+static void
+touch_handle_cancel(void *data, struct wl_touch *wl_touch)
+{
+}
+
+static const struct wl_touch_listener touch_listener = {
+ touch_handle_down,
+ touch_handle_up,
+ touch_handle_motion,
+ touch_handle_frame,
+ touch_handle_cancel,
+};
+
+static void
+keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
+ uint32_t format, int fd, uint32_t size)
+{
+}
+
+static void
+keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, struct wl_surface *surface,
+ struct wl_array *keys)
+{
+}
+
+static void
+keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, struct wl_surface *surface)
+{
+}
+
+static void
+keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, uint32_t time, uint32_t key,
+ uint32_t state)
+{
+ struct display *d = data;
+
+ if (!d->shell)
+ return;
+
+ if (key == KEY_F11 && state) {
+ if (d->window->fullscreen)
+ zxdg_toplevel_v6_unset_fullscreen(d->window->xdg_toplevel);
+ else
+ zxdg_toplevel_v6_set_fullscreen(d->window->xdg_toplevel, NULL);
+ } else if (key == KEY_ESC && state)
+ running = 0;
+}
+
+static void
+keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, uint32_t mods_depressed,
+ uint32_t mods_latched, uint32_t mods_locked,
+ uint32_t group)
+{
+}
+
+static const struct wl_keyboard_listener keyboard_listener = {
+ keyboard_handle_keymap,
+ keyboard_handle_enter,
+ keyboard_handle_leave,
+ keyboard_handle_key,
+ keyboard_handle_modifiers,
+};
+
+static void
+seat_handle_capabilities(void *data, struct wl_seat *seat,
+ enum wl_seat_capability caps)
+{
+ struct display *d = data;
+
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !d->pointer) {
+ d->pointer = wl_seat_get_pointer(seat);
+ wl_pointer_add_listener(d->pointer, &pointer_listener, d);
+ } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && d->pointer) {
+ wl_pointer_destroy(d->pointer);
+ d->pointer = NULL;
+ }
+
+ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
+ d->keyboard = wl_seat_get_keyboard(seat);
+ wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
+ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
+ wl_keyboard_destroy(d->keyboard);
+ d->keyboard = NULL;
+ }
+
+ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !d->touch) {
+ d->touch = wl_seat_get_touch(seat);
+ wl_touch_set_user_data(d->touch, d);
+ wl_touch_add_listener(d->touch, &touch_listener, d);
+ } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && d->touch) {
+ wl_touch_destroy(d->touch);
+ d->touch = NULL;
+ }
+}
+
+static const struct wl_seat_listener seat_listener = {
+ seat_handle_capabilities,
+};
+
+
+static void
+xdg_shell_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
+{
+ zxdg_shell_v6_pong(shell, serial);
+}
+
+static const struct zxdg_shell_v6_listener xdg_shell_listener = {
+ xdg_shell_ping,
+};
+
+static void
+dmabuf_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format)
+{
+ fprintf(stderr, "debug: Support drm_format 0x%x \n", format);
+}
+
+static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
+ dmabuf_format
+};
+
+static void
+registry_handle_global(void *data, struct wl_registry *registry,
+ uint32_t name, const char *interface, uint32_t version)
+{
+ struct display *d = data;
+
+ if (strcmp(interface, "wl_compositor") == 0) {
+ d->compositor =
+ wl_registry_bind(registry, name,
+ &wl_compositor_interface, 2);
+ } else if (strcmp(interface, "zxdg_shell_v6") == 0) {
+ d->shell = wl_registry_bind(registry, name,
+ &zxdg_shell_v6_interface, 1);
+ zxdg_shell_v6_add_listener(d->shell, &xdg_shell_listener, d);
+ } else if (strcmp(interface, "wl_seat") == 0) {
+ d->seat = wl_registry_bind(registry, name,
+ &wl_seat_interface, 1);
+ wl_seat_add_listener(d->seat, &seat_listener, d);
+ } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
+ d->fshell = wl_registry_bind(registry, name,
+ &zwp_fullscreen_shell_v1_interface, 1);
+ } else if (strcmp(interface, "wl_shm") == 0) {
+ d->shm = wl_registry_bind(registry, name,
+ &wl_shm_interface, 1);
+ d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm);
+ if (!d->cursor_theme) {
+ fprintf(stderr, "unable to load default theme\n");
+ return;
+ }
+ d->default_cursor =
+ wl_cursor_theme_get_cursor(d->cursor_theme, "grabbing");
+ if (!d->default_cursor) {
+ fprintf(stderr, "unable to load default grabbing pointer\n");
+ // TODO: abort ?
+ }
+ //} else if (strcmp(interface, "ivi_application") == 0) {
+ // d->ivi_application =
+ // wl_registry_bind(registry, name,
+ // &ivi_application_interface, 1);
+ } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
+ d->dmabuf = wl_registry_bind(registry, name,
+ &zwp_linux_dmabuf_v1_interface, 1);
+ zwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener, d);
+ } else if (strcmp(interface, "config_switch") == 0) {
+ d->config_switch =
+ wl_registry_bind(registry, name,
+ &config_switch_interface, 1);
+ }
+}
+
+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 void
+destroy_display(struct display *display)
+{
+ if (display->dmabuf)
+ zwp_linux_dmabuf_v1_destroy(display->dmabuf);
+
+ if (display->shell)
+ zxdg_shell_v6_destroy(display->shell);
+
+ if (display->fshell)
+ zwp_fullscreen_shell_v1_release(display->fshell);
+
+ if (display->compositor)
+ wl_compositor_destroy(display->compositor);
+
+ wl_surface_destroy(display->cursor_surface);
+ if (display->cursor_theme)
+ wl_cursor_theme_destroy(display->cursor_theme);
+
+ //if (display->ivi_application)
+ // ivi_application_destroy(display->ivi_application);
+
+ wl_registry_destroy(display->registry);
+ wl_display_flush(display->display);
+ wl_display_disconnect(display->display);
+ free(display);
+}
+
+static struct display *
+create_display(struct window *window)
+{
+ struct display *display;
+
+ display = malloc(sizeof *display);
+ if (display == NULL) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ display->display = wl_display_connect(NULL);
+ assert(display->display);
+ display->window = window;
+
+ display->registry = wl_display_get_registry(display->display);
+ wl_registry_add_listener(display->registry,
+ &registry_listener, display);
+ wl_display_roundtrip(display->display);
+ if (display->dmabuf == NULL) {
+ fprintf(stderr, "No zwp_linux_dmabuf_v1 global found\n");
+ exit(1);
+ }
+ wl_display_roundtrip(display->display);
+
+ return display;
+}
+
+static void
+signal_int(int signum)
+{
+ running = 0;
+}
+
+/*
+ * parse the message inputed for rawdata
+ * egg: -F /usr/share/weston/rawdata.nv16:720x480@5
+ * filename:widthxheight@format
+*/
+static int parse_file(struct file_arg *file, char *p)
+{
+ char *end;
+ char *pPos = p;
+ int len, i;
+
+ len = strlen(pPos) + 1;
+ for (i = 0; i < len; i++)
+ if(pPos[i] == ':')
+ pPos[i] = '\0';
+
+ memcpy(file->filename, pPos, strlen(pPos) + 1);
+ pPos = pPos + strlen(pPos) + 1;
+ file->width = strtoul(pPos, &end, 10);
+ if (*end != 'x')
+ return -EINVAL;
+ pPos = end + 1;
+ file->height = strtoul(pPos, &end, 10);
+ if (*end != '@')
+ return -EINVAL;
+ pPos = end + 1;
+ file->format = strtoul(pPos, &end, 10);
+ if (*end != '\0')
+ return -EINVAL;
+ return 0;
+}
+
+static void init_window(struct window *window)
+{
+ window->geometry.width = 0;
+ window->geometry.height = 0;
+ window->buffer_size = 32;
+ window->transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ window->opaque = 1;
+ window->overlay = 0;
+ window->format = 0;
+ window->drm_card_fd = -1;
+}
+
+static void
+usage(int error_code)
+{
+ fprintf(stderr, "Usage: mtkdraw-dma [OPTIONS]\n\n"
+ " -f Run in fullscreen mode(only desktop-shell valid)\n"
+ " -o Create an opaque surface\n"
+ " -s Use a 16 bpp EGL config\n"
+ " -t Set display buffer transform(0~7)\n"
+ " -F rawdata message(rawdata size provided is 320x480)\n"
+ " eg:-F /usr/share/weston/rawdata.nv16:320x480@5\n"
+ " @14 stand for nv16 format, formats supported as follows\n"
+ " now only support 8 formats\n"
+ " 0 --> IMG_FORMAT_RGB565\n"
+ " 1 --> IMG_FORMAT_XRGB8888\n"
+ " 2 --> IMG_FORMAT_ARGB8888\n"
+ " 3 --> IMG_FORMAT_YUYV\n"
+ " 4 --> IMG_FORMAT_NV12\n"
+ " 5 --> IMG_FORMAT_NV16\n"
+ " 6 --> IMG_FORMAT_YUV420\n"
+ " 7 --> IMG_FORMAT_YVU420\n"
+ " -d Enable debug output\n"
+ " -overlay Enable overlay switch\n"
+ " -h This help text\n\n");
+
+ exit(error_code);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sigaction sigint;
+ struct display *display;
+ struct window window = { 0 };
+ int i, ret = 0;
+ struct file_arg *file;
+
+ init_window(&window);
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp("-f", argv[i]) == 0)
+ window.fullscreen = 1;
+ else if (strcmp("-o", argv[i]) == 0)
+ window.opaque = 0;
+ else if (strcmp("-s", argv[i]) == 0)
+ window.buffer_size = 16;
+ else if (strcmp("-t", argv[i]) == 0)
+ window.transform = atoi(argv[++i]);
+ else if (strcmp("-F", argv[i]) == 0){
+ ret = parse_file(&window.image.fProp, argv[++i]);
+ if (ret < 0)
+ fprintf(stderr, "error: input error, like: -F "
+ "/usr/share/weston/rawdata.nv16:320x480@5\n");
+ }
+ else if (strcmp("-d", argv[i]) == 0)
+ debug = 1;
+ else if (strcmp("-overlay", argv[i]) == 0)
+ window.overlay = 1;
+ else if (strcmp("-h", argv[i]) == 0)
+ usage(EXIT_SUCCESS);
+ else
+ usage(EXIT_FAILURE);
+ }
+
+ file = &window.image.fProp;
+ if((file->width == 0) || (file->height ==0) || (file->filename == 0))
+ {
+ /*default sample*/
+ file->width = 320;
+ file->height = 480;
+ file->format = IMG_FORMAT_NV16;
+ snprintf(file->filename, MAX_LEN, "/usr/share/weston/rawdata.nv16");
+ fprintf(stderr, "debug: You have choose the default example!\n");
+ }
+
+ fprintf(stderr, "debug: The file is %s width/height/format[%d %d %d]\n",
+ file->filename, file->width, file->height, file->format);
+
+ window.geometry.width = file->width;
+ window.geometry.height = file->height;
+ window.window_size = window.geometry;
+
+ display = create_display(&window);
+ window.display = display;
+ //display->window = &window;
+
+ create_surface(&window);
+
+ ret = init_img_texture(&window);
+ if (ret < 0){
+ fprintf(stderr, "error: init_img_texture failed\n");
+ return -1;
+ }
+
+ window.drm_card_fd = _kms_device_fd();
+ if (window.drm_card_fd < 0) {
+ fprintf(stderr, "error: fail to get drm_card_fd !\n");
+ return -1;
+ }
+ /*
+ * setting sprite_switch = 0, indicate not walk overlay
+ * setting sprite_switch = 1, indicate walk overlay
+ */
+ if(window.overlay)
+ config_switch_set_sprite_switch(window.switch_set, 1);
+ else
+ config_switch_set_sprite_switch(window.switch_set, 0);
+
+ sigint.sa_handler = signal_int;
+ sigemptyset(&sigint.sa_mask);
+ sigint.sa_flags = SA_RESETHAND;
+ sigaction(SIGINT, &sigint, NULL);
+
+ if (!window.wait_for_configure)
+ redraw(&window, NULL, 0);
+
+ while (running && ret != -1)
+ ret = wl_display_dispatch(display->display);
+
+ fprintf(stderr, "debug: simple-configure-mtk exiting\n");
+ destroy_surface(&window);
+ destroy_display(display);
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
index 96acf75..e91261d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -440,6 +440,7 @@ if ! test "x$enable_simple_dmabuf_v4l_client" = "xno"; then
enable_simple_dmabuf_v4l_client="$have_simple_dmabuf_v4l_client"
fi
AM_CONDITIONAL(BUILD_SIMPLE_DMABUF_V4L_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
+AM_CONDITIONAL(BUILD_SIMPLE_CONFIGURE_MTK_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
AC_ARG_ENABLE(clients, [ --enable-clients],, enable_clients=yes)
AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes)
--
2.6.4