mirror of
https://gitlab.freedesktop.org/emersion/libliftoff.git
synced 2024-12-26 21:59:18 +01:00
Stop re-using a previous configuration when FB attributes change
If FB attributes change, we might be able to take advantage of a plane we couldn't use before. Closes: https://gitlab.freedesktop.org/emersion/libliftoff/-/issues/71
This commit is contained in:
parent
a669c85be6
commit
ab72b0d5c6
3 changed files with 105 additions and 6 deletions
50
alloc.c
50
alloc.c
|
@ -517,6 +517,18 @@ apply_current(struct liftoff_device *device, drmModeAtomicReq *req)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
fb_info_needs_realloc(const drmModeFB2 *a, const drmModeFB2 *b)
|
||||||
|
{
|
||||||
|
if (a->width != b->width || a->height != b->height ||
|
||||||
|
a->pixel_format != b->pixel_format || a->modifier != b->modifier)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* TODO: consider checking pitch and offset? */
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
layer_needs_realloc(struct liftoff_layer *layer)
|
layer_needs_realloc(struct liftoff_layer *layer)
|
||||||
{
|
{
|
||||||
|
@ -529,21 +541,30 @@ layer_needs_realloc(struct liftoff_layer *layer)
|
||||||
|
|
||||||
for (i = 0; i < layer->props_len; i++) {
|
for (i = 0; i < layer->props_len; i++) {
|
||||||
prop = &layer->props[i];
|
prop = &layer->props[i];
|
||||||
if (prop->value == prop->prev_value) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If FB_ID changes from non-zero to zero, we don't need to
|
/* If FB_ID changes from non-zero to zero, we don't need to
|
||||||
* display this layer anymore, so we may be able to re-use its
|
* display this layer anymore, so we may be able to re-use its
|
||||||
* plane for another layer. If FB_ID changes from zero to
|
* plane for another layer. If FB_ID changes from zero to
|
||||||
* non-zero, we might be able to find a plane for this layer.
|
* non-zero, we might be able to find a plane for this layer.
|
||||||
* If FB_ID changes from non-zero to non-zero, we can try to
|
* If FB_ID changes from non-zero to non-zero and the FB
|
||||||
* re-use the previous allocation. */
|
* attributes didn't change, we can try to re-use the previous
|
||||||
|
* allocation. */
|
||||||
if (strcmp(prop->name, "FB_ID") == 0) {
|
if (strcmp(prop->name, "FB_ID") == 0) {
|
||||||
if (prop->value == 0 || prop->prev_value == 0) {
|
if (prop->value == 0 || prop->prev_value == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* TODO: check format/modifier is the same? */
|
|
||||||
|
if (fb_info_needs_realloc(&layer->fb_info,
|
||||||
|
&layer->prev_fb_info)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For all properties except FB_ID, we can skip realloc if the
|
||||||
|
* value didn't change. */
|
||||||
|
if (prop->value == prop->prev_value) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,6 +660,22 @@ update_layers_priority(struct liftoff_device *device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_layers_fb_info(struct liftoff_output *output)
|
||||||
|
{
|
||||||
|
struct liftoff_layer *layer;
|
||||||
|
|
||||||
|
/* We don't know what the library user did in-between
|
||||||
|
* liftoff_output_apply() calls. They might've removed the FB and
|
||||||
|
* re-created a completely different one which happens to have the same
|
||||||
|
* FB ID. */
|
||||||
|
liftoff_list_for_each(layer, &output->layers, link) {
|
||||||
|
memset(&layer->fb_info, 0, sizeof(layer->fb_info));
|
||||||
|
layer_cache_fb_info(layer);
|
||||||
|
/* TODO: propagate error? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
log_reuse(struct liftoff_output *output)
|
log_reuse(struct liftoff_output *output)
|
||||||
{
|
{
|
||||||
|
@ -697,6 +734,7 @@ liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
|
||||||
device = output->device;
|
device = output->device;
|
||||||
|
|
||||||
update_layers_priority(device);
|
update_layers_priority(device);
|
||||||
|
update_layers_fb_info(output);
|
||||||
|
|
||||||
ret = reuse_previous_alloc(output, req, flags);
|
ret = reuse_previous_alloc(output, req, flags);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
|
|
@ -51,6 +51,7 @@ struct liftoff_layer {
|
||||||
int current_priority, pending_priority;
|
int current_priority, pending_priority;
|
||||||
/* prop added or force_composition changed */
|
/* prop added or force_composition changed */
|
||||||
bool changed;
|
bool changed;
|
||||||
|
drmModeFB2 fb_info, prev_fb_info; /* cached FB info */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct liftoff_layer_property {
|
struct liftoff_layer_property {
|
||||||
|
@ -107,6 +108,9 @@ layer_has_fb(struct liftoff_layer *layer);
|
||||||
bool
|
bool
|
||||||
layer_is_visible(struct liftoff_layer *layer);
|
layer_is_visible(struct liftoff_layer *layer);
|
||||||
|
|
||||||
|
int
|
||||||
|
layer_cache_fb_info(struct liftoff_layer *layer);
|
||||||
|
|
||||||
int
|
int
|
||||||
plane_apply(struct liftoff_plane *plane, struct liftoff_layer *layer,
|
plane_apply(struct liftoff_plane *plane, struct liftoff_layer *layer,
|
||||||
drmModeAtomicReq *req);
|
drmModeAtomicReq *req);
|
||||||
|
|
57
layer.c
57
layer.c
|
@ -1,6 +1,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <xf86drm.h>
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
struct liftoff_layer *
|
struct liftoff_layer *
|
||||||
|
@ -178,6 +179,7 @@ layer_mark_clean(struct liftoff_layer *layer)
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
layer->changed = false;
|
layer->changed = false;
|
||||||
|
layer->prev_fb_info = layer->fb_info;
|
||||||
|
|
||||||
for (i = 0; i < layer->props_len; i++) {
|
for (i = 0; i < layer->props_len; i++) {
|
||||||
layer->props[i].prev_value = layer->props[i].value;
|
layer->props[i].prev_value = layer->props[i].value;
|
||||||
|
@ -239,3 +241,58 @@ layer_is_visible(struct liftoff_layer *layer)
|
||||||
return layer_has_fb(layer);
|
return layer_has_fb(layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
layer_cache_fb_info(struct liftoff_layer *layer)
|
||||||
|
{
|
||||||
|
struct liftoff_layer_property *fb_id_prop;
|
||||||
|
drmModeFB2 *fb_info;
|
||||||
|
size_t i, j, num_planes;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
fb_id_prop = layer_get_property(layer, "FB_ID");
|
||||||
|
if (fb_id_prop == NULL || fb_id_prop->value == 0) {
|
||||||
|
memset(&layer->fb_info, 0, sizeof(layer->fb_info));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer->fb_info.fb_id == fb_id_prop->value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_info = drmModeGetFB2(layer->output->device->drm_fd, fb_id_prop->value);
|
||||||
|
if (fb_info == NULL) {
|
||||||
|
if (errno == EINVAL) {
|
||||||
|
return 0; /* old kernel */
|
||||||
|
}
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* drmModeGetFB2() always creates new GEM handles -- close these, we
|
||||||
|
* won't use them and we don't want to leak them */
|
||||||
|
num_planes = sizeof(fb_info->handles) / sizeof(fb_info->handles[0]);
|
||||||
|
for (i = 0; i < num_planes; i++) {
|
||||||
|
if (fb_info->handles[i] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = drmCloseBufferHandle(layer->output->device->drm_fd,
|
||||||
|
fb_info->handles[i]);
|
||||||
|
if (ret != 0) {
|
||||||
|
liftoff_log_errno(LIFTOFF_ERROR, "drmCloseBufferHandle");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we don't double-close a handle */
|
||||||
|
for (j = i + 1; j < num_planes; j++) {
|
||||||
|
if (fb_info->handles[j] == fb_info->handles[i]) {
|
||||||
|
fb_info->handles[j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fb_info->handles[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer->fb_info = *fb_info;
|
||||||
|
drmModeFreeFB2(fb_info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue