mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-20 04:40:07 +01:00
Merge branch 'drm-offload-background-color' into 'main'
Draft: backend-drm: Add support for the BACKGROUND_COLOR CRTC property See merge request wayland/weston!1845
This commit is contained in:
commit
8584e65e15
6 changed files with 82 additions and 17 deletions
|
|
@ -562,6 +562,8 @@ struct drm_crtc {
|
|||
|
||||
/* CRTC prop WDRM_CRTC_GAMMA_LUT_SIZE */
|
||||
uint32_t lut_size;
|
||||
|
||||
uint64_t background_color;
|
||||
};
|
||||
|
||||
struct drm_output {
|
||||
|
|
@ -725,6 +727,9 @@ drm_output_get_plane_type_name(struct drm_plane *p)
|
|||
struct drm_crtc *
|
||||
drm_crtc_find(struct drm_device *device, uint32_t crtc_id);
|
||||
|
||||
bool
|
||||
drm_crtc_supports_background_color(struct drm_crtc *crtc);
|
||||
|
||||
struct drm_head *
|
||||
drm_head_find_by_connector(struct drm_backend *backend, struct drm_device *device, uint32_t connector_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -197,5 +197,6 @@ enum wdrm_crtc_property {
|
|||
WDRM_CRTC_GAMMA_LUT,
|
||||
WDRM_CRTC_GAMMA_LUT_SIZE,
|
||||
WDRM_CRTC_VRR_ENABLED,
|
||||
WDRM_CRTC_BACKGROUND_COLOR,
|
||||
WDRM_CRTC__COUNT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2437,6 +2437,10 @@ drm_crtc_create(struct drm_device *device, uint32_t crtc_id, uint32_t pipe)
|
|||
drm_property_get_value(&crtc->props_crtc[WDRM_CRTC_GAMMA_LUT_SIZE],
|
||||
props, 0);
|
||||
|
||||
crtc->background_color =
|
||||
drm_property_get_value(&crtc->props_crtc[WDRM_CRTC_BACKGROUND_COLOR],
|
||||
props, 0);
|
||||
|
||||
/* Add it to the last position of the DRM-backend CRTC list */
|
||||
wl_list_insert(device->crtc_list.prev, &crtc->link);
|
||||
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ const struct drm_property_info crtc_props[] = {
|
|||
[WDRM_CRTC_GAMMA_LUT] = { .name = "GAMMA_LUT", },
|
||||
[WDRM_CRTC_GAMMA_LUT_SIZE] = { .name = "GAMMA_LUT_SIZE", },
|
||||
[WDRM_CRTC_VRR_ENABLED] = { .name = "VRR_ENABLED", },
|
||||
[WDRM_CRTC_BACKGROUND_COLOR] = { .name = "BACKGROUND_COLOR", },
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1035,6 +1036,15 @@ crtc_add_prop_zero_ok(drmModeAtomicReq *req, struct drm_crtc *crtc,
|
|||
return crtc_add_prop(req, crtc, prop, val);
|
||||
}
|
||||
|
||||
bool
|
||||
drm_crtc_supports_background_color(struct drm_crtc *crtc)
|
||||
{
|
||||
if (crtc->props_crtc[WDRM_CRTC_BACKGROUND_COLOR].prop_id != 0)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
connector_add_prop(drmModeAtomicReq *req, struct drm_connector *connector,
|
||||
enum wdrm_connector_property prop, uint64_t val)
|
||||
|
|
@ -1334,6 +1344,21 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
|||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED,
|
||||
wdrm_vrr_enabled_from_output(output));
|
||||
|
||||
{
|
||||
struct drm_property_info *info = &crtc->props_crtc[WDRM_CRTC_BACKGROUND_COLOR];
|
||||
|
||||
if (info->prop_id == 0)
|
||||
drm_debug(b, "\t\t\t[CRTC:%lu] %lu (%s) -> %llu (0x%llx) (not supported by driver)\n",
|
||||
(unsigned long) crtc->crtc_id,
|
||||
(unsigned long) info->prop_id, info->name,
|
||||
(unsigned long long) crtc->background_color,
|
||||
(unsigned long long) crtc->background_color);
|
||||
else
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc,
|
||||
WDRM_CRTC_BACKGROUND_COLOR,
|
||||
crtc->background_color);
|
||||
}
|
||||
|
||||
/* No need for the DPMS property, since it is implicit in
|
||||
* routing and CRTC activity. */
|
||||
wl_list_for_each(head, &output->base.head_list, base.output_link) {
|
||||
|
|
|
|||
|
|
@ -794,13 +794,11 @@ drm_output_find_plane_for_view(struct drm_output_state *state,
|
|||
}
|
||||
|
||||
static bool
|
||||
is_paint_node_solid_opaque_black(struct weston_paint_node *pnode)
|
||||
is_paint_node_solid_opaque(struct weston_paint_node *pnode)
|
||||
{
|
||||
return pnode->draw_solid && pnode->is_fully_opaque &&
|
||||
pnode->valid_transform &&
|
||||
(pnode->surf_xform_valid && !pnode->surf_xform.transform) &&
|
||||
pnode->solid.r == 0.0f && pnode->solid.g == 0.0f &&
|
||||
pnode->solid.b == 0.0f;
|
||||
(pnode->surf_xform_valid && !pnode->surf_xform.transform);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -812,12 +810,15 @@ lower_solid_views_to_background_region(struct drm_output *output,
|
|||
struct drm_backend *b = device->backend;
|
||||
struct weston_paint_node **visible_pnode;
|
||||
struct wl_array visible_pnodes_new;
|
||||
struct weston_solid_buffer_values background_region_color = {0};
|
||||
|
||||
wl_array_init(&visible_pnodes_new);
|
||||
wl_array_for_each(visible_pnode, visible_pnodes) {
|
||||
struct weston_paint_node *pnode = *visible_pnode;
|
||||
struct weston_paint_node **visible_pnode_new;
|
||||
struct weston_view *ev = pnode->view;
|
||||
bool background_color_matches;
|
||||
bool background_color_supported;
|
||||
pixman_region32_t tmp;
|
||||
|
||||
drm_debug(b, "\t\t\t[view] evaluating view %p for scene"
|
||||
|
|
@ -825,7 +826,21 @@ lower_solid_views_to_background_region(struct drm_output *output,
|
|||
ev, output->base.name,
|
||||
(unsigned long) output->base.id);
|
||||
|
||||
if (is_paint_node_solid_opaque_black(pnode)) {
|
||||
background_color_matches =
|
||||
is_paint_node_solid_opaque(pnode) &&
|
||||
(!pixman_region32_not_empty(background_region) ||
|
||||
(background_region_color.r == pnode->solid.r &&
|
||||
background_region_color.g == pnode->solid.g &&
|
||||
background_region_color.b == pnode->solid.b));
|
||||
|
||||
background_color_supported =
|
||||
is_paint_node_solid_opaque(pnode) &&
|
||||
(drm_crtc_supports_background_color(output->crtc) ||
|
||||
(pnode->solid.r == 0.0f &&
|
||||
pnode->solid.g == 0.0f &&
|
||||
pnode->solid.b == 0.0f));
|
||||
|
||||
if (background_color_matches && background_color_supported) {
|
||||
drm_debug(b, "\t\t\t\t[view] ignoring view %p " \
|
||||
"(opaque-black solid buffer r %f g %f b %f " \
|
||||
"a %f)\n",
|
||||
|
|
@ -835,15 +850,31 @@ lower_solid_views_to_background_region(struct drm_output *output,
|
|||
pixman_region32_union(background_region,
|
||||
background_region,
|
||||
&pnode->visible);
|
||||
|
||||
background_region_color.a = 1.0f;
|
||||
background_region_color.r = pnode->solid.r;
|
||||
background_region_color.g = pnode->solid.g;
|
||||
background_region_color.b = pnode->solid.b;
|
||||
|
||||
if (drm_crtc_supports_background_color(output->crtc)) {
|
||||
uint64_t a16, r16, g16, b16;
|
||||
|
||||
a16 = 0xffff;
|
||||
r16 = 0xffff * background_region_color.r;
|
||||
g16 = 0xffff * background_region_color.g;
|
||||
b16 = 0xffff * background_region_color.b;
|
||||
|
||||
output->crtc->background_color =
|
||||
a16 << 48 | r16 << 32 | g16 << 16 | b16;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We can support this with the 'CRTC background colour'
|
||||
* property */
|
||||
if (pnode->draw_solid) {
|
||||
drm_debug(b, "\t\t\t\t[view] not assigning view %p to "
|
||||
"a plane (non-opaque-black solid buffer r %f "
|
||||
"g %f b %f a %f)\n",
|
||||
"a plane (background-incompatible solid "
|
||||
"buffer r %f g %f b %f a %f)\n",
|
||||
ev, pnode->solid.r, pnode->solid.g,
|
||||
pnode->solid.b, pnode->solid.a);
|
||||
wl_array_release(&visible_pnodes_new);
|
||||
|
|
@ -1149,6 +1180,9 @@ drm_output_propose_state(struct weston_output *output_base,
|
|||
*
|
||||
* See https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#plane-abstraction
|
||||
*
|
||||
* For other colors the same applies if the BACKGROUND_COLOR DRM
|
||||
* property is supported.
|
||||
*
|
||||
* All said views can thus be ignored during plane assignment.
|
||||
*/
|
||||
pixman_region32_init(&background_region);
|
||||
|
|
|
|||
|
|
@ -430,10 +430,8 @@ TEST(drm_offload_fullscreen_semi_transparent_black_background) {
|
|||
|
||||
/*
|
||||
* Test that a fullscreen client with opaque-white single-pixel-buffer with a
|
||||
* smaller-than-fullscreen-sized dmabuf subsurface above is *not* presented via
|
||||
* smaller-than-fullscreen-sized dmabuf subsurface above is presented via
|
||||
* direct-scanout.
|
||||
*
|
||||
* This should be optimized in the future.
|
||||
*/
|
||||
TEST(drm_offload_fullscreen_semi_transparent_white_background) {
|
||||
struct xdg_client *xdg_client;
|
||||
|
|
@ -501,7 +499,7 @@ TEST(drm_offload_fullscreen_semi_transparent_white_background) {
|
|||
wl_surface_commit(overlay_surface);
|
||||
wl_surface_commit(surface);
|
||||
presentation_wait_nofail(client, &result);
|
||||
test_assert_enum(result, FB_PRESENTED);
|
||||
test_assert_enum(result, FB_PRESENTED_ZERO_COPY);
|
||||
|
||||
wp_viewport_destroy(viewport);
|
||||
wl_subsurface_destroy(overlay_subsurface);
|
||||
|
|
@ -770,9 +768,7 @@ TEST(drm_offload_fullscreen_black_background_red_subsurface_underlay) {
|
|||
|
||||
/*
|
||||
* Test that a windowed / not-fullscreen client on top of a solid background is
|
||||
* *not* presented via direct-scanout.
|
||||
*
|
||||
* This should be optimized in the future.
|
||||
* presented via direct-scanout.
|
||||
*/
|
||||
TEST(drm_offload_windowed) {
|
||||
struct xdg_client *xdg_client;
|
||||
|
|
@ -816,7 +812,7 @@ TEST(drm_offload_windowed) {
|
|||
&result);
|
||||
wl_surface_commit(surface);
|
||||
presentation_wait_nofail(client, &result);
|
||||
test_assert_enum(result, FB_PRESENTED);
|
||||
test_assert_enum(result, FB_PRESENTED_ZERO_COPY);
|
||||
|
||||
client_buffer_util_destroy_buffer(buffer);
|
||||
destroy_xdg_surface(xdg_surface);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue