Revert "backend-drm: Teach drm_property_info_populate() to retrieve range values"

Due to an error in driving GitLab, this commit erroneously contained the
entirety of !267 (zpos support in the KMS backend) squashed into one
single commit, pushed into master.

In order to keep the history clean, this is being reverted; a rebased
version of !267 with the clear individual commits which were already
present will be applied in its place.

This reverts commit 95e3b0deae.
dev
Daniel Stone 5 years ago
parent 95e3b0deae
commit 2cb926c558
  1. 44
      libweston/backend-drm/drm-internal.h
  2. 73
      libweston/backend-drm/drm.c
  3. 53
      libweston/backend-drm/kms.c
  4. 7
      libweston/backend-drm/state-helpers.c
  5. 730
      libweston/backend-drm/state-propose.c
  6. 35
      libweston/compositor.c
  7. 6
      libweston/libweston-internal.h

@ -72,10 +72,6 @@
#define GBM_BO_USE_LINEAR (1 << 4) #define GBM_BO_USE_LINEAR (1 << 4)
#endif #endif
#ifndef DRM_PLANE_ZPOS_INVALID_PLANE
#define DRM_PLANE_ZPOS_INVALID_PLANE 0xffffffffffffffffULL
#endif
/** /**
* A small wrapper to print information into the 'drm-backend' debug scope. * A small wrapper to print information into the 'drm-backend' debug scope.
* *
@ -148,11 +144,8 @@ struct drm_property_enum_info {
struct drm_property_info { struct drm_property_info {
const char *name; /**< name as string (static, not freed) */ const char *name; /**< name as string (static, not freed) */
uint32_t prop_id; /**< KMS property object ID */ uint32_t prop_id; /**< KMS property object ID */
uint32_t flags;
unsigned int num_enum_values; /**< number of enum values */ unsigned int num_enum_values; /**< number of enum values */
struct drm_property_enum_info *enum_values; /**< array of enum values */ struct drm_property_enum_info *enum_values; /**< array of enum values */
unsigned int num_range_values;
uint64_t range_values[2];
}; };
/** /**
@ -173,7 +166,6 @@ enum wdrm_plane_property {
WDRM_PLANE_IN_FORMATS, WDRM_PLANE_IN_FORMATS,
WDRM_PLANE_IN_FENCE_FD, WDRM_PLANE_IN_FENCE_FD,
WDRM_PLANE_FB_DAMAGE_CLIPS, WDRM_PLANE_FB_DAMAGE_CLIPS,
WDRM_PLANE_ZPOS,
WDRM_PLANE__COUNT WDRM_PLANE__COUNT
}; };
@ -369,16 +361,6 @@ struct drm_output_state {
struct wl_list plane_list; struct wl_list plane_list;
}; };
/**
* An instance of this class is created each time we believe we have a plane
* suitable to be used by a view as a direct scan-out. The list is initalized
* and populated locally.
*/
struct drm_plane_zpos {
struct drm_plane *plane;
struct wl_list link; /**< :candidate_plane_zpos_list */
};
/** /**
* Plane state holds the dynamic state for a plane: where it is positioned, * Plane state holds the dynamic state for a plane: where it is positioned,
* and which buffer it is currently displaying. * and which buffer it is currently displaying.
@ -400,8 +382,6 @@ struct drm_plane_state {
int32_t dest_x, dest_y; int32_t dest_x, dest_y;
uint32_t dest_w, dest_h; uint32_t dest_w, dest_h;
uint64_t zpos;
bool complete; bool complete;
/* We don't own the fd, so we shouldn't close it */ /* We don't own the fd, so we shouldn't close it */
@ -443,9 +423,6 @@ struct drm_plane {
/* The last state submitted to the kernel for this plane. */ /* The last state submitted to the kernel for this plane. */
struct drm_plane_state *state_cur; struct drm_plane_state *state_cur;
uint64_t zpos_min;
uint64_t zpos_max;
struct wl_list link; struct wl_list link;
struct { struct {
@ -546,22 +523,6 @@ to_drm_mode(struct weston_mode *base)
return container_of(base, struct drm_mode, base); return container_of(base, struct drm_mode, base);
} }
static inline const char *
drm_output_get_plane_type_name(struct drm_plane *p)
{
switch (p->type) {
case WDRM_PLANE_TYPE_PRIMARY:
return "primary";
case WDRM_PLANE_TYPE_CURSOR:
return "cursor";
case WDRM_PLANE_TYPE_OVERLAY:
return "overlay";
default:
assert(0);
break;
}
}
struct drm_output * struct drm_output *
drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id); drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id);
@ -618,9 +579,6 @@ uint64_t
drm_property_get_value(struct drm_property_info *info, drm_property_get_value(struct drm_property_info *info,
const drmModeObjectProperties *props, const drmModeObjectProperties *props,
uint64_t def); uint64_t def);
uint64_t *
drm_property_get_range_values(struct drm_property_info *info,
const drmModeObjectProperties *props);
int int
drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane, drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane,
const drmModeObjectProperties *props); const drmModeObjectProperties *props);
@ -737,7 +695,7 @@ void
drm_plane_state_put_back(struct drm_plane_state *state); drm_plane_state_put_back(struct drm_plane_state *state);
bool bool
drm_plane_state_coords_for_view(struct drm_plane_state *state, drm_plane_state_coords_for_view(struct drm_plane_state *state,
struct weston_view *ev, uint64_t zpos); struct weston_view *ev);
void void
drm_assign_planes(struct weston_output *output_base, void *repaint_data); drm_assign_planes(struct weston_output *output_base, void *repaint_data);

