History

drm: Add CRTC background color property

Some display controllers can be hardware programmed to show non-black colors for pixels that are either not covered by any plane or are exposed through transparent regions of higher planes. This feature can help reduce memory bandwidth usage, e.g. in compositors managing a UI with a solid background color while using smaller planes to render the remaining content. To support this capability, introduce the BACKGROUND_COLOR standard DRM mode property, which can be attached to a CRTC through the drm_crtc_attach_background_color_property() helper function. Additionally, define a 64-bit ARGB format value to be built with the help of a couple of dedicated DRM_ARGB64_PREP*() helpers. Individual color components can be extracted with desired precision using the corresponding DRM_ARGB64_GET*() macros.

Cristian Ciocaltea committed 8 months ago

Commit 4c684591 parent de9e2b39 files · +147 −5Browse files

Unified · Split

9 files
  1. drivers/gpu/drm/drm_atomic.c +1 −0
  2. drivers/gpu/drm/drm_atomic_state_helper.c +1 −0
  3. drivers/gpu/drm/drm_atomic_uapi.c +4 −0
  4. drivers/gpu/drm/drm_blend.c +35 −4
  5. drivers/gpu/drm/drm_mode_config.c +6 −0
  6. include/drm/drm_blend.h +3 −1
  7. include/drm/drm_crtc.h +12 −0
  8. include/drm/drm_mode_config.h +5 −0
  9. include/uapi/drm/drm_mode.h +80 −0
