diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index 83e20dc0a..f73b31356 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -461,6 +461,8 @@ struct drm_plane_state { uint64_t zpos; uint16_t alpha; + enum wdrm_plane_blend blend_mode; + enum wdrm_plane_color_encoding color_encoding; enum wdrm_plane_color_range color_range; @@ -1041,6 +1043,10 @@ bool drm_plane_supports_color_range(struct drm_plane *plane, enum wdrm_plane_color_range range); +bool +drm_plane_supports_blend_mode(struct drm_plane *plane, + enum wdrm_plane_blend blend_mode); + void drm_output_render(struct drm_output_state *state); diff --git a/libweston/backend-drm/drm-kms-enums.h b/libweston/backend-drm/drm-kms-enums.h index 60c1f0fdd..70a91634d 100644 --- a/libweston/backend-drm/drm-kms-enums.h +++ b/libweston/backend-drm/drm-kms-enums.h @@ -56,6 +56,7 @@ enum wdrm_plane_property { WDRM_PLANE_ZPOS, WDRM_PLANE_ROTATION, WDRM_PLANE_ALPHA, + WDRM_PLANE_BLEND, WDRM_PLANE_COLOR_ENCODING, WDRM_PLANE_COLOR_PIPELINE, WDRM_PLANE_COLOR_RANGE, @@ -179,6 +180,17 @@ enum wdrm_colorop_lut3d_interpolation { WDRM_COLOROP_LUT3D_INTERPOLATION__COUNT, }; +/** + * Possible values for the WDRM_PLANE_BLEND property. + */ +enum wdrm_plane_blend { + WDRM_PLANE_BLEND_NONE = 0, + WDRM_PLANE_BLEND_PREMULT, + WDRM_PLANE_BLEND_COVERAGE, + WDRM_PLANE_BLEND__COUNT +}; +#define WDRM_PLANE_BLEND_DEFAULT WDRM_PLANE_BLEND_PREMULT + /** * List of properties attached to a DRM connector */ diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c index 1c234fc2a..eb8225dab 100644 --- a/libweston/backend-drm/kms.c +++ b/libweston/backend-drm/kms.c @@ -109,6 +109,18 @@ struct drm_property_enum_info plane_color_range_enums[] = { }, }; +struct drm_property_enum_info plane_blend_enums[] = { + [WDRM_PLANE_BLEND_NONE] = { + .name = "None", + }, + [WDRM_PLANE_BLEND_PREMULT] = { + .name = "Pre-multiplied", + }, + [WDRM_PLANE_BLEND_COVERAGE] = { + .name = "Coverage", + }, +}; + const struct drm_property_info plane_props[] = { [WDRM_PLANE_TYPE] = { .name = "type", @@ -135,6 +147,11 @@ const struct drm_property_info plane_props[] = { .num_enum_values = WDRM_PLANE_ROTATION__COUNT, }, [WDRM_PLANE_ALPHA] = { .name = "alpha" }, + [WDRM_PLANE_BLEND] = { + .name = "pixel blend mode", + .enum_values = plane_blend_enums, + .num_enum_values = WDRM_PLANE_BLEND__COUNT, + }, [WDRM_PLANE_COLOR_ENCODING] = { .name = "COLOR_ENCODING", .enum_values = plane_color_encoding_enums, @@ -815,6 +832,31 @@ drm_plane_supports_color_range(struct drm_plane *plane, return enum_info->valid; } +/** + * Check if a blend mode is supported by a KMS plane + * + * If the blend mode property is not supported by the plane, this assumes that + * the blend mode is unsupported if different from WDRM_PLANE_BLEND_DEFAULT. + * + * @param plane The KMS plane + * @param blend_mode The blend mode to check + * @return True if supported, false otherwise + */ +bool +drm_plane_supports_blend_mode(struct drm_plane *plane, + enum wdrm_plane_blend blend_mode) +{ + const struct drm_property_info *info = &plane->props[WDRM_PLANE_BLEND]; + const struct drm_property_enum_info *enum_info; + + if (info->prop_id == 0) + return blend_mode == WDRM_PLANE_BLEND_DEFAULT; + + enum_info = &info->enum_values[blend_mode]; + + return enum_info->valid; +} + /** * Mark an output state as current on the output, i.e. it has been * submitted to the kernel. The mode argument determines whether this @@ -1603,6 +1645,28 @@ drm_plane_set_color_range(struct drm_plane *plane, color_range); } +static int +drm_plane_set_blend_mode(struct drm_plane *plane, + enum wdrm_plane_blend blend_mode, + drmModeAtomicReq *req) +{ + struct weston_compositor *wc = plane->base.compositor; + + weston_assert_s32_ge(wc, blend_mode, 0); + weston_assert_s32_lt(wc, blend_mode, WDRM_PLANE_BLEND__COUNT); + + if (plane->props[WDRM_PLANE_BLEND].prop_id == 0) { + if (blend_mode == WDRM_PLANE_BLEND_DEFAULT) + return 0; + + return -1; + } + + weston_assert_true(wc, drm_plane_supports_blend_mode(plane, blend_mode)); + + return plane_add_prop_enum(req, plane, WDRM_PLANE_BLEND, blend_mode); +} + static bool colorop_enforce(drmModeAtomicReq *req, const struct drm_colorop *colorop, char **err_msg) @@ -1952,6 +2016,10 @@ drm_output_apply_state_atomic(struct drm_output_state *state, WDRM_PLANE_ALPHA, plane_state->alpha); + ret |= drm_plane_set_blend_mode(plane, + plane_state->blend_mode, + req); + ret |= drm_plane_set_color_encoding(plane, plane_state->color_encoding, req); diff --git a/libweston/backend-drm/state-helpers.c b/libweston/backend-drm/state-helpers.c index f36cf597e..998c36983 100644 --- a/libweston/backend-drm/state-helpers.c +++ b/libweston/backend-drm/state-helpers.c @@ -59,6 +59,8 @@ drm_plane_state_alloc(struct drm_output_state *state_output, state->alpha = (plane->alpha_max < DRM_PLANE_ALPHA_OPAQUE) ? plane->alpha_max : DRM_PLANE_ALPHA_OPAQUE; + state->blend_mode = WDRM_PLANE_BLEND_DEFAULT; + state->color_encoding = WDRM_PLANE_COLOR_ENCODING_DEFAULT; state->color_range = WDRM_PLANE_COLOR_RANGE_DEFAULT;