From 433c8b3244b4c4e665aac5510e50d0f2dbe93d31 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 22 Mar 2013 16:59:27 +0000 Subject: basic window opening working --- src/surface/wld.c | 287 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 234 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/surface/wld.c b/src/surface/wld.c index d450738..ded996d 100644 --- a/src/surface/wld.c +++ b/src/surface/wld.c @@ -13,15 +13,22 @@ #include #include -#include -#include +#include +#include +#include +#include +#include +#include +#if 0 #include #include #include #include #include #include +#endif +#include #include "libnsfb.h" #include "libnsfb_event.h" @@ -33,6 +40,8 @@ #include "plot.h" #include "cursor.h" +#if 0 + #if defined(NSFB_NEED_HINTS_ALLOC) static xcb_size_hints_t * xcb_alloc_size_hints(void) @@ -574,11 +583,14 @@ xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) } +#endif + static int wld_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { } +#if 0 static int x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { @@ -766,6 +778,7 @@ create_blank_cursor(xcb_connection_t *conn, const xcb_screen_t *scr) } return cur; } +#endif /** structure for display, registry and other global objects that * should be cached when connecting to a wayland instance @@ -794,19 +807,19 @@ struct wld_connection { }; -/** shared memory interface format available callback +/** shared memory interface format available callback * * @param ctx context from when listener was added. - * @param wl_shm The shared memory object. - * @param format The available shared memory format. Found in - * wayland-client-protocol.h there are currently only two + * @param wl_shm The shared memory object. + * @param format The available shared memory format. Found in + * wayland-client-protocol.h there are currently only two * formats available (A|X)RGB8888 so using a bitfield is ok. */ static void shm_format(void *ctx, struct wl_shm *wl_shm, uint32_t format) { struct wld_connection* connection = ctx; - + connection->shm_formats |= (1 << format); } @@ -818,7 +831,7 @@ struct wl_shm_listener shm_listenter = { /** registry global addition callback * - * @param ctx context from when listener was added + * @param ctx context from when listener was added */ static void registry_handle_global(void *ctx, @@ -850,8 +863,8 @@ registry_handle_global(void *ctx, * and add a listener for the shared memory callbacks */ connection->shm = wl_registry_bind(registry, - id, - &wl_shm_interface, + id, + &wl_shm_interface, 1); if (connection->shm != NULL) { connection->shm_formats = 0; @@ -875,6 +888,30 @@ static const struct wl_registry_listener registry_listener = { }; +static void +free_connection(struct wld_connection* connection) +{ + if (connection->compositor != NULL) { + wl_compositor_destroy(connection->compositor); + } + + if (connection->shell != NULL) { + wl_shell_destroy(connection->shell); + } + + if (connection->shm != NULL) { + wl_shm_destroy(connection->shm); + } + + wl_registry_destroy(connection->registry); + + wl_display_flush(connection->display); + + wl_display_disconnect(connection->display); + + free(connection); +} + /** construct a new connection to the wayland instance and aquire all * necessary global objects */ @@ -928,7 +965,7 @@ new_connection(void) wl_display_roundtrip(connection->display); /* check the XRGB8888 shared memory format is available */ - if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888))) { + if (!(connection->shm_formats & (1 << WL_SHM_FORMAT_XRGB8888))) { fprintf(stderr, "WL_SHM_FORMAT_XRGB8888 not available\n"); free_connection(connection); @@ -939,33 +976,11 @@ new_connection(void) return connection; } -static void -free_connection(struct wld_connection* connection) -{ - if (connection->compositor != NULL) { - wl_compositor_destroy(connection->compositor); - } - - if (connection->shell != NULL) { - wl_shell_destroy(connection->shell); - } - - if (connection->shm != NULL) { - wl_shm_destroy(connection->shm); - } - - wl_registry_destroy(connection->registry); - - wl_display_flush(connection->display); - - wl_display_disconnect(connection->display); - - free(connection); -} typedef struct wldstate_s { struct wld_connection* connection; /**< connection to wayland server */ struct wld_window *window; + struct wld_shm_buffer *shm_buffer; #if 0 xcb_connection_t *connection; /* The x server connection */ xcb_screen_t *screen; /* The screen to put the window on */ @@ -989,14 +1004,8 @@ struct wld_window { struct wl_surface *surface; struct wl_shell_surface *shell_surface; - struct wl_callback *callback; int width, height; - -#if 0 - struct buffer buffers[2]; - struct buffer *prev_buffer; -#endif }; static void @@ -1034,7 +1043,6 @@ new_window(struct wld_connection *connection, int width, int height) } window->connection = connection; - window->callback = NULL; window->width = width; window->height = height; @@ -1069,10 +1077,6 @@ new_window(struct wld_connection *connection, int width, int height) static void free_window(struct wld_window *window) { - if (window->callback != NULL) { - - wl_callback_destroy(window->callback); - } wl_shell_surface_destroy(window->shell_surface); wl_surface_destroy(window->surface); @@ -1080,6 +1084,143 @@ free_window(struct wld_window *window) free(window); } +/* + * 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. + */ +static int +os_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + + 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 = mkostemp(name, O_CLOEXEC); + if (fd >= 0) + unlink(name); + + free(name); + + if (fd < 0) + return -1; + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +struct wld_shm_buffer { + struct wl_buffer *buffer; /**< wayland buffer object */ + void *data; /**< mapped memory */ + int size; /**< size of mapped memory */ + bool inuse; /**< flag to indicate if the buffer has been released + * after commit to a surface. + */ +}; + +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct wld_shm_buffer *shmbuf = data; + + shmbuf->inuse = false; +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static struct wld_shm_buffer * +new_shm_buffer(struct wl_shm *shm, + int width, + int height, + uint32_t format) +{ + struct wl_shm_pool *pool; + struct wld_shm_buffer *shmbuff; + int fd; + int stride; + + shmbuff = calloc(1, sizeof(struct wld_shm_buffer)); + if (shmbuff == NULL) { + return NULL; + } + + stride = width * 4; + shmbuff->size = stride * height; + + fd = os_create_anonymous_file(shmbuff->size); + if (fd < 0) { + free(shmbuff); + return NULL; + } + + shmbuff->data = mmap(NULL, + shmbuff->size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + 0); + if (shmbuff->data == MAP_FAILED) { + close(fd); + free(shmbuff); + return NULL; + } + + pool = wl_shm_create_pool(shm, fd, shmbuff->size); + shmbuff->buffer = wl_shm_pool_create_buffer(pool, + 0, + width, + height, + stride, + format); + wl_shm_pool_destroy(pool); + close(fd); + + if (shmbuff->buffer == NULL) { + munmap(shmbuff->data, shmbuff->size); + free(shmbuff); + return NULL; + } + + wl_buffer_add_listener(shmbuff->buffer, &buffer_listener, shmbuff); + + return shmbuff; +} + +static void free_shm_buffer(struct wld_shm_buffer *shmbuf) +{ + munmap(shmbuf->data, shmbuf->size); + free(shmbuf); +} static int wld_initialise(nsfb_t *nsfb) { @@ -1101,19 +1242,38 @@ static int wld_initialise(nsfb_t *nsfb) wldstate->connection = new_connection(); if (wldstate->connection == NULL) { fprintf(stderr, "Error initialising wayland connection\n"); + free(wldstate); + return -1; /* error */ } - wldstate->window = new_window(wldstate->connection, - nsfb->width, + wldstate->window = new_window(wldstate->connection, + nsfb->width, nsfb->height); - if (wldstate->connection == NULL) { + if (wldstate->window == NULL) { fprintf(stderr, "Error creating wayland window\n"); free_connection(wldstate->connection); free(wldstate); + + return -1; /* error */ + } + + wldstate->shm_buffer = new_shm_buffer(wldstate->connection->shm, + nsfb->width, + nsfb->height, + WL_SHM_FORMAT_XRGB8888); + if (wldstate->shm_buffer == NULL) { + fprintf(stderr, "Error creating wayland shared memory\n"); + + free_window(wldstate->window); + + free_connection(wldstate->connection); + + free(wldstate); + return -1; /* error */ } @@ -1130,11 +1290,14 @@ static int wld_finalise(nsfb_t *nsfb) return 0; /* not initialised */ } + free_shm_buffer(wldstate->shm_buffer); + free_window(wldstate->window); free_connection(wldstate->connection); } +#if 0 static int x_initialise(nsfb_t *nsfb) { uint32_t mask; @@ -1265,11 +1428,29 @@ static int x_finalise(nsfb_t *nsfb) return 0; } +#endif static bool wld_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) { + wldstate_t *wldstate = nsfb->surface_priv; + int ret = 0; + + if (wldstate == NULL) { + return false; + } + + ret = wl_display_dispatch(wldstate->connection->display); + if (ret == -1) { + /* error, time to quit */ + event->type = NSFB_EVENT_CONTROL; + event->value.controlcode = NSFB_CONTROL_QUIT; + return true; + } + + return false; } +#if 0 static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) { xcb_generic_event_t *e; @@ -1423,12 +1604,9 @@ static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) return true; } +#endif static int wld_claim(nsfb_t *nsfb, nsfb_bbox_t *box) -{ -} - -static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box) { struct nsfb_cursor_s *cursor = nsfb->cursor; @@ -1440,12 +1618,12 @@ static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box) return 0; } - static int wld_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) { } +#if 0 static int x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) { @@ -1477,11 +1655,13 @@ x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) } return true; } +#endif static int wld_update(nsfb_t *nsfb, nsfb_bbox_t *box) { } +#if 0 static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box) { xstate_t *xstate = nsfb->surface_priv; @@ -1496,6 +1676,7 @@ static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box) return 0; } +#endif const nsfb_surface_rtns_t wld_rtns = { .initialise = wld_initialise, -- cgit v1.2.3