Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

render/pixman: avoid copy when creating textures #2892

Merged
merged 5 commits into from
Jun 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/render/pixman.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ struct wlr_pixman_texture {
struct wlr_pixman_renderer *renderer;
struct wl_list link; // wlr_pixman_renderer.textures

void *data;
pixman_image_t *image;
const struct wlr_pixel_format_info *format;
pixman_format_code_t format;
const struct wlr_pixel_format_info *format_info;

void *data; // if created via texture_from_pixels
struct wlr_buffer *buffer; // if created via texture_from_buffer
};

pixman_format_code_t get_pixman_format_from_drm(uint32_t fmt);
Expand Down
35 changes: 30 additions & 5 deletions include/types/wlr_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@

#include <wlr/types/wlr_buffer.h>

struct wlr_shm_client_buffer {
struct wlr_buffer base;

uint32_t format;
size_t stride;

// The following fields are NULL if the client has destroyed the wl_buffer
struct wl_resource *resource;
struct wl_shm_buffer *shm_buffer;

// This is used to keep the backing storage alive after the client has
// destroyed the wl_buffer
struct wl_shm_pool *saved_shm_pool;
void *saved_data;

struct wl_listener resource_destroy;
struct wl_listener release;
};

struct wlr_shm_client_buffer *shm_client_buffer_create(
struct wl_resource *resource);

/**
* Buffer capabilities.
*
Expand All @@ -16,13 +38,16 @@ enum wlr_buffer_cap {
};

/**
* Access a pointer to the allocated data from the underlying implementation,
* its format and its stride.
* Get a pointer to a region of memory referring to the buffer's underlying
* storage. The format and stride can be used to interpret the memory region
* contents.
*
* The returned pointer should be pointing to a valid memory location for read
* and write operations.
* The returned pointer should be pointing to a valid memory region for read
* and write operations. The returned pointer is only valid up to the next
* buffer_end_data_ptr_access call.
*/
bool buffer_get_data_ptr(struct wlr_buffer *buffer, void **data,
bool buffer_begin_data_ptr_access(struct wlr_buffer *buffer, void **data,
uint32_t *format, size_t *stride);
void buffer_end_data_ptr_access(struct wlr_buffer *buffer);

#endif
6 changes: 4 additions & 2 deletions include/wlr/types/wlr_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ struct wlr_buffer_impl {
void (*destroy)(struct wlr_buffer *buffer);
bool (*get_dmabuf)(struct wlr_buffer *buffer,
struct wlr_dmabuf_attributes *attribs);
bool (*get_data_ptr)(struct wlr_buffer *buffer, void **data,
uint32_t *format, size_t *stride);
bool (*get_shm)(struct wlr_buffer *buffer,
struct wlr_shm_attributes *attribs);
bool (*begin_data_ptr_access)(struct wlr_buffer *buffer, void **data,
uint32_t *format, size_t *stride);
void (*end_data_ptr_access)(struct wlr_buffer *buffer);
};

/**
Expand All @@ -47,6 +48,7 @@ struct wlr_buffer {

bool dropped;
size_t n_locks;
bool accessing_data_ptr;

struct {
struct wl_signal destroy;
Expand Down
3 changes: 2 additions & 1 deletion render/allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ struct wlr_buffer *wlr_allocator_create_buffer(struct wlr_allocator *alloc,
return NULL;
}
if (alloc->buffer_caps & WLR_BUFFER_CAP_DATA_PTR) {
assert(buffer->impl->get_data_ptr);
assert(buffer->impl->begin_data_ptr_access &&
buffer->impl->end_data_ptr_access);
}
if (alloc->buffer_caps & WLR_BUFFER_CAP_DMABUF) {
assert(buffer->impl->get_dmabuf);
Expand Down
11 changes: 8 additions & 3 deletions render/drm_dumb_allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,19 @@ static struct wlr_drm_dumb_buffer *create_buffer(
return NULL;
}

static bool drm_dumb_buffer_get_data_ptr(struct wlr_buffer *wlr_buffer, void **data,
uint32_t *format, size_t *stride) {
static bool drm_dumb_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
void **data, uint32_t *format, size_t *stride) {
struct wlr_drm_dumb_buffer *buf = drm_dumb_buffer_from_buffer(wlr_buffer);
*data = buf->data;
*stride = buf->stride;
*format = buf->format;
return true;
}

static void drm_dumb_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
// This space is intentionally left blank
}

static bool buffer_get_dmabuf(struct wlr_buffer *wlr_buffer,
struct wlr_dmabuf_attributes *attribs) {
struct wlr_drm_dumb_buffer *buf = drm_dumb_buffer_from_buffer(wlr_buffer);
Expand All @@ -153,7 +157,8 @@ static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
static const struct wlr_buffer_impl buffer_impl = {
.destroy = buffer_destroy,
.get_dmabuf = buffer_get_dmabuf,
.get_data_ptr = drm_dumb_buffer_get_data_ptr,
.begin_data_ptr_access = drm_dumb_buffer_begin_data_ptr_access,
.end_data_ptr_access = drm_dumb_buffer_end_data_ptr_access,
};

static const struct wlr_allocator_interface allocator_impl;
Expand Down
35 changes: 25 additions & 10 deletions render/gles2/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <wlr/util/log.h>
#include "render/gles2.h"
#include "render/pixel_format.h"
#include "types/wlr_buffer.h"
#include "util/signal.h"

static const struct wlr_texture_impl texture_impl;
Expand Down Expand Up @@ -364,15 +365,9 @@ static void texture_handle_buffer_destroy(struct wl_listener *listener,
gles2_texture_destroy(texture);
}

struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
struct wlr_buffer *buffer) {
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);

struct wlr_dmabuf_attributes dmabuf;
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
return false;
}

static struct wlr_texture *gles2_texture_from_dmabuf_buffer(
struct wlr_gles2_renderer *renderer, struct wlr_buffer *buffer,
struct wlr_dmabuf_attributes *dmabuf) {
struct wlr_gles2_texture *texture;
wl_list_for_each(texture, &renderer->textures, link) {
if (texture->buffer == buffer) {
Expand All @@ -386,7 +381,7 @@ struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
}

struct wlr_texture *wlr_texture =
gles2_texture_from_dmabuf(wlr_renderer, &dmabuf);
gles2_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf);
if (wlr_texture == NULL) {
return false;
}
Expand All @@ -400,6 +395,26 @@ struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
return &texture->wlr_texture;
}

struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
struct wlr_buffer *buffer) {
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);

void *data;
uint32_t format;
size_t stride;
struct wlr_dmabuf_attributes dmabuf;
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
return gles2_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf);
} else if (buffer_begin_data_ptr_access(buffer, &data, &format, &stride)) {
struct wlr_texture *tex = gles2_texture_from_pixels(wlr_renderer,
format, stride, buffer->width, buffer->height, data);
buffer_end_data_ptr_access(buffer);
return tex;
} else {
return NULL;
}
}

void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture,
struct wlr_gles2_texture_attribs *attribs) {
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
Expand Down
Loading