-SUBDIRS = src
+SUBDIRS = shared src
if test $enable_wayland_backend = yes; then
AC_DEFINE(ENABLE_WAYLAND_BACKEND, 1, [Enable wayland backend])
PKG_CHECK_MODULES(WAYLAND_BACKEND, [wayland-client >= 1.6.00])
+fi
+
+AC_ARG_ENABLE(wayland-backend-egl,
+ AC_HELP_STRING([--enable-wayland-backend-egl], [enable wayland backend EGL support]),
+ [enable_wayland_backend_egl=$enableval -a test $enable_wayland_backend=yes],
+ [enable_wayland_backend_egl=yes])
+
+AM_CONDITIONAL(ENABLE_WAYLAND_BACKEND_EGL, test $enable_wayland_backend_egl = yes)
- if test $enable_wayland_backend = yes; then
- PKG_CHECK_MODULES(WAYLAND_BACKEND, [wayland-egl])
- fi
+if test $enable_wayland_backend_egl = yes; then
+ AC_DEFINE(ENABLE_WAYLAND_BACKEND_EGL, 1, [Enable wayland backend EGL support])
+ PKG_CHECK_MODULES(WAYLAND_BACKEND, [wayland-egl])
fi
# drm backend
# Output files
AC_CONFIG_FILES([
Makefile
+shared/Makefile
src/Makefile
])
--- /dev/null
+noinst_LTLIBRARIES = libshared.la
+libshared_la_SOURCES = pepper-os-compat.h \
+ pepper-os-compat.c
--- /dev/null
+#include "pepper-os-compat.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+static int
+set_cloexec_or_close(int fd)
+{
+ long flags;
+
+ if (fd == -1)
+ return -1;
+
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1)
+ goto err;
+
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+ goto err;
+
+ return fd;
+
+err:
+ close(fd);
+ return -1;
+}
+
+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;
+}
+
+int
+pepper_create_anonymous_file(off_t size)
+{
+ static const char template[] = "/pepper-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;
+}
--- /dev/null
+/*
+ * Copyright © 2012 Collabora, Ltd.
+ *
+ * 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.
+ */
+
+/* This source code was taken from weston's os-compatability.h. */
+
+#ifndef PEPPER_OS_COMPAT_H
+#define PEPPER_OS_COMPAT_H
+
+#include <stdio.h>
+
+int
+pepper_create_anonymous_file(off_t size);
+
+#endif /* PEPPER_OS_COMPAT_H */
# pepper library
lib_LTLIBRARIES += libpepper.la
-include_HEADERS += pepper.h
+include_HEADERS += pepper.h pepper-pixman-renderer.h
libpepper_la_CFLAGS = $(LIB_PEPPER_CFLAGS) -Wall
libpepper_la_LIBADD = $(LIB_PEPPER_LIBS)
surface.c \
region.c \
buffer.c \
- renderer.c
+ renderer.c \
+ pixman-renderer.c
# gl renderer
if ENABLE_GL_RENDERER
if ENABLE_WAYLAND_BACKEND
include_HEADERS += modules/wayland/pepper-wayland.h
-libpepper_la_CFLAGS += $(WAYLAND_BACKEND_CFLAGS)
-libpepper_la_LIBADD += $(WAYLAND_BACKEND_LIBS)
+libpepper_la_CFLAGS += $(WAYLAND_BACKEND_CFLAGS) -I$(top_srcdir)/shared/
+libpepper_la_LIBADD += $(WAYLAND_BACKEND_LIBS) $(top_builddir)/shared/libshared.la
libpepper_la_SOURCES += modules/wayland/wayland-internal.h \
modules/wayland/wayland-common.c \
/* TODO: Change logging destination. */
-#define PEPPER_ERROR(fmt, ...) \
- do { \
- printf(fmt, ##__VA_ARGS__); \
+#define PEPPER_ERROR(fmt, ...) \
+ do { \
+ printf("%s:%s: "fmt, __FILE__, __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#define PEPPER_TRACE PEPPER_ERROR
-#include "pepper.h"
+#include "pepper-gl-renderer.h"
#include "common.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
pepper_wayland_destroy(pepper_wayland_t *conn);
PEPPER_API pepper_output_t *
-pepper_wayland_output_create(pepper_wayland_t *conn, int32_t w, int32_t h);
+pepper_wayland_output_create(pepper_wayland_t *conn, int32_t w, int32_t h, const char *renderer);
#ifdef __cplusplus
}
+#include <config.h>
#include "pepper-wayland.h"
#include <wayland-client.h>
#include <common.h>
+#include <pixman.h>
+
+#if ENABLE_WAYLAND_BACKEND_EGL
+#include <wayland-egl.h>
+#endif
+
+#define NUM_SHM_BUFFERS 2
typedef struct wayland_output wayland_output_t;
typedef struct wayland_seat wayland_seat_t;
+typedef struct wayland_shm_buffer wayland_shm_buffer_t;
struct pepper_wayland
{
};
+struct wayland_shm_buffer
+{
+ struct wl_buffer *buffer;
+ void *pixels;
+ int size;
+ pixman_image_t *image;
+ pixman_region32_t damage;
+ void *data;
+
+ struct wl_list link;
+};
+
struct wayland_output
{
pepper_wayland_t *conn;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
+
+ pepper_renderer_t *renderer;
+
+ struct {
+ /* list containing free wl_shm_buffers. */
+ struct wl_list free_buffers;
+ } shm;
+
+#if ENABLE_WAYLAND_BACKEND_EGL
+ struct {
+ struct wl_egl_window *window;
+ } egl;
+#endif
};
struct wayland_seat
#include "wayland-internal.h"
+#include <pepper-os-compat.h>
+#include <string.h>
+#include <pepper-pixman-renderer.h>
-static const char *maker_name = "wayland";
-static const char *model_name = "wayland";
+#if ENABLE_WAYLAND_BACKEND_EGL && ENABLE_GL_RENDERER
+#include <pepper-gl-renderer.h>
+#endif
+
+static const char *maker_name = "wayland";
+static const char *model_name = "wayland";
+static const char *default_renderer = "pixman";
static void
shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial)
return PEPPER_TRUE;
}
+static void
+wayland_output_schedule_repaint(void *o, void *data)
+{
+ /* TODO: */
+}
+
static const pepper_output_interface_t wayland_output_interface =
{
wayland_output_destroy,
wayland_output_get_mode_count,
wayland_output_get_mode,
wayland_output_set_mode,
+
+ wayland_output_schedule_repaint,
};
static void
wayland_output_destroy(output);
}
+static pepper_bool_t
+init_gl_renderer(wayland_output_t *output)
+{
+#if ENABLE_WAYLAND_BACKEND_EGL
+ output->egl.window = wl_egl_window_create(output->surface, output->w, output->h);
+
+ if (!output->egl.window)
+ return PEPPER_FALSE;
+
+ output->renderer = pepper_gl_renderer_create(output->conn->display,
+ output->egl.window,
+ PEPPER_FORMAT_ARGB8888,
+ NULL);
+
+ if (output->renderer)
+ return PEPPER_TRUE;
+
+ /* Clean up. */
+ wl_egl_window_destroy(output->egl.window);
+ output->egl.window = NULL;
+#endif
+
+ return PEPPER_FALSE;
+}
+
+static pepper_bool_t
+init_pixman_renderer(wayland_output_t *output)
+{
+ wl_list_init(&output->shm.free_buffers);
+
+ output->renderer = pepper_pixman_renderer_create();
+
+ if (output->renderer)
+ return PEPPER_TRUE;
+
+ return PEPPER_FALSE;
+}
+
+static pepper_bool_t
+init_renderer(wayland_output_t *output, const char *name)
+{
+ if (strcmp(name, "gl") == 0)
+ {
+ return init_gl_renderer(output);
+ }
+ else if (strcmp(name, "pixman") == 0)
+ {
+ return init_pixman_renderer(output);
+ }
+
+ return PEPPER_FALSE;
+}
+
PEPPER_API pepper_output_t *
-pepper_wayland_output_create(pepper_wayland_t *conn, int32_t w, int32_t h)
+pepper_wayland_output_create(pepper_wayland_t *conn, int32_t w, int32_t h, const char *renderer)
{
pepper_output_t *base;
wayland_output_t *output;
output->conn_destroy_listener.notify = handle_connection_destroy;
wl_signal_add(&conn->destroy_signal, &output->conn_destroy_listener);
+ /* Create renderer. */
+ if (!renderer)
+ renderer = default_renderer;
+
+ if (!init_renderer(output, renderer))
+ {
+ wayland_output_destroy(output);
+ return NULL;
+ }
+
return base;
}
--- /dev/null
+#ifndef PEPPER_PIXMAN_RENDERER_H
+#define PEPPER_PIXMAN_RENDERER_H
+
+#include "pepper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PEPPER_API pepper_renderer_t *
+pepper_pixman_renderer_create();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PEPPER_PIXMAN_RENDERER_H */
--- /dev/null
+#include "pepper-pixman-renderer.h"
+#include "common.h"
+#include <pixman.h>
+
+typedef struct pixman_renderer pixman_renderer_t;
+
+struct pixman_renderer
+{
+ pepper_renderer_t base;
+
+ pixman_image_t *target;
+};
+
+static PEPPER_INLINE pixman_format_code_t
+get_pixman_format(pepper_format_t format)
+{
+ switch (format)
+ {
+ case PEPPER_FORMAT_ARGB8888:
+ return PIXMAN_a8r8g8b8;
+ case PEPPER_FORMAT_XRGB8888:
+ return PIXMAN_x8r8g8b8;
+ case PEPPER_FORMAT_RGB888:
+ return PIXMAN_r8g8b8;
+ case PEPPER_FORMAT_RGB565:
+ return PIXMAN_r5g6b5;
+ case PEPPER_FORMAT_ABGR8888:
+ return PIXMAN_a8b8g8r8;
+ case PEPPER_FORMAT_XBGR8888:
+ return PIXMAN_x8b8g8r8;
+ case PEPPER_FORMAT_BGR888:
+ return PIXMAN_b8g8r8;
+ case PEPPER_FORMAT_BGR565:
+ return PIXMAN_b5g6r5;
+ case PEPPER_FORMAT_ALPHA:
+ return PIXMAN_a8;
+ default:
+ break;
+ }
+
+ return (pixman_format_code_t)0;
+}
+
+static void
+pixman_renderer_destroy(pepper_renderer_t *r)
+{
+ pixman_renderer_t *renderer = (pixman_renderer_t *)r;
+
+ if (renderer->target)
+ pixman_image_unref(renderer->target);
+
+ pepper_free(renderer);
+}
+
+static pepper_bool_t
+pixman_renderer_read_pixels(pepper_renderer_t *r, int x, int y, int w, int h,
+ void *pixels, pepper_format_t format)
+{
+ pixman_renderer_t *renderer = (pixman_renderer_t *)r;
+ pixman_image_t *dst;
+ pixman_format_code_t pixman_format;
+ int stride;
+
+ if (!renderer->target)
+ return PEPPER_FALSE;
+
+ pixman_format = get_pixman_format(format);
+
+ if (!pixman_format)
+ {
+ PEPPER_ERROR("Invalid format.\n");
+ return PEPPER_FALSE;
+ }
+
+ stride = (PEPPER_FORMAT_BPP(format) / 8) * w;
+ dst = pixman_image_create_bits(pixman_format, w, h, pixels, stride);
+
+ if (!dst)
+ {
+ PEPPER_ERROR("Failed to create pixman image.\n");
+ return PEPPER_FALSE;
+ }
+
+ pixman_image_composite(PIXMAN_OP_SRC, renderer->target, NULL, dst, x, y, 0, 0, 0, 0, w, h);
+ return PEPPER_TRUE;
+}
+
+static pepper_bool_t
+pixman_renderer_set_render_target(pepper_renderer_t *r, void *target)
+{
+ pixman_renderer_t *renderer = (pixman_renderer_t *)r;
+ pixman_image_t *image = target;
+
+ if (renderer->target)
+ pixman_image_unref(renderer->target);
+
+ pixman_image_ref(image);
+ renderer->target = image;
+
+ return PEPPER_TRUE;
+}
+
+static void
+pixman_renderer_draw(pepper_renderer_t *r, void *data)
+{
+ pixman_renderer_t *renderer = (pixman_renderer_t *)r;
+
+ if (renderer->target)
+ {
+ /* TODO: */
+ pixman_image_t *image = renderer->target;
+ pixman_fill(pixman_image_get_data(image),
+ pixman_image_get_stride(image),
+ PIXMAN_FORMAT_BPP(pixman_image_get_format(image)),
+ 0, 0,
+ pixman_image_get_width(image),
+ pixman_image_get_height(image),
+ 0xffffffff);
+ }
+}
+
+PEPPER_API pepper_renderer_t *
+pepper_pixman_renderer_create()
+{
+ pixman_renderer_t *renderer;
+
+ renderer = pepper_calloc(1, sizeof(pixman_renderer_t));
+ if (!renderer)
+ return NULL;
+
+ renderer->base.destroy = pixman_renderer_destroy;
+ renderer->base.read_pixels = pixman_renderer_read_pixels;
+ renderer->base.set_render_target = pixman_renderer_set_render_target;
+ renderer->base.draw = pixman_renderer_draw;
+
+ return &renderer->base;
+}