mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Merge branch 'shm-mmap-offset' into 'main'
Add extended shared memory attach support Closes #217 See merge request wayland/wayland!161
This commit is contained in:
commit
118b02230d
4 changed files with 144 additions and 42 deletions
|
|
@ -26,6 +26,7 @@ compiler_flags = [
|
|||
'-Wstrict-prototypes',
|
||||
'-Wmissing-prototypes',
|
||||
'-fvisibility=hidden',
|
||||
'-D_FILE_OFFSET_BITS=64',
|
||||
]
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
|
|
|||
|
|
@ -105,8 +105,10 @@ formats = {}
|
|||
for ident, val in idents.items():
|
||||
formats[drm_format_to_wl(ident)] = val.lower()
|
||||
# Special case for ARGB8888 and XRGB8888
|
||||
formats["argb8888"] = "0"
|
||||
formats["xrgb8888"] = "1"
|
||||
for (i, j) in enumerate(("argb8888", "xrgb8888")):
|
||||
formats[j + "_new"] = formats[j]
|
||||
descriptions[j + "_new"] = descriptions[j]
|
||||
formats[j] = str(i)
|
||||
|
||||
print("Loaded {} formats from drm_fourcc.h".format(len(formats)), file=sys.stderr)
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@
|
|||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_shm_pool" version="2">
|
||||
<interface name="wl_shm_pool" version="3">
|
||||
<description summary="a shared memory pool">
|
||||
The wl_shm_pool object encapsulates a piece of memory shared
|
||||
between the compositor and client. Through the wl_shm_pool
|
||||
|
|
@ -233,9 +233,16 @@
|
|||
of the next. The format is the pixel format of the buffer and
|
||||
must be one of those advertised through the wl_shm.format event.
|
||||
|
||||
A buffer will keep a reference to the pool it was created from
|
||||
A buffer will keep a reference to the pool it was created from,
|
||||
so it is valid to destroy the pool immediately after creating
|
||||
a buffer from it.
|
||||
|
||||
The offset must not be negative. If it is negative, an
|
||||
invalid_stride error is raised. This limits offsets to a
|
||||
maximum of 2^31 - 1 bytes.
|
||||
|
||||
The version of the returned buffer is 1, regardless of the
|
||||
version of the pool from which it was created.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wl_buffer" summary="buffer to create"/>
|
||||
<arg name="offset" type="int" summary="buffer byte offset within the pool"/>
|
||||
|
|
@ -267,6 +274,11 @@
|
|||
file descriptor passed at creation time. It is the client's
|
||||
responsibility to ensure that the file is at least as big as
|
||||
the new pool size.
|
||||
|
||||
If the pool was created using version 3 or later of the wl_shm
|
||||
interface, this request cannot be called once any buffers have
|
||||
been created. Attempting to do so will result in an
|
||||
already_mapped error.
|
||||
</description>
|
||||
<arg name="size" type="int" summary="new size of the pool, in bytes"/>
|
||||
</request>
|
||||
|
|
@ -292,27 +304,35 @@
|
|||
<entry name="invalid_format" value="0" summary="buffer format is not known"/>
|
||||
<entry name="invalid_stride" value="1" summary="invalid size or stride during pool or buffer creation"/>
|
||||
<entry name="invalid_fd" value="2" summary="mmapping the file descriptor failed"/>
|
||||
<entry name="already_mapped" value="3"
|
||||
summary="a pool was created with version 3 or later of wl_shm, and an attempt was made to resize it after it had already been mapped"/>
|
||||
</enum>
|
||||
|
||||
<enum name="format">
|
||||
<description summary="pixel formats">
|
||||
This describes the memory layout of an individual pixel.
|
||||
|
||||
All renderers should support argb8888 and xrgb8888 but any other
|
||||
All compositors must support argb8888 and xrgb8888. Compositors
|
||||
supporting wl_shm v3 must support argb8888_new and xrgb8888_new
|
||||
as well, even with version 1 wl_shm_pool objects. All other
|
||||
formats are optional and may not be supported by the particular
|
||||
renderer in use.
|
||||
|
||||
The drm format codes match the macros defined in drm_fourcc.h, except
|
||||
argb8888 and xrgb8888. The formats actually supported by the compositor
|
||||
will be reported by the format event.
|
||||
will be reported by the format event, and are not limited to those in
|
||||
this enum. Starting with version 2, argb8888_new and xrgb8888_new values
|
||||
are provided, which match the corresponding values in drm_fourcc.h.
|
||||
|
||||
For all wl_shm formats and unless specified in another protocol
|
||||
extension, pre-multiplied alpha is used for pixel values.
|
||||
All wl_shm formats use pre-multiplied alpha for pixel values, unless
|
||||
another protocol extension states otherwise.
|
||||
</description>
|
||||
<!-- Note to protocol writers: don't update this list manually, instead
|
||||
run the automated script that keeps it in sync with drm_fourcc.h. -->
|
||||
<entry name="argb8888" value="0" summary="32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian"/>
|
||||
<entry name="xrgb8888" value="1" summary="32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian"/>
|
||||
<entry name="argb8888_new" value="0x34325241" summary="[31:0] A:R:G:B 8:8:8:8 little endian"/>
|
||||
<entry name="xrgb8888_new" value="0x34325258" summary="[31:0] x:R:G:B 8:8:8:8 little endian"/>
|
||||
<entry name="c8" value="0x20203843" summary="8-bit color index format, [7:0] C"/>
|
||||
<entry name="rgb332" value="0x38424752" summary="8-bit RGB format, [7:0] R:G:B 3:3:2"/>
|
||||
<entry name="bgr233" value="0x38524742" summary="8-bit BGR format, [7:0] B:G:R 2:3:3"/>
|
||||
|
|
@ -442,7 +462,12 @@
|
|||
|
||||
The pool can be used to create shared memory based buffer
|
||||
objects. The server will mmap size bytes of the passed file
|
||||
descriptor, to use as backing memory for the pool.
|
||||
descriptor, to use as backing memory for the pool. If it is
|
||||
unable to do so, an invalid_fd error is raised.
|
||||
|
||||
The size must be greater than zero. Sizes less or equal to zero
|
||||
raise an invalid_stride error. This prevents the creation of
|
||||
pools larger than 2^31 - 1 bytes.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
|
||||
<arg name="fd" type="fd" summary="file descriptor for the pool"/>
|
||||
|
|
@ -468,6 +493,35 @@
|
|||
Objects created via this interface remain unaffected.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
<request name="create_pool2" since="3">
|
||||
<description summary="create a shm pool">
|
||||
Create a new wl_shm_pool object.
|
||||
|
||||
The pool can be used to create shared memory based buffer
|
||||
objects. The server will mmap size bytes of the passed file
|
||||
descriptor at the provided offset to use as backing memory for
|
||||
the pool. If it is unable to do so, an invalid_fd error is
|
||||
raised.
|
||||
|
||||
This request provides a strict superset of the functionality
|
||||
provided by create_pool. In particular, calling this request
|
||||
with offset_lo and offset_hi set to 0 is equivalent to calling
|
||||
create_pool.
|
||||
|
||||
If the size is zero or greater than 2^31 - 1, an invalid_stride
|
||||
error is raised. Compositors are not allowed to impose
|
||||
arbitrary limits on the offset, beyond those imposed by the
|
||||
operating system. In particular, the offset may be negative
|
||||
when cast to an off_t, and may be larger than 2^32 - 1.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
|
||||
<arg name="fd" type="fd" summary="file descriptor for the pool"/>
|
||||
<arg name="size" type="uint" summary="pool size, in bytes"/>
|
||||
<arg name="offset_lo" type="uint" summary="low-order 32 bits of offset for mmap, in bytes"/>
|
||||
<arg name="offset_hi" type="uint" summary="high-order 32 bits of offset for mmap, in bytes"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_buffer" version="1">
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -67,8 +68,8 @@ struct wl_shm_pool {
|
|||
#ifndef MREMAP_MAYMOVE
|
||||
/* The following three fields are needed for mremap() emulation. */
|
||||
int mmap_fd;
|
||||
int mmap_flags;
|
||||
int mmap_prot;
|
||||
#else
|
||||
bool mapped_yet;
|
||||
#endif
|
||||
bool sigbus_is_impossible;
|
||||
};
|
||||
|
|
@ -91,7 +92,7 @@ struct wl_shm_buffer {
|
|||
int32_t width, height;
|
||||
int32_t stride;
|
||||
uint32_t format;
|
||||
int offset;
|
||||
int32_t offset;
|
||||
struct wl_shm_pool *pool;
|
||||
};
|
||||
|
||||
|
|
@ -111,7 +112,7 @@ shm_pool_grow_mapping(struct wl_shm_pool *pool)
|
|||
#else
|
||||
data = wl_os_mremap_maymove(pool->mmap_fd, pool->data, &pool->size,
|
||||
pool->new_size, pool->mmap_prot,
|
||||
pool->mmap_flags);
|
||||
MAP_SHARED);
|
||||
if (pool->size != 0 && pool->resource != NULL) {
|
||||
wl_resource_post_error(pool->resource,
|
||||
WL_SHM_ERROR_INVALID_FD,
|
||||
|
|
@ -164,7 +165,8 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
|
|||
|
||||
munmap(pool->data, pool->size);
|
||||
#ifndef MREMAP_MAYMOVE
|
||||
close(pool->mmap_fd);
|
||||
if (pool->mmap_fd != -1)
|
||||
close(pool->mmap_fd);
|
||||
#endif
|
||||
free(pool);
|
||||
}
|
||||
|
|
@ -214,22 +216,15 @@ static const struct wl_buffer_interface shm_buffer_interface = {
|
|||
};
|
||||
|
||||
static bool
|
||||
format_is_supported(struct wl_client *client, uint32_t format)
|
||||
extra_format_is_supported(struct wl_client *client, uint32_t format)
|
||||
{
|
||||
struct wl_display *display = wl_client_get_display(client);
|
||||
struct wl_array *formats;
|
||||
struct wl_array *formats = wl_display_get_additional_shm_formats(display);
|
||||
uint32_t *p;
|
||||
|
||||
switch (format) {
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
return true;
|
||||
default:
|
||||
formats = wl_display_get_additional_shm_formats(display);
|
||||
wl_array_for_each(p, formats)
|
||||
if (*p == format)
|
||||
return true;
|
||||
}
|
||||
wl_array_for_each(p, formats)
|
||||
if (*p == format)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -254,7 +249,18 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
|||
struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
|
||||
struct wl_shm_buffer *buffer;
|
||||
|
||||
if (!format_is_supported(client, format)) {
|
||||
switch (format) {
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
case WL_SHM_FORMAT_ARGB8888_NEW:
|
||||
format = WL_SHM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
case WL_SHM_FORMAT_XRGB8888_NEW:
|
||||
format = WL_SHM_FORMAT_XRGB8888;
|
||||
break;
|
||||
default:
|
||||
if (extra_format_is_supported(client, format))
|
||||
break;
|
||||
wl_resource_post_error(resource,
|
||||
WL_SHM_ERROR_INVALID_FORMAT,
|
||||
"invalid format 0x%x", format);
|
||||
|
|
@ -266,11 +272,21 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
|||
offset > pool->size - stride * height) {
|
||||
wl_resource_post_error(resource,
|
||||
WL_SHM_ERROR_INVALID_STRIDE,
|
||||
"invalid width, height or stride (%dx%d, %u)",
|
||||
width, height, stride);
|
||||
"invalid offset, width, height or stride "
|
||||
"(%" PRIi32 ", %" PRIi32 "x%" PRIi32 ", %" PRIu32 ")",
|
||||
offset, width, height, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wl_resource_get_version(resource) > 2) {
|
||||
#ifndef MREMAP_MAYMOVE
|
||||
close(pool->mmap_fd);
|
||||
pool->mmap_fd = -1;
|
||||
#else
|
||||
pool->mapped_yet = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
buffer = zalloc(sizeof *buffer);
|
||||
if (buffer == NULL) {
|
||||
wl_client_post_no_memory(client);
|
||||
|
|
@ -327,6 +343,7 @@ shm_pool_resize(struct wl_client *client, struct wl_resource *resource,
|
|||
int32_t size)
|
||||
{
|
||||
struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
|
||||
uint32_t version = wl_resource_get_version(resource);
|
||||
|
||||
if (size < pool->size) {
|
||||
wl_resource_post_error(resource,
|
||||
|
|
@ -335,6 +352,23 @@ shm_pool_resize(struct wl_client *client, struct wl_resource *resource,
|
|||
return;
|
||||
}
|
||||
|
||||
assert(pool->internal_refcount > 0);
|
||||
assert(pool->external_refcount >= 0);
|
||||
if (version > 2 &&
|
||||
#ifndef MREMAP_MAYMOVE
|
||||
pool->mmap_fd == -1
|
||||
#else
|
||||
pool->mapped_yet
|
||||
#endif
|
||||
) {
|
||||
wl_resource_post_error(
|
||||
resource,
|
||||
WL_SHM_ERROR_ALREADY_MAPPED,
|
||||
"Cannot resize a pool of version greater than 1 "
|
||||
"once it has been mapped.");
|
||||
return;
|
||||
}
|
||||
|
||||
pool->new_size = size;
|
||||
|
||||
/* If the compositor has taken references on this pool it
|
||||
|
|
@ -353,23 +387,28 @@ static const struct wl_shm_pool_interface shm_pool_interface = {
|
|||
};
|
||||
|
||||
static void
|
||||
shm_create_pool(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, int fd, int32_t size)
|
||||
shm_create_pool2(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, int fd, uint32_t size, uint32_t offset_low,
|
||||
uint32_t offset_high)
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
struct stat statbuf;
|
||||
uint64_t offset;
|
||||
uint32_t version;
|
||||
int seals;
|
||||
int prot;
|
||||
int flags;
|
||||
uint32_t version;
|
||||
|
||||
if (size <= 0) {
|
||||
if (size <= 0 || size > (uint32_t) INT32_MAX) {
|
||||
wl_resource_post_error(resource,
|
||||
WL_SHM_ERROR_INVALID_STRIDE,
|
||||
"invalid size (%d)", size);
|
||||
"invalid size (%" PRIu32 ")", size);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
static_assert((uint64_t)(off_t) UINT64_MAX == UINT64_MAX,
|
||||
"libwayland-server must be built with 64-bit (or more) off_t");
|
||||
version = wl_resource_get_version(resource);
|
||||
offset = (uint64_t) offset_high << 32 | (uint64_t) offset_low;
|
||||
pool = zalloc(sizeof *pool);
|
||||
if (pool == NULL) {
|
||||
wl_client_post_no_memory(client);
|
||||
|
|
@ -393,9 +432,7 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource,
|
|||
pool->external_refcount = 0;
|
||||
pool->size = size;
|
||||
pool->new_size = size;
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
flags = MAP_SHARED;
|
||||
pool->data = mmap(NULL, size, prot, flags, fd, 0);
|
||||
pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) offset);
|
||||
if (pool->data == MAP_FAILED) {
|
||||
wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
|
||||
"failed mmap fd %d: %s", fd,
|
||||
|
|
@ -405,8 +442,6 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource,
|
|||
#ifndef MREMAP_MAYMOVE
|
||||
/* We may need to keep the fd, prot and flags to emulate mremap(). */
|
||||
pool->mmap_fd = fd;
|
||||
pool->mmap_prot = prot;
|
||||
pool->mmap_flags = flags;
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
|
|
@ -439,9 +474,17 @@ shm_release(struct wl_client *client, struct wl_resource *resource)
|
|||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void
|
||||
shm_create_pool(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, int fd, int32_t size)
|
||||
{
|
||||
shm_create_pool2(client, resource, id, fd, (uint32_t) size, 0, 0);
|
||||
}
|
||||
|
||||
static const struct wl_shm_interface shm_interface = {
|
||||
shm_create_pool,
|
||||
shm_release,
|
||||
.create_pool = shm_create_pool,
|
||||
.release = shm_release,
|
||||
.create_pool2 = shm_create_pool2,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -463,6 +506,8 @@ bind_shm(struct wl_client *client,
|
|||
|
||||
wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888);
|
||||
wl_shm_send_format(resource, WL_SHM_FORMAT_XRGB8888);
|
||||
wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888_NEW);
|
||||
wl_shm_send_format(resource, WL_SHM_FORMAT_XRGB8888_NEW);
|
||||
|
||||
additional_formats = wl_display_get_additional_shm_formats(display);
|
||||
wl_array_for_each(p, additional_formats)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue