mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
wlr_raster: Introduce new abstraction
This commit is contained in:
parent
3b3ed21e61
commit
057fd1a0e3
3 changed files with 209 additions and 0 deletions
86
include/wlr/types/wlr_raster.h
Normal file
86
include/wlr/types/wlr_raster.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_RASTER_H
|
||||
#define WLR_TYPES_WLR_RASTER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct wlr_buffer;
|
||||
struct wlr_texture;
|
||||
struct wlr_renderer;
|
||||
struct wlr_drm_syncobj_timeline;
|
||||
|
||||
struct wlr_raster {
|
||||
// May be NULL
|
||||
struct wlr_buffer *buffer;
|
||||
|
||||
uint32_t width, height;
|
||||
bool opaque;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||
uint64_t wait_point;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
// private state
|
||||
|
||||
size_t n_locks;
|
||||
|
||||
struct wl_listener buffer_release;
|
||||
|
||||
struct wlr_texture *texture;
|
||||
struct wl_listener renderer_destroy;
|
||||
};
|
||||
|
||||
struct wlr_raster_create_options {
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||
uint64_t wait_point;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new wlr_raster being backed by the given buffer. The raster will
|
||||
* not lock the given buffer meaning that once it's released, the raster will
|
||||
* NULL its buffer reference and potentially become invalid.
|
||||
* The creation function is referenced: once the creator is done with the raster,
|
||||
* wlr_raster_unlock must be called as the reference count will start at 1
|
||||
* from creation.
|
||||
*
|
||||
* Options can be NULL.
|
||||
*/
|
||||
struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer,
|
||||
const struct wlr_raster_create_options *options);
|
||||
|
||||
/**
|
||||
* Lock the raster for use. As long as the raster has at least one lock, it
|
||||
* will not be destroyed.
|
||||
*/
|
||||
struct wlr_raster *wlr_raster_lock(struct wlr_raster *raster);
|
||||
|
||||
/**
|
||||
* Unlock the raster. This must be called after wlr_raster_lock once the raster
|
||||
* has been finished being used or after creation from wlr_raster_create.
|
||||
*/
|
||||
void wlr_raster_unlock(struct wlr_raster *raster);
|
||||
|
||||
/**
|
||||
* Returns the texture allocated for this renderer. If there is none,
|
||||
* a new texture will be created and attached to this wlr_raster. Users do not
|
||||
* own the texture returned by this function and can only be used for read-only
|
||||
* purposes.
|
||||
*
|
||||
* Will return NULL if the creation was unsuccessful.
|
||||
*/
|
||||
struct wlr_texture *wlr_raster_obtain_texture(struct wlr_raster *raster,
|
||||
struct wlr_renderer *renderer);
|
||||
|
||||
#endif
|
||||
|
|
@ -68,6 +68,7 @@ wlr_files += files(
|
|||
'wlr_presentation_time.c',
|
||||
'wlr_primary_selection_v1.c',
|
||||
'wlr_primary_selection.c',
|
||||
'wlr_raster.c',
|
||||
'wlr_region.c',
|
||||
'wlr_relative_pointer_v1.c',
|
||||
'wlr_screencopy_v1.c',
|
||||
|
|
|
|||
122
types/wlr_raster.c
Normal file
122
types/wlr_raster.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#include <assert.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
|
||||
#include <wlr/types/wlr_raster.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/wlr_texture.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include "types/wlr_buffer.h"
|
||||
|
||||
static void raster_handle_buffer_release(struct wl_listener *listener, void *data) {
|
||||
struct wlr_raster *raster = wl_container_of(listener, raster, buffer_release);
|
||||
raster->buffer = NULL;
|
||||
wl_list_remove(&raster->buffer_release.link);
|
||||
wl_list_init(&raster->buffer_release.link);
|
||||
}
|
||||
|
||||
struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer,
|
||||
const struct wlr_raster_create_options *options) {
|
||||
struct wlr_raster *raster = calloc(1, sizeof(*raster));
|
||||
if (!raster) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wl_signal_init(&raster->events.destroy);
|
||||
|
||||
assert(buffer);
|
||||
raster->opaque = buffer_is_opaque(buffer);
|
||||
raster->width = buffer->width;
|
||||
raster->height = buffer->height;
|
||||
raster->buffer = buffer;
|
||||
|
||||
raster->n_locks = 1;
|
||||
|
||||
raster->buffer_release.notify = raster_handle_buffer_release;
|
||||
wl_signal_add(&raster->buffer->events.release, &raster->buffer_release);
|
||||
|
||||
if (options && options->wait_timeline) {
|
||||
raster->wait_timeline = wlr_drm_syncobj_timeline_ref(options->wait_timeline);
|
||||
raster->wait_point = options->wait_point;
|
||||
}
|
||||
|
||||
return raster;
|
||||
}
|
||||
|
||||
static void raster_consider_destroy(struct wlr_raster *raster) {
|
||||
if (raster->n_locks > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&raster->events.destroy, NULL);
|
||||
|
||||
if (raster->texture) {
|
||||
wl_list_remove(&raster->renderer_destroy.link);
|
||||
wlr_texture_destroy(raster->texture);
|
||||
}
|
||||
|
||||
wl_list_remove(&raster->buffer_release.link);
|
||||
wlr_drm_syncobj_timeline_unref(raster->wait_timeline);
|
||||
free(raster);
|
||||
}
|
||||
|
||||
struct wlr_raster *wlr_raster_lock(struct wlr_raster *raster) {
|
||||
raster->n_locks++;
|
||||
return raster;
|
||||
}
|
||||
|
||||
void wlr_raster_unlock(struct wlr_raster *raster) {
|
||||
if (!raster) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(raster->n_locks > 0);
|
||||
|
||||
raster->n_locks--;
|
||||
raster_consider_destroy(raster);
|
||||
}
|
||||
|
||||
static void raster_detach(struct wlr_raster *raster, struct wlr_texture *texture) {
|
||||
assert(texture);
|
||||
assert(raster->texture == texture);
|
||||
|
||||
wl_list_remove(&raster->renderer_destroy.link);
|
||||
raster->texture = NULL;
|
||||
}
|
||||
|
||||
static void handle_renderer_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_raster *raster = wl_container_of(listener, raster, renderer_destroy);
|
||||
raster_detach(raster, raster->texture);
|
||||
}
|
||||
|
||||
static void raster_attach(struct wlr_raster *raster, struct wlr_texture *texture) {
|
||||
assert(texture->width == raster->width && texture->height == raster->height);
|
||||
assert(!raster->texture);
|
||||
|
||||
raster->renderer_destroy.notify = handle_renderer_destroy;
|
||||
wl_signal_add(&texture->renderer->events.destroy, &raster->renderer_destroy);
|
||||
|
||||
raster->texture = texture;
|
||||
}
|
||||
|
||||
struct wlr_texture *wlr_raster_obtain_texture(struct wlr_raster *raster,
|
||||
struct wlr_renderer *renderer) {
|
||||
if (raster->texture) {
|
||||
assert(raster->texture->renderer == renderer);
|
||||
return raster->texture;
|
||||
}
|
||||
|
||||
assert(raster->buffer);
|
||||
|
||||
struct wlr_client_buffer *client_buffer =
|
||||
wlr_client_buffer_get(raster->buffer);
|
||||
if (client_buffer != NULL) {
|
||||
return client_buffer->texture;
|
||||
}
|
||||
|
||||
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, raster->buffer);
|
||||
if (texture) {
|
||||
raster_attach(raster, texture);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue