mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2024-11-25 08:32:30 +00:00
c74f89d4f8
We can just use a regular assignment instead. This is more type-safe since there is no need to provide the struct size. The remaining memcpy() calls perform array copies or copies from void pointers (which may be unaligned).
121 lines
3.4 KiB
C
121 lines
3.4 KiB
C
#include <assert.h>
|
|
#include <drm_fourcc.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
#include <wlr/interfaces/wlr_buffer.h>
|
|
#include <wlr/render/allocator.h>
|
|
#include <wlr/render/drm_format_set.h>
|
|
#include <wlr/util/log.h>
|
|
|
|
#include "render/pixel_format.h"
|
|
#include "render/allocator/shm.h"
|
|
#include "util/shm.h"
|
|
|
|
static const struct wlr_buffer_impl buffer_impl;
|
|
|
|
static struct wlr_shm_buffer *shm_buffer_from_buffer(
|
|
struct wlr_buffer *wlr_buffer) {
|
|
assert(wlr_buffer->impl == &buffer_impl);
|
|
struct wlr_shm_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
|
|
return buffer;
|
|
}
|
|
|
|
static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
|
struct wlr_shm_buffer *buffer = shm_buffer_from_buffer(wlr_buffer);
|
|
munmap(buffer->data, buffer->size);
|
|
close(buffer->shm.fd);
|
|
free(buffer);
|
|
}
|
|
|
|
static bool buffer_get_shm(struct wlr_buffer *wlr_buffer,
|
|
struct wlr_shm_attributes *shm) {
|
|
struct wlr_shm_buffer *buffer = shm_buffer_from_buffer(wlr_buffer);
|
|
*shm = buffer->shm;
|
|
return true;
|
|
}
|
|
|
|
static bool shm_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
|
|
uint32_t flags, void **data, uint32_t *format, size_t *stride) {
|
|
struct wlr_shm_buffer *buffer = shm_buffer_from_buffer(wlr_buffer);
|
|
*data = buffer->data;
|
|
*format = buffer->shm.format;
|
|
*stride = buffer->shm.stride;
|
|
return true;
|
|
}
|
|
|
|
static void shm_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
|
|
// This space is intentionally left blank
|
|
}
|
|
|
|
static const struct wlr_buffer_impl buffer_impl = {
|
|
.destroy = buffer_destroy,
|
|
.get_shm = buffer_get_shm,
|
|
.begin_data_ptr_access = shm_buffer_begin_data_ptr_access,
|
|
.end_data_ptr_access = shm_buffer_end_data_ptr_access,
|
|
};
|
|
|
|
static struct wlr_buffer *allocator_create_buffer(
|
|
struct wlr_allocator *wlr_allocator, int width, int height,
|
|
const struct wlr_drm_format *format) {
|
|
const struct wlr_pixel_format_info *info =
|
|
drm_get_pixel_format_info(format->format);
|
|
if (info == NULL) {
|
|
wlr_log(WLR_ERROR, "Unsupported pixel format 0x%"PRIX32, format->format);
|
|
return NULL;
|
|
}
|
|
|
|
struct wlr_shm_buffer *buffer = calloc(1, sizeof(*buffer));
|
|
if (buffer == NULL) {
|
|
return NULL;
|
|
}
|
|
wlr_buffer_init(&buffer->base, &buffer_impl, width, height);
|
|
|
|
// TODO: consider using a single file for multiple buffers
|
|
int stride = pixel_format_info_min_stride(info, width); // TODO: align?
|
|
buffer->size = stride * height;
|
|
buffer->shm.fd = allocate_shm_file(buffer->size);
|
|
if (buffer->shm.fd < 0) {
|
|
free(buffer);
|
|
return NULL;
|
|
}
|
|
|
|
buffer->shm.format = format->format;
|
|
buffer->shm.width = width;
|
|
buffer->shm.height = height;
|
|
buffer->shm.stride = stride;
|
|
buffer->shm.offset = 0;
|
|
|
|
buffer->data = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
buffer->shm.fd, 0);
|
|
if (buffer->data == MAP_FAILED) {
|
|
wlr_log_errno(WLR_ERROR, "mmap failed");
|
|
close(buffer->shm.fd);
|
|
free(buffer);
|
|
return NULL;
|
|
}
|
|
|
|
return &buffer->base;
|
|
}
|
|
|
|
static void allocator_destroy(struct wlr_allocator *wlr_allocator) {
|
|
free(wlr_allocator);
|
|
}
|
|
|
|
static const struct wlr_allocator_interface allocator_impl = {
|
|
.destroy = allocator_destroy,
|
|
.create_buffer = allocator_create_buffer,
|
|
};
|
|
|
|
struct wlr_allocator *wlr_shm_allocator_create(void) {
|
|
struct wlr_shm_allocator *allocator = calloc(1, sizeof(*allocator));
|
|
if (allocator == NULL) {
|
|
return NULL;
|
|
}
|
|
wlr_allocator_init(&allocator->base, &allocator_impl,
|
|
WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_SHM);
|
|
|
|
wlr_log(WLR_DEBUG, "Created shm allocator");
|
|
return &allocator->base;
|
|
}
|