Skip to content

Commit a3a80ac

Browse files
cristiccpopcornmix
authored andcommitted
drm: Add CRTC background color property
Commit 4c68459 upstream. 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. Co-developed-by: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Tested-by: Diederik de Haas <diederik@cknow-tech.com> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> Link: https://patch.msgid.link/20260303-rk3588-bgcolor-v8-2-fee377037ad1@collabora.com Signed-off-by: Daniel Stone <daniels@collabora.com>
1 parent 139a09e commit a3a80ac

9 files changed

Lines changed: 147 additions & 5 deletions

File tree

drivers/gpu/drm/drm_atomic.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
475475
drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
476476
drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
477477
drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
478+
drm_printf(p, "\tbackground_color=%llx\n", state->background_color);
478479

479480
if (crtc->funcs->atomic_print_state)
480481
crtc->funcs->atomic_print_state(p, state);

drivers/gpu/drm/drm_atomic_state_helper.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state,
7575
struct drm_crtc *crtc)
7676
{
7777
crtc_state->crtc = crtc;
78+
crtc_state->background_color = DRM_ARGB64_PREP(0xffff, 0, 0, 0);
7879
}
7980
EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset);
8081

drivers/gpu/drm/drm_atomic_uapi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,8 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
454454
&replaced);
455455
state->color_mgmt_changed |= replaced;
456456
return ret;
457+
} else if (property == config->background_color_property) {
458+
state->background_color = val;
457459
} else if (property == config->prop_out_fence_ptr) {
458460
s32 __user *fence_ptr = u64_to_user_ptr(val);
459461

@@ -501,6 +503,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
501503
*val = (state->ctm) ? state->ctm->base.id : 0;
502504
else if (property == config->gamma_lut_property)
503505
*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
506+
else if (property == config->background_color_property)
507+
*val = state->background_color;
504508
else if (property == config->prop_out_fence_ptr)
505509
*val = 0;
506510
else if (property == crtc->scaling_filter_property)

drivers/gpu/drm/drm_blend.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,6 @@
191191
* plane does not expose the "alpha" property, then this is
192192
* assumed to be 1.0
193193
*
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-
*
198194
* SCALING_FILTER:
199195
* Indicates scaling filter to be used for plane scaler
200196
*
@@ -207,6 +203,25 @@
207203
*
208204
* Drivers can set up this property for a plane by calling
209205
* 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.
210225
*/
211226

212227
/**
@@ -654,3 +669,19 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane,
654669
return 0;
655670
}
656671
EXPORT_SYMBOL(drm_plane_create_blend_mode_property);
672+
673+
/**
674+
* drm_crtc_attach_background_color_property - attach background color property
675+
* @crtc: drm crtc
676+
*
677+
* Attaches the background color property to @crtc. The property defaults to
678+
* solid black and will accept 64-bit ARGB values in the format generated by
679+
* DRM_ARGB64_PREP*() helpers.
680+
*/
681+
void drm_crtc_attach_background_color_property(struct drm_crtc *crtc)
682+
{
683+
drm_object_attach_property(&crtc->base,
684+
crtc->dev->mode_config.background_color_property,
685+
DRM_ARGB64_PREP(0xffff, 0, 0, 0));
686+
}
687+
EXPORT_SYMBOL(drm_crtc_attach_background_color_property);

drivers/gpu/drm/drm_mode_config.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
380380
return -ENOMEM;
381381
dev->mode_config.gamma_lut_size_property = prop;
382382

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+
383389
prop = drm_property_create(dev,
384390
DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
385391
"IN_FORMATS", 0);

include/drm/drm_blend.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@
3131
#define DRM_MODE_BLEND_COVERAGE 1
3232
#define DRM_MODE_BLEND_PIXEL_NONE 2
3333

34-
struct drm_device;
3534
struct drm_atomic_state;
35+
struct drm_crtc;
36+
struct drm_device;
3637
struct drm_plane;
3738
struct drm_connector;
3839

@@ -59,6 +60,7 @@ int drm_atomic_normalize_zpos(struct drm_device *dev,
5960
struct drm_atomic_state *state);
6061
int drm_plane_create_blend_mode_property(struct drm_plane *plane,
6162
unsigned int supported_modes);
63+
void drm_crtc_attach_background_color_property(struct drm_crtc *crtc);
6264

6365
int drm_connector_create_rotation_property(struct drm_connector *conn,
6466
unsigned int rotation,

include/drm/drm_crtc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,18 @@ struct drm_crtc_state {
274274
*/
275275
struct drm_property_blob *gamma_lut;
276276

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+
277289
/**
278290
* @target_vblank:
279291
*

include/drm/drm_mode_config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,11 @@ struct drm_mode_config {
832832
* gamma LUT as supported by the driver (read-only).
833833
*/
834834
struct drm_property *gamma_lut_size_property;
835+
/**
836+
* @background_color_property: Optional CRTC property to set the
837+
* background color.
838+
*/
839+
struct drm_property *background_color_property;
835840

836841
/**
837842
* @suggested_x_property: Optional connector property with a hint for

include/uapi/drm/drm_mode.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#ifndef _DRM_MODE_H
2828
#define _DRM_MODE_H
2929

30+
#include <linux/bits.h>
31+
#include <linux/const.h>
32+
3033
#include "drm.h"
3134

3235
#if defined(__cplusplus)
@@ -1546,6 +1549,83 @@ struct drm_mode_closefb {
15461549
__u32 pad;
15471550
};
15481551

1552+
/*
1553+
* Put 16-bit ARGB values into a standard 64-bit representation that can be
1554+
* used for ioctl parameters, inter-driver communication, etc.
1555+
*
1556+
* If the component values being provided contain less than 16 bits of
1557+
* precision, use a conversion ratio to get a better color approximation.
1558+
* The ratio is computed as (2^16 - 1) / (2^bpc - 1), where bpc and 16 are
1559+
* the input and output precision, respectively.
1560+
* Also note bpc must be greater than 0.
1561+
*/
1562+
#define __DRM_ARGB64_PREP(c, shift) \
1563+
(((__u64)(c) & __GENMASK(15, 0)) << (shift))
1564+
1565+
#define __DRM_ARGB64_PREP_BPC(c, shift, bpc) \
1566+
({ \
1567+
__u16 mask = __GENMASK((bpc) - 1, 0); \
1568+
__u16 conv = __KERNEL_DIV_ROUND_CLOSEST((mask & (c)) * \
1569+
__GENMASK(15, 0), mask);\
1570+
__DRM_ARGB64_PREP(conv, shift); \
1571+
})
1572+
1573+
#define DRM_ARGB64_PREP(alpha, red, green, blue) \
1574+
( \
1575+
__DRM_ARGB64_PREP(alpha, 48) | \
1576+
__DRM_ARGB64_PREP(red, 32) | \
1577+
__DRM_ARGB64_PREP(green, 16) | \
1578+
__DRM_ARGB64_PREP(blue, 0) \
1579+
)
1580+
1581+
#define DRM_ARGB64_PREP_BPC(alpha, red, green, blue, bpc) \
1582+
({ \
1583+
__typeof__(bpc) __bpc = bpc; \
1584+
__DRM_ARGB64_PREP_BPC(alpha, 48, __bpc) | \
1585+
__DRM_ARGB64_PREP_BPC(red, 32, __bpc) | \
1586+
__DRM_ARGB64_PREP_BPC(green, 16, __bpc) | \
1587+
__DRM_ARGB64_PREP_BPC(blue, 0, __bpc); \
1588+
})
1589+
1590+
/*
1591+
* Extract the specified color component from a standard 64-bit ARGB value.
1592+
*
1593+
* If the requested precision is less than 16 bits, make use of a conversion
1594+
* ratio calculated as (2^bpc - 1) / (2^16 - 1), where bpc and 16 are the
1595+
* output and input precision, respectively.
1596+
*
1597+
* If speed is more important than accuracy, use DRM_ARGB64_GET*_BPCS()
1598+
* instead of DRM_ARGB64_GET*_BPC() in order to replace the expensive
1599+
* division with a simple bit right-shift operation.
1600+
*/
1601+
#define __DRM_ARGB64_GET(c, shift) \
1602+
((__u16)(((__u64)(c) >> (shift)) & __GENMASK(15, 0)))
1603+
1604+
#define __DRM_ARGB64_GET_BPC(c, shift, bpc) \
1605+
({ \
1606+
__u16 comp = __DRM_ARGB64_GET(c, shift); \
1607+
__KERNEL_DIV_ROUND_CLOSEST(comp * __GENMASK((bpc) - 1, 0), \
1608+
__GENMASK(15, 0)); \
1609+
})
1610+
1611+
#define __DRM_ARGB64_GET_BPCS(c, shift, bpc) \
1612+
(__DRM_ARGB64_GET(c, shift) >> (16 - (bpc)))
1613+
1614+
#define DRM_ARGB64_GETA(c) __DRM_ARGB64_GET(c, 48)
1615+
#define DRM_ARGB64_GETR(c) __DRM_ARGB64_GET(c, 32)
1616+
#define DRM_ARGB64_GETG(c) __DRM_ARGB64_GET(c, 16)
1617+
#define DRM_ARGB64_GETB(c) __DRM_ARGB64_GET(c, 0)
1618+
1619+
#define DRM_ARGB64_GETA_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 48, bpc)
1620+
#define DRM_ARGB64_GETR_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 32, bpc)
1621+
#define DRM_ARGB64_GETG_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 16, bpc)
1622+
#define DRM_ARGB64_GETB_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 0, bpc)
1623+
1624+
#define DRM_ARGB64_GETA_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 48, bpc)
1625+
#define DRM_ARGB64_GETR_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 32, bpc)
1626+
#define DRM_ARGB64_GETG_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 16, bpc)
1627+
#define DRM_ARGB64_GETB_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 0, bpc)
1628+
15491629
#if defined(__cplusplus)
15501630
}
15511631
#endif

0 commit comments

Comments
 (0)