Add wlr_compositor buffer API

This also rolls wlr_buffer into wlr_renderer as a user of this new API.
This commit is contained in:
Scott Anderson 2019-05-15 23:52:13 +12:00
parent 21db2418b7
commit 8630988eae
10 changed files with 518 additions and 370 deletions

View file

@ -19,8 +19,10 @@ enum wlr_renderer_read_pixels_flags {
WLR_RENDERER_READ_PIXELS_Y_INVERT = 1,
};
struct wlr_renderer_impl;
struct wlr_compositor;
struct wlr_commit;
struct wlr_drm_format_set;
struct wlr_renderer_impl;
struct wlr_renderer {
const struct wlr_renderer_impl *impl;
@ -107,11 +109,14 @@ bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
*/
bool wlr_renderer_format_supported(struct wlr_renderer *r,
enum wl_shm_format fmt);
void wlr_renderer_init_wl_display(struct wlr_renderer *r,
struct wl_display *wl_display);
/**
* Destroys this wlr_renderer. Textures must be destroyed separately.
*/
void wlr_renderer_destroy(struct wlr_renderer *renderer);
void wlr_renderer_set_compositor(struct wlr_renderer *renderer,
struct wlr_compositor *comp);
struct wlr_texture *wlr_commit_get_texture(struct wlr_commit *commit);
#endif

View file

@ -1,6 +1,5 @@
install_headers(
'wlr_box.h',
'wlr_buffer.h',
'wlr_compositor.h',
'wlr_cursor.h',
'wlr_data_control_v1.h',

View file

@ -1,71 +0,0 @@
/*
* 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_BUFFER_H
#define WLR_TYPES_WLR_BUFFER_H
#include <pixman.h>
#include <wayland-server.h>
/**
* A client buffer.
*/
struct wlr_buffer {
/**
* The buffer resource, if any. Will be NULL if the client destroys it.
*/
struct wl_resource *resource;
/**
* The buffer's texture, if any. A buffer will not have a texture if the
* client destroys the buffer before it has been released.
*/
struct wlr_texture *texture;
bool released;
size_t n_refs;
struct wl_listener resource_destroy;
};
struct wlr_renderer;
/**
* Check if a resource is a wl_buffer resource.
*/
bool wlr_resource_is_buffer(struct wl_resource *resource);
/**
* Get the size of a wl_buffer resource.
*/
bool wlr_buffer_get_resource_size(struct wl_resource *resource,
struct wlr_renderer *renderer, int *width, int *height);
/**
* Upload a buffer to the GPU and reference it.
*/
struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer,
struct wl_resource *resource);
/**
* Reference the buffer.
*/
struct wlr_buffer *wlr_buffer_ref(struct wlr_buffer *buffer);
/**
* Unreference the buffer. After this call, `buffer` may not be accessed
* anymore.
*/
void wlr_buffer_unref(struct wlr_buffer *buffer);
/**
* Try to update the buffer's content. On success, returns the updated buffer
* and destroys the provided `buffer`. On error, `buffer` is intact and NULL is
* returned.
*
* Fails if there's more than one reference to the buffer or if the texture
* isn't mutable.
*/
struct wlr_buffer *wlr_buffer_apply_damage(struct wlr_buffer *buffer,
struct wl_resource *resource, pixman_region32_t *damage);
#endif

View file

@ -9,20 +9,79 @@
#ifndef WLR_TYPES_WLR_COMPOSITOR_H
#define WLR_TYPES_WLR_COMPOSITOR_H
#include <pixman.h>
#include <wayland-server.h>
#include <wlr/render/wlr_renderer.h>
struct wlr_commit;
struct wlr_output;
struct wlr_surface;
/*
* This represents a client-side wl_buffer.
*
* All of the wl_buffer "factory interfaces" are not managed by wlr_compositor,
* but we still need to know some extra information beyond the wl_resource
* handle. This information is retrieved by the callbacks specified in
* wlr_compositor_buffer_impl.
*
* If you are using wlr_renderer, you do not need to worry about this type, as
* wlr_renderer handles the buffer factory interfaces and the callbacks, but
* you must call wlr_renderer_set_compositor to set this up.
*/
struct wlr_buffer {
struct wl_resource *resource;
size_t ref_cnt;
/*
* This should contain the protocol name of this buffer, used for some
* protocol conformance checks (e.g. "wl_shm"). As a special case,
* buffers created with the EGL extension "EGL_WL_bind_wayland_display"
* will be called "egl", regardless of what the underlying protocol is
* called (i.e. NOT "wl_drm"). This should point to statically
* allocated memory.
*/
const char *protocol;
/*
* The size of the buffer in buffer coordinates.
* i.e. no scaling, cropping, or transforms applied.
*/
int32_t width;
int32_t height;
};
/*
* See struct wlr_buffer
*/
struct wlr_compositor_buffer_impl {
struct wlr_buffer *(*create)(void *data, struct wlr_buffer *buf,
pixman_region32_t *damage, struct wl_resource *res);
struct wlr_buffer *(*ref)(struct wlr_buffer *buf);
void (*unref)(struct wlr_buffer *buf);
};
/*
* Implementation of the wl_compositor global.
*
* This is responsible for creating wl_surfaces and wl_regions.
*
* The wlr_compositor's lifetime to tied to the lifetime of the wl_display
* it was created with, meaning that calling wl_display_destroy will destroy
* the wlr_compositor. There is no way to destroy it earlier than this,
* as clients can not be expected to handle this being removed.
*
* Is is an error to create two wlr_compositors for the same wl_display or
* otherwise advertise a second wl_compositor global on it.
*/
struct wlr_compositor {
struct wl_display *display;
struct wl_global *global;
struct wlr_renderer *renderer;
uint32_t ids;
const struct wlr_compositor_buffer_impl *buffer_impl;
void *buffer_data;
struct {
struct wl_signal new_surface;
struct wl_signal new_surface_2;
@ -32,6 +91,11 @@ struct wlr_compositor {
struct wl_listener display_destroy;
};
struct wlr_compositor_new_state_args {
struct wlr_commit *old;
struct wlr_commit *new;
};
struct wlr_surface_2 {
struct wl_resource *resource;
struct wlr_compositor *compositor;
@ -39,13 +103,13 @@ struct wlr_surface_2 {
/*
* This should contain the name of the protocol to prevent conflicts.
* e.g. "xdg_toplevel".
* Also, it should point to statically allocated memory.
* This should point to statically allocated memory.
*/
const char *role_name;
void *role_data;
struct wl_list committed;
struct wl_list frame_callbacks;
struct wl_list committed; // struct wlr_commit.link
struct wl_list frame_callbacks; // struct wl_resource
struct {
struct wl_signal commit;
@ -56,8 +120,6 @@ struct wlr_surface_2 {
};
/*
* wlr_commit
*
* A wlr_commit is a description for a "coherent presentation" of a surface's
* contents, or could also be thought of as a "snaphot" of the surface at
* commit time. It should contain all of the information to correctly display
@ -76,38 +138,59 @@ struct wlr_surface_2 {
* For a surface, there will always be exactly 1 pending commit for a surface.
* see wlr_surface_get_pending
*
* Excluding the time when a before the first complete commit is ready, there
* will always be at least 1 complete commit for a surface. The latest complete
* Excluding the time before the first complete commit is ready, there will
* always be at least 1 complete commit for a surface. The latest complete
* commit is called the current commit.
* see wlr_surface_get_commit
*
* wlr_commits are reference counted. If you wish to save the contents of a
* commit for future use, simply do not unreference the commit. A referenced
* wlr_commit will even persist after the surface is destroyed, which can be
* useful for fade-out animations. Any extensions to wlr_surface should be
* prepared for the associated wlr_surface to not be available.
* commit for future use, simply do not unreference the commit.
*
* Upon commit destruction, several actions may be performed on objects which
* will affect clients. For example, wl_buffer.release may be called for the
* attached buffer. Holding onto too many commits for too long may cause
* resource starvation in clients, so care should be taken to unreference
* commits as soon as they're no longer needed.
*
* Inhibitiors:
* -----------
*
* Each commit has a counter of inhibitors, which means that the commit is
* being prevented from becoming "complete". The intended use-case is for
* wl_subsurfaces preventing themselves from being presented until their
* parent has been commited, and wp_linux_explicit_synchronization from
* being presented until a fence is signalled.
*
* Inhibitors don't have any effect on commits which are already complete.
*
* Orphaned Commits:
* ----------------
*
* A commit will stay valid even after the associated surface has been
* destroyed by the client. Such a commit is called an orphaned commit.
* Pending commits can never be orphaned, as wl_surface.commit can never be
* called on them.
*
* This can be useful for fade-out animations of a client's surface.
*
* Any extension to wlr_commit should be prepared for the associated
* wlr_surface to not be available.
*/
struct wlr_commit {
struct wl_list link;
struct wlr_compositor *compositor;
struct wlr_surface_2 *surface;
// If the user has called wl_surface.commit
// If the client has called wl_surface.commit
bool committed;
// See wlr_commit_inhibit
size_t inhibit;
size_t ref_cnt;
// wl_surface.attach
struct wlr_buffer *buffer;
struct wl_resource *buffer_resource;
int32_t sx, sy;
// wl_surface.damage
pixman_region32_t surface_damage;
// wl_surface.frame
struct wl_list frame_callbacks;
// wl_surface.set_opaque_region
@ -119,37 +202,83 @@ struct wlr_commit {
// wl_surface.set_buffer_scale
int32_t scale;
// wl_surface.damage_buffer
pixman_region32_t buffer_damage;
pixman_region32_t damage;
size_t state_len;
void **state;
struct {
/*
* arg: struct wlr_commit *this
* The client called wl_surface.commit.
*/
struct wl_signal commit;
/*
* arg: struct wlr_commit *this
* The commit has transitioned to the complete state, and is
* now ready to be presented.
*/
struct wl_signal complete;
/*
* arg: struct wlr_commit *this
* The wlr_commit has been destroyed.
*/
struct wl_signal destroy;
} events;
};
struct wlr_compositor_new_state_args {
struct wlr_commit *old;
struct wlr_commit *new;
};
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
struct wlr_renderer *renderer);
struct wlr_compositor *wlr_compositor_create(struct wl_display *display);
void wlr_compositor_set_buffer_impl(struct wlr_compositor *comp,
void *data, const struct wlr_compositor_buffer_impl *impl);
uint32_t wlr_compositor_register(struct wlr_compositor *compositor);
struct wlr_surface_2 *wlr_surface_from_resource_2(struct wl_resource *resource);
/*
* Get the latest complete commit for a surface.
* This increases the reference count of the commit.
*
* Returns NULL if there is no complete commit yet.
*/
struct wlr_commit *wlr_surface_get_commit(struct wlr_surface_2 *surface);
/*
* Get the current pending commit for a surface.
* This DOES NOT increase the reference count of the commit.
* This is not intended to be used outside of extensions to wlr_commit.
*
* This will never fail.
*/
struct wlr_commit *wlr_surface_get_pending(struct wlr_surface_2 *surface);
/*
* Gets the latest committed or complete commit.
* This increases the reference count of the commit.
* This is not intended to be used outside of extensions to wlr_commit.
*
* If you are looking for the latest complete commit, use
* wlr_surface_get_commit instead.
*
* Returns NULL if there is no committed/complete commit yet.
*/
struct wlr_commit *wlr_surface_get_latest(struct wlr_surface_2 *surface);
void wlr_surface_send_enter_2(struct wlr_surface_2 *surf, struct wlr_output *output);
void wlr_surface_send_leave_2(struct wlr_surface_2 *surf, struct wlr_output *output);
/*
* Increases the reference count of a commit.
* commit must be non-null.
*
* commit is returned from this function as a convinience to do
* `struct wlr_commit *saved = wlr_commit_ref(commit);`
*/
struct wlr_commit *wlr_commit_ref(struct wlr_commit *commit);
/*
* Decreases the reference count for a commit.
* commit must be non-null and have a positive reference count.
*
* The commit is not necessarily freed immediately when the reference count
* reaches zero, depending on its state and position in the commit queue.
*/
void wlr_commit_unref(struct wlr_commit *commit);
bool wlr_commit_is_complete(struct wlr_commit *c);