Home | History | Annotate | Download | only in wayland
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.11
      4  *
      5  * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke (at) googlemail.com>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 #include "util/u_memory.h"
     27 #include "util/u_inlines.h"
     28 
     29 #include "pipe/p_compiler.h"
     30 #include "pipe/p_screen.h"
     31 #include "pipe/p_context.h"
     32 #include "pipe/p_state.h"
     33 
     34 #include "sw/wayland/wayland_sw_winsys.h"
     35 
     36 #include "egllog.h"
     37 
     38 #include "native_wayland.h"
     39 
     40 #include <wayland-client.h>
     41 #include "wayland-egl-priv.h"
     42 
     43 #include <sys/types.h>
     44 #include <sys/stat.h>
     45 #include <fcntl.h>
     46 
     47 struct wayland_shm_display {
     48    struct wayland_display base;
     49 
     50    const struct native_event_handler *event_handler;
     51    struct wl_shm *wl_shm;
     52 };
     53 
     54 static INLINE struct wayland_shm_display *
     55 wayland_shm_display(const struct native_display *ndpy)
     56 {
     57    return (struct wayland_shm_display *) ndpy;
     58 }
     59 
     60 
     61 static void
     62 wayland_shm_display_destroy(struct native_display *ndpy)
     63 {
     64    struct wayland_shm_display *shmdpy = wayland_shm_display(ndpy);
     65 
     66    if (shmdpy->base.configs)
     67       FREE(shmdpy->base.configs);
     68    if (shmdpy->base.own_dpy)
     69       wl_display_disconnect(shmdpy->base.dpy);
     70 
     71    ndpy_uninit(ndpy);
     72 
     73    FREE(shmdpy);
     74 }
     75 
     76 static struct wl_buffer *
     77 wayland_create_shm_buffer(struct wayland_display *display,
     78                           struct wayland_surface *surface,
     79                           enum native_attachment attachment)
     80 {
     81    struct wayland_shm_display *shmdpy = (struct wayland_shm_display *) display;
     82    struct pipe_screen *screen = shmdpy->base.base.screen;
     83    struct pipe_resource *resource;
     84    struct winsys_handle wsh;
     85    uint width, height;
     86    enum wl_shm_format format;
     87    struct wl_buffer *buffer;
     88    struct wl_shm_pool *pool;
     89 
     90    resource = resource_surface_get_single_resource(surface->rsurf, attachment);
     91    resource_surface_get_size(surface->rsurf, &width, &height);
     92 
     93    screen->resource_get_handle(screen, resource, &wsh);
     94 
     95    pipe_resource_reference(&resource, NULL);
     96 
     97    switch (surface->color_format) {
     98    case PIPE_FORMAT_B8G8R8A8_UNORM:
     99       format = WL_SHM_FORMAT_ARGB8888;
    100       break;
    101    case PIPE_FORMAT_B8G8R8X8_UNORM:
    102       format = WL_SHM_FORMAT_XRGB8888;
    103       break;
    104    default:
    105       return NULL;
    106       break;
    107    }
    108 
    109    pool = wl_shm_create_pool(shmdpy->wl_shm, wsh.fd, wsh.size);
    110    buffer = wl_shm_pool_create_buffer(pool, 0, width, height,
    111                                       wsh.stride, format);
    112    wl_shm_pool_destroy(pool);
    113 
    114    return buffer;
    115 }
    116 
    117 static void
    118 shm_handle_format(void *data, struct wl_shm *shm, uint32_t format)
    119 {
    120    struct wayland_shm_display *shmdpy = data;
    121 
    122    switch (format) {
    123    case WL_SHM_FORMAT_ARGB8888:
    124       shmdpy->base.formats |= HAS_ARGB8888;
    125       break;
    126    case WL_SHM_FORMAT_XRGB8888:
    127       shmdpy->base.formats |= HAS_XRGB8888;
    128       break;
    129    }
    130 }
    131 
    132 static const struct wl_shm_listener shm_listener = {
    133    shm_handle_format
    134 };
    135 
    136 static void
    137 registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
    138                        const char *interface, uint32_t version)
    139 {
    140    struct wayland_shm_display *shmdpy = data;
    141 
    142    if (strcmp(interface, "wl_shm") == 0) {
    143       shmdpy->wl_shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
    144       wl_shm_add_listener(shmdpy->wl_shm, &shm_listener, shmdpy);
    145    }
    146 }
    147 
    148 static const struct wl_registry_listener registry_listener = {
    149        registry_handle_global
    150 };
    151 
    152 static boolean
    153 wayland_shm_display_init_screen(struct native_display *ndpy)
    154 {
    155    struct wayland_shm_display *shmdpy = wayland_shm_display(ndpy);
    156    struct sw_winsys *winsys = NULL;
    157 
    158    shmdpy->base.queue = wl_display_create_queue(shmdpy->base.dpy);
    159    shmdpy->base.registry = wl_display_get_registry(shmdpy->base.dpy);
    160    wl_proxy_set_queue((struct wl_proxy *) shmdpy->base.registry,
    161                       shmdpy->base.queue);
    162    wl_registry_add_listener(shmdpy->base.registry, &registry_listener, shmdpy);
    163    if (wayland_roundtrip(&shmdpy->base) < 0 || shmdpy->wl_shm == NULL)
    164       return FALSE;
    165 
    166    if (shmdpy->base.formats == 0)
    167       wl_display_roundtrip(shmdpy->base.dpy);
    168    if (shmdpy->base.formats == 0)
    169       return FALSE;
    170 
    171    winsys = wayland_create_sw_winsys(shmdpy->base.dpy);
    172    if (!winsys)
    173       return FALSE;
    174 
    175    shmdpy->base.base.screen =
    176       shmdpy->event_handler->new_sw_screen(&shmdpy->base.base, winsys);
    177 
    178    if (!shmdpy->base.base.screen) {
    179       _eglLog(_EGL_WARNING, "failed to create shm screen");
    180       return FALSE;
    181    }
    182 
    183    return TRUE;
    184 }
    185 
    186 struct wayland_display *
    187 wayland_create_shm_display(struct wl_display *dpy,
    188                            const struct native_event_handler *event_handler)
    189 {
    190    struct wayland_shm_display *shmdpy;
    191 
    192    shmdpy = CALLOC_STRUCT(wayland_shm_display);
    193    if (!shmdpy)
    194       return NULL;
    195 
    196    shmdpy->event_handler = event_handler;
    197 
    198    shmdpy->base.dpy = dpy;
    199    if (!shmdpy->base.dpy) {
    200       wayland_shm_display_destroy(&shmdpy->base.base);
    201       return NULL;
    202    }
    203 
    204    shmdpy->base.base.init_screen = wayland_shm_display_init_screen;
    205    shmdpy->base.base.destroy = wayland_shm_display_destroy;
    206    shmdpy->base.create_buffer = wayland_create_shm_buffer;
    207 
    208    return &shmdpy->base;
    209 }
    210 
    211 /* vim: set sw=3 ts=8 sts=3 expandtab: */
    212