Add wlr_texture_set

When performing cross-GPU operations we need to keep track of where
a buffer has been imported and where it has been copied. This is
what a texture set does. It keeps a dictionary of renderers and
if a wlr_texture has been created for them. The user can request a
texture for a particular renderer, and it will perform any blits
needed and cache the result.
This commit is contained in:
Austin Shafer 2022-07-27 09:46:02 -04:00
parent 5a38cc57c8
commit a446e1801f
2 changed files with 506 additions and 0 deletions

View file

@ -18,6 +18,7 @@
struct wlr_buffer;
struct wlr_renderer;
struct wlr_texture_impl;
struct wlr_multi_gpu;
struct wlr_texture {
const struct wlr_texture_impl *impl;
@ -82,4 +83,123 @@ void wlr_texture_destroy(struct wlr_texture *texture);
struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer,
struct wlr_buffer *buffer);
struct wlr_texture_renderer_pair {
struct wlr_renderer *renderer;
struct wlr_texture *texture;
struct wlr_allocator *allocator;
};
/**
* The texture set provides a mapping between renderers and the texture
* imported into them. You can use it to query a texture for a particular
* renderer and it will handle importing and any blitting that needs to
* take place.
*/
struct wlr_texture_set {
/* The buffer this texture set was made from */
struct wlr_buffer *buffer;
struct wl_listener buffer_release;
/**
* Index into pairings of the device that this texture directly
* imports into. This texture is "native" to that device, and
* will have to be blitted to other gpus.
*
* This will be -1 if no buffer has been imported yet.
*/
int32_t native_pair;
struct wlr_multi_gpu *multi_gpu;
/*
* This will cache the result of creating a linear-layout version of
* this texture on the native device. This can then be imported into
* the other GPUs.
*/
uint32_t format;
void *pixel_data;
uint32_t width;
uint32_t height;
/* This is the size of the pairings array */
int pairing_count;
struct wlr_texture_renderer_pair *pairings;
};
/**
* Create an empty texture set. When setting up our wlr_multi_gpu struct we put
* all renderers into a list. This lets us iterate them from here. If this
* request is made on a renderer not in the multi-GPU set, then the list will
* be of length 1, and the renderer will be the only entry in the set.
*
* A buffer must be imported for this set to be used.
*/
struct wlr_texture_set *wlr_texture_set_create(struct wlr_renderer *renderer,
struct wlr_allocator *allocator);
/**
* Add a renderer to the set. This adds an entry to the set tracking this renderer
* in the set's internal list. No texture is created for this renderer.
*/
void wlr_texture_set_add_renderer(struct wlr_texture_set *set, struct wlr_renderer *renderer,
struct wlr_allocator *allocator);
/*
* Imports a buffer into the texture set. This initializes the native_pair
* internal state and returns true if the buffer was imported on at least one
* of the renderers in the set.
*
* This should only be called once per texture set initialization.
*/
bool wlr_texture_set_import_buffer(struct wlr_texture_set *set, struct wlr_buffer *buffer);
/**
* Create a new texture set from a DMA-BUF. The returned texture is immutable.
* The dmabuf will be imported on only one of the mgpu renderers in the system,
* no copies will be made. Returns NULL if the dmabuf could not be imported into
* any renderer.
*/
struct wlr_texture_set *wlr_texture_set_from_dmabuf(struct wlr_renderer *renderer,
struct wlr_dmabuf_attributes *attribs);
/**
* Create a new texture set from a buffer.
*/
struct wlr_texture_set *wlr_texture_set_from_buffer(struct wlr_renderer *renderer,
struct wlr_buffer *buffer);
/**
* Request a wlr_texture for this resource that is compatible with the given
* renderer. This allows for on-demand cross-GPU blits in multi-GPU setups.
* The texture will have been imported into the renderer that corresponds to
* its native device. If a texture is requeseted with a different renderer,
* this function will perform a blit and return the appropriate texture.
*
* Textures are cached, so if multiple requests with a non-native renderer
* are made there will be only one blit.
*/
struct wlr_texture *wlr_texture_set_get_tex_for_renderer(struct wlr_texture_set *set,
struct wlr_renderer *renderer);
/**
* Get the wlr_texture corresponding to the texture's local GPU. This is the GPU it
* is directly importable into.
*/
struct wlr_texture *wlr_texture_set_get_native_texture(struct wlr_texture_set *set);
/**
* Get the linear pixel data for the backing texture.
*/
void *wlr_texture_set_get_linear_data(struct wlr_texture_set *set);
/**
* Update all textures in a set with the contents of the next buffer. This will call
* wlr_texture_update_from_buffer for each texture in the set.
*/
bool wlr_texture_set_update_from_buffer(struct wlr_texture_set *set,
struct wlr_buffer *next, const pixman_region32_t *damage);
/**
* Destroys the texture set and all textures held inside it.
*/
void wlr_texture_set_destroy(struct wlr_texture_set *set);
#endif