2019-09-12 10:39:06 +02:00
|
|
|
#ifndef LIFTOFF_H
|
|
|
|
#define LIFTOFF_H
|
|
|
|
|
2019-10-07 08:47:53 +02:00
|
|
|
#include <stdarg.h>
|
2020-12-06 15:07:03 +01:00
|
|
|
#include <stdbool.h>
|
2019-09-12 10:39:06 +02:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <xf86drmMode.h>
|
|
|
|
|
2019-11-24 12:59:10 +01:00
|
|
|
struct liftoff_device;
|
2019-09-30 20:19:27 +02:00
|
|
|
struct liftoff_output;
|
|
|
|
struct liftoff_layer;
|
2021-02-23 18:01:38 +01:00
|
|
|
struct liftoff_plane;
|
2019-09-30 20:19:27 +02:00
|
|
|
|
2019-09-12 10:39:06 +02:00
|
|
|
/**
|
2020-12-06 15:23:01 +01:00
|
|
|
* Initialize libliftoff for a DRM node.
|
|
|
|
*
|
2021-02-23 18:10:47 +01:00
|
|
|
* The node is expected to have DRM_CLIENT_CAP_ATOMIC enabled. libliftoff takes
|
|
|
|
* ownership of the file descriptor.
|
2019-09-12 10:39:06 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
struct liftoff_device *
|
|
|
|
liftoff_device_create(int drm_fd);
|
|
|
|
|
2020-12-06 15:23:01 +01:00
|
|
|
/**
|
|
|
|
* Destroy a libliftoff device.
|
|
|
|
*
|
|
|
|
* The caller is expected to destroy the outputs and layers explicitly.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_device_destroy(struct liftoff_device *device);
|
|
|
|
|
2021-02-23 18:01:38 +01:00
|
|
|
/**
|
|
|
|
* Register all available hardware planes to be managed by the libliftoff
|
|
|
|
* device.
|
|
|
|
*
|
|
|
|
* Users should call this function if they don't manually set any plane property
|
|
|
|
* and instead use libliftoff layers.
|
2021-07-30 16:19:29 +02:00
|
|
|
*
|
|
|
|
* Zero is returned on success, negative errno on error.
|
2021-02-23 18:01:38 +01:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
int
|
|
|
|
liftoff_device_register_all_planes(struct liftoff_device *device);
|
2021-02-23 18:01:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a hardware plane to be managed by the libliftoff device.
|
|
|
|
*
|
|
|
|
* Users should call this function for each plane they don't want to manually
|
|
|
|
* manage. Registering the same plane twice is an error.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
struct liftoff_plane *
|
|
|
|
liftoff_plane_create(struct liftoff_device *device, uint32_t plane_id);
|
|
|
|
|
2021-02-23 18:01:38 +01:00
|
|
|
/**
|
|
|
|
* Unregister a hardware plane.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_plane_destroy(struct liftoff_plane *plane);
|
2021-02-23 18:01:38 +01:00
|
|
|
|
2021-07-01 11:39:45 +02:00
|
|
|
/**
|
|
|
|
* Obtain the object ID of the plane.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
uint32_t
|
|
|
|
liftoff_plane_get_id(struct liftoff_plane *plane);
|
2021-07-01 11:39:45 +02:00
|
|
|
|
2019-09-12 10:39:06 +02:00
|
|
|
/**
|
2022-09-28 21:00:06 +02:00
|
|
|
* Build a layer to plane mapping and append the plane configuration to req.
|
2020-12-06 15:23:01 +01:00
|
|
|
*
|
2022-09-28 21:00:06 +02:00
|
|
|
* Callers are expected to commit req afterwards and can figure out which
|
|
|
|
* layers need composition via liftoff_layer_needs_composition().
|
2020-11-10 16:27:55 +01:00
|
|
|
*
|
2022-09-28 21:00:06 +02:00
|
|
|
* flags is the atomic commit flags the caller intends to use.
|
2021-07-27 12:28:00 +02:00
|
|
|
*
|
|
|
|
* Zero is returned on success, negative errno on error.
|
2019-09-12 10:39:06 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
int
|
|
|
|
liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
|
|
|
|
uint32_t flags);
|
2019-09-12 10:39:06 +02:00
|
|
|
|
|
|
|
/**
|
2020-12-06 15:23:01 +01:00
|
|
|
* Make the device manage a CRTC's planes.
|
|
|
|
*
|
|
|
|
* The returned output allows callers to attach layers.
|
2019-09-12 10:39:06 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
struct liftoff_output *
|
|
|
|
liftoff_output_create(struct liftoff_device *device, uint32_t crtc_id);
|
|
|
|
|
2020-12-06 15:23:01 +01:00
|
|
|
/**
|
|
|
|
* Destroy a libliftoff output.
|
|
|
|
*
|
|
|
|
* The caller is expected to destroy the output's layers explicitly.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_output_destroy(struct liftoff_output *output);
|
|
|
|
|
2019-09-30 20:22:01 +02:00
|
|
|
/**
|
2020-12-06 15:23:01 +01:00
|
|
|
* Indicate on which layer composition can take place.
|
|
|
|
*
|
|
|
|
* Users should be able to blend layers that haven't been mapped to a plane to
|
|
|
|
* this layer. The composition layer won't be used if all other layers have been
|
|
|
|
* mapped to a plane. There is at most one composition layer per output.
|
2019-09-30 20:22:01 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_output_set_composition_layer(struct liftoff_output *output,
|
|
|
|
struct liftoff_layer *layer);
|
|
|
|
|
2020-12-06 15:07:03 +01:00
|
|
|
/**
|
|
|
|
* Check whether this output needs composition.
|
|
|
|
*
|
|
|
|
* An output doesn't need composition if all visible layers could be mapped to a
|
|
|
|
* plane. In other words, if an output needs composition, at least one layer
|
2022-09-28 21:00:06 +02:00
|
|
|
* will return true when liftoff_layer_needs_composition() is called.
|
2020-12-06 15:07:03 +01:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
bool
|
|
|
|
liftoff_output_needs_composition(struct liftoff_output *output);
|
2019-09-12 10:39:06 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new layer on an output.
|
2020-12-06 15:23:01 +01:00
|
|
|
*
|
|
|
|
* A layer is a virtual plane. Users can create as many layers as they want and
|
|
|
|
* set any KMS property on them, without any constraint. libliftoff will try
|
|
|
|
* to map layers to hardware planes on a best-effort basis. The user will need
|
|
|
|
* to manually handle layers that couldn't be mapped to a plane.
|
2019-09-12 10:39:06 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
struct liftoff_layer *
|
|
|
|
liftoff_layer_create(struct liftoff_output *output);
|
|
|
|
|
2020-12-06 15:23:01 +01:00
|
|
|
/**
|
|
|
|
* Destroy a layer.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_layer_destroy(struct liftoff_layer *layer);
|
|
|
|
|
2019-09-12 10:39:06 +02:00
|
|
|
/**
|
2020-12-06 15:23:01 +01:00
|
|
|
* Set a property on the layer.
|
|
|
|
*
|
|
|
|
* Any plane property can be set (except CRTC_ID). If none of the planes support
|
|
|
|
* the property, the layer won't be mapped to any plane.
|
2019-12-13 11:36:09 +01:00
|
|
|
*
|
|
|
|
* Setting a zero FB_ID disables the layer.
|
2021-08-09 11:27:08 +02:00
|
|
|
*
|
|
|
|
* Zero is returned on success, negative errno on error.
|
2019-09-12 10:39:06 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
int
|
|
|
|
liftoff_layer_set_property(struct liftoff_layer *layer, const char *name,
|
|
|
|
uint64_t value);
|
|
|
|
|
2022-08-05 23:08:24 +02:00
|
|
|
/**
|
|
|
|
* Unset a property on the layer.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
liftoff_layer_unset_property(struct liftoff_layer *layer, const char *name);
|
|
|
|
|
2019-12-13 11:36:09 +01:00
|
|
|
/**
|
2020-12-06 15:23:01 +01:00
|
|
|
* Force composition on this layer.
|
|
|
|
*
|
|
|
|
* This unsets any previous FB_ID value. To switch back to direct scan-out, set
|
|
|
|
* FB_ID again.
|
2019-12-13 11:36:09 +01:00
|
|
|
*
|
|
|
|
* This can be used when no KMS FB ID is available for this layer but it still
|
|
|
|
* needs to be displayed (e.g. the buffer cannot be imported in KMS).
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_layer_set_fb_composited(struct liftoff_layer *layer);
|
|
|
|
|
2020-12-06 15:07:03 +01:00
|
|
|
/**
|
|
|
|
* Check whether this layer needs composition.
|
|
|
|
*
|
|
|
|
* A layer needs composition if it's visible and if it couldn't be mapped to a
|
|
|
|
* plane.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
bool
|
|
|
|
liftoff_layer_needs_composition(struct liftoff_layer *layer);
|
|
|
|
|
2019-09-12 10:39:06 +02:00
|
|
|
/**
|
2020-12-06 15:23:01 +01:00
|
|
|
* Retrieve the plane mapped to this layer.
|
|
|
|
*
|
2021-07-01 11:49:36 +02:00
|
|
|
* NULL is returned if no plane is mapped.
|
2019-09-12 10:39:06 +02:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
struct liftoff_plane *
|
|
|
|
liftoff_layer_get_plane(struct liftoff_layer *layer);
|
2019-09-12 10:39:06 +02:00
|
|
|
|
2023-02-06 10:57:13 +01:00
|
|
|
/**
|
|
|
|
* Check whether a plane is a candidate for this layer.
|
|
|
|
*
|
|
|
|
* A plane is a candidate if it could potentially be used for the layer with
|
|
|
|
* a buffer with the same size. The buffer may need to be re-allocated with
|
|
|
|
* formats and modifiers accepted by the plane.
|
|
|
|
*
|
|
|
|
* This can be used to implemented a feedback loop: if a layer isn't mapped to
|
|
|
|
* a plane, loop over the candidate planes, and re-allocate the layer's FB
|
|
|
|
* according to the IN_FORMATS property.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
liftoff_layer_is_candidate_plane(struct liftoff_layer *layer,
|
|
|
|
struct liftoff_plane *plane);
|
|
|
|
|
2021-03-31 12:44:24 +02:00
|
|
|
enum liftoff_log_priority {
|
2019-10-07 08:47:53 +02:00
|
|
|
LIFTOFF_SILENT,
|
|
|
|
LIFTOFF_ERROR,
|
2019-12-12 15:44:45 +01:00
|
|
|
LIFTOFF_DEBUG,
|
2019-10-07 08:47:53 +02:00
|
|
|
};
|
|
|
|
|
2021-03-31 12:44:24 +02:00
|
|
|
typedef void (*liftoff_log_handler)(enum liftoff_log_priority priority,
|
|
|
|
const char *fmt, va_list args);
|
2019-10-07 08:47:53 +02:00
|
|
|
|
2020-12-06 15:23:01 +01:00
|
|
|
/**
|
2021-03-31 12:44:24 +02:00
|
|
|
* Set libliftoff's log priority.
|
2020-12-06 15:23:01 +01:00
|
|
|
*
|
2021-03-31 12:44:24 +02:00
|
|
|
* Only messages with a priority higher than the provided priority will be
|
|
|
|
* logged. The default priority is LIFTOFF_ERROR.
|
2020-12-06 15:23:01 +01:00
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_log_set_priority(enum liftoff_log_priority priority);
|
|
|
|
|
2021-03-31 12:44:24 +02:00
|
|
|
/**
|
|
|
|
* Set libliftoff's log handler.
|
|
|
|
*
|
|
|
|
* The default handler prints messages to stderr. NULL restores the default
|
|
|
|
* handler.
|
|
|
|
*/
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_log_set_handler(liftoff_log_handler handler);
|
2019-10-07 08:47:53 +02:00
|
|
|
|
2019-09-12 10:39:06 +02:00
|
|
|
#endif
|