mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-03-21 14:30:35 +01:00
drm: Make underlay/overlay per output
Now that we have per output plane lists, we can make the overlay/underlay subtype be part of the plane handle, and make the has_underlay property part of the output. This fixes bugs on platforms where not all CRTCs have the same minimum zpos, and underlays can be broken for all outputs because one output doesn't have any. Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
parent
6527c586d3
commit
bbcd7d005b
4 changed files with 65 additions and 52 deletions
|
|
@ -445,7 +445,7 @@ drm_output_pick_format_egl(struct drm_output *output)
|
|||
}
|
||||
|
||||
if (min_bpc != 0) {
|
||||
if (b->has_underlay) {
|
||||
if (output->has_underlay) {
|
||||
output->format =
|
||||
find_compatible_format(compositor, &supported_formats,
|
||||
min_bpc, component_type,
|
||||
|
|
@ -456,7 +456,7 @@ drm_output_pick_format_egl(struct drm_output *output)
|
|||
weston_log("Disabling underlay planes: EGL GBM or the primary plane for output '%s'\n" \
|
||||
"does not support format with min bpc %u and alpha channel.\n",
|
||||
output->base.name, min_bpc);
|
||||
b->has_underlay = false;
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
output->format =
|
||||
|
|
@ -486,11 +486,11 @@ drm_output_pick_format_egl(struct drm_output *output)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (b->has_underlay && (b->format->bits.a == 0)) {
|
||||
if (output->has_underlay && (b->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: b->format %s does not have alpha channel,\n"
|
||||
"which is required to support underlay planes.\n",
|
||||
b->format->drm_format_name);
|
||||
b->has_underlay = false;
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
output->format = b->format;
|
||||
|
|
@ -513,7 +513,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
|||
return -1;
|
||||
|
||||
format[0] = output->format;
|
||||
if (!b->has_underlay)
|
||||
if (!output->has_underlay)
|
||||
format[1] = fallback_format_for(output->format);
|
||||
|
||||
options.formats = format;
|
||||
|
|
@ -703,11 +703,11 @@ drm_output_pick_format_vulkan(struct drm_output *output)
|
|||
assert(b->format);
|
||||
output->format = b->format;
|
||||
|
||||
if (b->has_underlay && (output->format->bits.a == 0)) {
|
||||
if (output->has_underlay && (output->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: output '%s' with format %s does not have alpha channel,\n"
|
||||
"which is required to support underlay planes.\n",
|
||||
output->base.name, output->format->drm_format_name);
|
||||
b->has_underlay = false;
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -266,9 +266,6 @@ struct drm_backend {
|
|||
|
||||
uint32_t pageflip_timeout;
|
||||
|
||||
/* True, if underlay planes exist. */
|
||||
bool has_underlay;
|
||||
|
||||
struct weston_log_scope *debug;
|
||||
|
||||
struct {
|
||||
|
|
@ -448,8 +445,6 @@ struct drm_plane {
|
|||
struct drm_device *device;
|
||||
|
||||
enum wdrm_plane_type type;
|
||||
/* Whether this plane supports overlay, underlay, or both */
|
||||
enum drm_plane_subtype subtype;
|
||||
|
||||
uint32_t possible_crtcs;
|
||||
uint32_t plane_id;
|
||||
|
|
@ -476,6 +471,9 @@ struct drm_plane_handle {
|
|||
struct drm_output *output;
|
||||
struct drm_plane *plane;
|
||||
|
||||
/* Whether this plane supports overlay, underlay, or both */
|
||||
enum drm_plane_subtype subtype;
|
||||
|
||||
struct wl_list link; /* drm_output::plane_handle_list */
|
||||
};
|
||||
|
||||
|
|
@ -604,6 +602,9 @@ struct drm_output {
|
|||
/* List of hardware planes this output can use */
|
||||
struct wl_list plane_handle_list;
|
||||
|
||||
/* True, if underlay planes exist. */
|
||||
bool has_underlay;
|
||||
|
||||
uint32_t gbm_cursor_handle[2];
|
||||
struct drm_fb *gbm_cursor_fb[2];
|
||||
struct drm_plane_handle *cursor_handle;
|
||||
|
|
@ -727,24 +728,29 @@ to_drm_mode(struct weston_mode *base)
|
|||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_plane_type_name(struct drm_plane *p)
|
||||
drm_output_get_plane_type_name_internal(struct drm_plane *p, struct drm_plane_handle *h)
|
||||
{
|
||||
assert(!p || !h);
|
||||
|
||||
if (h)
|
||||
p = h->plane;
|
||||
|
||||
switch (p->type) {
|
||||
case WDRM_PLANE_TYPE_PRIMARY:
|
||||
return "primary";
|
||||
case WDRM_PLANE_TYPE_CURSOR:
|
||||
return "cursor";
|
||||
case WDRM_PLANE_TYPE_OVERLAY:
|
||||
switch (p->subtype) {
|
||||
if (!h)
|
||||
return "overlay(no subtype)";
|
||||
|
||||
switch (h->subtype) {
|
||||
case PLANE_SUBTYPE_OVERLAY_ONLY:
|
||||
return "overlay";
|
||||
case PLANE_SUBTYPE_UNDERLAY_ONLY:
|
||||
return "underlay";
|
||||
case PLANE_SUBTYPE_BOTH:
|
||||
return "over/underlay";
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
|
|
@ -753,6 +759,18 @@ drm_output_get_plane_type_name(struct drm_plane *p)
|
|||
}
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_plane_type_name(struct drm_plane *p)
|
||||
{
|
||||
return drm_output_get_plane_type_name_internal(p, NULL);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_handle_type_name(struct drm_plane_handle *h)
|
||||
{
|
||||
return drm_output_get_plane_type_name_internal(NULL, h);
|
||||
}
|
||||
|
||||
struct drm_crtc *
|
||||
drm_crtc_find(struct drm_device *device, uint32_t crtc_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -1574,13 +1574,12 @@ drm_plane_create_handle(struct drm_plane *plane, struct drm_output *output)
|
|||
static void
|
||||
create_sprites(struct drm_device *device)
|
||||
{
|
||||
struct drm_backend *b = device->backend;
|
||||
drmModePlaneRes *kplane_res;
|
||||
drmModePlane *kplane;
|
||||
struct drm_plane *drm_plane;
|
||||
uint32_t i;
|
||||
uint32_t next_plane_idx = 0;
|
||||
uint64_t primary_plane_zpos_min = DRM_PLANE_ZPOS_INVALID_PLANE;
|
||||
|
||||
kplane_res = drmModeGetPlaneResources(device->kms_device->fd);
|
||||
|
||||
if (!kplane_res) {
|
||||
|
|
@ -1596,35 +1595,11 @@ create_sprites(struct drm_device *device)
|
|||
|
||||
drm_plane = drm_plane_create(device, kplane);
|
||||
drmModeFreePlane(kplane);
|
||||
if (!drm_plane)
|
||||
continue;
|
||||
|
||||
if (drm_plane->type == WDRM_PLANE_TYPE_PRIMARY)
|
||||
primary_plane_zpos_min = drm_plane->zpos_min;
|
||||
}
|
||||
|
||||
wl_list_for_each (drm_plane, &device->plane_list, link) {
|
||||
wl_list_for_each (drm_plane, &device->plane_list, link)
|
||||
drm_plane->plane_idx = next_plane_idx++;
|
||||
|
||||
if (primary_plane_zpos_min == DRM_PLANE_ZPOS_INVALID_PLANE ||
|
||||
drm_plane->zpos_max == DRM_PLANE_ZPOS_INVALID_PLANE ||
|
||||
drm_plane->zpos_min == DRM_PLANE_ZPOS_INVALID_PLANE)
|
||||
continue;
|
||||
|
||||
if (drm_plane->zpos_min < primary_plane_zpos_min &&
|
||||
drm_plane->zpos_max >= primary_plane_zpos_min) {
|
||||
drm_plane->subtype = PLANE_SUBTYPE_BOTH;
|
||||
b->has_underlay = true;
|
||||
} else if (drm_plane->zpos_min < primary_plane_zpos_min &&
|
||||
drm_plane->zpos_max < primary_plane_zpos_min) {
|
||||
drm_plane->subtype = PLANE_SUBTYPE_UNDERLAY_ONLY;
|
||||
b->has_underlay = true;
|
||||
} else {
|
||||
drm_plane->subtype = PLANE_SUBTYPE_OVERLAY_ONLY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
drmModeFreePlaneResources(kplane_res);
|
||||
}
|
||||
|
||||
|
|
@ -1895,12 +1870,12 @@ drm_output_pick_format_pixman(struct drm_output *output)
|
|||
|
||||
output->format = b->format;
|
||||
|
||||
if (b->has_underlay && (output->format->bits.a == 0)) {
|
||||
if (output->has_underlay && (output->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: "
|
||||
"output '%s' with format %s does not have alpha channel, "
|
||||
"which is required to support underlay planes.\n",
|
||||
output->base.name, output->format->drm_format_name);
|
||||
b->has_underlay = false;
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -2582,6 +2557,8 @@ drm_output_init_planes(struct drm_output *output)
|
|||
{
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_plane *plane, *scanout_plane, *cursor_plane;
|
||||
struct drm_plane_handle *handle;
|
||||
uint64_t primary_plane_zpos_min;
|
||||
|
||||
scanout_plane = drm_output_find_special_plane(device, output,
|
||||
WDRM_PLANE_TYPE_PRIMARY);
|
||||
|
|
@ -2590,6 +2567,7 @@ drm_output_init_planes(struct drm_output *output)
|
|||
output->base.name);
|
||||
return -1;
|
||||
}
|
||||
primary_plane_zpos_min = scanout_plane->zpos_min;
|
||||
|
||||
/* Failing to find a cursor plane is not fatal, as we'll fall back
|
||||
* to software cursor. */
|
||||
|
|
@ -2614,6 +2592,24 @@ drm_output_init_planes(struct drm_output *output)
|
|||
assert(output->scanout_handle);
|
||||
assert(!cursor_plane || output->cursor_handle);
|
||||
|
||||
output->has_underlay = false;
|
||||
wl_list_for_each(handle, &output->plane_handle_list, link) {
|
||||
plane = handle->plane;
|
||||
|
||||
if (plane->zpos_min < primary_plane_zpos_min &&
|
||||
plane->zpos_max >= primary_plane_zpos_min) {
|
||||
handle->subtype = PLANE_SUBTYPE_BOTH;
|
||||
output->has_underlay = true;
|
||||
} else if (plane->zpos_min < primary_plane_zpos_min &&
|
||||
plane->zpos_max < primary_plane_zpos_min) {
|
||||
handle->subtype = PLANE_SUBTYPE_UNDERLAY_ONLY;
|
||||
output->has_underlay = true;
|
||||
} else {
|
||||
handle->subtype = PLANE_SUBTYPE_OVERLAY_ONLY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4620,7 +4616,6 @@ drm_backend_create(struct weston_compositor *compositor,
|
|||
b->pageflip_timeout = config->pageflip_timeout;
|
||||
b->use_pixman_shadow = config->use_pixman_shadow;
|
||||
b->offload_blend_to_output = config->offload_blend_to_output;
|
||||
b->has_underlay = false;
|
||||
|
||||
b->debug = weston_compositor_add_log_scope(compositor, "drm-backend",
|
||||
"Debug messages from DRM/KMS backend\n",
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ drm_output_prepare_cursor_paint_node(struct drm_output_state *output_state,
|
|||
assert(!plane->state_cur->handle ||
|
||||
plane->state_cur->handle->output == output);
|
||||
|
||||
p_name = drm_output_get_plane_type_name(plane);
|
||||
p_name = drm_output_get_handle_type_name(handle);
|
||||
|
||||
/* We use GBM to import SHM buffers. */
|
||||
assert(b->gbm);
|
||||
|
|
@ -662,7 +662,7 @@ drm_output_find_plane_for_view(struct drm_output_state *state,
|
|||
/* assemble a list with possible candidates */
|
||||
wl_list_for_each(handle, &output->plane_handle_list, link) {
|
||||
struct drm_plane *plane = handle->plane;
|
||||
const char *p_name = drm_output_get_plane_type_name(plane);
|
||||
const char *p_name = drm_output_get_handle_type_name(handle);
|
||||
uint64_t zpos;
|
||||
bool mm_underlay_only = false;
|
||||
|
||||
|
|
@ -753,7 +753,7 @@ drm_output_find_plane_for_view(struct drm_output_state *state,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!b->has_underlay && mm_underlay_only) {
|
||||
if (!output->has_underlay && mm_underlay_only) {
|
||||
drm_debug(b, "\t\t\t\t[plane] not adding plane %d to "
|
||||
"candidate list: plane is below the primary "
|
||||
"plane and backend format (%s) is opaque, "
|
||||
|
|
@ -1126,7 +1126,7 @@ drm_output_propose_state(struct weston_output *output_base,
|
|||
pixman_region32_intersect(&tmp, &renderer_region,
|
||||
&pnode->clipped_view);
|
||||
if (pixman_region32_not_empty(&tmp)) {
|
||||
if (b->has_underlay) {
|
||||
if (output->has_underlay) {
|
||||
need_underlay = true;
|
||||
} else {
|
||||
pnode->try_view_on_plane_failure_reasons |=
|
||||
|
|
@ -1385,7 +1385,7 @@ drm_assign_planes(struct weston_output *output_base)
|
|||
if (target_plane) {
|
||||
drm_debug(b, "\t[repaint] view %s on %s plane %lu\n",
|
||||
ev->internal_name,
|
||||
drm_output_get_plane_type_name(target_plane),
|
||||
drm_output_get_handle_type_name(target_handle),
|
||||
(unsigned long) target_plane->plane_id);
|
||||
weston_paint_node_move_to_plane(pnode, &target_plane->base);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue