1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
#ifndef LIFTOFF_H
#define LIFTOFF_H
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <xf86drmMode.h>
struct liftoff_device;
struct liftoff_output;
struct liftoff_layer;
struct liftoff_plane;
/**
* Initialize libliftoff for a DRM node.
*
* The node is expected to have DRM_CLIENT_CAP_ATOMIC enabled. libliftoff takes
* ownership of the file descriptor.
*/
struct liftoff_device *
liftoff_device_create(int drm_fd);
/**
* Destroy a libliftoff device.
*
* The caller is expected to destroy the outputs and layers explicitly.
*/
void
liftoff_device_destroy(struct liftoff_device *device);
/**
* 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.
*
* Zero is returned on success, negative errno on error.
*/
int
liftoff_device_register_all_planes(struct liftoff_device *device);
/**
* 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.
*/
struct liftoff_plane *
liftoff_plane_create(struct liftoff_device *device, uint32_t plane_id);
/**
* Unregister a hardware plane.
*/
void
liftoff_plane_destroy(struct liftoff_plane *plane);
/**
* Obtain the object ID of the plane.
*/
uint32_t
liftoff_plane_get_id(struct liftoff_plane *plane);
/**
* Options for liftoff_output_apply().
*/
struct liftoff_output_apply_options {
/* Timeout in nanoseconds. If zero, a default timeout is used. */
int64_t timeout_ns;
};
/**
* Build a layer to plane mapping and append the plane configuration to req.
*
* Callers are expected to commit req afterwards and can figure out which
* layers need composition via liftoff_layer_needs_composition().
*
* flags is the atomic commit flags the caller intends to use. If options is
* NULL, defaults are used.
*
* Zero is returned on success, negative errno on error.
*/
int
liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
uint32_t flags,
const struct liftoff_output_apply_options *options);
/**
* Make the device manage a CRTC's planes.
*
* The returned output allows callers to attach layers.
*/
struct liftoff_output *
liftoff_output_create(struct liftoff_device *device, uint32_t crtc_id);
/**
* Destroy a libliftoff output.
*
* The caller is expected to destroy the output's layers explicitly.
*/
void
liftoff_output_destroy(struct liftoff_output *output);
/**
* 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.
*/
void
liftoff_output_set_composition_layer(struct liftoff_output *output,
struct liftoff_layer *layer);
/**
* 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
* will return true when liftoff_layer_needs_composition() is called.
*/
bool
liftoff_output_needs_composition(struct liftoff_output *output);
/**
* Create a new layer on an output.
*
* 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.
*/
struct liftoff_layer *
liftoff_layer_create(struct liftoff_output *output);
/**
* Destroy a layer.
*/
void
liftoff_layer_destroy(struct liftoff_layer *layer);
/**
* 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.
*
* Setting a zero FB_ID disables the layer.
*
* Zero is returned on success, negative errno on error.
*/
int
liftoff_layer_set_property(struct liftoff_layer *layer, const char *name,
uint64_t value);
/**
* Unset a property on the layer.
*/
void
liftoff_layer_unset_property(struct liftoff_layer *layer, const char *name);
/**
* Force composition on this layer.
*
* This unsets any previous FB_ID value. To switch back to direct scan-out, set
* FB_ID again.
*
* 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).
*/
void
liftoff_layer_set_fb_composited(struct liftoff_layer *layer);
/**
* Check whether this layer needs composition.
*
* A layer needs composition if it's visible and if it couldn't be mapped to a
* plane.
*/
bool
liftoff_layer_needs_composition(struct liftoff_layer *layer);
/**
* Retrieve the plane mapped to this layer.
*
* NULL is returned if no plane is mapped.
*/
struct liftoff_plane *
liftoff_layer_get_plane(struct liftoff_layer *layer);
/**
* 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);
enum liftoff_log_priority {
LIFTOFF_SILENT,
LIFTOFF_ERROR,
LIFTOFF_DEBUG,
};
typedef void (*liftoff_log_handler)(enum liftoff_log_priority priority,
const char *fmt, va_list args);
/**
* Set libliftoff's log priority.
*
* Only messages with a priority higher than the provided priority will be
* logged. The default priority is LIFTOFF_ERROR.
*/
void
liftoff_log_set_priority(enum liftoff_log_priority priority);
/**
* Set libliftoff's log handler.
*
* The default handler prints messages to stderr. NULL restores the default
* handler.
*/
void
liftoff_log_set_handler(liftoff_log_handler handler);
#endif
|