swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit 029cdb9d180d628cfbe828135948ab59caa52b8d
parent f0e0669bc3f4cf991674300e298e311472ba3cc8
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 28 Aug 2019 15:00:04 -0700

Implement linux-dmabuf protocol

Diffstat:
M.gitignore | 1+
Alibswc/dmabuf.c | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/dmabuf.h | 31+++++++++++++++++++++++++++++++
Mlibswc/drm.c | 8+++++++-
Mlibswc/local.mk | 5++++-
Mprotocol/local.mk | 3++-
6 files changed, 259 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -8,6 +8,7 @@ protocol/wayland-drm-protocol.c protocol/wayland-drm-server-protocol.h protocol/xdg-shell-protocol.c protocol/xdg-shell-server-protocol.h +protocol/linux-dmabuf-unstable-v1-server-protocol.h /.deps/ /swc.pc diff --git a/libswc/dmabuf.c b/libswc/dmabuf.c @@ -0,0 +1,214 @@ +/* swc: dmabuf.c + * + * Copyright (c) 2019 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dmabuf.h" +#include "drm.h" +#include "internal.h" +#include "util.h" +#include "wayland_buffer.h" + +#include <stdint.h> +#include <stdlib.h> +#include <drm_fourcc.h> +#include <unistd.h> +#include <wld/wld.h> +#include <wld/drm.h> +#include "linux-dmabuf-unstable-v1-server-protocol.h" + +struct params { + struct wl_resource *resource; + int fd[4]; + uint32_t offset[4]; + uint32_t stride[4]; + uint64_t modifier[4]; + bool created; +}; + +static void +destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +add(struct wl_client *client, struct wl_resource *resource, int32_t fd, uint32_t i, uint32_t offset, uint32_t stride, uint32_t modifier_hi, uint32_t modifier_lo) +{ + struct params *params = wl_resource_get_user_data(resource); + + if (params->created) { + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "buffer already created"); + return; + } + if (i > ARRAY_LENGTH(params->fd)) { + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, "plane index too large"); + return; + } + if (params->fd[i] != -1) { + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET, "buffer plane already set"); + return; + } + params->fd[i] = fd; + params->offset[i] = offset; + params->stride[i] = stride; + params->modifier[i] = (uint64_t)modifier_hi << 32 | modifier_lo; +} + +static void +create_immed(struct wl_client *client, struct wl_resource *resource, uint32_t id, + int32_t width, int32_t height, uint32_t format, uint32_t flags) +{ + struct params *params = wl_resource_get_user_data(resource); + struct wld_buffer *buffer; + struct wl_resource *buffer_resource; + union wld_object object; + int num_planes, i; + + if (params->created) { + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "buffer already created"); + return; + } + params->created = true; + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + num_planes = 1; + break; + default: + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "unsupported format %#" PRIx32, format); + return; + } + for (i = 0; i < num_planes; ++i) { + if (params->fd[i] == -1) + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "missing plane %d", i); + } + for (; i < ARRAY_LENGTH(params->fd); ++i) { + if (params->fd[i] != -1) + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "too many planes"); + } + object.i = params->fd[0]; + buffer = wld_import_buffer(swc.drm->context, WLD_DRM_OBJECT_PRIME_FD, object, width, height, format, params->stride[0]); + for (i = 0; i < num_planes; ++i) { + close(params->fd[i]); + params->fd[i] = -1; + } + if (!buffer) + zwp_linux_buffer_params_v1_send_failed(resource); + + buffer_resource = wayland_buffer_create_resource(client, 1, id, buffer); + if (!buffer_resource) { + if (buffer) + wld_buffer_unreference(buffer); + wl_resource_post_no_memory(resource); + return; + } + if (id == 0 && buffer) + zwp_linux_buffer_params_v1_send_created(resource, buffer_resource); +} + +static void +create(struct wl_client *client, struct wl_resource *resource, + int32_t width, int32_t height, uint32_t format, uint32_t flags) +{ + create_immed(client, resource, 0, width, height, format, flags); +} + +static const struct zwp_linux_buffer_params_v1_interface params_impl = { + .destroy = destroy, + .add = add, + .create = create, + .create_immed = create_immed, +}; + +static void +params_destroy(struct wl_resource *resource) +{ + struct params *params = wl_resource_get_user_data(resource); + int i; + + for (i = 0; i < ARRAY_LENGTH(params->fd); ++i) + close(params->fd[i]); +} + +static void +create_params(struct wl_client *client, struct wl_resource *resource, uint32_t id) +{ + struct params *params; + int i; + + params = malloc(sizeof(*params)); + if (!params) + goto error0; + params->created = false; + params->resource = wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, wl_resource_get_version(resource), id); + if (!params->resource) + goto error1; + for (i = 0; i < ARRAY_LENGTH(params->fd); ++i) + params->fd[i] = -1; + wl_resource_set_implementation(params->resource, &params_impl, params, params_destroy); + return; + +error1: + free(params); +error0: + wl_resource_post_no_memory(resource); +} + +static const struct zwp_linux_dmabuf_v1_interface dmabuf_impl = { + .destroy = destroy, + .create_params = create_params, +}; + +static void +bind_dmabuf(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + static const uint32_t formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + }; + uint64_t modifier = DRM_FORMAT_MOD_INVALID; + struct wl_resource *resource; + size_t i; + + if (version > 3) + version = 3; + resource = wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &dmabuf_impl, NULL, NULL); + for (i = 0; i < ARRAY_LENGTH(formats); ++i) { + if (version >= 3) { + /* TODO: need a way to query DRM modifiers of wld */ + zwp_linux_dmabuf_v1_send_modifier(resource, formats[i], modifier >> 32, modifier & 0xffffffff); + } else { + zwp_linux_dmabuf_v1_send_format(resource, formats[i]); + } + } +} + +struct wl_global * +swc_dmabuf_create(struct wl_display *display) +{ + return wl_global_create(display, &zwp_linux_dmabuf_v1_interface, 3, NULL, &bind_dmabuf); +} diff --git a/libswc/dmabuf.h b/libswc/dmabuf.h @@ -0,0 +1,31 @@ +/* swc: libswc/dmabuf.h + * + * Copyright (c) 2019 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SWC_DMABUF_H +#define SWC_DMABUF_H + +struct wl_display; + +struct wl_global *swc_dmabuf_create(struct wl_display *display); + +#endif diff --git a/libswc/drm.c b/libswc/drm.c @@ -22,6 +22,7 @@ */ #include "drm.h" +#include "dmabuf.h" #include "event.h" #include "internal.h" #include "launch.h" @@ -53,6 +54,7 @@ static struct { uint32_t taken_ids; struct wl_global *global; + struct wl_global *dmabuf; struct wl_event_source *event_source; } drm; @@ -299,11 +301,15 @@ drm_initialize(void) if (!wld_drm_is_dumb(swc.drm->context)) { drm.global = wl_global_create(swc.display, &wl_drm_interface, 2, NULL, &bind_drm); - if (!drm.global) { ERROR("Could not create wl_drm global\n"); goto error4; } + + drm.dmabuf = swc_dmabuf_create(swc.display); + if (!drm.dmabuf) { + WARNING("Could not create wp_linux_dmabuf global\n"); + } } return true; diff --git a/libswc/local.mk b/libswc/local.mk @@ -28,6 +28,7 @@ SWC_SOURCES = \ libswc/data.c \ libswc/data_device.c \ libswc/data_device_manager.c \ + libswc/dmabuf.c \ libswc/drm.c \ libswc/input.c \ libswc/keyboard.c \ @@ -55,7 +56,8 @@ SWC_SOURCES = \ libswc/xdg_shell.c \ protocol/swc-protocol.c \ protocol/wayland-drm-protocol.c \ - protocol/xdg-shell-protocol.c + protocol/xdg-shell-protocol.c \ + protocol/linux-dmabuf-unstable-v1-protocol.c ifeq ($(ENABLE_LIBUDEV),1) $(dir)_CFLAGS += -DENABLE_LIBUDEV @@ -68,6 +70,7 @@ SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo) # Explicitly state dependencies on generated files objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo) $(call objects,compositor panel_manager panel screen): protocol/swc-server-protocol.h +$(call objects,dmabuf): protocol/linux-dmabuf-unstable-v1-server-protocol.h $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h $(call objects,xdg_shell): protocol/xdg-shell-server-protocol.h $(call objects,pointer): cursor/cursor_data.h diff --git a/protocol/local.mk b/protocol/local.mk @@ -6,7 +6,8 @@ wayland_protocols := $(call pkgconfig,wayland-protocols,variable=pkgdatadir,DATA PROTOCOL_EXTENSIONS = \ $(dir)/swc.xml \ $(dir)/wayland-drm.xml \ - $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml + $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml \ + $(wayland_protocols)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml $(dir)_PACKAGES := wayland-server