drivers/gpu/drm/drm_atomic.c+1−0
@@ -475,6 +475,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, · 474 unmodified lines
475 drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);475 drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
476 drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);476 drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
477 drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));477 drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
478 drm_printf(p, "\tbackground_color=%llx\n", state->background_color);
478 479
479 if (crtc->funcs->atomic_print_state)480 if (crtc->funcs->atomic_print_state)
480 crtc->funcs->atomic_print_state(p, state);481 crtc->funcs->atomic_print_state(p, state);
drivers/gpu/drm/drm_atomic_state_helper.c+1−0
@@ -75,6 +75,7 @@ __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state, · 74 unmodified lines
75 struct drm_crtc *crtc)75 struct drm_crtc *crtc)
76{76{
77 crtc_state->crtc = crtc;77 crtc_state->crtc = crtc;
78 crtc_state->background_color = DRM_ARGB64_PREP(0xffff, 0, 0, 0);
78}79}
79EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset);80EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset);
80 81
drivers/gpu/drm/drm_atomic_uapi.c+4−0
@@ -454,6 +454,8 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, · 453 unmodified lines
454 &replaced);454 &replaced);
455 state->color_mgmt_changed |= replaced;455 state->color_mgmt_changed |= replaced;
456 return ret;456 return ret;
457 } else if (property == config->background_color_property) {
458 state->background_color = val;
457 } else if (property == config->prop_out_fence_ptr) {459 } else if (property == config->prop_out_fence_ptr) {
458 s32 __user *fence_ptr = u64_to_user_ptr(val);460 s32 __user *fence_ptr = u64_to_user_ptr(val);
459 461
@@ -501,6 +503,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, · 41 unmodified lines
501 *val = (state->ctm) ? state->ctm->base.id : 0;503 *val = (state->ctm) ? state->ctm->base.id : 0;
502 else if (property == config->gamma_lut_property)504 else if (property == config->gamma_lut_property)
503 *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;505 *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
506 else if (property == config->background_color_property)
507 *val = state->background_color;
504 else if (property == config->prop_out_fence_ptr)508 else if (property == config->prop_out_fence_ptr)
505 *val = 0;509 *val = 0;
506 else if (property == crtc->scaling_filter_property)510 else if (property == crtc->scaling_filter_property)
drivers/gpu/drm/drm_blend.c+35−4
@@ -191,10 +191,6 @@ · 190 unmodified lines
191 * plane does not expose the "alpha" property, then this is191 * plane does not expose the "alpha" property, then this is
192 * assumed to be 1.0192 * assumed to be 1.0
193 *193 *
194 * Note that all the property extensions described here apply either to the
195 * plane or the CRTC (e.g. for the background color, which currently is not
196 * exposed and assumed to be black).
197 *
198 * SCALING_FILTER:194 * SCALING_FILTER:
199 * Indicates scaling filter to be used for plane scaler195 * Indicates scaling filter to be used for plane scaler
200 *196 *
@@ -207,6 +203,25 @@ · 6 unmodified lines
207 *203 *
208 * Drivers can set up this property for a plane by calling204 * Drivers can set up this property for a plane by calling
209 * drm_plane_create_scaling_filter_property205 * drm_plane_create_scaling_filter_property
206 *
207 * The property extensions described above all apply to the plane. Drivers
208 * may also expose the following crtc property extension:
209 *
210 * BACKGROUND_COLOR:
211 * Background color is set up with drm_crtc_attach_background_color_property(),
212 * and expects a 64-bit ARGB value following DRM_FORMAT_ARGB16161616, as
213 * generated by the DRM_ARGB64_PREP*() helpers. It controls the color of a
214 * full-screen layer that exists below all planes. This color will be used
215 * for pixels not covered by any plane and may also be blended with plane
216 * contents as allowed by a plane's alpha values.
217 * The background color defaults to black, and is assumed to be black for
218 * drivers that do not expose this property. Although background color
219 * isn't a plane, it is assumed that the color provided here undergoes the
220 * CRTC degamma/CSC/gamma transformations applied after the planes blending.
221 * Note that the color value includes an alpha channel, hence non-opaque
222 * background color values are allowed, but since physically transparent
223 * monitors do not (yet) exists, the final alpha value may not reach the
224 * video sink or it may simply ignore it.
210 */225 */
211 226
212/**227/**
@@ -621,3 +636,19 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane, · 408 unmodified lines
621 return 0;636 return 0;
622}637}
623EXPORT_SYMBOL(drm_plane_create_blend_mode_property);638EXPORT_SYMBOL(drm_plane_create_blend_mode_property);
639
640/**
641 * drm_crtc_attach_background_color_property - attach background color property
642 * @crtc: drm crtc
643 *
644 * Attaches the background color property to @crtc. The property defaults to
645 * solid black and will accept 64-bit ARGB values in the format generated by
646 * DRM_ARGB64_PREP*() helpers.
647 */
648void drm_crtc_attach_background_color_property(struct drm_crtc *crtc)
649{
650 drm_object_attach_property(&crtc->base,
651 crtc->dev->mode_config.background_color_property,
652 DRM_ARGB64_PREP(0xffff, 0, 0, 0));
653}
654EXPORT_SYMBOL(drm_crtc_attach_background_color_property);
drivers/gpu/drm/drm_mode_config.c+6−0
@@ -380,6 +380,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) · 379 unmodified lines
380 return -ENOMEM;380 return -ENOMEM;
381 dev->mode_config.gamma_lut_size_property = prop;381 dev->mode_config.gamma_lut_size_property = prop;
382 382
383 prop = drm_property_create_range(dev, 0,
384 "BACKGROUND_COLOR", 0, U64_MAX);
385 if (!prop)
386 return -ENOMEM;
387 dev->mode_config.background_color_property = prop;
388
383 prop = drm_property_create(dev,389 prop = drm_property_create(dev,
384 DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,390 DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
385 "IN_FORMATS", 0);391 "IN_FORMATS", 0);
include/drm/drm_blend.h+3−1
@@ -31,8 +31,9 @@ · 30 unmodified lines
31#define DRM_MODE_BLEND_COVERAGE 131#define DRM_MODE_BLEND_COVERAGE 1
32#define DRM_MODE_BLEND_PIXEL_NONE 232#define DRM_MODE_BLEND_PIXEL_NONE 2
33 33
34struct drm_device;
35struct drm_atomic_state;34struct drm_atomic_state;
35struct drm_crtc;
36struct drm_device;
36struct drm_plane;37struct drm_plane;
37 38
38static inline bool drm_rotation_90_or_270(unsigned int rotation)39static inline bool drm_rotation_90_or_270(unsigned int rotation)
@@ -58,4 +59,5 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, · 19 unmodified lines
58 struct drm_atomic_state *state);59 struct drm_atomic_state *state);
59int drm_plane_create_blend_mode_property(struct drm_plane *plane,60int drm_plane_create_blend_mode_property(struct drm_plane *plane,
60 unsigned int supported_modes);61 unsigned int supported_modes);
62void drm_crtc_attach_background_color_property(struct drm_crtc *crtc);
61#endif63#endif
include/drm/drm_crtc.h+12−0
@@ -274,6 +274,18 @@ struct drm_crtc_state { · 273 unmodified lines
274 */274 */
275 struct drm_property_blob *gamma_lut;275 struct drm_property_blob *gamma_lut;
276 276
277 /**
278 * @background_color:
279 *
280 * RGB value representing the CRTC's background color. The background
281 * color (aka "canvas color") of a CRTC is the color that will be used
282 * for pixels not covered by a plane, or covered by transparent pixels
283 * of a plane. The value here should be built using DRM_ARGB64_PREP*()
284 * helpers, while the individual color components can be extracted with
285 * desired precision via the DRM_ARGB64_GET*() macros.
286 */
287 u64 background_color;
288
277 /**289 /**
278 * @target_vblank:290 * @target_vblank:
279 *291 *
include/drm/drm_mode_config.h+5−0
@@ -836,6 +836,11 @@ struct drm_mode_config { · 835 unmodified lines
836 * gamma LUT as supported by the driver (read-only).836 * gamma LUT as supported by the driver (read-only).
837 */837 */
838 struct drm_property *gamma_lut_size_property;838 struct drm_property *gamma_lut_size_property;
839 /**
840 * @background_color_property: Optional CRTC property to set the
841 * background color.
842 */
843 struct drm_property *background_color_property;
839 844
840 /**845 /**
841 * @suggested_x_property: Optional connector property with a hint for846 * @suggested_x_property: Optional connector property with a hint for
include/uapi/drm/drm_mode.h+80−0
@@ -27,6 +27,9 @@ · 26 unmodified lines
27#ifndef _DRM_MODE_H27#ifndef _DRM_MODE_H
28#define _DRM_MODE_H28#define _DRM_MODE_H
29 29
30#include <linux/bits.h>
31#include <linux/const.h>
32
30#include "drm.h"33#include "drm.h"
31 34
32#if defined(__cplusplus)35#if defined(__cplusplus)
@@ -1549,6 +1552,83 @@ struct drm_mode_closefb { · 1516 unmodified lines
1549 __u32 pad;1552 __u32 pad;
1550};1553};
1551 1554
1555/*
1556 * Put 16-bit ARGB values into a standard 64-bit representation that can be
1557 * used for ioctl parameters, inter-driver communication, etc.
1558 *
1559 * If the component values being provided contain less than 16 bits of
1560 * precision, use a conversion ratio to get a better color approximation.
1561 * The ratio is computed as (2^16 - 1) / (2^bpc - 1), where bpc and 16 are
1562 * the input and output precision, respectively.
1563 * Also note bpc must be greater than 0.
1564 */
1565#define __DRM_ARGB64_PREP(c, shift) \
1566 (((__u64)(c) & __GENMASK(15, 0)) << (shift))
1567
1568#define __DRM_ARGB64_PREP_BPC(c, shift, bpc) \
1569({ \
1570 __u16 mask = __GENMASK((bpc) - 1, 0); \
1571 __u16 conv = __KERNEL_DIV_ROUND_CLOSEST((mask & (c)) * \
1572 __GENMASK(15, 0), mask);\
1573 __DRM_ARGB64_PREP(conv, shift); \
1574})
1575
1576#define DRM_ARGB64_PREP(alpha, red, green, blue) \
1577( \
1578 __DRM_ARGB64_PREP(alpha, 48) | \
1579 __DRM_ARGB64_PREP(red, 32) | \
1580 __DRM_ARGB64_PREP(green, 16) | \
1581 __DRM_ARGB64_PREP(blue, 0) \
1582)
1583
1584#define DRM_ARGB64_PREP_BPC(alpha, red, green, blue, bpc) \
1585({ \
1586 __typeof__(bpc) __bpc = bpc; \
1587 __DRM_ARGB64_PREP_BPC(alpha, 48, __bpc) | \
1588 __DRM_ARGB64_PREP_BPC(red, 32, __bpc) | \
1589 __DRM_ARGB64_PREP_BPC(green, 16, __bpc) | \
1590 __DRM_ARGB64_PREP_BPC(blue, 0, __bpc); \
1591})
1592
1593/*
1594 * Extract the specified color component from a standard 64-bit ARGB value.
1595 *
1596 * If the requested precision is less than 16 bits, make use of a conversion
1597 * ratio calculated as (2^bpc - 1) / (2^16 - 1), where bpc and 16 are the
1598 * output and input precision, respectively.
1599 *
1600 * If speed is more important than accuracy, use DRM_ARGB64_GET*_BPCS()
1601 * instead of DRM_ARGB64_GET*_BPC() in order to replace the expensive
1602 * division with a simple bit right-shift operation.
1603 */
1604#define __DRM_ARGB64_GET(c, shift) \
1605 ((__u16)(((__u64)(c) >> (shift)) & __GENMASK(15, 0)))
1606
1607#define __DRM_ARGB64_GET_BPC(c, shift, bpc) \
1608({ \
1609 __u16 comp = __DRM_ARGB64_GET(c, shift); \
1610 __KERNEL_DIV_ROUND_CLOSEST(comp * __GENMASK((bpc) - 1, 0), \
1611 __GENMASK(15, 0)); \
1612})
1613
1614#define __DRM_ARGB64_GET_BPCS(c, shift, bpc) \
1615 (__DRM_ARGB64_GET(c, shift) >> (16 - (bpc)))
1616
1617#define DRM_ARGB64_GETA(c) __DRM_ARGB64_GET(c, 48)
1618#define DRM_ARGB64_GETR(c) __DRM_ARGB64_GET(c, 32)
1619#define DRM_ARGB64_GETG(c) __DRM_ARGB64_GET(c, 16)
1620#define DRM_ARGB64_GETB(c) __DRM_ARGB64_GET(c, 0)
1621
1622#define DRM_ARGB64_GETA_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 48, bpc)
1623#define DRM_ARGB64_GETR_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 32, bpc)
1624#define DRM_ARGB64_GETG_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 16, bpc)
1625#define DRM_ARGB64_GETB_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 0, bpc)
1626
1627#define DRM_ARGB64_GETA_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 48, bpc)
1628#define DRM_ARGB64_GETR_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 32, bpc)
1629#define DRM_ARGB64_GETG_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 16, bpc)
1630#define DRM_ARGB64_GETB_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 0, bpc)
1631
1552#if defined(__cplusplus)1632#if defined(__cplusplus)
1553}1633}
1554#endif1634#endif