Add new output cursor API

This commit is contained in:
Scott Anderson 2019-09-15 20:05:37 +12:00
parent b2d717dccc
commit f5e5b3eec3
3 changed files with 147 additions and 7 deletions

View file

@ -25,6 +25,9 @@ struct wlr_output_impl {
bool (*move_cursor)(struct wlr_output *output, int x, int y);
void (*destroy)(struct wlr_output *output);
bool (*attach_render)(struct wlr_output *output, int *buffer_age);
bool (*cursor_try_set_size)(struct wlr_output *output, int *x, int *y);
bool (*cursor_attach_render)(struct wlr_output *output, int *buffer_age);
bool (*cursor_commit)(struct wlr_output *output);
bool (*commit)(struct wlr_output *output);
bool (*set_gamma)(struct wlr_output *output, size_t size,
const uint16_t *r, const uint16_t *g, const uint16_t *b);

View file

@ -46,6 +46,20 @@ struct wlr_output_state {
struct wlr_buffer *buffer; // if WLR_OUTPUT_STATE_BUFFER_SCANOUT
};
enum wlr_output_cursor_field {
WLR_OUTPUT_CURSOR_BUFFER = 1 << 0,
WLR_OUTPUT_CURSOR_ENABLE = 1 << 1,
WLR_OUTPUT_CURSOR_POS = 1 << 2,
};
struct wlr_output_cursor {
uint32_t committed; // enum wlr_output_cursor_state_field
bool enabled;
int x, y;
int hotspot_x, hotspot_y;
};
struct wlr_output_impl;
/**
@ -91,6 +105,7 @@ struct wlr_output {
float transform_matrix[9];
struct wlr_output_state pending;
struct wlr_output_cursor cursor_pending;
struct {
// Request to render a frame
@ -280,13 +295,90 @@ void wlr_output_lock_attach_render(struct wlr_output *output, bool lock);
*/
void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock);
#if 0
bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height,
int32_t hotspot_x, int32_t hotspot_y);
bool wlr_output_cursor_move(struct wlr_output_cursor *cursor,
double x, double y);
#endif
/**
* Hardware cursors:
*
* Hardware cursors are a feature of GPUs that allow a small framebuffer
* to be displayed over the main framebuffer. This is more efficient than
* drawing onto the main framebuffer using e.g. OpenGL.
*
* Not every backend/output will support hardware cursors, so you must always
* be prepared to fall back to rendering the cursor to the main framebuffer
* yourself.
*
* Hardware cursors are always in output buffer coordinates, and does not take
* scale nor rotation into account. You are responsible for doing this
* yourself.
*
* Hardware cursors are always in the ARGB8888 format.
*/
/**
* Sets the size of the hardware cursor buffer to the values pointed to by
* x and y.
*
* Some backends have strict requirements for the cursor size and may not be
* able to use the size you requested exactly. The actual value used will be
* left in x and y. If this is not large enough for the cursor you wish to
* draw, you should fall back to using software cursors.
*
* This returns false if the backend does not support hardware cursors or from
* some other internal error. Either way, you should fall back to using
* software cursors.
*/
bool wlr_output_cursor_try_set_size(struct wlr_output *output, int *x, int *y);
/**
* Attaches the renderer to the cursor buffer.
*
* You must successfully call `wlr_output_cursor_try_set_size` at least once
* before using this. Any rendering done will be applied on
* `wlr_output_cursor_commit`.
*/
bool wlr_output_cursor_attach_render(struct wlr_output *output, int *buffer_age);
/**
* Enables displaying the hardware cursor.
*
* This does not affect the ability to render to the cursor. It only sets
* whether or not it will be displayed. By default, the cursor is disabled.
*
* This will be applied on `wlr_output_cursor_commit`.
*/
void wlr_output_cursor_enable(struct wlr_output *output, bool enable);
/**
* Moves the position of the hardware cursor on the main framebuffer.
*
* This is in output buffer coordinates. Negative values and values that would
* place the cursor partially or entirely off the main framebuffer are allowed.
*
* The hotspot is the point on the cursor buffer (from the top left) where the
* cursor actually points. For example, with a cursor representing a hand, the
* hotspot may be over the index finger, rather than the top left corner.
*
* Some backends may not be able to move the cursor freely, but may still be
* able to make use of the hotspot to correctly show the cursor.
*
* This will be applied on `wlr_output_cursor_commit`.
*/
void wlr_output_cursor_move(struct wlr_output *output, int x, int y,
int hotspot_x, int hotspot_y);
/**
* Apply pending cursor state.
*
* This may or may not be synchronized with the output, and would be applied on
* `wlr_output_commit`, depending on the backend limitations. However, it's
* advised to assume that they are sychronized and do any cursor operations at
* the same time you render to the output.
*
* If you have called `wlr_output_cursor_attach_render`, you must call this
* function before `wlr_output_attach_render`, otherwise you risk losing or
* corrupting rendering state.
*/
bool wlr_output_cursor_commit(struct wlr_output *output);
/**
* Returns the transform that, when composed with `tr`, gives

View file

@ -628,6 +628,51 @@ void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock) {
output->software_cursor_locks);
}
bool wlr_output_cursor_try_set_size(struct wlr_output *output, int *x, int *y) {
if (!output->impl->cursor_try_set_size) {
return false;
}
return output->impl->cursor_try_set_size(output, x, y);
}
bool wlr_output_cursor_attach_render(struct wlr_output *output, int *buffer_age) {
if (!output->impl->cursor_attach_render) {
return false;
}
if (!output->impl->cursor_attach_render(output, buffer_age)) {
return false;
}
output->cursor_pending.committed |= WLR_OUTPUT_CURSOR_BUFFER;
return true;
}
void wlr_output_cursor_enable(struct wlr_output *output, bool enable) {
output->cursor_pending.enabled = enable;
output->cursor_pending.committed |= WLR_OUTPUT_CURSOR_ENABLE;
}
void wlr_output_cursor_move(struct wlr_output *output, int x, int y,
int hotspot_x, int hotspot_y) {
output->cursor_pending.x = x;
output->cursor_pending.y = y;
output->cursor_pending.hotspot_x = hotspot_x;
output->cursor_pending.hotspot_y = hotspot_y;
output->cursor_pending.committed |= WLR_OUTPUT_CURSOR_POS;
}
bool wlr_output_cursor_commit(struct wlr_output *output) {
if (!output->impl->cursor_commit) {
return false;
}
bool ret = output->impl->cursor_commit(output);
output->cursor_pending.committed = 0;
return ret;
}
#if 0
bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height,