@ -68,61 +68,6 @@
static const char default_seat[] = "seat0"; static const char default_seat[] = "seat0";
static void
drm_backend_create_faked_zpos(struct drm_backend *b)
{
struct drm_plane *plane;
uint64_t zpos = 0ULL;
uint64_t zpos_min_primary;
uint64_t zpos_min_overlay;
uint64_t zpos_min_cursor;
zpos_min_primary = zpos;
wl_list_for_each(plane, &b->plane_list, link) {
/* if the property is there, bail out sooner */
if (plane->props[WDRM_PLANE_ZPOS].prop_id != 0)
return;
if (plane->type != WDRM_PLANE_TYPE_PRIMARY)
continue;
zpos++;
}
zpos_min_overlay = zpos;
wl_list_for_each(plane, &b->plane_list, link) {
if (plane->type != WDRM_PLANE_TYPE_OVERLAY)
continue;
zpos++;
}
zpos_min_cursor = zpos;
wl_list_for_each(plane, &b->plane_list, link) {
if (plane->type != WDRM_PLANE_TYPE_CURSOR)
continue;
zpos++;
}
drm_debug(b, "[drm-backend] zpos property not found. "
"Using invented immutable zpos values:\n");
/* assume that invented zpos values are immutable */
wl_list_for_each(plane, &b->plane_list, link) {
if (plane->type == WDRM_PLANE_TYPE_PRIMARY) {
plane->zpos_min = zpos_min_primary;
plane->zpos_max = zpos_min_primary;
} else if (plane->type == WDRM_PLANE_TYPE_OVERLAY) {
plane->zpos_min = zpos_min_overlay;
plane->zpos_max = zpos_min_overlay;
} else if (plane->type == WDRM_PLANE_TYPE_CURSOR) {
plane->zpos_min = zpos_min_cursor;
plane->zpos_max = zpos_min_cursor;
}
drm_debug(b, "\t[plane] %s plane %d, zpos_min %"PRIu64", "
"zpos_max %"PRIu64"\n",
drm_output_get_plane_type_name(plane),
plane->plane_id, plane->zpos_min, plane->zpos_max);
}
}
static void static void
wl_array_remove_uint32(struct wl_array *array, uint32_t elm) wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
{ {
@ -735,7 +680,6 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
{ {
struct drm_plane *plane; struct drm_plane *plane;
drmModeObjectProperties *props; drmModeObjectProperties *props;
uint64_t *zpos_range_values;
uint32_t num_formats = (kplane) ? kplane->count_formats : 1; uint32_t num_formats = (kplane) ? kplane->count_formats : 1;
plane = zalloc(sizeof(*plane) + plane = zalloc(sizeof(*plane) +
@ -767,18 +711,6 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
props, props,
WDRM_PLANE_TYPE__COUNT); WDRM_PLANE_TYPE__COUNT);
zpos_range_values =
drm_property_get_range_values(&plane->props[WDRM_PLANE_ZPOS],
props);
if (zpos_range_values) {
plane->zpos_min = zpos_range_values[0];
plane->zpos_max = zpos_range_values[1];
} else {
plane->zpos_min = DRM_PLANE_ZPOS_INVALID_PLANE;
plane->zpos_max = DRM_PLANE_ZPOS_INVALID_PLANE;
}
if (drm_plane_populate_formats(plane, kplane, props) < 0) { if (drm_plane_populate_formats(plane, kplane, props) < 0) {
drmModeFreeObjectProperties(props); drmModeFreeObjectProperties(props);
goto err; goto err;
@ -792,8 +724,6 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
plane->count_formats = 1; plane->count_formats = 1;
plane->formats[0].format = format; plane->formats[0].format = format;
plane->type = type; plane->type = type;
plane->zpos_max = DRM_PLANE_ZPOS_INVALID_PLANE;
plane->zpos_min = DRM_PLANE_ZPOS_INVALID_PLANE;
} }
if (plane->type == WDRM_PLANE_TYPE__COUNT) if (plane->type == WDRM_PLANE_TYPE__COUNT)
@ -2911,9 +2841,6 @@ drm_backend_create(struct weston_compositor *compositor,
goto err_udev_input; goto err_udev_input;
} }
/* 'compute' faked zpos values in case HW doesn't expose any */
drm_backend_create_faked_zpos(b);
/* A this point we have some idea of whether or not we have a working /* A this point we have some idea of whether or not we have a working
* cursor plane. */ * cursor plane. */
if (!b->cursors_are_broken) if (!b->cursors_are_broken)

@ -77,7 +77,6 @@ const struct drm_property_info plane_props[] = {
[WDRM_PLANE_IN_FORMATS] = { .name = "IN_FORMATS" }, [WDRM_PLANE_IN_FORMATS] = { .name = "IN_FORMATS" },
[WDRM_PLANE_IN_FENCE_FD] = { .name = "IN_FENCE_FD" }, [WDRM_PLANE_IN_FENCE_FD] = { .name = "IN_FENCE_FD" },
[WDRM_PLANE_FB_DAMAGE_CLIPS] = { .name = "FB_DAMAGE_CLIPS" }, [WDRM_PLANE_FB_DAMAGE_CLIPS] = { .name = "FB_DAMAGE_CLIPS" },
[WDRM_PLANE_ZPOS] = { .name = "zpos" },
}; };
struct drm_property_enum_info dpms_state_enums[] = { struct drm_property_enum_info dpms_state_enums[] = {
@ -203,42 +202,6 @@ drm_property_get_value(struct drm_property_info *info,
return def; return def;
} }
/**
* Get the current range values of a KMS property
*
* Given a drmModeObjectGetProperties return, as well as the drm_property_info
* for the target property, return the current range values of that property,
*
* If the property is not present, or there's no it is not a prop range then
* NULL will be returned.
*
* @param info Internal structure for property to look up
* @param props Raw KMS properties for the target object
*/
uint64_t *
drm_property_get_range_values(struct drm_property_info *info,
const drmModeObjectProperties *props)
{
unsigned int i;
if (info->prop_id == 0)
return NULL;
for (i = 0; i < props->count_props; i++) {
if (props->props[i] != info->prop_id)
continue;
if (!(info->flags & DRM_MODE_PROP_RANGE) &&
!(info->flags & DRM_MODE_PROP_SIGNED_RANGE))
continue;
return info->range_values;
}
return NULL;
}
/** /**
* Cache DRM property values * Cache DRM property values
* *
@ -331,15 +294,6 @@ drm_property_info_populate(struct drm_backend *b,
} }
info[j].prop_id = props->props[i]; info[j].prop_id = props->props[i];
info[j].flags = prop->flags;
if (prop->flags & DRM_MODE_PROP_RANGE ||
prop->flags & DRM_MODE_PROP_SIGNED_RANGE) {
info[j].num_range_values = prop->count_values;
for (int i = 0; i < prop->count_values; i++)
info[j].range_values[i] = prop->values[i];
}
if (info[j].num_enum_values == 0) { if (info[j].num_enum_values == 0) {
drmModeFreeProperty(prop); drmModeFreeProperty(prop);
@ -1051,13 +1005,6 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
plane_state->in_fence_fd); plane_state->in_fence_fd);
} }
/* do note, that 'invented' zpos values are set as immutable */
if (plane_state->zpos != DRM_PLANE_ZPOS_INVALID_PLANE &&
plane_state->plane->zpos_min != plane_state->plane->zpos_max)
ret |= plane_add_prop(req, plane,
WDRM_PLANE_ZPOS,
plane_state->zpos);
if (ret != 0) { if (ret != 0) {
weston_log("couldn't set plane state\n"); weston_log("couldn't set plane state\n");
return ret; return ret;

@ -48,7 +48,6 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
state->output_state = state_output; state->output_state = state_output;
state->plane = plane; state->plane = plane;
state->in_fence_fd = -1; state->in_fence_fd = -1;
state->zpos = DRM_PLANE_ZPOS_INVALID_PLANE;
pixman_region32_init(&state->damage); pixman_region32_init(&state->damage);
/* Here we only add the plane state to the desired link, and not /* Here we only add the plane state to the desired link, and not
@ -81,7 +80,6 @@ drm_plane_state_free(struct drm_plane_state *state, bool force)
wl_list_init(&state->link); wl_list_init(&state->link);
state->output_state = NULL; state->output_state = NULL;
state->in_fence_fd = -1; state->in_fence_fd = -1;
state->zpos = DRM_PLANE_ZPOS_INVALID_PLANE;
pixman_region32_fini(&state->damage); pixman_region32_fini(&state->damage);
if (force || state != state->plane->state_cur) { if (force || state != state->plane->state_cur) {
@ -165,7 +163,7 @@ drm_plane_state_put_back(struct drm_plane_state *state)
*/ */
bool bool
drm_plane_state_coords_for_view(struct drm_plane_state *state, drm_plane_state_coords_for_view(struct drm_plane_state *state,
struct weston_view *ev, uint64_t zpos) struct weston_view *ev)
{ {
struct drm_output *output = state->output; struct drm_output *output = state->output;
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
@ -245,9 +243,6 @@ drm_plane_state_coords_for_view(struct drm_plane_state *state,
if (state->src_h > (uint32_t) ((buffer->height << 16) - state->src_y)) if (state->src_h > (uint32_t) ((buffer->height << 16) - state->src_y))
state->src_h = (buffer->height << 16) - state->src_y; state->src_h = (buffer->height << 16) - state->src_y;
/* apply zpos if available */
state->zpos = zpos;
return true; return true;
} }

@ -62,200 +62,155 @@ drm_propose_state_mode_to_string(enum drm_output_propose_state_mode mode)
return drm_output_propose_state_mode_as_string[mode]; return drm_output_propose_state_mode_as_string[mode];
} }
static void static struct drm_plane_state *
drm_output_add_zpos_plane(struct drm_plane *plane, struct wl_list *planes) drm_output_prepare_overlay_view(struct drm_output_state *output_state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode)
{ {
struct drm_backend *b = plane->backend; struct drm_output *output = output_state->output;
struct drm_plane_zpos *h_plane; struct weston_compositor *ec = output->base.compositor;
struct drm_plane_zpos *plane_zpos; struct drm_backend *b = to_drm_backend(ec);
struct drm_plane *p;
plane_zpos = zalloc(sizeof(*plane_zpos)); struct drm_plane_state *state = NULL;
if (!plane_zpos) struct drm_fb *fb;
return; unsigned int i;
int ret;
plane_zpos->plane = plane; enum {
NO_PLANES,
NO_PLANES_WITH_FORMAT,
NO_PLANES_ACCEPTED,
PLACED_ON_PLANE,
} availability = NO_PLANES;
drm_debug(b, "\t\t\t\t[plane] plane %d added to candidate list\n", assert(!b->sprites_are_broken);
plane->plane_id); assert(b->atomic_modeset);
if (wl_list_empty(planes)) { fb = drm_fb_get_from_view(output_state, ev);
wl_list_insert(planes, &plane_zpos->link); if (!fb) {
return; drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
" couldn't get fb\n", ev);
return NULL;
} }
h_plane = wl_container_of(planes->next, h_plane, link); wl_list_for_each(p, &b->plane_list, link) {
if (h_plane->plane->zpos_max >= plane->zpos_max) { if (p->type != WDRM_PLANE_TYPE_OVERLAY)
wl_list_insert(planes->prev, &plane_zpos->link); continue;
} else {
struct drm_plane_zpos *p_zpos = NULL;
if (wl_list_length(planes) == 1) { if (!drm_plane_is_available(p, output))
wl_list_insert(planes->prev, &plane_zpos->link); continue;
return;
}
wl_list_for_each(p_zpos, planes, link) { state = drm_output_state_get_plane(output_state, p);
if (p_zpos->plane->zpos_max > if (state->fb) {
plane_zpos->plane->zpos_max) state = NULL;
break; continue;
} }
wl_list_insert(p_zpos->link.prev, &plane_zpos->link); if (availability == NO_PLANES)
} availability = NO_PLANES_WITH_FORMAT;
}
static void
drm_output_destroy_zpos_plane(struct drm_plane_zpos *plane_zpos)
{
wl_list_remove(&plane_zpos->link);
free(plane_zpos);
}
static bool
drm_output_check_plane_has_view_assigned(struct drm_plane *plane,
struct drm_output_state *output_state)
{
struct drm_plane_state *ps;
wl_list_for_each(ps, &output_state->plane_list, link) {
if (ps->plane == plane && ps->fb)
return true;
}
return false;
}
static bool /* Check whether the format is supported */
drm_output_plane_has_valid_format(struct drm_plane *plane, for (i = 0; i < p->count_formats; i++) {
struct drm_output_state *state, unsigned int j;
struct drm_fb *fb)
{
struct drm_backend *b = plane->backend;
unsigned int i;
if (!fb) if (p->formats[i].format != fb->format->format)
return false; continue;
/* Check whether the format is supported */ if (fb->modifier == DRM_FORMAT_MOD_INVALID)
for (i = 0; i < plane->count_formats; i++) { break;
unsigned int j;
if (plane->formats[i].format != fb->format->format) for (j = 0; j < p->formats[i].count_modifiers; j++) {
if (p->formats[i].modifiers[j] == fb->modifier)
break;
}
if (j != p->formats[i].count_modifiers)
break;
}
if (i == p->count_formats) {
drm_plane_state_put_back(state);
state = NULL;
continue; continue;
if (fb->modifier == DRM_FORMAT_MOD_INVALID)
return true;
for (j = 0; j < plane->formats[i].count_modifiers; j++) {
if (plane->formats[i].modifiers[j] == fb->modifier)
return true;
} }
}
drm_debug(b, "\t\t\t\t[%s] not placing view on %s: " if (availability == NO_PLANES_WITH_FORMAT)
"no free %s planes matching format %s (0x%lx) " availability = NO_PLANES_ACCEPTED;
"modifier 0x%llx\n",
drm_output_get_plane_type_name(plane),
drm_output_get_plane_type_name(plane),
drm_output_get_plane_type_name(plane),
fb->format->drm_format_name,
(unsigned long) fb->format,
(unsigned long long) fb->modifier);
return false;
}
static bool
drm_output_plane_cursor_has_valid_format(struct weston_view *ev)
{
struct wl_shm_buffer *shmbuf =
wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource);
if (shmbuf && wl_shm_buffer_get_format(shmbuf) == WL_SHM_FORMAT_ARGB8888) state->ev = ev;
return true; state->output = output;
if (!drm_plane_state_coords_for_view(state, ev)) {
drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
"unsuitable transform\n", ev);
drm_plane_state_put_back(state);
state = NULL;
continue;
}
return false; /* If the surface buffer has an in-fence fd, but the plane
} * doesn't support fences, we can't place the buffer on this
* plane. */
if (ev->surface->acquire_fence_fd >= 0 &&
p->props[WDRM_PLANE_IN_FENCE_FD].prop_id == 0) {
drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
"no in-fence support\n", ev);
drm_plane_state_put_back(state);
state = NULL;
continue;
}
static struct drm_plane_state * /* We hold one reference for the lifetime of this function;
drm_output_prepare_overlay_view(struct drm_plane *plane, * from calling drm_fb_get_from_view, to the out label where
struct drm_output_state *output_state, * we unconditionally drop the reference. So, we take another
struct weston_view *ev, * reference here to live within the state. */
enum drm_output_propose_state_mode mode, state->fb = drm_fb_ref(fb);
struct drm_fb *fb, uint64_t zpos)
{
struct drm_output *output = output_state->output;
struct weston_compositor *ec = output->base.compositor;
struct drm_backend *b = to_drm_backend(ec);
struct drm_plane_state *state = NULL;
int ret;
assert(!b->sprites_are_broken); state->in_fence_fd = ev->surface->acquire_fence_fd;
assert(b->atomic_modeset);
if (!fb) { /* In planes-only mode, we don't have an incremental state to
drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " * test against, so we just hope it'll work. */
" couldn't get fb\n", ev); if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) {
return NULL; drm_debug(b, "\t\t\t\t[overlay] provisionally placing "
} "view %p on overlay %lu in planes-only mode\n",
ev, (unsigned long) p->plane_id);
availability = PLACED_ON_PLANE;
goto out;
}
state = drm_output_state_get_plane(output_state, plane); ret = drm_pending_state_test(output_state->pending_state);
/* we can't have a 'pending' framebuffer as never set one before reaching here */ if (ret == 0) {
assert(!state->fb); drm_debug(b, "\t\t\t\t[overlay] provisionally placing "
"view %p on overlay %d in mixed mode\n",
ev, p->plane_id);
availability = PLACED_ON_PLANE;
goto out;
}
state->ev = ev; drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay %lu "
state->output = output; "in mixed mode: kernel test failed\n",
ev, (unsigned long) p->plane_id);
if (!drm_plane_state_coords_for_view(state, ev, zpos)) {
drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
"unsuitable transform\n", ev);
drm_plane_state_put_back(state); drm_plane_state_put_back(state);
state = NULL; state = NULL;
goto out;
} }
/* If the surface buffer has an in-fence fd, but the plane switch (availability) {
* doesn't support fences, we can't place the buffer on this case NO_PLANES:
* plane. */
if (ev->surface->acquire_fence_fd >= 0 &&
plane->props[WDRM_PLANE_IN_FENCE_FD].prop_id == 0) {
drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
"no in-fence support\n", ev); "no free overlay planes\n", ev);
drm_plane_state_put_back(state); break;
state = NULL; case NO_PLANES_WITH_FORMAT:
goto out; drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
} "no free overlay planes matching format %s (0x%lx) "
"modifier 0x%llx\n",
/* We hold one reference for the lifetime of this function; from ev, fb->format->drm_format_name,
* calling drm_fb_get_from_view() in drm_output_prepare_plane_view(), (unsigned long) fb->format,
* so, we take another reference here to live within the state. */ (unsigned long long) fb->modifier);
state->fb = drm_fb_ref(fb); break;
case NO_PLANES_ACCEPTED:
state->in_fence_fd = ev->surface->acquire_fence_fd; case PLACED_ON_PLANE:
break;
/* In planes-only mode, we don't have an incremental state to
* test against, so we just hope it'll work. */
if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) {
drm_debug(b, "\t\t\t[overlay] provisionally placing "
"view %p on overlay %lu in planes-only mode\n",
ev, (unsigned long) plane->plane_id);
goto out;
}
ret = drm_pending_state_test(output_state->pending_state);
if (ret == 0) {
drm_debug(b, "\t\t\t[overlay] provisionally placing "
"view %p on overlay %d in mixed mode\n",
ev, plane->plane_id);
goto out;
} }
drm_debug(b, "\t\t\t[overlay] not placing view %p on overlay %lu "
"in mixed mode: kernel test failed\n",
ev, (unsigned long) plane->plane_id);
drm_plane_state_put_back(state);
state = NULL;
out: out:
drm_fb_unref(fb);
return state; return state;
} }
@ -299,14 +254,14 @@ cursor_bo_update(struct drm_plane_state *plane_state, struct weston_view *ev)
static struct drm_plane_state * static struct drm_plane_state *
drm_output_prepare_cursor_view(struct drm_output_state *output_state, drm_output_prepare_cursor_view(struct drm_output_state *output_state,
struct weston_view *ev, uint64_t zpos) struct weston_view *ev)
{ {
struct drm_output *output = output_state->output; struct drm_output *output = output_state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor); struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_plane *plane = output->cursor_plane; struct drm_plane *plane = output->cursor_plane;
struct drm_plane_state *plane_state; struct drm_plane_state *plane_state;
struct wl_shm_buffer *shmbuf;
bool needs_update = false; bool needs_update = false;
const char *p_name = drm_output_get_plane_type_name(plane);
assert(!b->cursors_are_broken); assert(!b->cursors_are_broken);
@ -323,6 +278,24 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
if (b->gbm == NULL) if (b->gbm == NULL)
return NULL; return NULL;
if (ev->surface->buffer_ref.buffer == NULL) {
drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane "
"(no buffer available)\n", ev);
return NULL;
}
shmbuf = wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource);
if (!shmbuf) {
drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane "
"(buffer isn't SHM)\n", ev);
return NULL;
}
if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB8888) {
drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane "
"(format 0x%lx unsuitable)\n",
ev, (unsigned long) wl_shm_buffer_get_format(shmbuf));
return NULL;
}
plane_state = plane_state =
drm_output_state_get_plane(output_state, output->cursor_plane); drm_output_state_get_plane(output_state, output->cursor_plane);
@ -332,20 +305,16 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
/* We can't scale with the legacy API, and we don't try to account for /* We can't scale with the legacy API, and we don't try to account for
* simple cropping/translation in cursor_bo_update. */ * simple cropping/translation in cursor_bo_update. */
plane_state->output = output; plane_state->output = output;
if (!drm_plane_state_coords_for_view(plane_state, ev, zpos)) { if (!drm_plane_state_coords_for_view(plane_state, ev))
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
"unsuitable transform\n", p_name, ev, p_name);
goto err; goto err;
}
if (plane_state->src_x != 0 || plane_state->src_y != 0 || if (plane_state->src_x != 0 || plane_state->src_y != 0 ||
plane_state->src_w > (unsigned) b->cursor_width << 16 || plane_state->src_w > (unsigned) b->cursor_width << 16 ||
plane_state->src_h > (unsigned) b->cursor_height << 16 || plane_state->src_h > (unsigned) b->cursor_height << 16 ||
plane_state->src_w != plane_state->dest_w << 16 || plane_state->src_w != plane_state->dest_w << 16 ||
plane_state->src_h != plane_state->dest_h << 16) { plane_state->src_h != plane_state->dest_h << 16) {
drm_debug(b, "\t\t\t\t[%s] not assigning view %p to %s plane " drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane "
"(positioning requires cropping or scaling)\n", "(positioning requires cropping or scaling)\n", ev);
p_name, ev, p_name);
goto err; goto err;
} }
@ -371,7 +340,7 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]); drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]);
if (needs_update) { if (needs_update) {
drm_debug(b, "\t\t\t\t[%s] copying new content to cursor BO\n", p_name); drm_debug(b, "\t\t\t\t[cursor] copying new content to cursor BO\n");
cursor_bo_update(plane_state, ev); cursor_bo_update(plane_state, ev);
} }
@ -384,8 +353,8 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
plane_state->dest_w = b->cursor_width; plane_state->dest_w = b->cursor_width;
plane_state->dest_h = b->cursor_height; plane_state->dest_h = b->cursor_height;
drm_debug(b, "\t\t\t\t[%s] provisionally assigned view %p to cursor\n", drm_debug(b, "\t\t\t\t[cursor] provisionally assigned view %p to cursor\n",
p_name, ev); ev);
return plane_state; return plane_state;
@ -396,7 +365,7 @@ err:
#else #else
static struct drm_plane_state * static struct drm_plane_state *
drm_output_prepare_cursor_view(struct drm_output_state *output_state, drm_output_prepare_cursor_view(struct drm_output_state *output_state,
struct weston_view *ev, uint64_t zpos) struct weston_view *ev)
{ {
return NULL; return NULL;
} }
@ -405,14 +374,14 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
static struct drm_plane_state * static struct drm_plane_state *
drm_output_prepare_scanout_view(struct drm_output_state *output_state, drm_output_prepare_scanout_view(struct drm_output_state *output_state,
struct weston_view *ev, struct weston_view *ev,
enum drm_output_propose_state_mode mode, enum drm_output_propose_state_mode mode)
struct drm_fb *fb, uint64_t zpos)
{ {
struct drm_output *output = output_state->output; struct drm_output *output = output_state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor); struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_plane *scanout_plane = output->scanout_plane; struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_plane_state *state; struct drm_plane_state *state;
const char *p_name = drm_output_get_plane_type_name(scanout_plane); struct drm_fb *fb;
pixman_box32_t *extents;
assert(!b->sprites_are_broken); assert(!b->sprites_are_broken);
assert(b->atomic_modeset); assert(b->atomic_modeset);
@ -420,25 +389,23 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
/* Check the view spans exactly the output size, calculated in the /* Check the view spans exactly the output size, calculated in the
* logical co-ordinate space. */ * logical co-ordinate space. */
if (!weston_view_matches_output_entirely(ev, &output->base)) { extents = pixman_region32_extents(&ev->transform.boundingbox);
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: " if (extents->x1 != output->base.x ||
" view does not match output entirely\n", extents->y1 != output->base.y ||
p_name, ev, p_name); extents->x2 != output->base.x + output->base.width ||
extents->y2 != output->base.y + output->base.height)
return NULL; return NULL;
}
/* If the surface buffer has an in-fence fd, but the plane doesn't /* If the surface buffer has an in-fence fd, but the plane doesn't
* support fences, we can't place the buffer on this plane. */ * support fences, we can't place the buffer on this plane. */
if (ev->surface->acquire_fence_fd >= 0 && if (ev->surface->acquire_fence_fd >= 0 &&
scanout_plane->props[WDRM_PLANE_IN_FENCE_FD].prop_id == 0) { scanout_plane->props[WDRM_PLANE_IN_FENCE_FD].prop_id == 0)
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
"no in-fence support\n", p_name, ev, p_name);
return NULL; return NULL;
}
fb = drm_fb_get_from_view(output_state, ev);
if (!fb) { if (!fb) {
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: " drm_debug(b, "\t\t\t\t[scanout] not placing view %p on scanout: "
" couldn't get fb\n", p_name, ev, p_name); " couldn't get fb\n", ev);
return NULL; return NULL;
} }
@ -450,24 +417,16 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
* and in the latter case, the view must have been marked as occluded, * and in the latter case, the view must have been marked as occluded,
* meaning we should never have ended up here. */ * meaning we should never have ended up here. */
assert(!state->fb); assert(!state->fb);
state->fb = fb;
/* take another reference here to live within the state */
state->fb = drm_fb_ref(fb);
state->ev = ev; state->ev = ev;
state->output = output; state->output = output;
if (!drm_plane_state_coords_for_view(state, ev, zpos)) { if (!drm_plane_state_coords_for_view(state, ev))
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
"unsuitable transform\n", p_name, ev, p_name);
goto err; goto err;
}
if (state->dest_x != 0 || state->dest_y != 0 || if (state->dest_x != 0 || state->dest_y != 0 ||
state->dest_w != (unsigned) output->base.current_mode->width || state->dest_w != (unsigned) output->base.current_mode->width ||
state->dest_h != (unsigned) output->base.current_mode->height) { state->dest_h != (unsigned) output->base.current_mode->height)
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
" invalid plane state\n", p_name, ev, p_name);
goto err; goto err;
}
state->in_fence_fd = ev->surface->acquire_fence_fd; state->in_fence_fd = ev->surface->acquire_fence_fd;
@ -480,252 +439,6 @@ err:
return NULL; return NULL;
} }
static bool
drm_output_plane_view_has_valid_format(struct drm_plane *plane,
struct drm_output_state *state,
struct weston_view *ev,
struct drm_fb *fb)
{
/* depending on the type of the plane we have different requirements */
switch (plane->type) {
case WDRM_PLANE_TYPE_CURSOR:
return drm_output_plane_cursor_has_valid_format(ev);
case WDRM_PLANE_TYPE_OVERLAY:
return drm_output_plane_has_valid_format(plane, state, fb);
case WDRM_PLANE_TYPE_PRIMARY:
return drm_output_plane_has_valid_format(plane, state, fb);
default:
assert(0);
return false;
}
return false;
}
static struct drm_plane_state *
drm_output_try_view_on_plane(struct drm_plane *plane,
struct drm_output_state *state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode,
struct drm_fb *fb, uint64_t zpos)
{
struct drm_backend *b = state->pending_state->backend;
struct weston_output *wet_output = &state->output->base;
bool view_matches_entire_output, scanout_has_view_assigned;
struct drm_plane *scanout_plane = state->output->scanout_plane;
struct drm_plane_state *ps = NULL;
const char *p_name = drm_output_get_plane_type_name(plane);
enum {
NO_PLANES, /* generic err-handle */
NO_PLANES_ACCEPTED,
PLACED_ON_PLANE,
} availability = NO_PLANES;
/* sanity checks in case we over/underflow zpos or pass incorrect
* values */
assert(zpos <= plane->zpos_max ||
zpos != DRM_PLANE_ZPOS_INVALID_PLANE);
switch (plane->type) {
case WDRM_PLANE_TYPE_CURSOR:
if (b->cursors_are_broken) {
availability = NO_PLANES_ACCEPTED;
goto out;
}
ps = drm_output_prepare_cursor_view(state, ev, zpos);
if (ps)
availability = PLACED_ON_PLANE;
break;
case WDRM_PLANE_TYPE_OVERLAY:
/* do not attempt to place it in the overlay if we don't have
* anything in the scanout/primary and the view doesn't cover
* the entire output */
view_matches_entire_output =
weston_view_matches_output_entirely(ev, wet_output);
scanout_has_view_assigned =
drm_output_check_plane_has_view_assigned(scanout_plane,
state);
if (view_matches_entire_output && !scanout_has_view_assigned) {
availability = NO_PLANES_ACCEPTED;
goto out;
}
ps = drm_output_prepare_overlay_view(plane, state, ev, mode,
fb, zpos);
if (ps)
availability = PLACED_ON_PLANE;
break;
case WDRM_PLANE_TYPE_PRIMARY:
if (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) {
availability = NO_PLANES_ACCEPTED;
goto out;
}
ps = drm_output_prepare_scanout_view(state, ev, mode,
fb, zpos);
if (ps)
availability = PLACED_ON_PLANE;
break;
default:
assert(0);
break;
}
out:
switch (availability) {
case NO_PLANES:
/* set initial to this catch-all case, such that
* prepare_cursor/overlay/scanout() should have/contain the
* reason for failling */
break;
case NO_PLANES_ACCEPTED:
drm_debug(b, "\t\t\t\t[plane] plane %d refusing to "
"place view %p in %s\n",
plane->plane_id, ev, p_name);
break;
case PLACED_ON_PLANE:
break;
}
return ps;
}
static int
drm_output_check_zpos_plane_states(struct drm_output_state *state)
{
struct drm_backend *b = state->pending_state->backend;
struct drm_plane_state *ps;
int ret = 0;
wl_list_for_each(ps, &state->plane_list, link) {
struct wl_list *next_node = ps->link.next;
bool found_dup = false;
/* find another plane with the same zpos value */
if (next_node == &state->plane_list)
break;
while (next_node && next_node != &state->plane_list) {
struct drm_plane_state *ps_next;
ps_next = container_of(next_node,
struct drm_plane_state,
link);
if (ps->zpos == ps_next->zpos) {
found_dup = true;
break;
}
next_node = next_node->next;
}
if (found_dup) {
ret = 1;
drm_debug(b, "\t\t\t[plane] found duplicate zpos values\n");
break;
}
}
return ret;
}
static struct drm_plane_state *
drm_output_prepare_plane_view(struct drm_output_state *state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode,
uint64_t current_lowest_zpos)
{
struct drm_output *output = state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_plane_state *ps = NULL;
struct drm_plane *plane;
struct drm_plane_zpos *p_zpos, *p_zpos_next;
struct wl_list zpos_candidate_list;
struct drm_fb *fb;
wl_list_init(&zpos_candidate_list);
/* check view for valid buffer, doesn't make sense to even try */
if (!weston_view_has_valid_buffer(ev))
return ps;
fb = drm_fb_get_from_view(state, ev);
/* assemble a list with possible candidates */
wl_list_for_each(plane, &b->plane_list, link) {
if (!drm_plane_is_available(plane, output))
continue;
if (drm_output_check_plane_has_view_assigned(plane, state)) {
drm_debug(b, "\t\t\t\t[plane] not adding plane %d to"
" candidate list: view already assigned "
"to a plane\n", plane->plane_id);
continue;
}
if (plane->zpos_min >= current_lowest_zpos) {
drm_debug(b, "\t\t\t\t[plane] not adding plane %d to "
"candidate list: minium zpos (%"PRIu64") "
"plane's above current lowest zpos "
"(%"PRIu64")\n", plane->plane_id,
plane->zpos_min, current_lowest_zpos);
continue;
}
if (!drm_output_plane_view_has_valid_format(plane, state, ev, fb)) {
drm_debug(b, "\t\t\t\t[plane] not adding plane %d to "
"candidate list: invalid pixel format\n",
plane->plane_id);
continue;
}
drm_output_add_zpos_plane(plane, &zpos_candidate_list);
}
/* go over the potential candidate list and try to find a possible
* plane suitable for \c ev; start with the highest zpos value of a
* plane to maximize our chances, but do note we pass the zpos value
* based on current tracked value by \c current_lowest_zpos_in_use */
while (!wl_list_empty(&zpos_candidate_list)) {
struct drm_plane_zpos *head_p_zpos =
wl_container_of(zpos_candidate_list.next,
head_p_zpos, link);
struct drm_plane *plane = head_p_zpos->plane;
const char *p_name = drm_output_get_plane_type_name(plane);
uint64_t zpos;
if (current_lowest_zpos == DRM_PLANE_ZPOS_INVALID_PLANE)
zpos = plane->zpos_max;
else
zpos = MIN(current_lowest_zpos - 1, plane->zpos_max);
drm_debug(b, "\t\t\t\t[plane] plane %d picked "
"from candidate list, type: %s\n",
plane->plane_id, p_name);
ps = drm_output_try_view_on_plane(plane, state, ev,
mode, fb, zpos);
drm_output_destroy_zpos_plane(head_p_zpos);
if (ps) {
drm_debug(b, "\t\t\t\t[view] view %p has been placed to "
"%s plane with computed zpos %"PRIu64"\n",
ev, p_name, zpos);
break;
}
}
wl_list_for_each_safe(p_zpos, p_zpos_next, &zpos_candidate_list, link)
drm_output_destroy_zpos_plane(p_zpos);
drm_fb_unref(fb);
return ps;
}
static struct drm_output_state * static struct drm_output_state *
drm_output_propose_state(struct weston_output *output_base, drm_output_propose_state(struct weston_output *output_base,
struct drm_pending_state *pending_state, struct drm_pending_state *pending_state,
@ -736,13 +449,10 @@ drm_output_propose_state(struct weston_output *output_base,
struct drm_output_state *state; struct drm_output_state *state;
struct drm_plane_state *scanout_state = NULL; struct drm_plane_state *scanout_state = NULL;
struct weston_view *ev; struct weston_view *ev;
pixman_region32_t surface_overlap, renderer_region, occluded_region;
pixman_region32_t surface_overlap, renderer_region, planes_region; bool planes_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY);
pixman_region32_t occluded_region;
bool renderer_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY); bool renderer_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY);
int ret; int ret;
uint64_t current_lowest_zpos = DRM_PLANE_ZPOS_INVALID_PLANE;
assert(!output->state_last); assert(!output->state_last);
state = drm_output_state_duplicate(output->state_cur, state = drm_output_state_duplicate(output->state_cur,
@ -792,19 +502,20 @@ drm_output_propose_state(struct weston_output *output_base,
(unsigned long) output->base.id); (unsigned long) output->base.id);
} }
/* - renderer_region contains the total region which which will be /*
* covered by the renderer * Find a surface for each sprite in the output using some heuristics:
* - planes_region contains the total region which has been covered by * 1) size
* hardware planes * 2) frequency of update
* - occluded_region contains the total region which which will be * 3) opacity (though some hw might support alpha blending)
* covered by the renderer and hardware planes, where the view's * 4) clipping (this can be fixed with color keys)
* visible-and-opaque region is added in both cases (the view's *
* opaque region accumulates there for each view); it is being used * The idea is to save on blitting since this should save power.
* to skip the view, if it is completely occluded; includes the * If we can get a large video surface on the sprite for example,
* situation where occluded_region covers entire output's region. * the main display surface may not need to update at all, and
* the client buffer can be used directly for the sprite surface
* as we do for flipping full screen surfaces.
*/ */
pixman_region32_init(&renderer_region); pixman_region32_init(&renderer_region);
pixman_region32_init(&planes_region);
pixman_region32_init(&occluded_region); pixman_region32_init(&occluded_region);
wl_list_for_each(ev, &output_base->compositor->view_list, link) { wl_list_for_each(ev, &output_base->compositor->view_list, link) {
@ -812,6 +523,7 @@ drm_output_propose_state(struct weston_output *output_base,
bool force_renderer = false; bool force_renderer = false;
pixman_region32_t clipped_view; pixman_region32_t clipped_view;
bool totally_occluded = false; bool totally_occluded = false;
bool overlay_occluded = false;
drm_debug(b, "\t\t\t[view] evaluating view %p for " drm_debug(b, "\t\t\t[view] evaluating view %p for "
"output %s (%lu)\n", "output %s (%lu)\n",
@ -834,7 +546,7 @@ drm_output_propose_state(struct weston_output *output_base,
force_renderer = true; force_renderer = true;
} }
if (!weston_view_has_valid_buffer(ev)) { if (!ev->surface->buffer_ref.buffer) {
drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane "
"(no buffer available)\n", ev); "(no buffer available)\n", ev);
force_renderer = true; force_renderer = true;
@ -849,9 +561,6 @@ drm_output_propose_state(struct weston_output *output_base,
pixman_region32_init(&surface_overlap); pixman_region32_init(&surface_overlap);
pixman_region32_subtract(&surface_overlap, &clipped_view, pixman_region32_subtract(&surface_overlap, &clipped_view,
&occluded_region); &occluded_region);
/* if the view is completely occluded then ignore that
* view; includes the case where occluded_region covers
* the entire output */
totally_occluded = !pixman_region32_not_empty(&surface_overlap); totally_occluded = !pixman_region32_not_empty(&surface_overlap);
if (totally_occluded) { if (totally_occluded) {
drm_debug(b, "\t\t\t\t[view] ignoring view %p " drm_debug(b, "\t\t\t\t[view] ignoring view %p "
@ -871,7 +580,6 @@ drm_output_propose_state(struct weston_output *output_base,
"(occluded by renderer views)\n", ev); "(occluded by renderer views)\n", ev);
force_renderer = true; force_renderer = true;
} }
pixman_region32_fini(&surface_overlap);
/* In case of enforced mode of content-protection do not /* In case of enforced mode of content-protection do not
* assign planes for a protected surface on an unsecured output. * assign planes for a protected surface on an unsecured output.
@ -883,18 +591,51 @@ drm_output_propose_state(struct weston_output *output_base,
force_renderer = true; force_renderer = true;
} }
if (!force_renderer) { /* We do not control the stacking order of overlay planes;
drm_debug(b, "\t\t\t[plane] started with zpos %"PRIu64"\n", * the scanout plane is strictly stacked bottom and the cursor
current_lowest_zpos); * plane top, but the ordering of overlay planes with respect
ps = drm_output_prepare_plane_view(state, ev, mode, * to each other is undefined. Make sure we do not have two
current_lowest_zpos); * planes overlapping each other. */
pixman_region32_intersect(&surface_overlap, &occluded_region,
&clipped_view);
if (pixman_region32_not_empty(&surface_overlap)) {
drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane "
"(occluded by other overlay planes)\n", ev);
overlay_occluded = true;
} }
pixman_region32_fini(&surface_overlap);
if (ps) { /* The cursor plane is 'special' in the sense that we can still
current_lowest_zpos = ps->zpos; * place it in the legacy API, and we gate that with a separate
drm_debug(b, "\t\t\t[plane] next zpos to use %"PRIu64"\n", * cursors_are_broken flag. */
current_lowest_zpos); if (!force_renderer && !overlay_occluded && !b->cursors_are_broken)
ps = drm_output_prepare_cursor_view(state, ev);
/* If sprites are disabled or the view is not fully opaque, we
* must put the view into the renderer - unless it has already
* been placed in the cursor plane, which can handle alpha. */
if (!ps && !planes_ok) {
drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane "
"(precluded by mode)\n", ev);
force_renderer = true;
}
if (!ps && !weston_view_is_opaque(ev, &clipped_view)) {
drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane "
"(view not fully opaque)\n", ev);
force_renderer = true;
}
/* Only try to place scanout surfaces in planes-only mode; in
* mixed mode, we have already failed to place a view on the
* scanout surface, forcing usage of the renderer on the
* scanout plane. */
if (!ps && !force_renderer && !renderer_ok)
ps = drm_output_prepare_scanout_view(state, ev, mode);
if (!ps && !overlay_occluded && !force_renderer)
ps = drm_output_prepare_overlay_view(state, ev, mode);
if (ps) {
/* If we have been assigned to an overlay or scanout /* If we have been assigned to an overlay or scanout
* plane, add this area to the occluded region, so * plane, add this area to the occluded region, so
* other views are known to be behind it. The cursor * other views are known to be behind it. The cursor
@ -903,22 +644,10 @@ drm_output_propose_state(struct weston_output *output_base,
* be added to the renderer region nor the occluded * be added to the renderer region nor the occluded
* region. */ * region. */
if (ps->plane->type != WDRM_PLANE_TYPE_CURSOR) { if (ps->plane->type != WDRM_PLANE_TYPE_CURSOR) {
pixman_region32_union(&planes_region,
&planes_region,
&clipped_view);
if (!weston_view_is_opaque(ev, &clipped_view))
pixman_region32_intersect(&clipped_view,
&clipped_view,
&ev->transform.opaque);
/* the visible-and-opaque region of this view
* will occlude views underneath it */
pixman_region32_union(&occluded_region, pixman_region32_union(&occluded_region,
&occluded_region, &occluded_region,
&clipped_view); &clipped_view);
pixman_region32_fini(&clipped_view); pixman_region32_fini(&clipped_view);
} }
continue; continue;
} }
@ -937,24 +666,9 @@ drm_output_propose_state(struct weston_output *output_base,
pixman_region32_union(&renderer_region, pixman_region32_union(&renderer_region,
&renderer_region, &renderer_region,
&clipped_view); &clipped_view);
if (!weston_view_is_opaque(ev, &clipped_view))
pixman_region32_intersect(&clipped_view,
&clipped_view,
&ev->transform.opaque);
pixman_region32_union(&occluded_region,
&occluded_region,
&clipped_view);
pixman_region32_fini(&clipped_view); pixman_region32_fini(&clipped_view);
drm_debug(b, "\t\t\t\t[view] view %p will be placed "
"on the renderer\n", ev);
} }
pixman_region32_fini(&renderer_region); pixman_region32_fini(&renderer_region);
pixman_region32_fini(&planes_region);
pixman_region32_fini(&occluded_region); pixman_region32_fini(&occluded_region);
/* In renderer-only mode, we can't test the state as we don't have a /* In renderer-only mode, we can't test the state as we don't have a
@ -962,14 +676,6 @@ drm_output_propose_state(struct weston_output *output_base,
if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY) if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY)
return state; return state;
/* check if we have invalid zpos values, like duplicate(s) */
ret = drm_output_check_zpos_plane_states(state);
if (ret != 0) {
drm_debug(b, "\t\t[view] failing state generation: "
"zpos values are in-consistent\n");
goto err;
}
/* Check to see if this state will actually work. */ /* Check to see if this state will actually work. */
ret = drm_pending_state_test(state->pending_state); ret = drm_pending_state_test(state->pending_state);
if (ret != 0) { if (ret != 0) {
@ -1058,7 +764,7 @@ drm_assign_planes(struct weston_output *output_base, void *repaint_data)
* to the buffer anyway, there is no side effects. * to the buffer anyway, there is no side effects.
*/ */
if (b->use_pixman || if (b->use_pixman ||
(weston_view_has_valid_buffer(ev) && (ev->surface->buffer_ref.buffer &&
(!wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) || (!wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) ||
(ev->surface->width <= b->cursor_width && (ev->surface->width <= b->cursor_width &&
ev->surface->height <= b->cursor_height)))) ev->surface->height <= b->cursor_height))))

