diff --git a/libweston/backend-drm/drm-gbm.c b/libweston/backend-drm/drm-gbm.c index 25a9cf858..f3caa035e 100644 --- a/libweston/backend-drm/drm-gbm.c +++ b/libweston/backend-drm/drm-gbm.c @@ -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; diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index 24ef662c4..1eceecdc5 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -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); diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 18a06a5f2..d68e38db4 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -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", diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c index 996ca5e16..9d3a41d2d 100644 --- a/libweston/backend-drm/state-propose.c +++ b/libweston/backend-drm/state-propose.c @@ -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 {