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 <stdlib.h>
     27 #include <sys/types.h>
     28 #include <sys/mman.h>
     29 #include <unistd.h>
     30 
     31 #include "pipe/p_compiler.h"
     32 #include "pipe/p_defines.h"
     33 #include "pipe/p_state.h"
     34 #include "util/u_format.h"
     35 #include "util/u_math.h"
     36 #include "util/u_memory.h"
     37 #include "state_tracker/sw_winsys.h"
     38 
     39 #include <wayland-client.h>
     40 #include "wayland_sw_winsys.h"
     41 
     42 struct wayland_sw_displaytarget
     43 {
     44    int fd;
     45    unsigned size;
     46 
     47    unsigned width;
     48    unsigned height;
     49    unsigned stride;
     50 
     51    enum pipe_format format;
     52 
     53    void *map;
     54    unsigned map_count;
     55 };
     56 
     57 struct wayland_sw_winsys
     58 {
     59    struct sw_winsys base;
     60 
     61    struct wl_display *display;
     62 };
     63 
     64 static INLINE struct wayland_sw_displaytarget *
     65 wayland_sw_displaytarget(struct sw_displaytarget *dt)
     66 {
     67    return (struct wayland_sw_displaytarget *) dt;
     68 }
     69 
     70 static INLINE struct wayland_sw_winsys *
     71 wayland_sw_winsys(struct sw_winsys *ws)
     72 {
     73    return (struct wayland_sw_winsys *) ws;
     74 }
     75 
     76 static void
     77 wayland_displaytarget_display(struct sw_winsys *ws,
     78                               struct sw_displaytarget *dt,
     79                               void *context_private)
     80 {
     81 }
     82 
     83 static void
     84 wayland_displaytarget_unmap(struct sw_winsys *ws,
     85                             struct sw_displaytarget *dt)
     86 {
     87    struct wayland_sw_displaytarget *wldt = wayland_sw_displaytarget(dt);
     88 
     89    wldt->map_count--;
     90    if (wldt->map_count > 0)
     91       return;
     92 
     93    munmap(wldt->map, wldt->size);
     94    wldt->map = NULL;
     95 }
     96 
     97 static void *
     98 wayland_displaytarget_map(struct sw_winsys *ws,
     99                           struct sw_displaytarget *dt,
    100                           unsigned flags)
    101 {
    102    struct wayland_sw_displaytarget *wldt = wayland_sw_displaytarget(dt);
    103    uint mmap_flags = 0;
    104 
    105    if (wldt->map) {
    106       wldt->map_count++;
    107       return wldt->map;
    108    }
    109 
    110    if (flags & PIPE_TRANSFER_READ)
    111       mmap_flags |= PROT_READ;
    112    if (flags & PIPE_TRANSFER_WRITE)
    113       mmap_flags |= PROT_WRITE;
    114 
    115    wldt->map = mmap(NULL, wldt->size, mmap_flags,
    116                     MAP_SHARED, wldt->fd, 0);
    117 
    118    if (wldt->map == MAP_FAILED)
    119       return NULL;
    120 
    121    wldt->map_count = 1;
    122 
    123    return wldt->map;
    124 }
    125 
    126 static void
    127 wayland_displaytarget_destroy(struct sw_winsys *ws,
    128                               struct sw_displaytarget *dt)
    129 {
    130    struct wayland_sw_displaytarget *wldt = wayland_sw_displaytarget(dt);
    131 
    132    if (wldt->map)
    133       wayland_displaytarget_unmap(ws, dt);
    134 
    135    FREE(wldt);
    136 }
    137 
    138 static boolean
    139 wayland_is_displaytarget_format_supported(struct sw_winsys *ws,
    140                                           unsigned tex_usage,
    141                                           enum pipe_format format)
    142 {
    143    switch (format) {
    144    case PIPE_FORMAT_B8G8R8X8_UNORM:
    145    case PIPE_FORMAT_B8G8R8A8_UNORM:
    146       return TRUE;
    147    default:
    148       return FALSE;
    149    }
    150 }
    151 
    152 static struct sw_displaytarget *
    153 wayland_displaytarget_create(struct sw_winsys *ws,
    154                              unsigned tex_usage,
    155                              enum pipe_format format,
    156                              unsigned width, unsigned height,
    157                              unsigned alignment,
    158                              unsigned *stride)
    159 {
    160    struct wayland_sw_displaytarget *wldt;
    161    unsigned nblocksy, format_stride;
    162    char filename[] = "/tmp/wayland-shm-XXXXXX";
    163 
    164    if (!wayland_is_displaytarget_format_supported(ws, tex_usage, format))
    165       return NULL;
    166 
    167    wldt = CALLOC_STRUCT(wayland_sw_displaytarget);
    168    if (!wldt)
    169       return NULL;
    170 
    171    wldt->map = NULL;
    172 
    173    wldt->format = format;
    174    wldt->width = width;
    175    wldt->height = height;
    176 
    177    format_stride = util_format_get_stride(format, width);
    178    wldt->stride = align(format_stride, alignment);
    179 
    180    nblocksy = util_format_get_nblocksy(format, height);
    181    wldt->size = wldt->stride * nblocksy;
    182 
    183    wldt->fd = mkstemp(filename);
    184    if (wldt->fd < 0) {
    185       FREE(wldt);
    186       return NULL;
    187    }
    188 
    189    if (ftruncate(wldt->fd, wldt->size) < 0) {
    190       unlink(filename);
    191       close(wldt->fd);
    192       FREE(wldt);
    193       return NULL;
    194    }
    195 
    196    unlink(filename);
    197 
    198    *stride = wldt->stride;
    199 
    200    return (struct sw_displaytarget *) wldt;
    201 }
    202 
    203 static struct sw_displaytarget *
    204 wayland_displaytarget_from_handle(struct sw_winsys *ws,
    205                                   const struct pipe_resource *templet,
    206                                   struct winsys_handle *whandle,
    207                                   unsigned *stride)
    208 {
    209    struct wayland_sw_displaytarget *wldt;
    210    unsigned nblocksy;
    211 
    212    if (!wayland_is_displaytarget_format_supported(ws, 0, templet->format))
    213       return NULL;
    214 
    215    wldt = CALLOC_STRUCT(wayland_sw_displaytarget);
    216    if (!wldt)
    217       return NULL;
    218 
    219    wldt->fd = whandle->fd;
    220    wldt->stride = whandle->stride;
    221    wldt->width = templet->width0;
    222    wldt->height = templet->height0;
    223    wldt->format = templet->format;
    224 
    225    nblocksy = util_format_get_nblocksy(wldt->format, wldt->height);
    226 
    227    wldt->size = wldt->stride * nblocksy;
    228 
    229    wldt->map = NULL;
    230 
    231    *stride = wldt->stride;
    232 
    233    return (struct sw_displaytarget *) wldt;
    234 }
    235 
    236 
    237 static boolean
    238 wayland_displaytarget_get_handle(struct sw_winsys *ws,
    239                                  struct sw_displaytarget *dt,
    240                                  struct winsys_handle *whandle)
    241 {
    242    struct wayland_sw_displaytarget *wldt = wayland_sw_displaytarget(dt);
    243 
    244    whandle->fd = wldt->fd;
    245    whandle->stride = wldt->stride;
    246    whandle->size = wldt->size;
    247 
    248    return TRUE;
    249 }
    250 
    251 static void
    252 wayland_destroy(struct sw_winsys *ws)
    253 {
    254    struct wayland_sw_winsys *wayland = wayland_sw_winsys(ws);
    255 
    256    FREE(wayland);
    257 }
    258 
    259 struct sw_winsys *
    260 wayland_create_sw_winsys(struct wl_display *display)
    261 {
    262    struct wayland_sw_winsys *wlws;
    263 
    264    wlws = CALLOC_STRUCT(wayland_sw_winsys);
    265    if (!wlws)
    266       return NULL;
    267 
    268    wlws->display = display;
    269 
    270    wlws->base.destroy = wayland_destroy;
    271    wlws->base.is_displaytarget_format_supported =
    272       wayland_is_displaytarget_format_supported;
    273 
    274    wlws->base.displaytarget_create = wayland_displaytarget_create;
    275    wlws->base.displaytarget_from_handle = wayland_displaytarget_from_handle;
    276    wlws->base.displaytarget_get_handle = wayland_displaytarget_get_handle;
    277    wlws->base.displaytarget_destroy = wayland_displaytarget_destroy;
    278    wlws->base.displaytarget_map = wayland_displaytarget_map;
    279    wlws->base.displaytarget_unmap = wayland_displaytarget_unmap;
    280 
    281    wlws->base.displaytarget_display = wayland_displaytarget_display;
    282 
    283    return &wlws->base;
    284 }
    285 
    286 /* vim: set sw=3 ts=8 sts=3 expandtab: */
    287