@ -1852,41 +1852,6 @@ weston_view_is_opaque(struct weston_view *ev, pixman_region32_t *region)
return ret; return ret;
} }
/** Check if the view has a valid buffer available
*
* @param ev The view to check if it has a valid buffer.
*
* Returns true if the view has a valid buffer or false otherwise.
*/
WL_EXPORT bool
weston_view_has_valid_buffer(struct weston_view *ev)
{
return ev->surface->buffer_ref.buffer != NULL;
}
/** Check if the view matches the entire output
*
* @param ev The view to check.
* @param output The output to check against.
*
* Returns true if the view does indeed matches the entire output.
*/
WL_EXPORT bool
weston_view_matches_output_entirely(struct weston_view *ev,
struct weston_output *output)
{
pixman_box32_t *extents =
pixman_region32_extents(&ev->transform.boundingbox);
if (extents->x1 != output->x ||
extents->y1 != output->y ||
extents->x2 != output->x + output->width ||
extents->y2 != output->y + output->height)
return false;
return true;
}
/* Check if a surface has a view assigned to it /* Check if a surface has a view assigned to it
* *
* The indicator is set manually when mapping * The indicator is set manually when mapping

@ -287,12 +287,6 @@ weston_view_from_global_float(struct weston_view *view,
bool bool
weston_view_is_opaque(struct weston_view *ev, pixman_region32_t *region); weston_view_is_opaque(struct weston_view *ev, pixman_region32_t *region);
bool
weston_view_has_valid_buffer(struct weston_view *ev);
bool
weston_view_matches_output_entirely(struct weston_view *ev,
struct weston_output *output);
void void
weston_view_move_to_plane(struct weston_view *view, weston_view_move_to_plane(struct weston_view *view,
struct weston_plane *plane); struct weston_plane *plane);

Loading…
Cancel
Save