This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ | | | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/ We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma
Documentation/gpu/drm-kms.rst | 90 +++ Documentation/gpu/rfc/drm_color_pipeline.rst | 167 ++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 12 + drivers/gpu/drm/drm_atomic_uapi.c | 38 ++ drivers/gpu/drm/drm_color_mgmt.c | 177 +++++- .../gpu/drm/i915/display/intel_atomic_plane.c | 6 + .../gpu/drm/i915/display/intel_atomic_plane.h | 2 + drivers/gpu/drm/i915/display/intel_color.c | 513 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 + .../drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 176 +++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 81 +++ include/uapi/drm/drm_mode.h | 58 ++ 16 files changed, 1337 insertions(+), 6 deletions(-) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com --- Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties +================================================== + +This is how a typical display color hardware pipeline looks like: + +-------------------------------------------+ + | RAM | + | +------+ +---------+ +---------+ | + | | FB 1 | | FB 2 | | FB N | | + | +------+ +---------+ +---------+ | + +-------------------------------------------+ + | Plane Color Hardware Block | + +--------------------------------------------+ + | +---v-----+ +---v-------+ +---v------+ | + | | Plane A | | Plane B | | Plane N | | + | | DeGamma | | Degamma | | Degamma | | + | +---+-----+ +---+-------+ +---+------+ | + | | | | | + | +---v-----+ +---v-------+ +---v------+ | + | |Plane A | | Plane B | | Plane N | | + | |CSC/CTM | | CSC/CTM | | CSC/CTM | | + | +---+-----+ +----+------+ +----+-----+ | + | | | | | + | +---v-----+ +----v------+ +----v-----+ | + | | Plane A | | Plane B | | Plane N | | + | | Gamma | | Gamma | | Gamma | | + | +---+-----+ +----+------+ +----+-----+ | + | | | | | + +--------------------------------------------+ ++------v--------------v---------------v-------| +|| || +|| Pipe Blender || ++--------------------+------------------------+ +| | | +| +-----------v----------+ | +| | Pipe DeGamma | | +| | | | +| +-----------+----------+ | +| | Pipe Color | +| +-----------v----------+ Hardware | +| | Pipe CSC/CTM | | +| | | | +| +-----------+----------+ | +| | | +| +-----------v----------+ | +| | Pipe Gamma | | +| | | | +| +-----------+----------+ | +| | | ++---------------------------------------------+ + | + v + Pipe Output + +Proposal is to have below properties for a plane: + +* Plane Degamma or Pre-Curve: + * This will be used to linearize the input framebuffer data. + * It will apply the reverse of the color transfer function. + * It can be a degamma curve or OETF for HDR. + * This linear data can be further acted on by the following + * color hardware blocks in the display hardware pipeline + +UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the + possible degamma modes and lut ranges supported by the platform. + This allows userspace to query and get the plane degamma color + caps and choose the appropriate degamma mode and create lut values + accordingly. + +UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values + to apply degamma curve using the h/w plane degamma processing + engine, thereby making the content as linear for further color + processing. Userspace gets the size of LUT and precision etc + from PLANE_DEGAMA_MODE_PROPERTY + +* Plane CTM + * This is a Property to program the color transformation matrix. + * This can be used to perform a color space conversion like + * BT2020 to BT709 or BT601 etc. + * This block is generally kept after the degamma unit so that + * linear data can be fed to it for conversion. + +UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients + to do color space conversion or any other enhancement by doing a + matrix multiplication using the h/w CTM processing engine + +* Plane Gamma or Post-Curve + * This can be used to perform 2 operations: + * non-lineralize the framebuffer data. Can be used for + * non linear blending. It can be a gamma curve or EOTF + * for HDR. + * Perform Tone Mapping operation. This is an operation + * done when blending is done with HDR and SDR content. + +UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the + possible gamma modes and lut ranges supported by the platform. + This allows userspace to query and get the plane gamma color + caps and choose the appropriate gamma mode and create lut values + accordingly. + +UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values + to apply gamma curve or perform tone mapping using the h/w plane + gamma processing engine, thereby making the content as linear + for further color processing. Userspace gets the size of LUT and + precision etc from PLANE_GAMA_MODE_PROPERTY + +This is part of one plane engine. Data from multiple planes will be +then fed to pipe where it will get blended. There is a similar set of +properties available at crtc level which acts on this blended data. + +Below is a sample usecase: + + ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ + │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ + │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR │ + │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone Mapping├────────┐ + └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ + │ + ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ + │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ + │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR ├─────┐ │ + │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │ │ + └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ + │ │ + ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ + │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ │ + │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data in├───┐ │ │ + │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │ + └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ + │ │ │ + │ │ │ + │ │ │ +┌───────────────────────────────────────────────────────────────────────────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone ├─────► TO Port + │ data linear │ │ Color Space │ │ Mapping/apply │ + │ after blend │ │ Conversion │ │ transfer func │ + └─────────────┘ └─────────────┘ └───────────────┘ + + +This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for gamut +conversion. It also includes Gamma support used to again non-linearize +data as per panel supported color space. These can be utilize by user +space to convert planes from one format to another, one color space to +another etc. + +Userspace can take smart blending decisions and utilize these hardware +supported plane color features to get accurate color profile. The same +can help in consistent color quality from source to panel taking +advantage of advanced color features in hardware. + +These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific implementation +on top of this series. + +Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
Hi,
is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
+==================================================
+This is how a typical display color hardware pipeline looks like:
Typical, or should we say that this is the abstract color pipeline that KMS assumes?
Then drivers map this to pieces of hardware the best they can and reject or do not expose the parts they cannot.
- +-------------------------------------------+
- | RAM |
- | +------+ +---------+ +---------+ |
- | | FB 1 | | FB 2 | | FB N | |
- | +------+ +---------+ +---------+ |
- +-------------------------------------------+
| Plane Color Hardware Block |
- +--------------------------------------------+
- | +---v-----+ +---v-------+ +---v------+ |
- | | Plane A | | Plane B | | Plane N | |
- | | DeGamma | | Degamma | | Degamma | |
- | +---+-----+ +---+-------+ +---+------+ |
- | | | | |
- | +---v-----+ +---v-------+ +---v------+ |
- | |Plane A | | Plane B | | Plane N | |
- | |CSC/CTM | | CSC/CTM | | CSC/CTM | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- | +---v-----+ +----v------+ +----v-----+ |
- | | Plane A | | Plane B | | Plane N | |
- | | Gamma | | Gamma | | Gamma | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- +--------------------------------------------+
++------v--------------v---------------v-------| +|| || +|| Pipe Blender || ++--------------------+------------------------+ +| | | +| +-----------v----------+ | +| | Pipe DeGamma | | +| | | | +| +-----------+----------+ | +| | Pipe Color | +| +-----------v----------+ Hardware | +| | Pipe CSC/CTM | | +| | | | +| +-----------+----------+ | +| | | +| +-----------v----------+ | +| | Pipe Gamma | | +| | | | +| +-----------+----------+ | +| | | ++---------------------------------------------+
|
v
Pipe Output
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
As you want to produce light-linear values, you use EOTF or inverse OETF.
The term OETF has a built-in assumption that that happens in a camera: it takes in light and produces and electrical signal. Lately I have personally started talking about non-linear encoding of color values, since EOTF is often associated with displays if nothing else is said (taking in an electrical signal and producing light).
So this would be decoding the color values into light-linear color values. That is what an EOTF does, yes, but I feel there is a nuanced difference. A piece of equipment implements an EOTF by turning an electrical signal into light, hence EOTF often refers to specific equipment. You could talk about content EOTF to denote content value encoding, as opposed to output or display EOTF, but that might be confusing if you look at e.g. the diagrams in BT.2100: is it the EOTF or is it the inverse OETF? Is the (inverse?) OOTF included?
So I try to side-step those questions by talking about encoding.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
I think this and the above description ties the intended use down too much. This is one possible way to use degamma, yes, but there may be others. Particularly if CTM can be replaced with a 3D LUT, then the degamma is more likely a shaper (non-linear adjustment to 3D LUT tap positions).
I would prefer the name pre-curve to underline that this can be whatever one wants it to be, but I understand that people may be more familiar with the name degamma.
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
Is enum with blob id values even a thing?
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
LUT size, precision, and other details of each degamma mode would be good to expose somehow. I kind of expected those would have been exposed through the above mentioned "enum with blob id values" where each blob content structure is defined by the respective enum value.
+* Plane CTM
- This is a Property to program the color transformation matrix.
No mode property here? Is there any hardware with something else than a matrix at this point?
Should we assume there will be hardware with something else, and have a CSC mode property with only a single enum value defined so far: "matrix"? Or do we say PLANE_CTM is a matrix and if you have something else in hardware, then invent a new property for it?
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
Speaking of color space conversions, we should probably define what happens to out-of-range color values. Converting color into smaller gamut or smaller dynamic range always has the risk of ending up with out-of-range values. I suppose those get simply clipped independently on each color channel, right?
Such clipping can change hue, so userspace would be better avoid triggering clipping at all, but we still need to know what would happen with out-of-range values.
We would also need to know when clipping will happen. If FP16 (half-float) FB produces out-of-range values and degamma stage is not used, will the CTM see original or clipped values? Or is that something we have to define as hardware-specific?
Generic userspace will try hard to avoid triggering hardware-specific behaviour, so you can expect such behaviour to go unused.
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
I like this wording better than the wording for pre-curve: "can", not "will". It leaves room for creative use of this processing block.
Tone-mapping is needed always when dynamic range differs, so also for HDR to HDR, not just SDR to/from HDR.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
The same comments here as with DEGAMMA.
+This is part of one plane engine. Data from multiple planes will be +then fed to pipe where it will get blended. There is a similar set of +properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR │
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR ├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │ │
- └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ │
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │
EOTF, not OETF, since it is converting E to O, electrical to optical.
│ │ │
│ │ │
│ │ │
+┌───────────────────────────────────────────────────────────────────────────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone ├─────► TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
Blending does not change whether the data is linear or not. I suppose in this example, CRTC degamma and CTM would be passthrough, and gamma would be the inverse display EOTF for encoding color values into what the monitor expects.
+This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for gamut +conversion. It also includes Gamma support used to again non-linearize +data as per panel supported color space. These can be utilize by user +space to convert planes from one format to another, one color space to +another etc.
FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work.
+Userspace can take smart blending decisions and utilize these hardware +supported plane color features to get accurate color profile. The same +can help in consistent color quality from source to panel taking +advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific implementation +on top of this series.
+Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
Thanks, pq
On Tuesday, October 12th, 2021 at 12:30, Pekka Paalanen ppaalanen@gmail.com wrote:
is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
Once everyone agrees, the RFC can land. I don't think a kernel tree is necessary. See:
On Tue, 12 Oct 2021 10:35:37 +0000 Simon Ser contact@emersion.fr wrote:
On Tuesday, October 12th, 2021 at 12:30, Pekka Paalanen ppaalanen@gmail.com wrote:
is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
Once everyone agrees, the RFC can land. I don't think a kernel tree is necessary. See:
Does this mean the RFC doc patch will land, but the code patches will remain in the review cycles waiting for userspace proving vehicles? Rather than e.g. committed as files that people would need to apply themselves? Or how does one find the code patches corresponding to RFC docs?
Thanks, pq
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:30 PM To: Simon Ser contact@emersion.fr Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 10:35:37 +0000 Simon Ser contact@emersion.fr wrote:
On Tuesday, October 12th, 2021 at 12:30, Pekka Paalanen
ppaalanen@gmail.com wrote:
is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
Once everyone agrees, the RFC can land. I don't think a kernel tree is necessary. See:
Does this mean the RFC doc patch will land, but the code patches will remain in the review cycles waiting for userspace proving vehicles? Rather than e.g. committed as files that people would need to apply themselves? Or how does one find the code patches corresponding to RFC docs?
As I understand, this section was added to finalize the design and debate on the UAPI, structures, headers and design etc. Once a general agreement is in place with all the stakeholders, we can have ack on design and approach and get it merged. This hence serves as an approved reference for the UAPI, accepted and agreed by community at large.
Once the code lands, all the documentation will be added to the right driver sections and helpers, like it's been done currently.
@daniel.vetter@ffwll.ch Hope this is the right understanding.
Thanks & Regards, Uma Shankar
Thanks, pq
On Tue, 12 Oct 2021 19:11:29 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:30 PM To: Simon Ser contact@emersion.fr Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 10:35:37 +0000 Simon Ser contact@emersion.fr wrote:
On Tuesday, October 12th, 2021 at 12:30, Pekka Paalanen
ppaalanen@gmail.com wrote:
is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
Once everyone agrees, the RFC can land. I don't think a kernel tree is necessary. See:
Does this mean the RFC doc patch will land, but the code patches will remain in the review cycles waiting for userspace proving vehicles? Rather than e.g. committed as files that people would need to apply themselves? Or how does one find the code patches corresponding to RFC docs?
As I understand, this section was added to finalize the design and debate on the UAPI, structures, headers and design etc. Once a general agreement is in place with all the stakeholders, we can have ack on design and approach and get it merged. This hence serves as an approved reference for the UAPI, accepted and agreed by community at large.
Once the code lands, all the documentation will be added to the right driver sections and helpers, like it's been done currently.
I'm just wondering: someone browses a kernel tree, and discovers this RFC doc in there. They want to see or test the latest (WIP) kernel implementation of it. How will they find the code / patches?
Thanks, pq
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Wednesday, October 13, 2021 12:56 PM To: Shankar, Uma uma.shankar@intel.com Cc: Simon Ser contact@emersion.fr; daniel.vetter@ffwll.ch; intel- gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 19:11:29 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:30 PM To: Simon Ser contact@emersion.fr Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 10:35:37 +0000 Simon Ser contact@emersion.fr wrote:
On Tuesday, October 12th, 2021 at 12:30, Pekka Paalanen
ppaalanen@gmail.com wrote:
is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
Once everyone agrees, the RFC can land. I don't think a kernel tree is necessary. See:
Does this mean the RFC doc patch will land, but the code patches will remain in the review cycles waiting for userspace proving vehicles? Rather than e.g. committed as files that people would need to apply themselves? Or how does one find the code patches corresponding to RFC docs?
As I understand, this section was added to finalize the design and debate on the UAPI, structures, headers and design etc. Once a general agreement is in place with all the stakeholders, we can have ack on design and approach and get it merged. This hence serves as an approved
reference for the UAPI, accepted and agreed by community at large.
Once the code lands, all the documentation will be added to the right driver sections and helpers, like it's been done currently.
I'm just wondering: someone browses a kernel tree, and discovers this RFC doc in there. They want to see or test the latest (WIP) kernel implementation of it. How will they find the code / patches?
Maybe we could include the WIP links here to help with getting the pieces, this may include the driver patches and also the userspace efforts as well.
Regards, Uma Shankar
Thanks, pq
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
Hi, is there a practise of landing proposal documents in the kernel? How does that work, will a kernel tree carry the patch files? Or should this document be worded like documentation for an accepted feature, and then the patches either land or don't?
A thread is forked for this query, we will conclude there.
+==================================================
+This is how a typical display color hardware pipeline looks like:
Typical, or should we say that this is the abstract color pipeline that KMS assumes?
Then drivers map this to pieces of hardware the best they can and reject or do not expose the parts they cannot.
Yeah sure Pekka, I will reword this to be clear.
- +-------------------------------------------+
- | RAM |
- | +------+ +---------+ +---------+ |
- | | FB 1 | | FB 2 | | FB N | |
- | +------+ +---------+ +---------+ |
- +-------------------------------------------+
| Plane Color Hardware Block |
- +--------------------------------------------+
- | +---v-----+ +---v-------+ +---v------+ |
- | | Plane A | | Plane B | | Plane N | |
- | | DeGamma | | Degamma | | Degamma | |
- | +---+-----+ +---+-------+ +---+------+ |
- | | | | |
- | +---v-----+ +---v-------+ +---v------+ |
- | |Plane A | | Plane B | | Plane N | |
- | |CSC/CTM | | CSC/CTM | | CSC/CTM | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- | +---v-----+ +----v------+ +----v-----+ |
- | | Plane A | | Plane B | | Plane N | |
- | | Gamma | | Gamma | | Gamma | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- +--------------------------------------------+
++------v--------------v---------------v-------| +|| || +|| Pipe Blender || ++--------------------+------------------------+ +| | | +| +-----------v----------+ | +| | Pipe DeGamma | | +| | | | +| +-----------+----------+ | +| | Pipe Color | +| +-----------v----------+ Hardware | +| | Pipe CSC/CTM | | +| | | | +| +-----------+----------+ | +| | | +| +-----------v----------+ | +| | Pipe Gamma | | +| | | | +| +-----------+----------+ | +| | | ++---------------------------------------------+
|
v
Pipe Output
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
As you want to produce light-linear values, you use EOTF or inverse OETF.
The term OETF has a built-in assumption that that happens in a camera: it takes in light and produces and electrical signal. Lately I have personally started talking about non-linear encoding of color values, since EOTF is often associated with displays if nothing else is said (taking in an electrical signal and producing light).
So this would be decoding the color values into light-linear color values. That is what an EOTF does, yes, but I feel there is a nuanced difference. A piece of equipment implements an EOTF by turning an electrical signal into light, hence EOTF often refers to specific equipment. You could talk about content EOTF to denote content value encoding, as opposed to output or display EOTF, but that might be confusing if you look at e.g. the diagrams in BT.2100: is it the EOTF or is it the inverse OETF? Is the (inverse?) OOTF included?
So I try to side-step those questions by talking about encoding.
The idea here is that frame buffer presented to display plane engine will be non-linear. So output of a media decode should result in content with EOTF applied. Playback transfer function (EOTF): inverse OETF plus rendering intent gamma.
To make it linear, we should apply the OETF. Confusion is whether OETF is equivalent to inverse EOTF, we could check this one out to confirm.
Here since the values for the pre-curve (or degamma as we have called it in past), accepts programmable lut values which makes it flexible enough to accommodate any values. This will hold for HDR as well as traditional gamma encoded SRGB data as well.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
I think this and the above description ties the intended use down too much. This is one possible way to use degamma, yes, but there may be others. Particularly if CTM can be replaced with a 3D LUT, then the degamma is more likely a shaper (non-linear adjustment to 3D LUT tap positions).
Yeah agree, this is just one of the usecases. Its just a lut table which can be used for other purposes as well and is not just limited to a linearization operation. I will update this.
I would prefer the name pre-curve to underline that this can be whatever one wants it to be, but I understand that people may be more familiar with the name degamma.
I feel pre-curve should be fine but yeah it deviates from naming of legacy crtc/pipe color properties. May be we can stay with legacy naming with more documentation to have its usecases clearly called out.
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which +advertizes the
Is enum with blob id values even a thing?
Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrjala@linux.intel.com brainchild)
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
This enum with blob id's is an interesting way to advertise segmented lut tables.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
For Intel's hardware these are luts but yeah AMD hardware seems to have these as fixed function units. We should think of a way to have this option as well in the UAPI. We could extend the DEGAMMA_MODE property to have all the info, and DEGAMMA_LUT_PROPERTY may not be needed based on some of the attributes passed via DEGAMMA_MODE. This can be one way to have room for both. @harry.wentland@amd.com thoughts ?
LUT size, precision, and other details of each degamma mode would be good to expose somehow. I kind of expected those would have been exposed through the above mentioned "enum with blob id values" where each blob content structure is defined by the respective enum value.
Yes, you are spot on here.
+* Plane CTM
- This is a Property to program the color transformation matrix.
No mode property here? Is there any hardware with something else than a matrix at this point?
Not that I am aware of.
Should we assume there will be hardware with something else, and have a CSC mode property with only a single enum value defined so far: "matrix"? Or do we say PLANE_CTM is a matrix and if you have something else in hardware, then invent a new property for it?
I think this should be good as we have this for crtc with no one complaining. There may be hardware with fixed function operation for the CSC but then its not a matrix and it would be pretty hardware dependent, so we can leave that from a generic UAPI.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
Sure, will drop this wording here. But one open will still remain for userspace, as to how it gets the pipeline dynamically for a respective hardware. Currently we have assumed that this would be the logical fixed order of hardware units.
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
Speaking of color space conversions, we should probably define what happens to out-of-range color values. Converting color into smaller gamut or smaller dynamic range always has the risk of ending up with out-of-range values. I suppose those get simply clipped independently on each color channel, right?
We have standard matrix to convert colorspaces. This is just the property of the colorspace, I guess clipping will be the only option here (irrespective of hardware)
Such clipping can change hue, so userspace would be better avoid triggering clipping at all, but we still need to know what would happen with out-of-range values.
We would also need to know when clipping will happen. If FP16 (half-float) FB produces out-of-range values and degamma stage is not used, will the CTM see original or clipped values? Or is that something we have to define as hardware-specific?
Generic userspace will try hard to avoid triggering hardware-specific behaviour, so you can expect such behaviour to go unused.
Here hardware should just operate on the matrix values programmed. This should be the limitation of the color space conversion operation and hardware may not have any role to play apart from just honoring the matrix values and producing the resultant output.
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
I like this wording better than the wording for pre-curve: "can", not "will". It leaves room for creative use of this processing block.
Ok thanks, will update pre-curve section as well.
Tone-mapping is needed always when dynamic range differs, so also for HDR to HDR, not just SDR to/from HDR.
Yes correct, will update.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
The same comments here as with DEGAMMA.
Noted.
+This is part of one plane engine. Data from multiple planes will be +then fed to pipe where it will get blended. There is a similar set +of properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR │
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone
Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR
├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ │
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data
in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │ │
EOTF, not OETF, since it is converting E to O, electrical to optical.
I think media decode would have given a EOTF applied data to be directly consumed by display sink (in case we have chosen a display pass through). Not sure here though, it’s a bit confusing.
- │ │ │
- │ │ │
+│ │ │
+┌────────────────────────────────────────────────────────────────── ──
+───────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone ├─────►
TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
Blending does not change whether the data is linear or not. I suppose in this example, CRTC degamma and CTM would be passthrough, and gamma would be the inverse display EOTF for encoding color values into what the monitor expects.
Yeah, will update this to make it clear.
+This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for +gamut conversion. It also includes Gamma support used to again +non-linearize data as per panel supported color space. These can be +utilize by user space to convert planes from one format to another, +one color space to another etc.
FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work.
This is great to hear that we are aligned wrt how the pipeline should work.
Thanks Pekka for taking time out and providing the feedback.
@harry.wentland@amd.com We can work together and build our design to accommodate both Intel and AMD's hardware needs. This will also make things generic enough for any other hardware vendor as well.
Thanks & Regards, Uma Shankar
+Userspace can take smart blending decisions and utilize these +hardware supported plane color features to get accurate color +profile. The same can help in consistent color quality from source +to panel taking advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific +implementation on top of this series.
+Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
Thanks, pq
On Tue, 12 Oct 2021 20:58:27 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
...
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
As you want to produce light-linear values, you use EOTF or inverse OETF.
The term OETF has a built-in assumption that that happens in a camera: it takes in light and produces and electrical signal. Lately I have personally started talking about non-linear encoding of color values, since EOTF is often associated with displays if nothing else is said (taking in an electrical signal and producing light).
So this would be decoding the color values into light-linear color values. That is what an EOTF does, yes, but I feel there is a nuanced difference. A piece of equipment implements an EOTF by turning an electrical signal into light, hence EOTF often refers to specific equipment. You could talk about content EOTF to denote content value encoding, as opposed to output or display EOTF, but that might be confusing if you look at e.g. the diagrams in BT.2100: is it the EOTF or is it the inverse OETF? Is the (inverse?) OOTF included?
So I try to side-step those questions by talking about encoding.
The idea here is that frame buffer presented to display plane engine will be non-linear. So output of a media decode should result in content with EOTF applied.
Hi,
sure, but the question is: which EOTF. There can be many different things called "EOTF" in a single pipeline, and then it's up to the document writer to make the difference between them. Comparing two documents with different conventions causes a lot of confusion in my personal experience, so it is good to define the concepts more carefully.
So output of a media decode should result in content with EOTF applied.
I suspect you have it backwards. Media decode produces electrical (non-linear) pixel color values. If EOTF was applied, they would be linear instead (and require more memory to achieve the same visual precision).
If you want to put it this way, you could say "with inverse EOTF applied", but that might be slightly confusing because it is already baked in to the video, it's not something a media decoder has to specifically apply, I think. However, the (inverse) EOTF in this case is the content EOTF, not the display EOTF.
If content and display EOTF differ, then one must apply first content EOTF and then inverse display EOTF to get values that are correctly encoded for the display. (This is necessary but not sufficient in general.) Mind, that this is not an OOTF nor an artistic adjustment, this is purely a value encoding conversion.
Playback transfer function (EOTF): inverse OETF plus rendering intent gamma.
Does "rendering intent gamma" refer to artistic adjustments, not OOTF?
cf. BT.2100 Annex 1, "The relationship between the OETF, the EOTF and the OOTF", although I find those diagrams somewhat confusing still. It does not seem to clearly account for transmission non-linear encoding being different from the display EOTF.
Different documents use OOTF to refer to different things. Then there is also the fundamental difference between PQ and HLG systems, where OOTF is by definition in different places of the camera-transmission-display pipeline.
To make it linear, we should apply the OETF. Confusion is whether OETF is equivalent to inverse EOTF, we could check this one out to confirm.
OETF does not make anything linear. By definition, OETF converts optical (linear) values into electrical (practically always non-linearly encoded) values.
Yes, EOTF is almost always not equal to inverse OETF because of the existence of OOTF. The applies to inverse EOTF vs. OETF as well.
From what I have learned, it is unexpected to assume that inverse of one is the other. That will cause confusion. Therefore, if you mean the inverse, spell it out as inverse. I used to make this same mistake, and some of it may still be left in https://gitlab.freedesktop.org/pq/color-and-hdr .
Here since the values for the pre-curve (or degamma as we have called it in past), accepts programmable lut values which makes it flexible enough to accommodate any values. This will hold for HDR as well as traditional gamma encoded SRGB data as well.
Yes.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
I think this and the above description ties the intended use down too much. This is one possible way to use degamma, yes, but there may be others. Particularly if CTM can be replaced with a 3D LUT, then the degamma is more likely a shaper (non-linear adjustment to 3D LUT tap positions).
Yeah agree, this is just one of the usecases. Its just a lut table which can be used for other purposes as well and is not just limited to a linearization operation. I will update this.
I would prefer the name pre-curve to underline that this can be whatever one wants it to be, but I understand that people may be more familiar with the name degamma.
I feel pre-curve should be fine but yeah it deviates from naming of legacy crtc/pipe color properties. May be we can stay with legacy naming with more documentation to have its usecases clearly called out.
That is fine by me.
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which +advertizes the
Is enum with blob id values even a thing?
Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrjala@linux.intel.com brainchild)
Yes, I think I can imagine how that works. The blobs are created immutable, unable to change once the plane has been advertised to userspace, because their IDs are used as enum values. But that is ok, because the blob describes capabilities that cannot change during the device's lifetime... or can they? What if you would want to extend the blob format, do you need a KMS client cap to change the format which would be impossible because you can't change an enum definition after it has been installed so you cannot swap the blob to a new one?
This also relies on enums being identified by their string names, because the numerical value is not a constant but a blob ID and gets determined when the immutable blob is created.
Did I understand correctly?
As a userspace developer, I can totally work with that.
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
This enum with blob id's is an interesting way to advertise segmented lut tables.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
For Intel's hardware these are luts but yeah AMD hardware seems to have these as fixed function units. We should think of a way to have this option as well in the UAPI. We could extend the DEGAMMA_MODE property to have all the info, and DEGAMMA_LUT_PROPERTY may not be needed based on some of the attributes passed via DEGAMMA_MODE. This can be one way to have room for both. @harry.wentland@amd.com thoughts ?
Yeah, though I don't think you can use DEGAMMA_MODE property to pass parameters to fixed-function curves. The parameters need another property. Would be natural to use the other property for LUT data when mode it set to LUT.
A trivial and made-up example of a parameterised fixed-function curve is pow(x, gamma), where gamma is the parameter.
LUT size, precision, and other details of each degamma mode would be good to expose somehow. I kind of expected those would have been exposed through the above mentioned "enum with blob id values" where each blob content structure is defined by the respective enum value.
Yes, you are spot on here.
+* Plane CTM
- This is a Property to program the color transformation matrix.
No mode property here? Is there any hardware with something else than a matrix at this point?
Not that I am aware of.
Should we assume there will be hardware with something else, and have a CSC mode property with only a single enum value defined so far: "matrix"? Or do we say PLANE_CTM is a matrix and if you have something else in hardware, then invent a new property for it?
I think this should be good as we have this for crtc with no one complaining. There may be hardware with fixed function operation for the CSC but then its not a matrix and it would be pretty hardware dependent, so we can leave that from a generic UAPI.
Ok. And if that eventually turns out to be a mistake, it's easy to invent more properties.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
Sure, will drop this wording here. But one open will still remain for userspace, as to how it gets the pipeline dynamically for a respective hardware. Currently we have assumed that this would be the logical fixed order of hardware units.
If we cannot model the abstract KMS pipeline as a fixed order of units (where each unit may exist or not), we need to take a few steps back here and look at what do we actually want to expose. That is a much bigger design problem which we are currently not even considering.
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
Speaking of color space conversions, we should probably define what happens to out-of-range color values. Converting color into smaller gamut or smaller dynamic range always has the risk of ending up with out-of-range values. I suppose those get simply clipped independently on each color channel, right?
We have standard matrix to convert colorspaces. This is just the property of the colorspace, I guess clipping will be the only option here (irrespective of hardware)
Such clipping can change hue, so userspace would be better avoid triggering clipping at all, but we still need to know what would happen with out-of-range values.
We would also need to know when clipping will happen. If FP16 (half-float) FB produces out-of-range values and degamma stage is not used, will the CTM see original or clipped values? Or is that something we have to define as hardware-specific?
Generic userspace will try hard to avoid triggering hardware-specific behaviour, so you can expect such behaviour to go unused.
Here hardware should just operate on the matrix values programmed. This should be the limitation of the color space conversion operation and hardware may not have any role to play apart from just honoring the matrix values and producing the resultant output.
I'm not talking about the matrix values. I'm talking about the values originating from the FB, are they clipped or not, before being processed by the matrix?
Userspace could want to use the matrix to bring out-of-range FB values into range, but that plan cannot work if the FB values get clipped already before the matrix.
I referred to FP16 format explicitly because that format can express values outside of the usual [0.0, 1.0] range in a framebuffer.
Of course, the matrix values themselves have some limits too, and userspace should somehow be aware of them.
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
I like this wording better than the wording for pre-curve: "can", not "will". It leaves room for creative use of this processing block.
Ok thanks, will update pre-curve section as well.
Tone-mapping is needed always when dynamic range differs, so also for HDR to HDR, not just SDR to/from HDR.
Yes correct, will update.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
The same comments here as with DEGAMMA.
Noted.
+This is part of one plane engine. Data from multiple planes will be +then fed to pipe where it will get blended. There is a similar set +of properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR │
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone
Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR
├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ │
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data
in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │ │
EOTF, not OETF, since it is converting E to O, electrical to optical.
I think media decode would have given a EOTF applied data to be directly consumed by display sink (in case we have chosen a display pass through). Not sure here though, it’s a bit confusing.
I hope I managed to explain this earlier in this email.
Display sinks "always" use non-linearly encoded values, because it saves bandwidth without losing visual quality. For the same reason, images tend to be stored with non-linear value encoding whenever possible.
Thanks, pq
- │ │ │
- │ │ │
+│ │ │
+┌────────────────────────────────────────────────────────────────── ──
+───────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone ├─────►
TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
Blending does not change whether the data is linear or not. I suppose in this example, CRTC degamma and CTM would be passthrough, and gamma would be the inverse display EOTF for encoding color values into what the monitor expects.
Yeah, will update this to make it clear.
+This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for +gamut conversion. It also includes Gamma support used to again +non-linearize data as per panel supported color space. These can be +utilize by user space to convert planes from one format to another, +one color space to another etc.
FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work.
This is great to hear that we are aligned wrt how the pipeline should work.
Thanks Pekka for taking time out and providing the feedback.
@harry.wentland@amd.com We can work together and build our design to accommodate both Intel and AMD's hardware needs. This will also make things generic enough for any other hardware vendor as well.
Thanks & Regards, Uma Shankar
+Userspace can take smart blending decisions and utilize these +hardware supported plane color features to get accurate color +profile. The same can help in consistent color quality from source +to panel taking advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific +implementation on top of this series.
+Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
Thanks, pq
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Wednesday, October 13, 2021 2:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: harry.wentland@amd.com; ville.syrjala@linux.intel.com; intel- gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 20:58:27 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
...
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
As you want to produce light-linear values, you use EOTF or inverse OETF.
The term OETF has a built-in assumption that that happens in a camera: it takes in light and produces and electrical signal. Lately I have personally started talking about non-linear encoding of color values, since EOTF is often associated with displays if nothing else is said (taking
in an electrical signal and producing light).
So this would be decoding the color values into light-linear color values. That is what an EOTF does, yes, but I feel there is a nuanced difference. A piece of equipment implements an EOTF by turning an electrical signal into light, hence EOTF often refers to specific equipment. You could talk about content EOTF to denote content value encoding, as opposed to output or display EOTF, but that might be confusing if you look at e.g. the diagrams in BT.2100: is it the EOTF
or is it the inverse OETF? Is the (inverse?) OOTF included?
So I try to side-step those questions by talking about encoding.
The idea here is that frame buffer presented to display plane engine will be non-
linear.
So output of a media decode should result in content with EOTF applied.
Hi,
sure, but the question is: which EOTF. There can be many different things called "EOTF" in a single pipeline, and then it's up to the document writer to make the difference between them. Comparing two documents with different conventions causes a lot of confusion in my personal experience, so it is good to define the concepts more carefully.
Hi Pekka, I think you have given some nice inputs to really deep dive and document here. Will update this with the right expectations wrt what transfer functions to be used at various stages in the operation pipeline.
So output of a media decode should result in content with EOTF applied.
I suspect you have it backwards. Media decode produces electrical (non-linear) pixel color values. If EOTF was applied, they would be linear instead (and require more memory to achieve the same visual precision).
If you want to put it this way, you could say "with inverse EOTF applied", but that might be slightly confusing because it is already baked in to the video, it's not something a media decoder has to specifically apply, I think. However, the (inverse) EOTF in this case is the content EOTF, not the display EOTF.
If content and display EOTF differ, then one must apply first content EOTF and then inverse display EOTF to get values that are correctly encoded for the display. (This is necessary but not sufficient in general.) Mind, that this is not an OOTF nor an artistic adjustment, this is purely a value encoding conversion.
0
Got it, thanks for correcting. Will also do some more study around this and update.
Playback transfer function (EOTF): inverse OETF plus rendering intent gamma.
Does "rendering intent gamma" refer to artistic adjustments, not OOTF? ]
This ideally should be OOTF adjustments here.
cf. BT.2100 Annex 1, "The relationship between the OETF, the EOTF and the OOTF", although I find those diagrams somewhat confusing still. It does not seem to clearly account for transmission non-linear encoding being different from the display EOTF.
Different documents use OOTF to refer to different things. Then there is also the fundamental difference between PQ and HLG systems, where OOTF is by definition in different places of the camera-transmission-display pipeline.
Agree this is a bit confusing, I admit I was much more confused than what you were for sure. Will do some research to get my understanding in place. Thanks for all the inputs.
To make it linear, we should apply the OETF. Confusion is whether OETF is equivalent to inverse EOTF, we could check this one out to confirm.
OETF does not make anything linear. By definition, OETF converts optical (linear) values into electrical (practically always non-linearly encoded) values.
Yes, EOTF is almost always not equal to inverse OETF because of the existence of OOTF. The applies to inverse EOTF vs. OETF as well.
From what I have learned, it is unexpected to assume that inverse of one is the other. That will cause confusion. Therefore, if you mean the inverse, spell it out as inverse. I used to make this same mistake, and some of it may still be left in https://gitlab.freedesktop.org/pq/color-and-hdr .
Got it.
Here since the values for the pre-curve (or degamma as we have called it in past), accepts programmable lut values which makes it flexible enough to
accommodate any values.
This will hold for HDR as well as traditional gamma encoded SRGB data as well.
Yes.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
I think this and the above description ties the intended use down too much. This is one possible way to use degamma, yes, but there may be others. Particularly if CTM can be replaced with a 3D LUT, then the degamma is more likely a shaper (non-linear adjustment to 3D LUT tap
positions).
Yeah agree, this is just one of the usecases. Its just a lut table which can be used for other purposes as well and is not just limited to a
linearization operation. I will update this.
I would prefer the name pre-curve to underline that this can be whatever one wants it to be, but I understand that people may be more familiar
with the name degamma.
I feel pre-curve should be fine but yeah it deviates from naming of legacy crtc/pipe
color properties.
May be we can stay with legacy naming with more documentation to have its
usecases clearly called out.
That is fine by me.
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which +advertizes the
Is enum with blob id values even a thing?
Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrjala@linux.intel.com brainchild)
Yes, I think I can imagine how that works. The blobs are created immutable, unable to change once the plane has been advertised to userspace, because their IDs are used as enum values. But that is ok, because the blob describes capabilities that cannot change during the device's lifetime... or can they? What if you would want to extend the blob format, do you need a KMS client cap to change the format which would be impossible because you can't change an enum definition after it has been installed so you cannot swap the blob to a new one?
This also relies on enums being identified by their string names, because the numerical value is not a constant but a blob ID and gets determined when the immutable blob is created.
Did I understand correctly?
Yes that’s right. We are not expecting these structures to change as they represent the platforms capabilities.
As a userspace developer, I can totally work with that.
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
This enum with blob id's is an interesting way to advertise segmented lut tables.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
For Intel's hardware these are luts but yeah AMD hardware seems to have these as fixed function units. We should think of a way to have this option as well in the UAPI. We could extend the DEGAMMA_MODE property to have all the info, and DEGAMMA_LUT_PROPERTY may not be needed based on some of the attributes passed via DEGAMMA_MODE. This can be
one way to have room for both.
@harry.wentland@amd.com thoughts ?
Yeah, though I don't think you can use DEGAMMA_MODE property to pass parameters to fixed-function curves. The parameters need another property. Would be natural to use the other property for LUT data when mode it set to LUT.
A trivial and made-up example of a parameterised fixed-function curve is pow(x, gamma), where gamma is the parameter.
We can maybe have a parallel property as well with proper documentation if this helps with flexibility for varying hardware vendors. UAPI document will list what to use and when. May be platform will not even list the other one which may make things less complicated to userspace.
LUT size, precision, and other details of each degamma mode would be good to expose somehow. I kind of expected those would have been exposed through the above mentioned "enum with blob id values" where each blob content structure is defined by the respective enum value.
Yes, you are spot on here.
+* Plane CTM
- This is a Property to program the color transformation matrix.
No mode property here? Is there any hardware with something else than a matrix at this point?
Not that I am aware of.
Should we assume there will be hardware with something else, and have a CSC mode property with only a single enum value defined so far: "matrix"? Or do we say PLANE_CTM is a matrix and if you have something else in hardware, then invent a new property for it?
I think this should be good as we have this for crtc with no one complaining. There may be hardware with fixed function operation for the CSC but then its not a matrix and it would be pretty hardware dependent, so we can leave that from a generic UAPI.
Ok. And if that eventually turns out to be a mistake, it's easy to invent more properties.
I feel that is what would be required. This is just another instance of what we have at crtc level.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
Sure, will drop this wording here. But one open will still remain for userspace, as to how it gets the pipeline dynamically for a respective hardware. Currently we have assumed that this would be the logical fixed order of hardware units.
If we cannot model the abstract KMS pipeline as a fixed order of units (where each unit may exist or not), we need to take a few steps back here and look at what do we actually want to expose. That is a much bigger design problem which we are currently not even considering.
I think most of the hardware vendor platforms have this pipeline, so we can implement the properties which include all the possible hardware blocks. If certain units don't exist, the respective properties should not be exposed which will make things easier for userspace.
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide +CTM
coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
Speaking of color space conversions, we should probably define what happens to out-of-range color values. Converting color into smaller gamut or smaller dynamic range always has the risk of ending up with out-of-range values. I suppose those get simply clipped independently on each
color channel, right?
We have standard matrix to convert colorspaces. This is just the property of the colorspace, I guess clipping will be the only option here (irrespective of hardware)
Such clipping can change hue, so userspace would be better avoid triggering clipping at all, but we still need to know what would happen with out-
of-range values.
We would also need to know when clipping will happen. If FP16 (half-float) FB produces out-of-range values and degamma stage is not used, will the CTM see original or clipped values? Or is that something we have to define as hardware-specific?
Generic userspace will try hard to avoid triggering hardware-specific behaviour, so you can expect such behaviour to go unused.
Here hardware should just operate on the matrix values programmed. This should be the limitation of the color space conversion operation and hardware may not have any role to play apart from just honoring the matrix values and producing the resultant output.
I'm not talking about the matrix values. I'm talking about the values originating from the FB, are they clipped or not, before being processed by the matrix?
Userspace could want to use the matrix to bring out-of-range FB values into range, but that plan cannot work if the FB values get clipped already before the matrix.
I referred to FP16 format explicitly because that format can express values outside of the usual [0.0, 1.0] range in a framebuffer.
Of course, the matrix values themselves have some limits too, and userspace should somehow be aware of them.
AFAIK, the values will not be clipped before being submitted to CSC blocks. But this can be confirmed to not leave any misconception here.
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
I like this wording better than the wording for pre-curve: "can", not "will". It leaves room for creative use of this processing block.
Ok thanks, will update pre-curve section as well.
Tone-mapping is needed always when dynamic range differs, so also for HDR to HDR, not just SDR to/from HDR.
Yes correct, will update.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
The same comments here as with DEGAMMA.
Noted.
+This is part of one plane engine. Data from multiple planes +will be then fed to pipe where it will get blended. There is a +similar set of properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR
│
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone
Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
│
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR
├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │
│
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
│
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data
in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │ │
EOTF, not OETF, since it is converting E to O, electrical to optical.
I think media decode would have given a EOTF applied data to be directly consumed by display sink (in case we have chosen a display pass through).
Not sure here though, it’s a bit confusing.
I hope I managed to explain this earlier in this email.
Display sinks "always" use non-linearly encoded values, because it saves bandwidth without losing visual quality. For the same reason, images tend to be stored with non-linear value encoding whenever possible.
Yeah, thanks for the explanation and useful pointers. Will work on it to put the right expectations in the document.
Thanks Pekka for the valuable feedback.
Regards, Uma Shankar
Thanks, pq
- │ │ │
- │ │ │
+│ │ │
+┌──────────────────────────────────────────────────────────────────
──
+───────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone +├─────►
TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
Blending does not change whether the data is linear or not. I suppose in this example, CRTC degamma and CTM would be passthrough, and gamma would be the inverse display EOTF for encoding color values into
what the monitor expects.
Yeah, will update this to make it clear.
+This patch series adds properties for plane color features. It +adds properties for degamma used to linearize data and CSC used +for gamut conversion. It also includes Gamma support used to +again non-linearize data as per panel supported color space. +These can be utilize by user space to convert planes from one +format to another, one color space to another etc.
FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work.
This is great to hear that we are aligned wrt how the pipeline should work.
Thanks Pekka for taking time out and providing the feedback.
@harry.wentland@amd.com We can work together and build our design to accommodate both Intel and AMD's hardware needs. This will also make things generic enough for any other hardware vendor as well.
Thanks & Regards, Uma Shankar
+Userspace can take smart blending decisions and utilize these +hardware supported plane color features to get accurate color +profile. The same can help in consistent color quality from +source to panel taking advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. +We can build up and add other platform/hardware specific +implementation on top of this series.
+Credits: Special mention and credits to Ville Syrjala for +coming up with a design for this feature and inputs. This +series is based on his original design and idea.
Thanks, pq
On Thu, 14 Oct 2021 19:44:25 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Wednesday, October 13, 2021 2:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: harry.wentland@amd.com; ville.syrjala@linux.intel.com; intel- gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 20:58:27 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
...
cf. BT.2100 Annex 1, "The relationship between the OETF, the EOTF and the OOTF", although I find those diagrams somewhat confusing still. It does not seem to clearly account for transmission non-linear encoding being different from the display EOTF.
Different documents use OOTF to refer to different things. Then there is also the fundamental difference between PQ and HLG systems, where OOTF is by definition in different places of the camera-transmission-display pipeline.
Agree this is a bit confusing, I admit I was much more confused than what you were for sure. Will do some research to get my understanding in place. Thanks for all the inputs.
I'm sure I was at least equally confused or even more at the start. I have just had a year of casual reading, discussions, and a W3C workshop attendance to improve my understanding. :-)
Now I know enough to be dangerous.
...
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which +advertizes the
Is enum with blob id values even a thing?
Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrjala@linux.intel.com brainchild)
Yes, I think I can imagine how that works. The blobs are created immutable, unable to change once the plane has been advertised to userspace, because their IDs are used as enum values. But that is ok, because the blob describes capabilities that cannot change during the device's lifetime... or can they? What if you would want to extend the blob format, do you need a KMS client cap to change the format which would be impossible because you can't change an enum definition after it has been installed so you cannot swap the blob to a new one?
This also relies on enums being identified by their string names, because the numerical value is not a constant but a blob ID and gets determined when the immutable blob is created.
Did I understand correctly?
Yes that’s right. We are not expecting these structures to change as they represent the platforms capabilities.
Until there comes a new platform whose capabilities you cannot quite describe with the existing structure. What's the plan to deal with that? A new enum value, like LUT2 instead of LUT? I suppose that works.
As a userspace developer, I can totally work with that.
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
This enum with blob id's is an interesting way to advertise segmented lut tables.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
For Intel's hardware these are luts but yeah AMD hardware seems to have these as fixed function units. We should think of a way to have this option as well in the UAPI. We could extend the DEGAMMA_MODE property to have all the info, and DEGAMMA_LUT_PROPERTY may not be needed based on some of the attributes passed via DEGAMMA_MODE. This can be
one way to have room for both.
@harry.wentland@amd.com thoughts ?
Yeah, though I don't think you can use DEGAMMA_MODE property to pass parameters to fixed-function curves. The parameters need another property. Would be natural to use the other property for LUT data when mode it set to LUT.
A trivial and made-up example of a parameterised fixed-function curve is pow(x, gamma), where gamma is the parameter.
We can maybe have a parallel property as well with proper documentation if this helps with flexibility for varying hardware vendors. UAPI document will list what to use and when. May be platform will not even list the other one which may make things less complicated to userspace.
I'm not sure I got what you're thinking. My idea is that the interpretation of the blob contents depends on the value of the mode enum. Obviously the two will always need to be set together by userspace to ensure they match, otherwise DRM needs to reject the commit.
The rest of your comments I agree with.
Thanks, pq
Thanks, Uma, for the updated patches. I'm finally finding time to go through them.
On 2021-10-15 03:42, Pekka Paalanen wrote:
On Thu, 14 Oct 2021 19:44:25 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Wednesday, October 13, 2021 2:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: harry.wentland@amd.com; ville.syrjala@linux.intel.com; intel- gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 20:58:27 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
...
cf. BT.2100 Annex 1, "The relationship between the OETF, the EOTF and the OOTF", although I find those diagrams somewhat confusing still. It does not seem to clearly account for transmission non-linear encoding being different from the display EOTF.
Different documents use OOTF to refer to different things. Then there is also the fundamental difference between PQ and HLG systems, where OOTF is by definition in different places of the camera-transmission-display pipeline.
Agree this is a bit confusing, I admit I was much more confused than what you were for sure. Will do some research to get my understanding in place. Thanks for all the inputs.
I'm sure I was at least equally confused or even more at the start. I have just had a year of casual reading, discussions, and a W3C workshop attendance to improve my understanding. :-)
Now I know enough to be dangerous.
...
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which +advertizes the
Is enum with blob id values even a thing?
Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrjala@linux.intel.com brainchild)
Yes, I think I can imagine how that works. The blobs are created immutable, unable to change once the plane has been advertised to userspace, because their IDs are used as enum values. But that is ok, because the blob describes capabilities that cannot change during the device's lifetime... or can they? What if you would want to extend the blob format, do you need a KMS client cap to change the format which would be impossible because you can't change an enum definition after it has been installed so you cannot swap the blob to a new one?
This also relies on enums being identified by their string names, because the numerical value is not a constant but a blob ID and gets determined when the immutable blob is created.
Did I understand correctly?
Yes that’s right. We are not expecting these structures to change as they represent the platforms capabilities.
Until there comes a new platform whose capabilities you cannot quite describe with the existing structure. What's the plan to deal with that? A new enum value, like LUT2 instead of LUT? I suppose that works.
See my comment on the coverletter. It would be great if we could come up with a PWL definition that's generic enough to work on all HW that uses PWL and not require compositors to learn a new LUT2 type in the future.
As a userspace developer, I can totally work with that.
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
This enum with blob id's is an interesting way to advertise segmented lut tables.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
For Intel's hardware these are luts but yeah AMD hardware seems to have these as fixed function units. We should think of a way to have this option as well in the UAPI. We could extend the DEGAMMA_MODE property to have all the info, and DEGAMMA_LUT_PROPERTY may not be needed based on some of the attributes passed via DEGAMMA_MODE. This can be
one way to have room for both.
@harry.wentland@amd.com thoughts ?
Yeah, though I don't think you can use DEGAMMA_MODE property to pass parameters to fixed-function curves. The parameters need another property. Would be natural to use the other property for LUT data when mode it set to LUT.
A trivial and made-up example of a parameterised fixed-function curve is pow(x, gamma), where gamma is the parameter.
It's a bit HW dependent. Some of AMD HW has some pre-defined EOTF ROMs who allowing us to program a RAM LUT in the same block. Other HW split those into two independent, consecutive blocks, a pre-defined EOTF ROM first, followed by a Gamma Correction RAM LUT.
These can probably both be supported the the proposed PLANE_DEGAMMA_LUT with enum values for the predefined (sRGB, BT2020, etc.) EOTFs, as well as an option for a programmable LUT.
Harry
We can maybe have a parallel property as well with proper documentation if this helps with flexibility for varying hardware vendors. UAPI document will list what to use and when. May be platform will not even list the other one which may make things less complicated to userspace.
I'm not sure I got what you're thinking. My idea is that the interpretation of the blob contents depends on the value of the mode enum. Obviously the two will always need to be set together by userspace to ensure they match, otherwise DRM needs to reject the commit.
The rest of your comments I agree with.
Thanks, pq
On 2021-10-14 15:44, Shankar, Uma wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Wednesday, October 13, 2021 2:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: harry.wentland@amd.com; ville.syrjala@linux.intel.com; intel- gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 12 Oct 2021 20:58:27 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties
...
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
As you want to produce light-linear values, you use EOTF or inverse OETF.
The term OETF has a built-in assumption that that happens in a camera: it takes in light and produces and electrical signal. Lately I have personally started talking about non-linear encoding of color values, since EOTF is often associated with displays if nothing else is said (taking
in an electrical signal and producing light).
So this would be decoding the color values into light-linear color values. That is what an EOTF does, yes, but I feel there is a nuanced difference. A piece of equipment implements an EOTF by turning an electrical signal into light, hence EOTF often refers to specific equipment. You could talk about content EOTF to denote content value encoding, as opposed to output or display EOTF, but that might be confusing if you look at e.g. the diagrams in BT.2100: is it the EOTF
or is it the inverse OETF? Is the (inverse?) OOTF included?
So I try to side-step those questions by talking about encoding.
The idea here is that frame buffer presented to display plane engine will be non-
linear.
So output of a media decode should result in content with EOTF applied.
Hi,
sure, but the question is: which EOTF. There can be many different things called "EOTF" in a single pipeline, and then it's up to the document writer to make the difference between them. Comparing two documents with different conventions causes a lot of confusion in my personal experience, so it is good to define the concepts more carefully.
Hi Pekka, I think you have given some nice inputs to really deep dive and document here. Will update this with the right expectations wrt what transfer functions to be used at various stages in the operation pipeline.
So output of a media decode should result in content with EOTF applied.
I suspect you have it backwards. Media decode produces electrical (non-linear) pixel color values. If EOTF was applied, they would be linear instead (and require more memory to achieve the same visual precision).
If you want to put it this way, you could say "with inverse EOTF applied", but that might be slightly confusing because it is already baked in to the video, it's not something a media decoder has to specifically apply, I think. However, the (inverse) EOTF in this case is the content EOTF, not the display EOTF.
If content and display EOTF differ, then one must apply first content EOTF and then inverse display EOTF to get values that are correctly encoded for the display. (This is necessary but not sufficient in general.) Mind, that this is not an OOTF nor an artistic adjustment, this is purely a value encoding conversion.
0
Got it, thanks for correcting. Will also do some more study around this and update.
Playback transfer function (EOTF): inverse OETF plus rendering intent gamma.
Does "rendering intent gamma" refer to artistic adjustments, not OOTF? ]
This ideally should be OOTF adjustments here.
cf. BT.2100 Annex 1, "The relationship between the OETF, the EOTF and the OOTF", although I find those diagrams somewhat confusing still. It does not seem to clearly account for transmission non-linear encoding being different from the display EOTF.
Different documents use OOTF to refer to different things. Then there is also the fundamental difference between PQ and HLG systems, where OOTF is by definition in different places of the camera-transmission-display pipeline.
Agree this is a bit confusing, I admit I was much more confused than what you were for sure. Will do some research to get my understanding in place. Thanks for all the inputs.
To make it linear, we should apply the OETF. Confusion is whether OETF is equivalent to inverse EOTF, we could check this one out to confirm.
OETF does not make anything linear. By definition, OETF converts optical (linear) values into electrical (practically always non-linearly encoded) values.
Yes, EOTF is almost always not equal to inverse OETF because of the existence of OOTF. The applies to inverse EOTF vs. OETF as well.
From what I have learned, it is unexpected to assume that inverse of one is the other. That will cause confusion. Therefore, if you mean the inverse, spell it out as inverse. I used to make this same mistake, and some of it may still be left in https://gitlab.freedesktop.org/pq/color-and-hdr .
Got it.
Here since the values for the pre-curve (or degamma as we have called it in past), accepts programmable lut values which makes it flexible enough to
accommodate any values.
This will hold for HDR as well as traditional gamma encoded SRGB data as well.
Yes.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
I think this and the above description ties the intended use down too much. This is one possible way to use degamma, yes, but there may be others. Particularly if CTM can be replaced with a 3D LUT, then the degamma is more likely a shaper (non-linear adjustment to 3D LUT tap
positions).
Yeah agree, this is just one of the usecases. Its just a lut table which can be used for other purposes as well and is not just limited to a
linearization operation. I will update this.
I would prefer the name pre-curve to underline that this can be whatever one wants it to be, but I understand that people may be more familiar
with the name degamma.
I feel pre-curve should be fine but yeah it deviates from naming of legacy crtc/pipe
color properties.
May be we can stay with legacy naming with more documentation to have its
usecases clearly called out.
That is fine by me.
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which +advertizes the
Is enum with blob id values even a thing?
Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrjala@linux.intel.com brainchild)
Yes, I think I can imagine how that works. The blobs are created immutable, unable to change once the plane has been advertised to userspace, because their IDs are used as enum values. But that is ok, because the blob describes capabilities that cannot change during the device's lifetime... or can they? What if you would want to extend the blob format, do you need a KMS client cap to change the format which would be impossible because you can't change an enum definition after it has been installed so you cannot swap the blob to a new one?
This also relies on enums being identified by their string names, because the numerical value is not a constant but a blob ID and gets determined when the immutable blob is created.
Did I understand correctly?
Yes that’s right. We are not expecting these structures to change as they represent the platforms capabilities.
As a userspace developer, I can totally work with that.
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
I agree that some sort of "mode" switch is necessary, and advertisement of capabilities as well.
This enum with blob id's is an interesting way to advertise segmented lut tables.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
So all degamma modes will always be some kind of LUT? That may be a bit restrictive, as I understand AMD may have predefined or parameterised curves that are not LUTs. So there should be room for an arbitrary structure of parameters, which can be passed in as a blob id, and the contents defined by the degamma mode.
For Intel's hardware these are luts but yeah AMD hardware seems to have these as fixed function units. We should think of a way to have this option as well in the UAPI. We could extend the DEGAMMA_MODE property to have all the info, and DEGAMMA_LUT_PROPERTY may not be needed based on some of the attributes passed via DEGAMMA_MODE. This can be
one way to have room for both.
@harry.wentland@amd.com thoughts ?
Yeah, though I don't think you can use DEGAMMA_MODE property to pass parameters to fixed-function curves. The parameters need another property. Would be natural to use the other property for LUT data when mode it set to LUT.
A trivial and made-up example of a parameterised fixed-function curve is pow(x, gamma), where gamma is the parameter.
We can maybe have a parallel property as well with proper documentation if this helps with flexibility for varying hardware vendors. UAPI document will list what to use and when. May be platform will not even list the other one which may make things less complicated to userspace.
LUT size, precision, and other details of each degamma mode would be good to expose somehow. I kind of expected those would have been exposed through the above mentioned "enum with blob id values" where each blob content structure is defined by the respective enum value.
Yes, you are spot on here.
+* Plane CTM
- This is a Property to program the color transformation matrix.
No mode property here? Is there any hardware with something else than a matrix at this point?
Not that I am aware of.
Should we assume there will be hardware with something else, and have a CSC mode property with only a single enum value defined so far: "matrix"? Or do we say PLANE_CTM is a matrix and if you have something else in hardware, then invent a new property for it?
I think this should be good as we have this for crtc with no one complaining. There may be hardware with fixed function operation for the CSC but then its not a matrix and it would be pretty hardware dependent, so we can leave that from a generic UAPI.
Ok. And if that eventually turns out to be a mistake, it's easy to invent more properties.
I feel that is what would be required. This is just another instance of what we have at crtc level.
Would a userspace client ever want to use both CTM and 3D LUT?
We could add a mode property to CTM to allow for a CTM or 3D LUT or we could add new properties for 3D LUT support.
3D LUT might come with shaper 1D LUTs that can be programmed in conjunction with the 3D LUT. 3D LUTs operating in non-linear space require less precision than 3D LUTs operating in linear space, hence the 1D LUT can be used to non-linearize the pixel data for 3D LUT operation.
FWIW, AMD HW (depending on generation) can do these operations (in this order):
1) 1D LUT (fixed or PWL programmable) 2) simple multiplier (for scaling SDR content to HDR output) 3) CTM matrix 4) 1D LUT (shaper LUT to non-linearize for more effective 3D LUT transform) 5) 3D LUT 6) 1D LUT (for non-linear blending, or to linearize after 3D LUT) 7) blending 8) CTM matrix 9) 1D LUT (shaper LUT like above) 10) 3D LUT 11) 1D LUT (generally for EOTF^-1 for display EOTF)
Not all blocks are available on all (current and future) HW.
I sketched a few diagrams that show how these might be used by a compositor if we exposed all of these blocks and should really try to add some of them to the color-and-hdr docs repo.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
Sure, will drop this wording here. But one open will still remain for userspace, as to how it gets the pipeline dynamically for a respective hardware. Currently we have assumed that this would be the logical fixed order of hardware units.
If we cannot model the abstract KMS pipeline as a fixed order of units (where each unit may exist or not), we need to take a few steps back here and look at what do we actually want to expose. That is a much bigger design problem which we are currently not even considering.
I think most of the hardware vendor platforms have this pipeline, so we can implement the properties which include all the possible hardware blocks. If certain units don't exist, the respective properties should not be exposed which will make things easier for userspace.
I think the color pipeline should be modeled in a way that makes sense from a color science standpoint and in a way that makes sense for compositor implementations. Fortunately HW design generally aligns with these intentions but we should be careful to not let HW design dictate KMS interfaces.
Harry
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide +CTM
coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
Speaking of color space conversions, we should probably define what happens to out-of-range color values. Converting color into smaller gamut or smaller dynamic range always has the risk of ending up with out-of-range values. I suppose those get simply clipped independently on each
color channel, right?
We have standard matrix to convert colorspaces. This is just the property of the colorspace, I guess clipping will be the only option here (irrespective of hardware)
Such clipping can change hue, so userspace would be better avoid triggering clipping at all, but we still need to know what would happen with out-
of-range values.
We would also need to know when clipping will happen. If FP16 (half-float) FB produces out-of-range values and degamma stage is not used, will the CTM see original or clipped values? Or is that something we have to define as hardware-specific?
Generic userspace will try hard to avoid triggering hardware-specific behaviour, so you can expect such behaviour to go unused.
Here hardware should just operate on the matrix values programmed. This should be the limitation of the color space conversion operation and hardware may not have any role to play apart from just honoring the matrix values and producing the resultant output.
I'm not talking about the matrix values. I'm talking about the values originating from the FB, are they clipped or not, before being processed by the matrix?
Userspace could want to use the matrix to bring out-of-range FB values into range, but that plan cannot work if the FB values get clipped already before the matrix.
I referred to FP16 format explicitly because that format can express values outside of the usual [0.0, 1.0] range in a framebuffer.
Of course, the matrix values themselves have some limits too, and userspace should somehow be aware of them.
AFAIK, the values will not be clipped before being submitted to CSC blocks. But this can be confirmed to not leave any misconception here.
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
I like this wording better than the wording for pre-curve: "can", not "will". It leaves room for creative use of this processing block.
Ok thanks, will update pre-curve section as well.
Tone-mapping is needed always when dynamic range differs, so also for HDR to HDR, not just SDR to/from HDR.
Yes correct, will update.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
The same comments here as with DEGAMMA.
Noted.
+This is part of one plane engine. Data from multiple planes +will be then fed to pipe where it will get blended. There is a +similar set of properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR
│
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone
Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
│
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR
├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │
│
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
│
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data
in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │ │
EOTF, not OETF, since it is converting E to O, electrical to optical.
I think media decode would have given a EOTF applied data to be directly consumed by display sink (in case we have chosen a display pass through).
Not sure here though, it’s a bit confusing.
I hope I managed to explain this earlier in this email.
Display sinks "always" use non-linearly encoded values, because it saves bandwidth without losing visual quality. For the same reason, images tend to be stored with non-linear value encoding whenever possible.
Yeah, thanks for the explanation and useful pointers. Will work on it to put the right expectations in the document.
Thanks Pekka for the valuable feedback.
Regards, Uma Shankar
Thanks, pq
- │ │ │
- │ │ │
+│ │ │
+┌──────────────────────────────────────────────────────────────────
──
+───────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone +├─────►
TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
Blending does not change whether the data is linear or not. I suppose in this example, CRTC degamma and CTM would be passthrough, and gamma would be the inverse display EOTF for encoding color values into
what the monitor expects.
Yeah, will update this to make it clear.
+This patch series adds properties for plane color features. It +adds properties for degamma used to linearize data and CSC used +for gamut conversion. It also includes Gamma support used to +again non-linearize data as per panel supported color space. +These can be utilize by user space to convert planes from one +format to another, one color space to another etc.
FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work.
This is great to hear that we are aligned wrt how the pipeline should work.
Thanks Pekka for taking time out and providing the feedback.
@harry.wentland@amd.com We can work together and build our design to accommodate both Intel and AMD's hardware needs. This will also make things generic enough for any other hardware vendor as well.
Thanks & Regards, Uma Shankar
+Userspace can take smart blending decisions and utilize these +hardware supported plane color features to get accurate color +profile. The same can help in consistent color quality from +source to panel taking advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. +We can build up and add other platform/hardware specific +implementation on top of this series.
+Credits: Special mention and credits to Ville Syrjala for +coming up with a design for this feature and inputs. This +series is based on his original design and idea.
Thanks, pq
On Tue, 26 Oct 2021 11:36:33 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-10-14 15:44, Shankar, Uma wrote:
...
+* Plane CTM
- This is a Property to program the color transformation matrix.
No mode property here? Is there any hardware with something else than a matrix at this point?
Not that I am aware of.
Should we assume there will be hardware with something else, and have a CSC mode property with only a single enum value defined so far: "matrix"? Or do we say PLANE_CTM is a matrix and if you have something else in hardware, then invent a new property for it?
I think this should be good as we have this for crtc with no one complaining. There may be hardware with fixed function operation for the CSC but then its not a matrix and it would be pretty hardware dependent, so we can leave that from a generic UAPI.
Ok. And if that eventually turns out to be a mistake, it's easy to invent more properties.
I feel that is what would be required. This is just another instance of what we have at crtc level.
Would a userspace client ever want to use both CTM and 3D LUT?
The only reason I can think of is to keep the 3D LUT size (number of taps) small. I suspect that if one can use a matrix to get close, and then fix the residual with a 3D LUT, the 3D LUT could be significantly smaller than if you'd need to bake the matrix into the 3D LUT. But this is just my own suspicion, I haven't looked for references about this topic.
IOW, it's a question of precision - the same reason as to why you would want a 1D LUT before and after a 3D LUT.
We could add a mode property to CTM to allow for a CTM or 3D LUT or we could add new properties for 3D LUT support.
3D LUT might come with shaper 1D LUTs that can be programmed in conjunction with the 3D LUT. 3D LUTs operating in non-linear space require less precision than 3D LUTs operating in linear space, hence the 1D LUT can be used to non-linearize the pixel data for 3D LUT operation.
FWIW, AMD HW (depending on generation) can do these operations (in this order):
- 1D LUT (fixed or PWL programmable)
- simple multiplier (for scaling SDR content to HDR output)
- CTM matrix
- 1D LUT (shaper LUT to non-linearize for more effective 3D LUT transform)
- 3D LUT
- 1D LUT (for non-linear blending, or to linearize after 3D LUT)
- blending
- CTM matrix
- 1D LUT (shaper LUT like above)
- 3D LUT
- 1D LUT (generally for EOTF^-1 for display EOTF)
Not all blocks are available on all (current and future) HW.
I sketched a few diagrams that show how these might be used by a compositor if we exposed all of these blocks and should really try to add some of them to the color-and-hdr docs repo.
Yes, please.
That pipeline looks pretty comprehensive.
Btw. how about YUV<->RGB conversion? Where would that matrix go? It needs to operate on non-linear values, while a color space conversion matrix needs to operate on linear color values.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
Sure, will drop this wording here. But one open will still remain for userspace, as to how it gets the pipeline dynamically for a respective hardware. Currently we have assumed that this would be the logical fixed order of hardware units.
If we cannot model the abstract KMS pipeline as a fixed order of units (where each unit may exist or not), we need to take a few steps back here and look at what do we actually want to expose. That is a much bigger design problem which we are currently not even considering.
I think most of the hardware vendor platforms have this pipeline, so we can implement the properties which include all the possible hardware blocks. If certain units don't exist, the respective properties should not be exposed which will make things easier for userspace.
I think the color pipeline should be modeled in a way that makes sense from a color science standpoint and in a way that makes sense for compositor implementations. Fortunately HW design generally aligns with these intentions but we should be careful to not let HW design dictate KMS interfaces.
I'm so happy to hear that!
Thanks, pq
On 2021-10-27 04:00, Pekka Paalanen wrote:
On Tue, 26 Oct 2021 11:36:33 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-10-14 15:44, Shankar, Uma wrote:
...
FWIW, AMD HW (depending on generation) can do these operations (in this order):
- 1D LUT (fixed or PWL programmable)
- simple multiplier (for scaling SDR content to HDR output)
- CTM matrix
- 1D LUT (shaper LUT to non-linearize for more effective 3D LUT transform)
- 3D LUT
- 1D LUT (for non-linear blending, or to linearize after 3D LUT)
- blending
- CTM matrix
- 1D LUT (shaper LUT like above)
- 3D LUT
- 1D LUT (generally for EOTF^-1 for display EOTF)
Not all blocks are available on all (current and future) HW.
I sketched a few diagrams that show how these might be used by a compositor if we exposed all of these blocks and should really try to add some of them to the color-and-hdr docs repo.
Yes, please.
That pipeline looks pretty comprehensive.
Btw. how about YUV<->RGB conversion? Where would that matrix go? It needs to operate on non-linear values, while a color space conversion matrix needs to operate on linear color values.
That is communicated via drm_framebuffer.format, and drm_plane's color_range and color_encoding. I expect it to happen before everything else, i.e. at step 0. It seems like any color management implementation I've seen is always operating in RGB.
Harry
> + * This can be used to perform a color space conversion like > + * BT2020 to BT709 or BT601 etc. > + * This block is generally kept after the degamma unit so that
Not "generally". If blocks can change places, then it becomes intractable for generic userspace to program.
Sure, will drop this wording here. But one open will still remain for userspace, as to how it gets the pipeline dynamically for a respective hardware. Currently we have assumed that this would be the logical fixed order of hardware units.
If we cannot model the abstract KMS pipeline as a fixed order of units (where each unit may exist or not), we need to take a few steps back here and look at what do we actually want to expose. That is a much bigger design problem which we are currently not even considering.
I think most of the hardware vendor platforms have this pipeline, so we can implement the properties which include all the possible hardware blocks. If certain units don't exist, the respective properties should not be exposed which will make things easier for userspace.
I think the color pipeline should be modeled in a way that makes sense from a color science standpoint and in a way that makes sense for compositor implementations. Fortunately HW design generally aligns with these intentions but we should be careful to not let HW design dictate KMS interfaces.
I'm so happy to hear that!
Thanks, pq
On 2021-10-12 16:58, Shankar, Uma wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar uma.shankar@intel.com wrote:
snip
+This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for +gamut conversion. It also includes Gamma support used to again +non-linearize data as per panel supported color space. These can be +utilize by user space to convert planes from one format to another, +one color space to another etc.
FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work.
This is great to hear that we are aligned wrt how the pipeline should work.
Thanks Pekka for taking time out and providing the feedback.
@harry.wentland@amd.com We can work together and build our design to accommodate both Intel and AMD's hardware needs. This will also make things generic enough for any other hardware vendor as well.
Definitely. I think we're on the right path. Personally I would like to arrive at a solid KMS definition for this by the time Weston guys get to the HDR enablement with SW composition so we can start looking at KMS offloading for HDR planes as next step.
Harry
Thanks & Regards, Uma Shankar
+Userspace can take smart blending decisions and utilize these +hardware supported plane color features to get accurate color +profile. The same can help in consistent color quality from source +to panel taking advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific +implementation on top of this series.
+Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
Thanks, pq
On 2021-09-06 17:38, Uma Shankar wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties +==================================================
+This is how a typical display color hardware pipeline looks like:
- +-------------------------------------------+
- | RAM |
- | +------+ +---------+ +---------+ |
- | | FB 1 | | FB 2 | | FB N | |
- | +------+ +---------+ +---------+ |
- +-------------------------------------------+
| Plane Color Hardware Block |
- +--------------------------------------------+
- | +---v-----+ +---v-------+ +---v------+ |
- | | Plane A | | Plane B | | Plane N | |
- | | DeGamma | | Degamma | | Degamma | |
- | +---+-----+ +---+-------+ +---+------+ |
- | | | | |
- | +---v-----+ +---v-------+ +---v------+ |
- | |Plane A | | Plane B | | Plane N | |
- | |CSC/CTM | | CSC/CTM | | CSC/CTM | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- | +---v-----+ +----v------+ +----v-----+ |
- | | Plane A | | Plane B | | Plane N | |
- | | Gamma | | Gamma | | Gamma | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- +--------------------------------------------+
++------v--------------v---------------v-------| +|| || +|| Pipe Blender || ++--------------------+------------------------+ +| | | +| +-----------v----------+ | +| | Pipe DeGamma | | +| | | | +| +-----------+----------+ | +| | Pipe Color | +| +-----------v----------+ Hardware | +| | Pipe CSC/CTM | | +| | | | +| +-----------+----------+ | +| | | +| +-----------v----------+ | +| | Pipe Gamma | | +| | | | +| +-----------+----------+ | +| | | ++---------------------------------------------+
|
v
Pipe Output
This diagram defines what happens before and after the blending space but did where does scaling fit into it? Scaling can look different when performed in linear or non-linear space so I think it is important to define where in the pipeline it sits.
In my view scaling would happen between plane degamma and plane CSC.
Harry
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
+* Plane CTM
- This is a Property to program the color transformation matrix.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
+This is part of one plane engine. Data from multiple planes will be +then fed to pipe where it will get blended. There is a similar set of +properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR │
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR ├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │ │
- └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ │
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │
│ │ │
│ │ │
│ │ │
+┌───────────────────────────────────────────────────────────────────────────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone ├─────► TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
+This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for gamut +conversion. It also includes Gamma support used to again non-linearize +data as per panel supported color space. These can be utilize by user +space to convert planes from one format to another, one color space to +another etc.
+Userspace can take smart blending decisions and utilize these hardware +supported plane color features to get accurate color profile. The same +can help in consistent color quality from source to panel taking +advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific implementation +on top of this series.
+Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
-----Original Message----- From: Harry Wentland harry.wentland@amd.com Sent: Tuesday, November 23, 2021 8:35 PM To: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org Cc: ville.syrjala@linux.intel.com; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On 2021-09-06 17:38, Uma Shankar wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties +==================================================
+This is how a typical display color hardware pipeline looks like:
- +-------------------------------------------+
- | RAM |
- | +------+ +---------+ +---------+ |
- | | FB 1 | | FB 2 | | FB N | |
- | +------+ +---------+ +---------+ |
- +-------------------------------------------+
| Plane Color Hardware Block |
- +--------------------------------------------+
- | +---v-----+ +---v-------+ +---v------+ |
- | | Plane A | | Plane B | | Plane N | |
- | | DeGamma | | Degamma | | Degamma | |
- | +---+-----+ +---+-------+ +---+------+ |
- | | | | |
- | +---v-----+ +---v-------+ +---v------+ |
- | |Plane A | | Plane B | | Plane N | |
- | |CSC/CTM | | CSC/CTM | | CSC/CTM | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- | +---v-----+ +----v------+ +----v-----+ |
- | | Plane A | | Plane B | | Plane N | |
- | | Gamma | | Gamma | | Gamma | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- +--------------------------------------------+
++------v--------------v---------------v-------| +|| || +|| Pipe Blender || ++--------------------+------------------------+ +| | | +| +-----------v----------+ | +| | Pipe DeGamma | | +| | | | +| +-----------+----------+ | +| | Pipe Color | +| +-----------v----------+ Hardware | +| | Pipe CSC/CTM | | +| | | | +| +-----------+----------+ | +| | | +| +-----------v----------+ | +| | Pipe Gamma | | +| | | | +| +-----------+----------+ | +| | | ++---------------------------------------------+
|
v
Pipe Output
This diagram defines what happens before and after the blending space but did where does scaling fit into it? Scaling can look different when performed in linear or non-linear space so I think it is important to define where in the pipeline it sits.
In my view scaling would happen between plane degamma and plane CSC.
Yeah we can add scaling as well to make it clear. Scaling ideally should happen after Degamma. In intel's case it is after the CSC.
Regards, Uma Shankar
Harry
+Proposal is to have below properties for a plane:
+* Plane Degamma or Pre-Curve:
- This will be used to linearize the input framebuffer data.
- It will apply the reverse of the color transfer function.
- It can be a degamma curve or OETF for HDR.
- This linear data can be further acted on by the following
- color hardware blocks in the display hardware pipeline
+UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible degamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane degamma color
caps and choose the appropriate degamma mode and create lut values
accordingly.
+UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply degamma curve using the h/w plane degamma processing
engine, thereby making the content as linear for further color
processing. Userspace gets the size of LUT and precision etc
from PLANE_DEGAMA_MODE_PROPERTY
+* Plane CTM
- This is a Property to program the color transformation matrix.
- This can be used to perform a color space conversion like
- BT2020 to BT709 or BT601 etc.
- This block is generally kept after the degamma unit so that
- linear data can be fed to it for conversion.
+UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients
to do color space conversion or any other enhancement by doing a
matrix multiplication using the h/w CTM processing engine
+* Plane Gamma or Post-Curve
- This can be used to perform 2 operations:
* non-lineralize the framebuffer data. Can be used for
* non linear blending. It can be a gamma curve or EOTF
* for HDR.
* Perform Tone Mapping operation. This is an operation
* done when blending is done with HDR and SDR content.
+UAPI Name: PLANE_GAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the
possible gamma modes and lut ranges supported by the platform.
This allows userspace to query and get the plane gamma color
caps and choose the appropriate gamma mode and create lut values
accordingly.
+UAPI Name: PLANE_GAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values
to apply gamma curve or perform tone mapping using the h/w plane
gamma processing engine, thereby making the content as linear
for further color processing. Userspace gets the size of LUT and
precision etc from PLANE_GAMA_MODE_PROPERTY
+This is part of one plane engine. Data from multiple planes will be +then fed to pipe where it will get blended. There is a similar set of +properties available at crtc level which acts on this blended data.
+Below is a sample usecase:
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐
- │FB1 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │
- │ ├─────►│Linearize- ├────►│ BT709 to ├────►│ SDR to HDR │
- │BT709 SDR │ │BT709 inverse│ │ BT2020 │ │ Tone
Mapping├────────┐
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │
│
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │
- │FB2 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │
- │ ├─────►│Linearize- ├────►│ BT601 to ├────►│ SDR to HDR
├─────┐ │
- │BT601 SDR │ │BT601 inverse│ │ BT2020 │ │ Tone Mapping│ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │
│ │
- ┌────────────┐ ┌─────────────┐ ┌─────────────┐
┌─────────────┐ │ │
- │FB3 │ │Degamma Block│ │ CTM Matrix │ │ Gamma Block │ │ │
- │ ├─────►│Linearize- ├────►│ NOP (Data in├────►│ NOP (Data
in├───┐ │ │
- │BT2020 HDR │ │HDR OETF │ │ BT2020) │ │ HDR) │ │ │ │
- └────────────┘ └─────────────┘ └─────────────┘
└─────────────┘ │ │ │
│ │ │
│ │ │
+│ │ │
+┌────────────────────────────────────────────────────────────────── ──
+───────────┴─┴──┘ +│ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ +│ │ CRTC Degamma│ │ CRTC CTM │ │ CRTC Gamma │ +└─┤ Use to make ├─────►│ Use for any ├─────►│ Use for Tone ├─────►
TO Port
- │ data linear │ │ Color Space │ │ Mapping/apply │
- │ after blend │ │ Conversion │ │ transfer func │
- └─────────────┘ └─────────────┘ └───────────────┘
+This patch series adds properties for plane color features. It adds +properties for degamma used to linearize data and CSC used for gamut +conversion. It also includes Gamma support used to again +non-linearize data as per panel supported color space. These can be +utilize by user space to convert planes from one format to another, +one color space to another etc.
+Userspace can take smart blending decisions and utilize these +hardware supported plane color features to get accurate color +profile. The same can help in consistent color quality from source to +panel taking advantage of advanced color features in hardware.
+These patches add the property interfaces and enable helper functions. +This series adds Intel's XE_LPD hw specific plane gamma feature. We +can build up and add other platform/hardware specific implementation +on top of this series.
+Credits: Special mention and credits to Ville Syrjala for coming up +with a design for this feature and inputs. This series is based on +his original design and idea.
On Thu, 25 Nov 2021 20:43:19 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Harry Wentland harry.wentland@amd.com Sent: Tuesday, November 23, 2021 8:35 PM To: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org Cc: ville.syrjala@linux.intel.com; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On 2021-09-06 17:38, Uma Shankar wrote:
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose.
Credits: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index 000000000000..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +================================================== +Display Color Pipeline: Proposed DRM Properties +==================================================
+This is how a typical display color hardware pipeline looks like:
- +-------------------------------------------+
- | RAM |
- | +------+ +---------+ +---------+ |
- | | FB 1 | | FB 2 | | FB N | |
- | +------+ +---------+ +---------+ |
- +-------------------------------------------+
| Plane Color Hardware Block |
- +--------------------------------------------+
- | +---v-----+ +---v-------+ +---v------+ |
- | | Plane A | | Plane B | | Plane N | |
- | | DeGamma | | Degamma | | Degamma | |
- | +---+-----+ +---+-------+ +---+------+ |
- | | | | |
- | +---v-----+ +---v-------+ +---v------+ |
- | |Plane A | | Plane B | | Plane N | |
- | |CSC/CTM | | CSC/CTM | | CSC/CTM | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- | +---v-----+ +----v------+ +----v-----+ |
- | | Plane A | | Plane B | | Plane N | |
- | | Gamma | | Gamma | | Gamma | |
- | +---+-----+ +----+------+ +----+-----+ |
- | | | | |
- +--------------------------------------------+
++------v--------------v---------------v-------| +|| || +|| Pipe Blender || ++--------------------+------------------------+ +| | | +| +-----------v----------+ | +| | Pipe DeGamma | | +| | | | +| +-----------+----------+ | +| | Pipe Color | +| +-----------v----------+ Hardware | +| | Pipe CSC/CTM | | +| | | | +| +-----------+----------+ | +| | | +| +-----------v----------+ | +| | Pipe Gamma | | +| | | | +| +-----------+----------+ | +| | | ++---------------------------------------------+
|
v
Pipe Output
This diagram defines what happens before and after the blending space but did where does scaling fit into it? Scaling can look different when performed in linear or non-linear space so I think it is important to define where in the pipeline it sits.
In my view scaling would happen between plane degamma and plane CSC.
Yeah we can add scaling as well to make it clear. Scaling ideally should happen after Degamma. In intel's case it is after the CSC.
Btw. are you aware that if a plane has an alpha channel which is used for pixel coverage (i.e. shape anti-aliasing), then non-nearest sampling and therefore also scaling must operate on alpha pre-multiplied optical (linear) values?
For the best results, of course.
So after degamma indeed, but you cannot degamma with pre-multiplied alpha, yet scaling should use pre-multiplied alpha.
Thanks, pq
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/* + * DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT + * can be used for either purpose, but not simultaneously. To expose + * modes that support gamma and degamma simultaneously the gamma mode + * must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA + * ranges. + */ +/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/* + * the last value of the previous range is the + * first value of the current range. + */ +#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6) + +struct drm_color_lut_range { + /* DRM_MODE_LUT_* */ + __u32 flags; + /* number of points on the curve */ + __u16 count; + /* input/output bits per component */ + __u8 input_bpc, output_bpc; + /* input start/end values */ + __s32 start, end; + /* output min/max values */ + __s32 min, max; +}; + +enum lut_type { + LUT_TYPE_DEGAMMA = 0, + LUT_TYPE_GAMMA = 1, +}; + +/* + * Creating 64 bit palette entries for better data + * precision. This will be required for HDR and + * similar color processing usecases. + */ +struct drm_color_lut_ext { + /* + * Data is U32.32 fixed point format. + */ + __u64 red; + __u64 green; + __u64 blue; + __u64 reserved; +}; + #define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
Yeah, I have no idea what it should mean if an FB has a format that allows values beyond [0.0, 1.0].
Thanks, pq
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
AMD HW defines the LUT addressing in floating point space and allows for addressing beyond 1.0. In fact on other OSes our driver uses [0.0, 1.0] for SDR LUTs and [0.0, 128.0] for HDR LUTs.
There are color spaces that extend beyond 1.0 and even into the negative range: https://en.wikipedia.org/wiki/ScRGB
I don't think we should define the LUT to be limited to [0.0, 1.0].
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
As well, LUT entries are defined to be U32.32 fixed point, also allowing for entries much greater than 1.0. If those are programmed as entries in the input (degamma) LUT how will they be used to address entries in the output (gamma) LUT?
Maybe we want to say the actual input values are being used to address the LUT entries? But if we look at segment 1 of Uma's d13_degamma_hdr definition we see that the range of 0 to (1 << 24) -1 is covered by 128 (1 << 7) entries, so the range of 0 to 256 (for RGB with 8 bpc) would only be covered by 2 LUT entries. So this interpretation doesn't make sense.
You can see, I'm still confused by these definitions. An IGT test would help explain the API intentions a bit better, though I would like to see more precise documentation.
Despite my confusion I think the segmented PWL definitions are a neat way to concisely describe the HW capabilities to userspace and a concise way for userspace to provide the LUT more precisely than with a uniformly spaced LUT.
Harry
Yeah, I have no idea what it should mean if an FB has a format that allows values beyond [0.0, 1.0].
Thanks, pq
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On Thu, Nov 04, 2021 at 12:27:56PM -0400, Harry Wentland wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
AMD HW defines the LUT addressing in floating point space and allows for addressing beyond 1.0. In fact on other OSes our driver uses [0.0, 1.0] for SDR LUTs and [0.0, 128.0] for HDR LUTs.
There are color spaces that extend beyond 1.0 and even into the negative range: https://en.wikipedia.org/wiki/ScRGB
I don't think we should define the LUT to be limited to [0.0, 1.0].
That is not the intention, or at least wasn't my intention when originally I proposed this gamma mode stuff. I specifically wanted support for extended values. So 0.0-1.0 is supposed to be just the range for the in gamut values.
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
The idea again is that 0.0-1.0 is the range for the in gamut values. IIRC our hw does have the possibility of scaling all the fp16 input values by some programmable constant factor, but exposing that would require yet another uapi addition.
As well, LUT entries are defined to be U32.32 fixed point, also allowing for entries much greater than 1.0. If those are programmed as entries in the input (degamma) LUT how will they be used to address entries in the output (gamma) LUT?
The u32.32 is a mistake I think. IMO we should be going for signed values everywhere. Though our hw does not actually let us directly program negative values for the LUT, rather the hw just reflects the whole curve across the origin so the lookup is basically just something like: output = input < 0 ? -lut[abs(input)] : lut[input];
That is why there is that proposed DRM_MODE_LUT_REFLECT_NEGATIVE flag.
I think nouveau had something funny in its lut programming that made me think that it might actually have straight up programmable LUT entries for negative inputs as well. But I'm not sure if anyone has actually tested that.
Maybe we want to say the actual input values are being used to address the LUT entries? But if we look at segment 1 of Uma's d13_degamma_hdr definition we see that the range of 0 to (1 << 24) -1 is covered by 128 (1 << 7) entries, so the range of 0 to 256 (for RGB with 8 bpc) would only be covered by 2 LUT entries. So this interpretation doesn't make sense.
You can see, I'm still confused by these definitions. An IGT test would help explain the API intentions a bit better, though I would like to see more precise documentation.
Despite my confusion I think the segmented PWL definitions are a neat way to concisely describe the HW capabilities to userspace and a concise way for userspace to provide the LUT more precisely than with a uniformly spaced LUT.
Harry
Yeah, I have no idea what it should mean if an FB has a format that allows values beyond [0.0, 1.0].
Thanks, pq
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On 2021-11-05 07:49, Ville Syrjälä wrote:
On Thu, Nov 04, 2021 at 12:27:56PM -0400, Harry Wentland wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
AMD HW defines the LUT addressing in floating point space and allows for addressing beyond 1.0. In fact on other OSes our driver uses [0.0, 1.0] for SDR LUTs and [0.0, 128.0] for HDR LUTs.
There are color spaces that extend beyond 1.0 and even into the negative range: https://en.wikipedia.org/wiki/ScRGB%3E%3E%3E I don't think we should define the LUT to be limited to [0.0, 1.0].
That is not the intention, or at least wasn't my intention when originally I proposed this gamma mode stuff. I specifically wanted support for extended values. So 0.0-1.0 is supposed to be just the range for the in gamut values.
Make sense and good to hear.
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
The idea again is that 0.0-1.0 is the range for the in gamut values. IIRC our hw does have the possibility of scaling all the fp16 input values by some programmable constant factor, but exposing that would require yet another uapi addition.
As well, LUT entries are defined to be U32.32 fixed point, also allowing for entries much greater than 1.0. If those are programmed as entries in the input (degamma) LUT how will they be used to address entries in the output (gamma) LUT?
The u32.32 is a mistake I think. IMO we should be going for signed values everywhere. Though our hw does not actually let us directly program negative values for the LUT, rather the hw just reflects the whole curve across the origin so the lookup is basically just something like: output = input < 0 ? -lut[abs(input)] : lut[input];
That is why there is that proposed DRM_MODE_LUT_REFLECT_NEGATIVE flag.
That's pretty much how I expect AMD HW to operate as well.
Harry
I think nouveau had something funny in its lut programming that made me think that it might actually have straight up programmable LUT entries for negative inputs as well. But I'm not sure if anyone has actually tested that.
Maybe we want to say the actual input values are being used to address the LUT entries? But if we look at segment 1 of Uma's d13_degamma_hdr definition we see that the range of 0 to (1 << 24) -1 is covered by 128 (1 << 7) entries, so the range of 0 to 256 (for RGB with 8 bpc) would only be covered by 2 LUT entries. So this interpretation doesn't make sense.
You can see, I'm still confused by these definitions. An IGT test would help explain the API intentions a bit better, though I would like to see more precise documentation.
Despite my confusion I think the segmented PWL definitions are a neat way to concisely describe the HW capabilities to userspace and a concise way for userspace to provide the LUT more precisely than with a uniformly spaced LUT.
Harry
Yeah, I have no idea what it should mean if an FB has a format that allows values beyond [0.0, 1.0].
Thanks, pq
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
AMD HW defines the LUT addressing in floating point space and allows for addressing beyond 1.0. In fact on other OSes our driver uses [0.0, 1.0] for SDR LUTs and [0.0, 128.0] for HDR LUTs.
Hi Harry,
that sounds like some kind of absolute luminance encoding. Very much like a PQ system. PQ system is very different to anything else, and fitting that with a relative luminance system (which is everything else in existence that I know of) has... things to be worked out.
I recall seeing some calculations where [0.0, 128.0] mapped very nicely to exactly the theoretical absolute dynamic range of the PQ system. It seems like that range is specifically tailored for operation in the PQ system.
There are color spaces that extend beyond 1.0 and even into the negative range: https://en.wikipedia.org/wiki/ScRGB
scRGB is really special. It's more like a pure mathematical representation than a color space. Just like you can take a color triplet in any well-defined color space, and multiply it with a totally arbitrary but invertible 3x3 matrix. You get totally arbitrary values as a result, but you are not actually changing anything. It's just a different encoding.
scRGB has two peculiar and different properties.
First, if no color component is negative, the values above 1.0 simply extend the dynamic range.
Second, if any color component has a negative value, that extends the color gamut, not just dynamic range. You can represent for example a red color out of your gamut by using slightly negative values for green and blue and compensate for the "negative light intensity" by increasing the red value above 1.0, without actually going outside of the "original" dynamic range.
When color spaces are usually defined, the properties are chosen such that all color components will be non-negative. That makes them intuitive, particularly with additive color models (RGB in particular), because the concept of negative light intensity does not exist in physics (but it can be emulated in color matching experiments by adding the negative component of the matching color as a positive component to the reference color instead).
Then there are the considerations of color gamut and available dynamic range, which are inter-dependent and together form the available color volume.
Traditional color management works with relative coordinates where the per-channel range [0.0, 1.0] defines the color volume with relative, not absolute, dynamic range. You also were not able to send values outside of min..max to a monitor, so might as well map those to 0.0 and 1.0. One could say the color volume definition is implicit here, with the added confusion that you don't actually know the absolute dynamic range (cd/m²).
Nowadays we have color spaces like BT.2020 which are larger than any actual display can realize. Therefore, it is not enough to know the color space to understand the available color volume, but you need explicit information about the color gamut as well.
We need to know the available color volume to be able to map content color volume nicely for the display. Likewise, we need to know the actual color volume of the content too for a good color mapping.
If you use scRGB, you lose all intuitiveness. You have the concept of negative light intensity which does not exist, but it is used simply as a means to represent a larger color gamut than what the primaries of the color space would imply. It can even extend to imaginary colors, colors that do not exist: there is no light spectrum that would result in that color in the human eye. (BT.2020 may be big, but all its colors are real.) So you need to be able to handle arbitrary color channel values, and you need explicit knowledge of the color volume you are working with.
Essentially I think this means that one would better be using floating point for everything, or maybe you can get away with formats like s32.32 which takes 64 bits when a 16-bit float might have been enough. But that then ties with the value encoding (linear vs. non-linear), so one can't make a blanket statement about it.
Anyway, all the above is for the userspace to figure out. I just think that using the range [0.0, 1.0] is very natural for most workflows, even HDR. I don't see a practical need to go beyond that range, but I'm also not against it. One can always program the [0.0, 1.0] range explicitly via KMS.
The choice of the encoding at any point is always arbitrary, as long as it doesn't lose too much information. The important thing is to be consistent in a pipeline. That is why I'm not really concerned about what range the abstract KMS pipeline is going to be defined with, as long as it is consistent. An example of inconsistent pipeline would be to allow arbitrary values in a LUT output, but defining only [0.0, 1.0] input domain for the next element in the pipeline. Since any pipeline element could be missing, you can't rely on some elements acting as "sanitizer" but any earlier element could be feeding directly into any later element.
I don't think we should define the LUT to be limited to [0.0, 1.0].
That is fine. You get to define the UAPI and semantics for that, and you also need to retrofit the existing pipeline components like CRTC GAMMA and DEGAMMA to work with it somehow or replace them. You also need to define how arbitrary values get converted to the cable.
However, what happens if we define the abstract KMS color pipeline in terms of supporting arbitrary values in any point of the pipeline, and hardware just doesn't work that way because it happens to be using e.g. limited integer arithmetic?
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
As well, LUT entries are defined to be U32.32 fixed point, also allowing for entries much greater than 1.0. If those are programmed as entries in the input (degamma) LUT how will they be used to address entries in the output (gamma) LUT?
Maybe we want to say the actual input values are being used to address the LUT entries? But if we look at segment 1 of Uma's d13_degamma_hdr definition we see that the range of 0 to (1 << 24) -1 is covered by 128 (1 << 7) entries, so the range of 0 to 256 (for RGB with 8 bpc) would only be covered by 2 LUT entries. So this interpretation doesn't make sense.
FWIW, it seems Vulkan has a long list of how to interpret each (integer) pixel format: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.htm...
Essentially NORM vs. INT.
Hmm, I wonder how SNORM actually works. The integer range has one more negative code points than positive code points, and zero. So if zero code maps to 0.0, max maps 1.0, and min maps to -1.0, then the conversion factor is different for negative vs. positive values?
Thanks, pq
You can see, I'm still confused by these definitions. An IGT test would help explain the API intentions a bit better, though I would like to see more precise documentation.
Despite my confusion I think the segmented PWL definitions are a neat way to concisely describe the HW capabilities to userspace and a concise way for userspace to provide the LUT more precisely than with a uniformly spaced LUT.
Harry
Yeah, I have no idea what it should mean if an FB has a format that allows values beyond [0.0, 1.0].
Thanks, pq
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On 2021-11-08 04:54, Pekka Paalanen wrote:
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
AMD HW defines the LUT addressing in floating point space and allows for addressing beyond 1.0. In fact on other OSes our driver uses [0.0, 1.0] for SDR LUTs and [0.0, 128.0] for HDR LUTs.
Hi Harry,
that sounds like some kind of absolute luminance encoding. Very much like a PQ system. PQ system is very different to anything else, and fitting that with a relative luminance system (which is everything else in existence that I know of) has... things to be worked out.
I recall seeing some calculations where [0.0, 128.0] mapped very nicely to exactly the theoretical absolute dynamic range of the PQ system. It seems like that range is specifically tailored for operation in the PQ system.
There are color spaces that extend beyond 1.0 and even into the negative range: https://en.wikipedia.org/wiki/ScRGB
scRGB is really special. It's more like a pure mathematical representation than a color space. Just like you can take a color triplet in any well-defined color space, and multiply it with a totally arbitrary but invertible 3x3 matrix. You get totally arbitrary values as a result, but you are not actually changing anything. It's just a different encoding.
scRGB has two peculiar and different properties.
First, if no color component is negative, the values above 1.0 simply extend the dynamic range.
Second, if any color component has a negative value, that extends the color gamut, not just dynamic range. You can represent for example a red color out of your gamut by using slightly negative values for green and blue and compensate for the "negative light intensity" by increasing the red value above 1.0, without actually going outside of the "original" dynamic range.
When color spaces are usually defined, the properties are chosen such that all color components will be non-negative. That makes them intuitive, particularly with additive color models (RGB in particular), because the concept of negative light intensity does not exist in physics (but it can be emulated in color matching experiments by adding the negative component of the matching color as a positive component to the reference color instead).
Then there are the considerations of color gamut and available dynamic range, which are inter-dependent and together form the available color volume.
Traditional color management works with relative coordinates where the per-channel range [0.0, 1.0] defines the color volume with relative, not absolute, dynamic range. You also were not able to send values outside of min..max to a monitor, so might as well map those to 0.0 and 1.0. One could say the color volume definition is implicit here, with the added confusion that you don't actually know the absolute dynamic range (cd/m²).
Nowadays we have color spaces like BT.2020 which are larger than any actual display can realize. Therefore, it is not enough to know the color space to understand the available color volume, but you need explicit information about the color gamut as well.
We need to know the available color volume to be able to map content color volume nicely for the display. Likewise, we need to know the actual color volume of the content too for a good color mapping.
If you use scRGB, you lose all intuitiveness. You have the concept of negative light intensity which does not exist, but it is used simply as a means to represent a larger color gamut than what the primaries of the color space would imply. It can even extend to imaginary colors, colors that do not exist: there is no light spectrum that would result in that color in the human eye. (BT.2020 may be big, but all its colors are real.) So you need to be able to handle arbitrary color channel values, and you need explicit knowledge of the color volume you are working with.
Essentially I think this means that one would better be using floating point for everything, or maybe you can get away with formats like s32.32 which takes 64 bits when a 16-bit float might have been enough. But that then ties with the value encoding (linear vs. non-linear), so one can't make a blanket statement about it.
Anyway, all the above is for the userspace to figure out. I just think that using the range [0.0, 1.0] is very natural for most workflows, even HDR. I don't see a practical need to go beyond that range, but I'm also not against it. One can always program the [0.0, 1.0] range explicitly via KMS.
I agree that this should be for userspace to figure out. For that reason (and because we see OSes that do funky things) I prefer to not limit userspace to [0.0, 1.0].
The choice of the encoding at any point is always arbitrary, as long as it doesn't lose too much information. The important thing is to be consistent in a pipeline. That is why I'm not really concerned about what range the abstract KMS pipeline is going to be defined with, as long as it is consistent. An example of inconsistent pipeline would be to allow arbitrary values in a LUT output, but defining only [0.0, 1.0] input domain for the next element in the pipeline. Since any pipeline element could be missing, you can't rely on some elements acting as "sanitizer" but any earlier element could be feeding directly into any later element.
I don't think we should define the LUT to be limited to [0.0, 1.0].
That is fine. You get to define the UAPI and semantics for that, and you also need to retrofit the existing pipeline components like CRTC GAMMA and DEGAMMA to work with it somehow or replace them. You also need to define how arbitrary values get converted to the cable.
However, what happens if we define the abstract KMS color pipeline in terms of supporting arbitrary values in any point of the pipeline, and hardware just doesn't work that way because it happens to be using e.g. limited integer arithmetic?
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
On the cable we send integer values, not floating point. AMD HW uses floating point internally, though, and the PWL API defines floating point entries, so on some level we need to be clear what the floating point entries mean. Either we document that to be [0.0, 1.0] or we have some UAPI to define it. I'm leaning toward the latter but have to think about it some more.
As well, LUT entries are defined to be U32.32 fixed point, also allowing for entries much greater than 1.0. If those are programmed as entries in the input (degamma) LUT how will they be used to address entries in the output (gamma) LUT?
Maybe we want to say the actual input values are being used to address the LUT entries? But if we look at segment 1 of Uma's d13_degamma_hdr definition we see that the range of 0 to (1 << 24) -1 is covered by 128 (1 << 7) entries, so the range of 0 to 256 (for RGB with 8 bpc) would only be covered by 2 LUT entries. So this interpretation doesn't make sense.
FWIW, it seems Vulkan has a long list of how to interpret each (integer) pixel format: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.htm...
Essentially NORM vs. INT.
Thanks for sharing.
Harry
Hmm, I wonder how SNORM actually works. The integer range has one more negative code points than positive code points, and zero. So if zero code maps to 0.0, max maps 1.0, and min maps to -1.0, then the conversion factor is different for negative vs. positive values?
Thanks, pq
You can see, I'm still confused by these definitions. An IGT test would help explain the API intentions a bit better, though I would like to see more precise documentation.
Despite my confusion I think the segmented PWL definitions are a neat way to concisely describe the HW capabilities to userspace and a concise way for userspace to provide the LUT more precisely than with a uniformly spaced LUT.
Harry
Yeah, I have no idea what it should mean if an FB has a format that allows values beyond [0.0, 1.0].
Thanks, pq
If some of these questions should be obvious I apologize for being a bit dense, though it helps to make this accessible to the lowest common denominator to ensure not only the smartest devs can work with this.
Harry
#define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
On Tue, Nov 09, 2021 at 03:47:58PM -0500, Harry Wentland wrote:
On 2021-11-08 04:54, Pekka Paalanen wrote:
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values.
This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware.
Signed-off-by: Uma Shankar uma.shankar@intel.com
include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; };
+/*
- DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT
- can be used for either purpose, but not simultaneously. To expose
- modes that support gamma and degamma simultaneously the gamma mode
- must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA
- ranges.
- */
+/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/*
- the last value of the previous range is the
- first value of the current range.
- */
+#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6)
+struct drm_color_lut_range {
- /* DRM_MODE_LUT_* */
- __u32 flags;
- /* number of points on the curve */
- __u16 count;
- /* input/output bits per component */
- __u8 input_bpc, output_bpc;
- /* input start/end values */
- __s32 start, end;
- /* output min/max values */
- __s32 min, max;
+};
+enum lut_type {
- LUT_TYPE_DEGAMMA = 0,
- LUT_TYPE_GAMMA = 1,
+};
+/*
- Creating 64 bit palette entries for better data
- precision. This will be required for HDR and
- similar color processing usecases.
- */
+struct drm_color_lut_ext {
- /*
* Data is U32.32 fixed point format.
*/
- __u64 red;
- __u64 green;
- __u64 blue;
- __u64 reserved;
+};
I've been drawing out examples of drm_color_lut_range defined PWLs and understand a bit better what you and Ville are trying to accomplish with it. It actually makes a lot of sense and would allow for a generic way to populate different PWL definitions with a generic function.
But I still have some key questions that either are not answered in these patch sets or that I somehow overlooked.
Can you explain how the U32.32 fixed point format relates to the input_bpc and output_bpc in drm_color_lut_range, as we as to the pixel coming in from the framebuffer.
E.g. if we have ARGB2101010 what happens to a 0x3ff red value (assuming alpha is non-multiplied)?
If the drm_color_lut_range segments are defined with input_bpc of 24 bpc will 0x3ff be zero-expanded to 24-bit? Is the 24 bpc an integer? I.e. would our 3xff be interpreted as 0x3ff << (24-10)?
Assuming the output_bpc is 16 bpc and the programmed LUT makes this 1-to-1 would the output value be 0x3ff << (16-10)?
On AMD HW the pipe-internal format is a custom floating point format. We could probably express that in terms of input/output_bpc and do the translation in our driver between that and the internal floating point format, depending on the framebuffer format, but there is the added complication of the magnitude of the pixel data and correlating HDR with SDR planes.
E.g. any SDR data would map from 0.0 to 1.0 floating point, while HDR content would map from 0.0 to some value larger than 1.0. I don't (yet) have a clear picture how to represent that with the drm_color_lut_range definition.
Hi Harry,
I think you just would not. Conceptually an SDR plane gets its very own LUT that converts the FB [0.0, 1.0] range to any appropriate [a >= 0.0, b <= 1.0] range in HDR. This is purely conceptual, in the terms of the abstract KMS color pipeline, where [0.0, 1.0] is always the full dynamic range at any point of the pipeline, meaning it is relative to its placement in the pipeline. If you want to use values >1.0 in hw, you can do so under the hood.
At least that is how I would imagine things. With LUTs in general, I don't think I have ever seen LUT input domain being explicitly defined to something else than [0.0, 1.0] relative to the elements in the LUT where 0.0 maps exactly to the first element and 1.0 maps exactly to the last element.
I'm of course open to other suggestions, but having values outside of [0.0, 1.0] range in the abstract pipeline will always raise the question: how do you feed those to the LUT next in the pipeline.
AMD HW defines the LUT addressing in floating point space and allows for addressing beyond 1.0. In fact on other OSes our driver uses [0.0, 1.0] for SDR LUTs and [0.0, 128.0] for HDR LUTs.
Hi Harry,
that sounds like some kind of absolute luminance encoding. Very much like a PQ system. PQ system is very different to anything else, and fitting that with a relative luminance system (which is everything else in existence that I know of) has... things to be worked out.
I recall seeing some calculations where [0.0, 128.0] mapped very nicely to exactly the theoretical absolute dynamic range of the PQ system. It seems like that range is specifically tailored for operation in the PQ system.
There are color spaces that extend beyond 1.0 and even into the negative range: https://en.wikipedia.org/wiki/ScRGB
scRGB is really special. It's more like a pure mathematical representation than a color space. Just like you can take a color triplet in any well-defined color space, and multiply it with a totally arbitrary but invertible 3x3 matrix. You get totally arbitrary values as a result, but you are not actually changing anything. It's just a different encoding.
scRGB has two peculiar and different properties.
First, if no color component is negative, the values above 1.0 simply extend the dynamic range.
Second, if any color component has a negative value, that extends the color gamut, not just dynamic range. You can represent for example a red color out of your gamut by using slightly negative values for green and blue and compensate for the "negative light intensity" by increasing the red value above 1.0, without actually going outside of the "original" dynamic range.
When color spaces are usually defined, the properties are chosen such that all color components will be non-negative. That makes them intuitive, particularly with additive color models (RGB in particular), because the concept of negative light intensity does not exist in physics (but it can be emulated in color matching experiments by adding the negative component of the matching color as a positive component to the reference color instead).
Then there are the considerations of color gamut and available dynamic range, which are inter-dependent and together form the available color volume.
Traditional color management works with relative coordinates where the per-channel range [0.0, 1.0] defines the color volume with relative, not absolute, dynamic range. You also were not able to send values outside of min..max to a monitor, so might as well map those to 0.0 and 1.0. One could say the color volume definition is implicit here, with the added confusion that you don't actually know the absolute dynamic range (cd/m²).
Nowadays we have color spaces like BT.2020 which are larger than any actual display can realize. Therefore, it is not enough to know the color space to understand the available color volume, but you need explicit information about the color gamut as well.
We need to know the available color volume to be able to map content color volume nicely for the display. Likewise, we need to know the actual color volume of the content too for a good color mapping.
If you use scRGB, you lose all intuitiveness. You have the concept of negative light intensity which does not exist, but it is used simply as a means to represent a larger color gamut than what the primaries of the color space would imply. It can even extend to imaginary colors, colors that do not exist: there is no light spectrum that would result in that color in the human eye. (BT.2020 may be big, but all its colors are real.) So you need to be able to handle arbitrary color channel values, and you need explicit knowledge of the color volume you are working with.
Essentially I think this means that one would better be using floating point for everything, or maybe you can get away with formats like s32.32 which takes 64 bits when a 16-bit float might have been enough. But that then ties with the value encoding (linear vs. non-linear), so one can't make a blanket statement about it.
Anyway, all the above is for the userspace to figure out. I just think that using the range [0.0, 1.0] is very natural for most workflows, even HDR. I don't see a practical need to go beyond that range, but I'm also not against it. One can always program the [0.0, 1.0] range explicitly via KMS.
I agree that this should be for userspace to figure out. For that reason (and because we see OSes that do funky things) I prefer to not limit userspace to [0.0, 1.0].
The choice of the encoding at any point is always arbitrary, as long as it doesn't lose too much information. The important thing is to be consistent in a pipeline. That is why I'm not really concerned about what range the abstract KMS pipeline is going to be defined with, as long as it is consistent. An example of inconsistent pipeline would be to allow arbitrary values in a LUT output, but defining only [0.0, 1.0] input domain for the next element in the pipeline. Since any pipeline element could be missing, you can't rely on some elements acting as "sanitizer" but any earlier element could be feeding directly into any later element.
I don't think we should define the LUT to be limited to [0.0, 1.0].
That is fine. You get to define the UAPI and semantics for that, and you also need to retrofit the existing pipeline components like CRTC GAMMA and DEGAMMA to work with it somehow or replace them. You also need to define how arbitrary values get converted to the cable.
However, what happens if we define the abstract KMS color pipeline in terms of supporting arbitrary values in any point of the pipeline, and hardware just doesn't work that way because it happens to be using e.g. limited integer arithmetic?
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
On the cable we send integer values, not floating point. AMD HW uses floating point internally, though, and the PWL API defines floating point entries, so on some level we need to be clear what the floating point entries mean. Either we document that to be [0.0, 1.0] or we have some UAPI to define it. I'm leaning toward the latter but have to think about it some more.
As for Intel hw if you have an integer pixel value of 0xff... (with however many bits you have with a specific pixel format) it will get extended to 0.fff... (to whatever precision the pipe has internally). So if we go by that a fixed point 1.0 value in the proposed drm_color_lut_range would be considered just outside the gamut. And pretty sure fp16 input of 1.0 should also result in a 0.fff... internal value as well [1]. I think that definition pretty much matches how GL UNORM<->float conversion works as well.
[1] though IIRC some our hw did get that a bit wrong and it actually generates a 1.0 fixed point value for the pipe
On Wed, 10 Nov 2021 00:02:16 +0200 Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Tue, Nov 09, 2021 at 03:47:58PM -0500, Harry Wentland wrote:
On 2021-11-08 04:54, Pekka Paalanen wrote:
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-09-06 17:38, Uma Shankar wrote: > Existing LUT precision structure is having only 16 bit > precision. This is not enough for upcoming enhanced hardwares > and advance usecases like HDR processing. Hence added a new > structure with 32 bit precision values. > > This also defines a new structure to define color lut ranges, > along with related macro definitions and enums. This will help > describe multi segmented lut ranges in the hardware. > > Signed-off-by: Uma Shankar uma.shankar@intel.com > --- > include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 58 insertions(+)
...
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
On the cable we send integer values, not floating point. AMD HW uses floating point internally, though, and the PWL API defines floating point entries, so on some level we need to be clear what the floating point entries mean. Either we document that to be [0.0, 1.0] or we have some UAPI to define it. I'm leaning toward the latter but have to think about it some more.
As for Intel hw if you have an integer pixel value of 0xff... (with however many bits you have with a specific pixel format) it will get extended to 0.fff... (to whatever precision the pipe has internally). So if we go by that a fixed point 1.0 value in the proposed drm_color_lut_range would be considered just outside the gamut. And pretty sure fp16 input of 1.0 should also result in a 0.fff... internal value as well [1]. I think that definition pretty much matches how GL UNORM<->float conversion works as well.
Does it work that way in GL though?
I've always thought that with GL_UNSIGNED_BYTE, 0xff maps to 1.0, not 255.0/256.0.
Taking a random spec: OpenGL ES 2.0.25
Section 2.1.2 Data Conversions says:
Normalized unsigned integers represent numbers in the range [0, 1]. The conversion from a normalized unsigned integer c to the corresponding floating-point f is defined as f = c / (2^b - 1)
Note how the divisor has -1.
Thanks, pq
[1] though IIRC some our hw did get that a bit wrong and it actually generates a 1.0 fixed point value for the pipe
On Wed, Nov 10, 2021 at 10:49:24AM +0200, Pekka Paalanen wrote:
On Wed, 10 Nov 2021 00:02:16 +0200 Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Tue, Nov 09, 2021 at 03:47:58PM -0500, Harry Wentland wrote:
On 2021-11-08 04:54, Pekka Paalanen wrote:
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote:
On Wed, 3 Nov 2021 11:08:13 -0400 Harry Wentland harry.wentland@amd.com wrote:
> On 2021-09-06 17:38, Uma Shankar wrote: >> Existing LUT precision structure is having only 16 bit >> precision. This is not enough for upcoming enhanced hardwares >> and advance usecases like HDR processing. Hence added a new >> structure with 32 bit precision values. >> >> This also defines a new structure to define color lut ranges, >> along with related macro definitions and enums. This will help >> describe multi segmented lut ranges in the hardware. >> >> Signed-off-by: Uma Shankar uma.shankar@intel.com >> --- >> include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ >> 1 file changed, 58 insertions(+)
...
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
On the cable we send integer values, not floating point. AMD HW uses floating point internally, though, and the PWL API defines floating point entries, so on some level we need to be clear what the floating point entries mean. Either we document that to be [0.0, 1.0] or we have some UAPI to define it. I'm leaning toward the latter but have to think about it some more.
As for Intel hw if you have an integer pixel value of 0xff... (with however many bits you have with a specific pixel format) it will get extended to 0.fff... (to whatever precision the pipe has internally). So if we go by that a fixed point 1.0 value in the proposed drm_color_lut_range would be considered just outside the gamut. And pretty sure fp16 input of 1.0 should also result in a 0.fff... internal value as well [1]. I think that definition pretty much matches how GL UNORM<->float conversion works as well.
Does it work that way in GL though?
I've always thought that with GL_UNSIGNED_BYTE, 0xff maps to 1.0, not 255.0/256.0.
Taking a random spec: OpenGL ES 2.0.25
Section 2.1.2 Data Conversions says:
Normalized unsigned integers represent numbers in the range [0, 1]. The conversion from a normalized unsigned integer c to the corresponding floating-point f is defined as f = c / (2^b - 1)
Note how the divisor has -1.
That seems to match what I said, or at least tried to say (~0 <-> 1.0 in float). drm_color_lut_range being fixed point would follow the ~0 side of that. Or at least that interpretation would very easily map to our hw.
On 2021-11-10 06:55, Ville Syrjälä wrote:
On Wed, Nov 10, 2021 at 10:49:24AM +0200, Pekka Paalanen wrote:
On Wed, 10 Nov 2021 00:02:16 +0200 Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Tue, Nov 09, 2021 at 03:47:58PM -0500, Harry Wentland wrote:
On 2021-11-08 04:54, Pekka Paalanen wrote:
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-04 04:38, Pekka Paalanen wrote: > On Wed, 3 Nov 2021 11:08:13 -0400 > Harry Wentland harry.wentland@amd.com wrote: > >> On 2021-09-06 17:38, Uma Shankar wrote: >>> Existing LUT precision structure is having only 16 bit >>> precision. This is not enough for upcoming enhanced hardwares >>> and advance usecases like HDR processing. Hence added a new >>> structure with 32 bit precision values. >>> >>> This also defines a new structure to define color lut ranges, >>> along with related macro definitions and enums. This will help >>> describe multi segmented lut ranges in the hardware. >>> >>> Signed-off-by: Uma Shankar uma.shankar@intel.com >>> --- >>> include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ >>> 1 file changed, 58 insertions(+)
...
If the framebuffer is not in FP16 the question then becomes how the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
On the cable we send integer values, not floating point. AMD HW uses floating point internally, though, and the PWL API defines floating point entries, so on some level we need to be clear what the floating point entries mean. Either we document that to be [0.0, 1.0] or we have some UAPI to define it. I'm leaning toward the latter but have to think about it some more.
As for Intel hw if you have an integer pixel value of 0xff... (with however many bits you have with a specific pixel format) it will get extended to 0.fff... (to whatever precision the pipe has internally). So if we go by that a fixed point 1.0 value in the proposed drm_color_lut_range would be considered just outside the gamut. And pretty sure fp16 input of 1.0 should also result in a 0.fff... internal value as well [1]. I think that definition pretty much matches how GL UNORM<->float conversion works as well.
Does it work that way in GL though?
I've always thought that with GL_UNSIGNED_BYTE, 0xff maps to 1.0, not 255.0/256.0.
Taking a random spec: OpenGL ES 2.0.25
Section 2.1.2 Data Conversions says:
Normalized unsigned integers represent numbers in the range [0, 1]. The conversion from a normalized unsigned integer c to the corresponding floating-point f is defined as f = c / (2^b - 1)
Note how the divisor has -1.
That seems to match what I said, or at least tried to say (~0 <-> 1.0 in float). drm_color_lut_range being fixed point would follow the ~0 side of that. Or at least that interpretation would very easily map to our hw.
If I understand you right Intel HW represents 0xff (assuming 8 bpc) as the largest (representable) float that is less than 1.0. That float would be bigger than 255.0/256.0 but smaller than 256.0/256.0.
Harry
On Wed, 10 Nov 2021 10:17:59 -0500 Harry Wentland harry.wentland@amd.com wrote:
On 2021-11-10 06:55, Ville Syrjälä wrote:
On Wed, Nov 10, 2021 at 10:49:24AM +0200, Pekka Paalanen wrote:
On Wed, 10 Nov 2021 00:02:16 +0200 Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Tue, Nov 09, 2021 at 03:47:58PM -0500, Harry Wentland wrote:
On 2021-11-08 04:54, Pekka Paalanen wrote:
On Thu, 4 Nov 2021 12:27:56 -0400 Harry Wentland harry.wentland@amd.com wrote:
> On 2021-11-04 04:38, Pekka Paalanen wrote: >> On Wed, 3 Nov 2021 11:08:13 -0400 >> Harry Wentland harry.wentland@amd.com wrote: >> >>> On 2021-09-06 17:38, Uma Shankar wrote: >>>> Existing LUT precision structure is having only 16 bit >>>> precision. This is not enough for upcoming enhanced hardwares >>>> and advance usecases like HDR processing. Hence added a new >>>> structure with 32 bit precision values. >>>> >>>> This also defines a new structure to define color lut ranges, >>>> along with related macro definitions and enums. This will help >>>> describe multi segmented lut ranges in the hardware. >>>> >>>> Signed-off-by: Uma Shankar uma.shankar@intel.com >>>> --- >>>> include/uapi/drm/drm_mode.h | 58 +++++++++++++++++++++++++++++++++++++ >>>> 1 file changed, 58 insertions(+)
...
> If the framebuffer is not in FP16 the question then becomes how > the integer pixel values relate to LUT addressing.
Traditionally, and in any API I've seen (GL, Vulkan), a usual mapping is to match minimum unsigned integer value to 0.0, and unsigned maximum integer value to 1.0. This is how things work on the cable too, right? (Also taking full vs. limited range video signal into account. And conversion to cable-YUV if that happens.)
If you want integer format FB values to map to something else, then you have to tag the FB with that range information, somehow. New UAPI.
On the cable we send integer values, not floating point. AMD HW uses floating point internally, though, and the PWL API defines floating point entries, so on some level we need to be clear what the floating point entries mean. Either we document that to be [0.0, 1.0] or we have some UAPI to define it. I'm leaning toward the latter but have to think about it some more.
As for Intel hw if you have an integer pixel value of 0xff... (with however many bits you have with a specific pixel format) it will get extended to 0.fff... (to whatever precision the pipe has internally). So if we go by that a fixed point 1.0 value in the proposed drm_color_lut_range would be considered just outside the gamut. And pretty sure fp16 input of 1.0 should also result in a 0.fff... internal value as well [1]. I think that definition pretty much matches how GL UNORM<->float conversion works as well.
Does it work that way in GL though?
I've always thought that with GL_UNSIGNED_BYTE, 0xff maps to 1.0, not 255.0/256.0.
...
That seems to match what I said, or at least tried to say (~0 <-> 1.0 in float). drm_color_lut_range being fixed point would follow the ~0 side of that. Or at least that interpretation would very easily map to our hw.
If I understand you right Intel HW represents 0xff (assuming 8 bpc) as the largest (representable) float that is less than 1.0. That float would be bigger than 255.0/256.0 but smaller than 256.0/256.0.
I was just really confused and re-reading what Ville wrote originally now makes sense to me.
So, not what Harry wrote. Let me attempt to reiterate and mark fixed point hex values with a h to discriminate from float values.
With 8-bit: 0x00 -> 0.000000..0h = 0.0 float 0xff -> 0.ffffff..fh = 1.0 float
Then 1.000..0h is the first value out of range.
Thanks, pq
Add Plane Degamma Mode as an enum property. Create a helper function for all plane color management features.
This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property.
Lut values will be sent through separate GAMMA_LUT blob property.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- Documentation/gpu/drm-kms.rst | 90 ++++++++++++++++++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 2 + drivers/gpu/drm/drm_atomic_uapi.c | 4 + drivers/gpu/drm/drm_color_mgmt.c | 93 ++++++++++++++++++++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 23 ++++++ 7 files changed, 212 insertions(+), 3 deletions(-)
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 1ef7951ded5e..f4658417bf20 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -545,9 +545,99 @@ Damage Tracking Properties Color Management Properties ---------------------------
+Below is how a typical hardware pipeline for color +will look like: + +.. kernel-render:: DOT + :alt: Display Color Pipeline + :caption: Display Color Pipeline Overview + + digraph "KMS" { + node [shape=box] + + subgraph cluster_static { + style=dashed + label="Display Color Hardware Blocks" + + node [bgcolor=grey style=filled] + "Plane Degamma A" -> "Plane CSC/CTM A" + "Plane CSC/CTM A" -> "Plane Gamma A" + "Pipe Blender" [color=lightblue,style=filled, width=5.25, height=0.75]; + "Plane Gamma A" -> "Pipe Blender" + "Pipe Blender" -> "Pipe DeGamma" + "Pipe DeGamma" -> "Pipe CSC/CTM" + "Pipe CSC/CTM" -> "Pipe Gamma" + "Pipe Gamma" -> "Pipe Output" + } + + subgraph cluster_static { + style=dashed + + node [shape=box] + "Plane Degamma B" -> "Plane CSC/CTM B" + "Plane CSC/CTM B" -> "Plane Gamma B" + "Plane Gamma B" -> "Pipe Blender" + } + + subgraph cluster_static { + style=dashed + + node [shape=box] + "Plane Degamma C" -> "Plane CSC/CTM C" + "Plane CSC/CTM C" -> "Plane Gamma C" + "Plane Gamma C" -> "Pipe Blender" + } + + subgraph cluster_fb { + style=dashed + label="RAM" + + node [shape=box width=1.7 height=0.2] + + "FB 1" -> "Plane Degamma A" + "FB 2" -> "Plane Degamma B" + "FB 3" -> "Plane Degamma C" + } + } + +In real world usecases, + +1. Plane Degamma can be used to linearize a non linear gamma +encoded framebuffer. This is needed to do any linear math like +color space conversion. For ex, linearize frames encoded in SRGB +or by HDR curve. + +2. Later Plane CTM block can convert the content to some different +colorspace. For ex, SRGB to BT2020 etc. + +3. Plane Gamma block can be used later to re-apply the non-linear +curve. This can also be used to apply Tone Mapping for HDR usecases. + +All the layers or framebuffers need to be converted to same color +space and format before blending. The plane color hardware blocks +can help with this. Once the Data is blended, similar color processing +can be done on blended output using pipe color hardware blocks. + +DRM Properties have been created to define and expose all these +hardware blocks to userspace. A userspace application (compositor +or any color app) can use these interfaces and define policies to +efficiently use the display hardware for such color operations. + +Pipe Color Management Properties +--------------------------------- + .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c :doc: overview
+Plane Color Management Properties +--------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c + :doc: Plane Color Properties + +.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c + :doc: export + Tile Group Property -------------------
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index ff1416cd609a..fddf9df15cd5 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -709,6 +709,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, drm_get_color_encoding_name(state->color_encoding)); drm_printf(p, "\tcolor-range=%s\n", drm_get_color_range_name(state->color_range)); + drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
if (plane->funcs->atomic_print_state) plane->funcs->atomic_print_state(p, state); diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index ddcf5c2c8e6a..f26b03853711 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -311,6 +311,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, state->fence = NULL; state->commit = NULL; state->fb_damage_clips = NULL; + + state->color_mgmt_changed = false; } EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 909f31833181..3c952123f747 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -596,6 +596,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, state->color_encoding = val; } else if (property == plane->color_range_property) { state->color_range = val; + } else if (property == plane->degamma_mode_property) { + state->degamma_mode = val; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, @@ -662,6 +664,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->color_encoding; } else if (property == plane->color_range_property) { *val = state->color_range; + } else if (property == plane->degamma_mode_property) { + *val = state->degamma_mode; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index bb14f488c8f6..085ed0d0db00 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -34,8 +34,8 @@ /** * DOC: overview * - * Color management or color space adjustments is supported through a set of 5 - * properties on the &drm_crtc object. They are set up by calling + * Pipe Color management or color space adjustments is supported through a + * set of 5 properties on the &drm_crtc object. They are set up by calling * drm_crtc_enable_color_mgmt(). * * "DEGAMMA_LUT”: @@ -584,6 +584,95 @@ int drm_plane_create_color_properties(struct drm_plane *plane, } EXPORT_SYMBOL(drm_plane_create_color_properties);
+/** + * DOC: Plane Color Properties + * + * Plane Color management or color space adjustments is supported + * through a set of 5 properties on the &drm_plane object. + * + * degamma_mode_property: + * Blob property which advertizes the possible degamma modes and + * lut ranges supported by the platform. This allows userspace + * to query and get the plane degamma color caps and choose the + * appropriate degamma mode and create lut values accordingly + * + */ +int drm_plane_create_color_mgmt_properties(struct drm_device *dev, + struct drm_plane *plane, + int num_values) +{ + struct drm_property *prop; + + prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "PLANE_DEGAMMA_MODE", num_values); + if (!prop) + return -ENOMEM; + + plane->degamma_mode_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); + +void drm_plane_attach_degamma_properties(struct drm_plane *plane) +{ + if (!plane->degamma_mode_property) + return; + + drm_object_attach_property(&plane->base, + plane->degamma_mode_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_degamma_properties); + +int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, + const char *name, + const struct drm_color_lut_range *ranges, + size_t length, enum lut_type type) +{ + struct drm_property_blob *blob; + struct drm_property *prop = NULL; + int num_ranges = length / sizeof(ranges[0]); + int i, ret, num_types_0; + + if (type == LUT_TYPE_DEGAMMA) + prop = plane->degamma_mode_property; + + if (!prop) + return -EINVAL; + + if (length == 0 && name) + return drm_property_add_enum(prop, 0, name); + + if (WARN_ON(length == 0 || length % sizeof(ranges[0]) != 0)) + return -EINVAL; + num_types_0 = hweight8(ranges[0].flags & (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_DEGAMMA)); + if (num_types_0 == 0) + return -EINVAL; + + for (i = 1; i < num_ranges; i++) { + int num_types = hweight8(ranges[i].flags & (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_DEGAMMA)); + + /* either all ranges have DEGAMMA|GAMMA or none have it */ + if (num_types_0 != num_types) + return -EINVAL; + } + + blob = drm_property_create_blob(plane->dev, length, ranges); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + ret = drm_property_add_enum(prop, blob->base.id, name); + if (ret) { + drm_property_blob_put(blob); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(drm_plane_color_add_gamma_degamma_mode_range); + /** * drm_color_lut_check - check validity of lookup table * @lut: property blob containing LUT to check diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h index c34a3e8030e1..d4128c7daa08 100644 --- a/include/drm/drm_mode_object.h +++ b/include/drm/drm_mode_object.h @@ -60,7 +60,7 @@ struct drm_mode_object { void (*free_cb)(struct kref *kref); };
-#define DRM_OBJECT_MAX_PROPERTY 24 +#define DRM_OBJECT_MAX_PROPERTY 26 /** * struct drm_object_properties - property tracking for &drm_mode_object */ diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 0c1102dc4d88..b9064101db2b 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -239,6 +239,15 @@ struct drm_plane_state {
/** @state: backpointer to global drm_atomic_state */ struct drm_atomic_state *state; + + /** + * @degamma_mode: This is a blob_id and exposes the platform capabilities + * wrt to various gamma modes and the respective lut ranges. This also + * helps user select a degamma mode amongst the supported ones. + */ + u32 degamma_mode; + + u8 color_mgmt_changed : 1; };
static inline struct drm_rect @@ -750,6 +759,12 @@ struct drm_plane { * scaling. */ struct drm_property *scaling_filter_property; + + /** + * @degamma_mode_property: Optional Plane property to set the LUT + * used to convert the framebuffer's colors to linear gamma. + */ + struct drm_property *degamma_mode_property; };
#define obj_to_plane(x) container_of(x, struct drm_plane, base) @@ -841,6 +856,14 @@ void drm_plane_force_disable(struct drm_plane *plane); int drm_mode_plane_set_obj_prop(struct drm_plane *plane, struct drm_property *property, uint64_t value); +int drm_plane_create_color_mgmt_properties(struct drm_device *dev, + struct drm_plane *plane, + int num_values); +void drm_plane_attach_degamma_properties(struct drm_plane *plane); +int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, + const char *name, + const struct drm_color_lut_range *ranges, + size_t length, enum lut_type type);
/** * drm_plane_find - find a &drm_plane
On Tue, 7 Sep 2021 03:08:45 +0530 Uma Shankar uma.shankar@intel.com wrote:
Add Plane Degamma Mode as an enum property. Create a helper function for all plane color management features.
This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property.
Lut values will be sent through separate GAMMA_LUT blob property.
Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/drm-kms.rst | 90 ++++++++++++++++++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 2 + drivers/gpu/drm/drm_atomic_uapi.c | 4 + drivers/gpu/drm/drm_color_mgmt.c | 93 ++++++++++++++++++++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 23 ++++++ 7 files changed, 212 insertions(+), 3 deletions(-)
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 1ef7951ded5e..f4658417bf20 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -545,9 +545,99 @@ Damage Tracking Properties Color Management Properties
+Below is how a typical hardware pipeline for color +will look like:
+.. kernel-render:: DOT
- :alt: Display Color Pipeline
- :caption: Display Color Pipeline Overview
- digraph "KMS" {
node [shape=box]
subgraph cluster_static {
style=dashed
label="Display Color Hardware Blocks"
node [bgcolor=grey style=filled]
"Plane Degamma A" -> "Plane CSC/CTM A"
"Plane CSC/CTM A" -> "Plane Gamma A"
"Pipe Blender" [color=lightblue,style=filled, width=5.25, height=0.75];
"Plane Gamma A" -> "Pipe Blender"
"Pipe Blender" -> "Pipe DeGamma"
"Pipe DeGamma" -> "Pipe CSC/CTM"
"Pipe CSC/CTM" -> "Pipe Gamma"
"Pipe Gamma" -> "Pipe Output"
}
subgraph cluster_static {
style=dashed
node [shape=box]
"Plane Degamma B" -> "Plane CSC/CTM B"
"Plane CSC/CTM B" -> "Plane Gamma B"
"Plane Gamma B" -> "Pipe Blender"
}
subgraph cluster_static {
style=dashed
node [shape=box]
"Plane Degamma C" -> "Plane CSC/CTM C"
"Plane CSC/CTM C" -> "Plane Gamma C"
"Plane Gamma C" -> "Pipe Blender"
}
subgraph cluster_fb {
style=dashed
label="RAM"
node [shape=box width=1.7 height=0.2]
"FB 1" -> "Plane Degamma A"
"FB 2" -> "Plane Degamma B"
"FB 3" -> "Plane Degamma C"
}
- }
+In real world usecases,
+1. Plane Degamma can be used to linearize a non linear gamma +encoded framebuffer. This is needed to do any linear math like +color space conversion. For ex, linearize frames encoded in SRGB +or by HDR curve.
Hi,
Maybe better to avoid the term "gamma" as the curves are not always a pure power function.
sRGB with a small s.
Thanks, pq
+2. Later Plane CTM block can convert the content to some different +colorspace. For ex, SRGB to BT2020 etc.
+3. Plane Gamma block can be used later to re-apply the non-linear +curve. This can also be used to apply Tone Mapping for HDR usecases.
+All the layers or framebuffers need to be converted to same color +space and format before blending. The plane color hardware blocks +can help with this. Once the Data is blended, similar color processing +can be done on blended output using pipe color hardware blocks.
+DRM Properties have been created to define and expose all these +hardware blocks to userspace. A userspace application (compositor +or any color app) can use these interfaces and define policies to +efficiently use the display hardware for such color operations.
+Pipe Color Management Properties +---------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c :doc: overview
+Plane Color Management Properties +---------------------------------
+.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
- :doc: Plane Color Properties
+.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
- :doc: export
Tile Group Property
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:20 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 03/22] drm: Add Plane Degamma Mode property
On Tue, 7 Sep 2021 03:08:45 +0530 Uma Shankar uma.shankar@intel.com wrote:
Add Plane Degamma Mode as an enum property. Create a helper function for all plane color management features.
This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property.
Lut values will be sent through separate GAMMA_LUT blob property.
Signed-off-by: Uma Shankar uma.shankar@intel.com
Documentation/gpu/drm-kms.rst | 90 ++++++++++++++++++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 2 + drivers/gpu/drm/drm_atomic_uapi.c | 4 + drivers/gpu/drm/drm_color_mgmt.c | 93 ++++++++++++++++++++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 23 ++++++ 7 files changed, 212 insertions(+), 3 deletions(-)
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 1ef7951ded5e..f4658417bf20 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -545,9 +545,99 @@ Damage Tracking Properties Color Management Properties
+Below is how a typical hardware pipeline for color will look like:
+.. kernel-render:: DOT
- :alt: Display Color Pipeline
- :caption: Display Color Pipeline Overview
- digraph "KMS" {
node [shape=box]
subgraph cluster_static {
style=dashed
label="Display Color Hardware Blocks"
node [bgcolor=grey style=filled]
"Plane Degamma A" -> "Plane CSC/CTM A"
"Plane CSC/CTM A" -> "Plane Gamma A"
"Pipe Blender" [color=lightblue,style=filled, width=5.25, height=0.75];
"Plane Gamma A" -> "Pipe Blender"
"Pipe Blender" -> "Pipe DeGamma"
"Pipe DeGamma" -> "Pipe CSC/CTM"
"Pipe CSC/CTM" -> "Pipe Gamma"
"Pipe Gamma" -> "Pipe Output"
}
subgraph cluster_static {
style=dashed
node [shape=box]
"Plane Degamma B" -> "Plane CSC/CTM B"
"Plane CSC/CTM B" -> "Plane Gamma B"
"Plane Gamma B" -> "Pipe Blender"
}
subgraph cluster_static {
style=dashed
node [shape=box]
"Plane Degamma C" -> "Plane CSC/CTM C"
"Plane CSC/CTM C" -> "Plane Gamma C"
"Plane Gamma C" -> "Pipe Blender"
}
subgraph cluster_fb {
style=dashed
label="RAM"
node [shape=box width=1.7 height=0.2]
"FB 1" -> "Plane Degamma A"
"FB 2" -> "Plane Degamma B"
"FB 3" -> "Plane Degamma C"
}
- }
+In real world usecases,
+1. Plane Degamma can be used to linearize a non linear gamma encoded +framebuffer. This is needed to do any linear math like color space +conversion. For ex, linearize frames encoded in SRGB or by HDR curve.
Hi,
Maybe better to avoid the term "gamma" as the curves are not always a pure power function.
sRGB with a small s.
Sure Pekka, will update these.
Thanks & Regards, Uma Shankar
Thanks, pq
+2. Later Plane CTM block can convert the content to some different +colorspace. For ex, SRGB to BT2020 etc.
+3. Plane Gamma block can be used later to re-apply the non-linear +curve. This can also be used to apply Tone Mapping for HDR usecases.
+All the layers or framebuffers need to be converted to same color +space and format before blending. The plane color hardware blocks can +help with this. Once the Data is blended, similar color processing +can be done on blended output using pipe color hardware blocks.
+DRM Properties have been created to define and expose all these +hardware blocks to userspace. A userspace application (compositor or +any color app) can use these interfaces and define policies to +efficiently use the display hardware for such color operations.
+Pipe Color Management Properties +---------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c :doc: overview
+Plane Color Management Properties +---------------------------------
+.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
- :doc: Plane Color Properties
+.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
- :doc: export
Tile Group Property
Add Plane Degamma Lut as a blob property. User will calculate the lut values, create the blob and send it to driver using this property. Lut calculation will be based on the gamma mode chosen out of the gamma mode exposed.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/drm_atomic_state_helper.c | 4 ++++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++++++++++ drivers/gpu/drm/drm_color_mgmt.c | 19 +++++++++++++++++++ include/drm/drm_plane.h | 14 ++++++++++++++ 4 files changed, 47 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index f26b03853711..6e358067cb7a 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -312,6 +312,9 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, state->commit = NULL; state->fb_damage_clips = NULL;
+ if (state->degamma_lut) + drm_property_blob_get(state->degamma_lut); + state->color_mgmt_changed = false; } EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); @@ -359,6 +362,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_crtc_commit_put(state->commit);
drm_property_blob_put(state->fb_damage_clips); + drm_property_blob_put(state->degamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 3c952123f747..904291b96ba9 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -598,6 +598,13 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, state->color_range = val; } else if (property == plane->degamma_mode_property) { state->degamma_mode = val; + } else if (property == plane->degamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + &state->degamma_lut, + val, -1, sizeof(struct drm_color_lut_ext), + &replaced); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, @@ -666,6 +673,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->color_range; } else if (property == plane->degamma_mode_property) { *val = state->degamma_mode; + } else if (property == plane->degamma_lut_property) { + *val = (state->degamma_lut) ? + state->degamma_lut->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 085ed0d0db00..29d0fc1e52b5 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -596,6 +596,12 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * to query and get the plane degamma color caps and choose the * appropriate degamma mode and create lut values accordingly * + * degamma_lut_property: + * Blob property which allows a userspace to provide LUT values + * to apply degamma curve using the h/w plane degamma processing + * engine, thereby making the content as linear for further color + * processing. + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -610,6 +616,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev,
plane->degamma_mode_property = prop;
+ prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_DEGAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + + plane->degamma_lut_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -621,6 +634,12 @@ void drm_plane_attach_degamma_properties(struct drm_plane *plane)
drm_object_attach_property(&plane->base, plane->degamma_mode_property, 0); + + if (!plane->degamma_lut_property) + return; + + drm_object_attach_property(&plane->base, + plane->degamma_lut_property, 0); } EXPORT_SYMBOL(drm_plane_attach_degamma_properties);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index b9064101db2b..fbfada0b990d 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -247,6 +247,14 @@ struct drm_plane_state { */ u32 degamma_mode;
+ /* @degamma_lut: + * + * Lookup table for converting framebuffer pixel data before apply the + * color conversion matrix @ctm. See drm_plane_enable_color_mgmt(). The + * blob (if not NULL) is an array of &struct drm_color_lut_ext. + */ + struct drm_property_blob *degamma_lut; + u8 color_mgmt_changed : 1; };
@@ -765,6 +773,12 @@ struct drm_plane { * used to convert the framebuffer's colors to linear gamma. */ struct drm_property *degamma_mode_property; + + /** + * @degamma_lut_property: Optional Plane property to set the LUT + * used to convert the framebuffer's colors to linear gamma. + */ + struct drm_property *degamma_lut_property; };
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
+ /* FIXME input bpc? */ +__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 128, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (1 << 27) - 1, + }, +}; + void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
Is the distribution of the 128 entries uniform? If so, is a uniform distribution of 128 points across most of the LUT good enough for HDR with 128 entries?
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.start and .end are only a single entry apart. Is this correct?
Harry
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
On Wed, Nov 03, 2021 at 11:10:37AM -0400, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
Is the distribution of the 128 entries uniform?
I guess this is the plane gamma thing despite being in intel_color.c, so yeah I think that's correct.
If so, is a uniform distribution of 128 points across most of the LUT good enough for HDR with 128 entries?
No idea how good this actually is. It is .24 so at least it does have a fair bit of precision.
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.start and .end are only a single entry apart. Is this correct?
One think I wanted to do is simplify this stuff by getting rid of .end entirely. So I think this should just be '.start=1<<24' (or whatever way we decide to specify the input precision, which is I think another slightly open question).
So for this thing we could just have: { .count = 128, .min = 0, .max = (1 << 24) - 1, .start = 0 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 1 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 3 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 7 << 24 },
+ flags/etc. which I left out for brevity.
So that is trying to indicate that the first 129 entries are equally spaced, and would be used to interpolate for input values [0.0,1.0). Input values [1.0,3.0) would interpolate between entry 128 and 129, and [3.0,7.0) would interpolate between entry 129 and 130.
On 2021-11-05 08:59, Ville Syrjälä wrote:
On Wed, Nov 03, 2021 at 11:10:37AM -0400, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
Is the distribution of the 128 entries uniform?
I guess this is the plane gamma thing despite being in intel_color.c, so yeah I think that's correct.
If so, is a uniform distribution of 128 points across most of the LUT good enough for HDR with 128 entries?
No idea how good this actually is. It is .24 so at least it does have a fair bit of precision.
Precision is good but you also need enough samples. Though that's probably less my concern and more your concern and should become apparent once its used.
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.start and .end are only a single entry apart. Is this correct?
One think I wanted to do is simplify this stuff by getting rid of .end entirely. So I think this should just be '.start=1<<24' (or whatever way we decide to specify the input precision, which is I think another slightly open question).
So for this thing we could just have: { .count = 128, .min = 0, .max = (1 << 24) - 1, .start = 0 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 1 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 3 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 7 << 24 },
- flags/etc. which I left out for brevity.
Makes sense. I like this.
So that is trying to indicate that the first 129 entries are equally spaced, and would be used to interpolate for input values [0.0,1.0). Input values [1.0,3.0) would interpolate between entry 128 and 129, and [3.0,7.0) would interpolate between entry 129 and 130.
What in the segment definition defines the 1.0 mark? In your example it seems to be at (1 << 24) but then we would have values that go beyond the input_bpc for the last three segments.
How about output_bpc? Would output_bpc somehow limit the U32.32 (or S31.32) entries, and if so, how?
Or should we treat input_/output_bpc only as capability reporting, so userspace can calculate the possible error when programming the LUT? Again, this leaves us with the question what the input_/output_bpc means for our PWL entries.
Harry
On Tue, Nov 09, 2021 at 03:19:47PM -0500, Harry Wentland wrote:
On 2021-11-05 08:59, Ville Syrjälä wrote:
On Wed, Nov 03, 2021 at 11:10:37AM -0400, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
Is the distribution of the 128 entries uniform?
I guess this is the plane gamma thing despite being in intel_color.c, so yeah I think that's correct.
If so, is a uniform distribution of 128 points across most of the LUT good enough for HDR with 128 entries?
No idea how good this actually is. It is .24 so at least it does have a fair bit of precision.
Precision is good but you also need enough samples. Though that's probably less my concern and more your concern and should become apparent once its used.
Yeah, for pipe gamma we have a few different variants with non-uniform spacing of the samples. But not here AFAICS for whatever reason.
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.start and .end are only a single entry apart. Is this correct?
One think I wanted to do is simplify this stuff by getting rid of .end entirely. So I think this should just be '.start=1<<24' (or whatever way we decide to specify the input precision, which is I think another slightly open question).
So for this thing we could just have: { .count = 128, .min = 0, .max = (1 << 24) - 1, .start = 0 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 1 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 3 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 7 << 24 },
- flags/etc. which I left out for brevity.
Makes sense. I like this.
So that is trying to indicate that the first 129 entries are equally spaced, and would be used to interpolate for input values [0.0,1.0). Input values [1.0,3.0) would interpolate between entry 128 and 129, and [3.0,7.0) would interpolate between entry 129 and 130.
What in the segment definition defines the 1.0 mark? In your example it seems to be at (1 << 24) but then we would have values that go beyond the input_bpc for the last three segments.
Yes, input_bpc would define the precision of the input values (.start). so 1.0 would be at 1<<input_bpc. Tne range of input values is allowed to extend outside the 0.0-1.0 range.
How about output_bpc? Would output_bpc somehow limit the U32.32 (or S31.32) entries, and if so, how?
output_bpc would define the actual precision of the output values, so again 1.0 would be 1<<output_bpc, and .min and .max define the min/max values (which can extend outside the 0.0-1.0 range). The alternative I guess would be to not have .output_bpc at all and just have .min/.max be s32.32 values. Though then you can't tell what the actual precision is. Same could be done for .input_bpc I suppose.
Or should we treat input_/output_bpc only as capability reporting, so userspace can calculate the possible error when programming the LUT? Again, this leaves us with the question what the input_/output_bpc means for our PWL entries.
Yeah, I mostly thought they might be interesting if userspace wants to know the exact precision. But not strictly necessary if you want just to go generate a "close enough" curve.
What's PWL?
On 2021-11-09 16:45, Ville Syrjälä wrote:
On Tue, Nov 09, 2021 at 03:19:47PM -0500, Harry Wentland wrote:
On 2021-11-05 08:59, Ville Syrjälä wrote:
On Wed, Nov 03, 2021 at 11:10:37AM -0400, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
Is the distribution of the 128 entries uniform?
I guess this is the plane gamma thing despite being in intel_color.c, so yeah I think that's correct.
If so, is a uniform distribution of 128 points across most of the LUT good enough for HDR with 128 entries?
No idea how good this actually is. It is .24 so at least it does have a fair bit of precision.
Precision is good but you also need enough samples. Though that's probably less my concern and more your concern and should become apparent once its used.
Yeah, for pipe gamma we have a few different variants with non-uniform spacing of the samples. But not here AFAICS for whatever reason.
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.start and .end are only a single entry apart. Is this correct?
One think I wanted to do is simplify this stuff by getting rid of .end entirely. So I think this should just be '.start=1<<24' (or whatever way we decide to specify the input precision, which is I think another slightly open question).
So for this thing we could just have: { .count = 128, .min = 0, .max = (1 << 24) - 1, .start = 0 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 1 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 3 << 24 }, { .count = 1, .min = 0, .max = (7 << 24) - 1, .start = 7 << 24 },
- flags/etc. which I left out for brevity.
Makes sense. I like this.
So that is trying to indicate that the first 129 entries are equally spaced, and would be used to interpolate for input values [0.0,1.0). Input values [1.0,3.0) would interpolate between entry 128 and 129, and [3.0,7.0) would interpolate between entry 129 and 130.
What in the segment definition defines the 1.0 mark? In your example it seems to be at (1 << 24) but then we would have values that go beyond the input_bpc for the last three segments.
Yes, input_bpc would define the precision of the input values (.start). so 1.0 would be at 1<<input_bpc. Tne range of input values is allowed to extend outside the 0.0-1.0 range.
How about output_bpc? Would output_bpc somehow limit the U32.32 (or S31.32) entries, and if so, how?
output_bpc would define the actual precision of the output values, so again 1.0 would be 1<<output_bpc, and .min and .max define the min/max values (which can extend outside the 0.0-1.0 range). The alternative I guess would be to not have .output_bpc at all and just have .min/.max be s32.32 values. Though then you can't tell what the actual precision is. Same could be done for .input_bpc I suppose.
Or should we treat input_/output_bpc only as capability reporting, so userspace can calculate the possible error when programming the LUT? Again, this leaves us with the question what the input_/output_bpc means for our PWL entries.
Yeah, I mostly thought they might be interesting if userspace wants to know the exact precision. But not strictly necessary if you want just to go generate a "close enough" curve.
What's PWL?
Got it, I think.
Piece-wise linear LUT, i.e. a (usually segmented) LUT that linearly interpolates in between entries.
Harry
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Harry
void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of these LUT descriptors. Userspace can then query them dynamically and pick the best one for its current use case.
The algorithm for choosing the best one might be something like: - prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc - prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals). - prefer one with extended range values if needed - for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
And I was thinking of even adding a new property type (eg. ENUM_BLOB) just for this sort of usecase. That could let us have a bit more generic code to do all the validation around the property values and whatnot.
The one nagging concern I really have with GAMMA_MODE is how a mix of old and new userspace would work. Though that is more of a generic issue with any new property really.
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state
*crtc_state)
} }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of these LUT descriptors. Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI descriptions as hints.
And I was thinking of even adding a new property type (eg. ENUM_BLOB) just for this sort of usecase. That could let us have a bit more generic code to do all the validation around the property values and whatnot.
The one nagging concern I really have with GAMMA_MODE is how a mix of old and new userspace would work. Though that is more of a generic issue with any new property really.
For plane properties getting added newly, old userspace will not get it so I think this should be ok. Newer userspace will implement this and get the new functionality. Problem will be in extending this to crtc where we have a legacy baggage, the client caps approach may help us there. Have it as part of separate series just to not mix it with this new plane stuff, though the idea remains same based on your design. Series below for reference: https://patchwork.freedesktop.org/series/90821/
Regards, Uma Shankar
-- Ville Syrjälä Intel
On 2021-11-11 15:42, Shankar, Uma wrote:
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state
*crtc_state)
} }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of these LUT descriptors. Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
Thanks for the explanation.
Uma, have you had a chance to sketch some of this out in IGT? I'm trying to see how userspace would do this in practice and will try to sketch an IGT test for this myself, but if you have it already we could share the effort.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI descriptions as hints.
The range might be enough, but we're already parsing hints like "GAMMA" or "DEGAMMA". I wonder if it would make sense to add a flag for "HDR" or "SDR" as well.
And I was thinking of even adding a new property type (eg. ENUM_BLOB) just for this sort of usecase. That could let us have a bit more generic code to do all the validation around the property values and whatnot.
The one nagging concern I really have with GAMMA_MODE is how a mix of old and new userspace would work. Though that is more of a generic issue with any new property really.
For plane properties getting added newly, old userspace will not get it so I think this should be ok. Newer userspace will implement this and get the new functionality. Problem will be in extending this to crtc where we have a legacy baggage, the client caps approach may help us there. Have it as part of separate series just to not mix it with this new plane stuff, though the idea remains same based on your design. Series below for reference: https://patchwork.freedesktop.org/series/90821/%3E%3E
Could we just assume we do a uniform LUT if userspace doesn't set a _MODE enum value for the respective gamma?
Maybe the _MODE should have a default enum value that means a uniform (legacy) LUT.
Harry
Regards, Uma Shankar
-- Ville Syrjälä Intel
-----Original Message----- From: Harry Wentland harry.wentland@amd.com Sent: Friday, November 12, 2021 2:41 AM To: Shankar, Uma uma.shankar@intel.com; Ville Syrjälä ville.syrjala@linux.intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On 2021-11-11 15:42, Shankar, Uma wrote:
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state
*crtc_state)
} }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of
these LUT descriptors.
Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the
respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
Thanks for the explanation.
Uma, have you had a chance to sketch some of this out in IGT? I'm trying to see how userspace would do this in practice and will try to sketch an IGT test for this myself, but if you have it already we could share the effort.
Yes Harry, we do have some sample IGT's to test this. Will send those out and will copy you and all the stakeholders.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI
descriptions as hints.
The range might be enough, but we're already parsing hints like "GAMMA" or "DEGAMMA". I wonder if it would make sense to add a flag for "HDR" or "SDR" as well.
On Intel hardware, we differentiate this with precision and have HDR planes (they have extra Lut precision and samples) separately called out. We could add SDR/HDR FLAG as well.
And I was thinking of even adding a new property type (eg. ENUM_BLOB) just for this sort of usecase. That could let us have a bit more generic code to do all the validation around the property values and
whatnot.
The one nagging concern I really have with GAMMA_MODE is how a mix of old and new userspace would work. Though that is more of a generic issue with any new property really.
For plane properties getting added newly, old userspace will not get it so I think
this should be ok.
Newer userspace will implement this and get the new functionality. Problem will be in extending this to crtc where we have a legacy baggage, the client caps approach may help us there. Have it as part of separate series just to not mix it with this new plane stuff, though the idea
remains same based on your design. Series below for reference:
Could we just assume we do a uniform LUT if userspace doesn't set a _MODE enum value for the respective gamma?
Maybe the _MODE should have a default enum value that means a uniform (legacy) LUT.
Yeah we could have this and document the behavior in UAPI description.
Regards, Uma Shankar
Harry
Regards, Uma Shankar
-- Ville Syrjälä Intel
On Thu, 11 Nov 2021 21:58:35 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Harry Wentland harry.wentland@amd.com Sent: Friday, November 12, 2021 2:41 AM To: Shankar, Uma uma.shankar@intel.com; Ville Syrjälä ville.syrjala@linux.intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On 2021-11-11 15:42, Shankar, Uma wrote:
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state
*crtc_state)
} }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Are you asking whether 'struct drm_color_lut_range` is defined in any userspace visible header?
It seems to be in patch 2.
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of
these LUT descriptors.
Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the
respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
Thanks for the explanation.
Uma, have you had a chance to sketch some of this out in IGT? I'm trying to see how userspace would do this in practice and will try to sketch an IGT test for this myself, but if you have it already we could share the effort.
Yes Harry, we do have some sample IGT's to test this. Will send those out and will copy you and all the stakeholders.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI
descriptions as hints.
The range might be enough, but we're already parsing hints like "GAMMA" or "DEGAMMA". I wonder if it would make sense to add a flag for "HDR" or "SDR" as well.
What hints are GAMMA or DEGAMMA and who's parsing them? I thought they are just arbitrary names to identify the element's position in the abstract pipeline.
On Intel hardware, we differentiate this with precision and have HDR planes (they have extra Lut precision and samples) separately called out. We could add SDR/HDR FLAG as well.
What about wide color gamut SDR? That probably needs more precision than "normal" SDR but is not HDR.
I can't think of how SDR/HDR flags would work or what they would mean. Feels a bit too simple for practice. Maybe that concept should be created by a hypothetical userspace helper library instead.
Thanks, pq
On 2021-11-12 03:37, Pekka Paalanen wrote:
On Thu, 11 Nov 2021 21:58:35 +0000 "Shankar, Uma" uma.shankar@intel.com wrote:
-----Original Message----- From: Harry Wentland harry.wentland@amd.com Sent: Friday, November 12, 2021 2:41 AM To: Shankar, Uma uma.shankar@intel.com; Ville Syrjälä ville.syrjala@linux.intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On 2021-11-11 15:42, Shankar, Uma wrote:
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote: > Define the structure with XE_LPD degamma lut ranges. HDR and SDR > planes have different capabilities, implemented respective > structure for the HDR planes. > > Signed-off-by: Uma Shankar uma.shankar@intel.com > --- > drivers/gpu/drm/i915/display/intel_color.c | 52 > ++++++++++++++++++++++ > 1 file changed, 52 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_color.c > b/drivers/gpu/drm/i915/display/intel_color.c > index afcb4bf3826c..6403bd74324b 100644 > --- a/drivers/gpu/drm/i915/display/intel_color.c > +++ b/drivers/gpu/drm/i915/display/intel_color.c > @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct > intel_crtc_state
*crtc_state)
> } > } > > + /* FIXME input bpc? */ > +__maybe_unused > +static const struct drm_color_lut_range d13_degamma_hdr[] = { > + /* segment 1 */ > + { > + .flags = (DRM_MODE_LUT_GAMMA | > + DRM_MODE_LUT_REFLECT_NEGATIVE | > + DRM_MODE_LUT_INTERPOLATE | > + DRM_MODE_LUT_NON_DECREASING), > + .count = 128, > + .input_bpc = 24, .output_bpc = 16, > + .start = 0, .end = (1 << 24) - 1, > + .min = 0, .max = (1 << 24) - 1, > + }, > + /* segment 2 */ > + { > + .flags = (DRM_MODE_LUT_GAMMA | > + DRM_MODE_LUT_REFLECT_NEGATIVE | > + DRM_MODE_LUT_INTERPOLATE | > + DRM_MODE_LUT_REUSE_LAST | > + DRM_MODE_LUT_NON_DECREASING), > + .count = 1, > + .input_bpc = 24, .output_bpc = 16, > + .start = (1 << 24) - 1, .end = 1 << 24, > + .min = 0, .max = (1 << 27) - 1, > + }, > + /* Segment 3 */ > + { > + .flags = (DRM_MODE_LUT_GAMMA | > + DRM_MODE_LUT_REFLECT_NEGATIVE | > + DRM_MODE_LUT_INTERPOLATE | > + DRM_MODE_LUT_REUSE_LAST | > + DRM_MODE_LUT_NON_DECREASING), > + .count = 1, > + .input_bpc = 24, .output_bpc = 16, > + .start = 1 << 24, .end = 3 << 24, > + .min = 0, .max = (1 << 27) - 1, > + }, > + /* Segment 4 */ > + { > + .flags = (DRM_MODE_LUT_GAMMA | > + DRM_MODE_LUT_REFLECT_NEGATIVE | > + DRM_MODE_LUT_INTERPOLATE | > + DRM_MODE_LUT_REUSE_LAST | > + DRM_MODE_LUT_NON_DECREASING), > + .count = 1, > + .input_bpc = 24, .output_bpc = 16, > + .start = 3 << 24, .end = 7 << 24, > + .min = 0, .max = (1 << 27) - 1, > + }, > +};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Are you asking whether 'struct drm_color_lut_range` is defined in any userspace visible header?
It seems to be in patch 2.
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of
these LUT descriptors.
Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the
respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
Thanks for the explanation.
Uma, have you had a chance to sketch some of this out in IGT? I'm trying to see how userspace would do this in practice and will try to sketch an IGT test for this myself, but if you have it already we could share the effort.
Yes Harry, we do have some sample IGT's to test this. Will send those out and will copy you and all the stakeholders.
Thanks. The set is on my list of items to review.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI
descriptions as hints.
The range might be enough, but we're already parsing hints like "GAMMA" or "DEGAMMA". I wonder if it would make sense to add a flag for "HDR" or "SDR" as well.
What hints are GAMMA or DEGAMMA and who's parsing them? I thought they are just arbitrary names to identify the element's position in the abstract pipeline.
They are provided with the segment definitions, e.g. in https://patchwork.freedesktop.org/patch/452589/?series=90826&rev=2
I believe they are indicating whether a segment definition is intended for degamma (linearization) use or for gamma (delinearization) use.
On Intel hardware, we differentiate this with precision and have HDR planes (they have extra Lut precision and samples) separately called out. We could add SDR/HDR FLAG as well.
What about wide color gamut SDR? That probably needs more precision than "normal" SDR but is not HDR.
I can't think of how SDR/HDR flags would work or what they would mean. Feels a bit too simple for practice. Maybe that concept should be created by a hypothetical userspace helper library instead.
Maybe this is a decision best left up to compositors. A compositor will know best what precision and range it needs.
Harry
Thanks, pq
On Thu, Nov 11, 2021 at 04:10:41PM -0500, Harry Wentland wrote:
On 2021-11-11 15:42, Shankar, Uma wrote:
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state
*crtc_state)
} }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of these LUT descriptors. Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
Thanks for the explanation.
Uma, have you had a chance to sketch some of this out in IGT? I'm trying to see how userspace would do this in practice and will try to sketch an IGT test for this myself, but if you have it already we could share the effort.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI descriptions as hints.
The range might be enough, but we're already parsing hints like "GAMMA" or "DEGAMMA". I wonder if it would make sense to add a flag for "HDR" or "SDR" as well.
And I was thinking of even adding a new property type (eg. ENUM_BLOB) just for this sort of usecase. That could let us have a bit more generic code to do all the validation around the property values and whatnot.
The one nagging concern I really have with GAMMA_MODE is how a mix of old and new userspace would work. Though that is more of a generic issue with any new property really.
For plane properties getting added newly, old userspace will not get it so I think this should be ok. Newer userspace will implement this and get the new functionality. Problem will be in extending this to crtc where we have a legacy baggage, the client caps approach may help us there. Have it as part of separate series just to not mix it with this new plane stuff, though the idea remains same based on your design. Series below for reference: https://patchwork.freedesktop.org/series/90821/%3E%3E
Could we just assume we do a uniform LUT if userspace doesn't set a _MODE enum value for the respective gamma?
Maybe the _MODE should have a default enum value that means a uniform (legacy) LUT.
Yeah, it definitely needs a default like that. But the problem arises when new userspace sets it to something else and then hands the reins over to some old userspace that doesn't know how to reset it back to default.
On Fri, 12 Nov 2021 16:54:35 +0200 Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Thu, Nov 11, 2021 at 04:10:41PM -0500, Harry Wentland wrote:
On 2021-11-11 15:42, Shankar, Uma wrote:
-----Original Message----- From: Ville Syrjälä ville.syrjala@linux.intel.com Sent: Thursday, November 11, 2021 10:13 PM To: Harry Wentland harry.wentland@amd.com Cc: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org; ppaalanen@gmail.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote:
On 2021-09-06 17:38, Uma Shankar wrote:
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com
drivers/gpu/drm/i915/display/intel_color.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state
*crtc_state)
} }
- /* FIXME input bpc? */
+__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = {
- /* segment 1 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_NON_DECREASING),
.count = 128,
.input_bpc = 24, .output_bpc = 16,
.start = 0, .end = (1 << 24) - 1,
.min = 0, .max = (1 << 24) - 1,
- },
- /* segment 2 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = (1 << 24) - 1, .end = 1 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 3 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 1 << 24, .end = 3 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
- /* Segment 4 */
- {
.flags = (DRM_MODE_LUT_GAMMA |
DRM_MODE_LUT_REFLECT_NEGATIVE |
DRM_MODE_LUT_INTERPOLATE |
DRM_MODE_LUT_REUSE_LAST |
DRM_MODE_LUT_NON_DECREASING),
.count = 1,
.input_bpc = 24, .output_bpc = 16,
.start = 3 << 24, .end = 7 << 24,
.min = 0, .max = (1 << 27) - 1,
- },
+};
If I understand this right, userspace would need this definition in order to populate the degamma blob. Should this sit in a UAPI header?
Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay.
My original idea (not sure it's fully realized in this series) is to have a new GAMMA_MODE/etc. enum property on each crtc (or plane) for which each enum value points to a kernel provided blob that contains one of these LUT descriptors. Userspace can then query them dynamically and pick the best one for its current use case.
We have this as part of the series Ville. Patch 3 of this series creates a DEGAMMA_MODE property just for this. With that userspace can just query the blob_id's and will get the various degamma mode possible and the respective segment and lut distributions.
This will be generic, so for userspace it should just be able to query this and parse and get the lut distribution and segment ranges.
Thanks for the explanation.
Uma, have you had a chance to sketch some of this out in IGT? I'm trying to see how userspace would do this in practice and will try to sketch an IGT test for this myself, but if you have it already we could share the effort.
The algorithm for choosing the best one might be something like:
- prefer LUT with bpc >= FB bpc, but perhaps not needlessly high bpc
- prefer interpolated vs. direct lookup based on current needs (eg. X could prefer direct lookup to get directcolor visuals).
- prefer one with extended range values if needed
- for HDR prefer smaller step size in dark tones, for SDR perhaps prefer a more uniform step size
Or maybe we should include some kind of usage hints as well?
I think the segment range and distribution of lut should be enough for a userspace to pick the right ones, but we can add some examples in UAPI descriptions as hints.
The range might be enough, but we're already parsing hints like "GAMMA" or "DEGAMMA". I wonder if it would make sense to add a flag for "HDR" or "SDR" as well.
And I was thinking of even adding a new property type (eg. ENUM_BLOB) just for this sort of usecase. That could let us have a bit more generic code to do all the validation around the property values and whatnot.
The one nagging concern I really have with GAMMA_MODE is how a mix of old and new userspace would work. Though that is more of a generic issue with any new property really.
For plane properties getting added newly, old userspace will not get it so I think this should be ok. Newer userspace will implement this and get the new functionality. Problem will be in extending this to crtc where we have a legacy baggage, the client caps approach may help us there. Have it as part of separate series just to not mix it with this new plane stuff, though the idea remains same based on your design. Series below for reference: https://patchwork.freedesktop.org/series/90821/%3E%3E
Could we just assume we do a uniform LUT if userspace doesn't set a _MODE enum value for the respective gamma?
Maybe the _MODE should have a default enum value that means a uniform (legacy) LUT.
Yeah, it definitely needs a default like that. But the problem arises when new userspace sets it to something else and then hands the reins over to some old userspace that doesn't know how to reset it back to default.
This very problem is the one where I have been suggesting that userspace that supports temporarily handing DRM-master to something else needs to be prepared to save and restore also unrecognized KMS properties.
We've also had talk about a "reset" switch in KMS, but I forget the conclusion.
Both ideas lack the people working on them. I don't think we can design each new KMS property ad hoc to somehow magically be compatible with old vs. new client interoperation. In fact, the problem exists already with e.g. the old GAMMA etc. properties.
OTOH, when a userspace client is reported to misbehave because something else left KMS in a funny state, it is just too easy to simply patch the innocent but misbehaving client to understand whatever new property the other one was using, particularly if it's just to reset it to some hardcoded expected value. So it's unclear if this problem even needs a solution.
Thanks, pq
Add macros to define Plane Degamma registers
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 313432ed6196..919982c878ac 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -262,6 +262,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) INTEL_INFO(dev_priv)->cursor_offsets[PIPE_A] + (reg) + \ DISPLAY_MMIO_BASE(dev_priv))
+/* Plane Gamma Registers */ +#define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) + #define __MASKED_FIELD(mask, value) ((mask) << 16 | (value)) #define _MASKED_FIELD(mask, value) ({ \ if (__builtin_constant_p(mask)) \ @@ -11366,6 +11369,55 @@ enum skl_power_gate { _PAL_PREC_MULTI_SEG_DATA_A, \ _PAL_PREC_MULTI_SEG_DATA_B)
+/* Display13 Plane Degmma Reg */ +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A 0x701d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B 0x711d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A 0x702d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B 0x712d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A 0x701d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B 0x711d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A 0x702d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B 0x712d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_INDEX_1_A 0x704d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1_B 0x714d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_A 0x705d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_B 0x715d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_1_A 0x704d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1_B 0x714d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_A 0x705d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_B 0x715d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_2_B) +#define PLANE_PRE_CSC_GAMC_DATA(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_2(pipe)) + /* pipe CSC & degamma/gamma LUTs on CHV */ #define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900) #define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904)
Enable and initialize plane color features. Also initialize the color features of HDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com Signed-off-by: Bhanuprakash Modem bhanuprakash.modem@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 22 +++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_color.h | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 6403bd74324b..2307a2e4d73d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -25,6 +25,7 @@ #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" +#include <drm/drm_plane.h>
#define CTM_COEFF_SIGN (1ULL << 63)
@@ -2093,7 +2094,6 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) }
/* FIXME input bpc? */ -__maybe_unused static const struct drm_color_lut_range d13_degamma_hdr[] = { /* segment 1 */ { @@ -2144,6 +2144,26 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { }, };
+int intel_plane_color_init(struct drm_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->dev); + int ret = 0; + + if (DISPLAY_VER(dev_priv) >= 13) { + drm_plane_create_color_mgmt_properties(plane->dev, plane, 2); + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", + NULL, 0, + LUT_TYPE_DEGAMMA); + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", + d13_degamma_hdr, + sizeof(d13_degamma_hdr), + LUT_TYPE_DEGAMMA); + drm_plane_attach_degamma_properties(plane); + } + + return ret; +} + void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 173727aaa24d..b8850bb1b0c9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -10,6 +10,7 @@
struct intel_crtc_state; struct intel_crtc; +struct drm_plane; struct drm_property_blob;
void intel_color_init(struct intel_crtc *crtc); @@ -21,5 +22,6 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat bool intel_color_lut_equal(struct drm_property_blob *blob1, struct drm_property_blob *blob2, u32 gamma_mode, u32 bit_precision); +int intel_plane_color_init(struct drm_plane *plane);
#endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index be2392bbcecc..a937a20e4c49 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -391,6 +391,9 @@ struct drm_i915_display_funcs { */ void (*load_luts)(const struct intel_crtc_state *crtc_state); void (*read_luts)(struct intel_crtc_state *crtc_state); + /* Add Plane Color callbacks */ + void (*load_plane_csc_matrix)(const struct drm_plane_state *plane_state); + void (*load_plane_luts)(const struct drm_plane_state *plane_state); };
Add the Color capabilities of SDR planes.
Signed-off-by: Uma Shankar uma.shankar@intel.com Signed-off-by: Bhanuprakash Modem bhanuprakash.modem@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 67 ++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 2307a2e4d73d..fd0bfdf85703 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -25,6 +25,7 @@ #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_sprite.h" #include <drm/drm_plane.h>
#define CTM_COEFF_SIGN (1ULL << 63) @@ -2144,6 +2145,57 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { }, };
+ /* FIXME input bpc? */ +static const struct drm_color_lut_range d13_degamma_sdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 16, .output_bpc = 16, + .start = 0, .end = (1 << 16) - (1 << 16) / 33, + .min = 0, .max = (1 << 16) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = (1 << 16) - (1 << 16) / 33, .end = 1 << 16, + .min = 0, .max = 1 << 16, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = 1 << 16, .end = 3 << 16, + .min = 0, .max = (8 << 16) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = 3 << 16, .end = 7 << 16, + .min = 0, .max = (8 << 16) - 1, + }, +}; + int intel_plane_color_init(struct drm_plane *plane) { struct drm_i915_private *dev_priv = to_i915(plane->dev); @@ -2154,10 +2206,17 @@ int intel_plane_color_init(struct drm_plane *plane) ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", NULL, 0, LUT_TYPE_DEGAMMA); - ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", - d13_degamma_hdr, - sizeof(d13_degamma_hdr), - LUT_TYPE_DEGAMMA); + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", + d13_degamma_hdr, + sizeof(d13_degamma_hdr), + LUT_TYPE_DEGAMMA); + else + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, + "plane degamma", + d13_degamma_sdr, + sizeof(d13_degamma_sdr), + LUT_TYPE_DEGAMMA); drm_plane_attach_degamma_properties(plane); }
Extract the LUT and program plane degamma registers.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 116 +++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 2 + 2 files changed, 118 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index fd0bfdf85703..62df5122309a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -126,6 +126,29 @@ static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state lut_is_legacy(crtc_state->hw.gamma_lut); }
+/* + * Added to accommodate enhanced LUT precision. + * Max LUT precision is 32 bits. + */ +static u64 drm_color_lut_extract_ext(u64 user_input, u32 bit_precision) +{ + u64 val = user_input & 0xffffffff; + u32 max; + + if (bit_precision > 32) + return 0; + + max = 0xffffffff >> (32 - bit_precision); + /* Round only if we're not using full precision. */ + if (bit_precision < 32) { + val += 1UL << (32 - bit_precision - 1); + val >>= 32 - bit_precision; + } + + return ((user_input & 0xffffffff00000000) | + clamp_val(val, 0, max)); +} + /* * When using limited range, multiply the matrix given by userspace by * the matrix that we would use for the limited range. @@ -2196,6 +2219,97 @@ static const struct drm_color_lut_range d13_degamma_sdr[] = { }, };
+static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *degamma_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + lut_size = 128; + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (degamma_lut) { + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(degamma_lut[i].green, 24); + u32 lut_val = (word & 0xffffff); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + /* Program the max register to clamp values > 1.0. */ + while (i < 131) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + degamma_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 130); + } + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + + /* + * First 3 planes are HDR, so reduce by 3 to get to the right + * SDR plane offset + */ + plane = plane - 3; + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (degamma_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + degamma_lut[i].green); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + degamma_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + 1 << 16); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + +static void d13_plane_load_luts(const struct drm_plane_state *plane_state) +{ + const struct drm_property_blob *degamma_lut_blob = + plane_state->degamma_lut; + struct drm_color_lut_ext *degamma_lut = NULL; + + if (degamma_lut_blob) { + degamma_lut = degamma_lut_blob->data; + d13_program_plane_degamma_lut(plane_state, degamma_lut, 0); + } +} + int intel_plane_color_init(struct drm_plane *plane) { struct drm_i915_private *dev_priv = to_i915(plane->dev); @@ -2217,6 +2331,8 @@ int intel_plane_color_init(struct drm_plane *plane) d13_degamma_sdr, sizeof(d13_degamma_sdr), LUT_TYPE_DEGAMMA); + + dev_priv->display.load_plane_luts = d13_plane_load_luts; drm_plane_attach_degamma_properties(plane); }
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 919982c878ac..0c36a330734f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7232,6 +7232,7 @@ enum { #define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28) #define PLANE_COLOR_INPUT_CSC_ENABLE (1 << 20) /* ICL+ */ #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) /* Pre-ICL */ +#define PLANE_PRE_CSC_GAMMA_ENABLE (1 << 14) #define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17) #define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601 (1 << 17) #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17) @@ -11381,6 +11382,7 @@ enum skl_power_gate { #define PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe), \ _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe)) +#define PLANE_PAL_PREC_AUTO_INCREMENT (1 << 10)
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A 0x701d4 #define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B 0x711d4
Extended glk_plane_color_ctl to have plane color checks. This helps enabling the degamma or gamma block based on user inputs.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 724e7b04f3b6..4187a670e840 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -960,6 +960,11 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, u32 plane_color_ctl = 0;
plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + + /* FIXME needs hw.degamma_lut */ + if (plane_state->uapi.degamma_lut) + plane_color_ctl |= PLANE_PRE_CSC_GAMMA_ENABLE; + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
Initialize plane color features for XE_LPD.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 ++ 2 files changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 62e5a2a77fd4..854f37b49681 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -64,5 +64,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); void intel_plane_helper_add(struct intel_plane *plane); +int intel_plane_color_init(struct drm_plane *plane);
#endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4187a670e840..c4e01ae4343c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2184,6 +2184,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, BIT(DRM_SCALING_FILTER_DEFAULT) | BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
+ intel_plane_color_init(&plane->base); + intel_plane_helper_add(plane);
return plane;
Load plane color luts as part of atomic plane updates. This will be done only if the plane color luts are changed.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 3 +++ drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/intel_color.c | 9 +++++++++ 3 files changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 47234d898549..8796fc86b2e5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -513,6 +513,9 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane);
+ if (new_plane_state->uapi.color_mgmt_changed) + intel_color_load_plane_luts(&new_plane_state->uapi); + if (new_plane_state->uapi.visible || new_plane_state->planar_slave) { intel_update_plane(plane, new_crtc_state, new_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 854f37b49681..3001f4d69b4d 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -65,5 +65,6 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); void intel_plane_helper_add(struct intel_plane *plane); int intel_plane_color_init(struct drm_plane *plane); +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state);
#endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 62df5122309a..f5a9af858d1b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -22,6 +22,7 @@ * */
+#include "intel_atomic_plane.h" #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" @@ -2310,6 +2311,14 @@ static void d13_plane_load_luts(const struct drm_plane_state *plane_state) } }
+void intel_color_load_plane_luts(const struct drm_plane_state *plane_state) +{ + struct drm_device *dev = plane_state->plane->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + dev_priv->display.load_plane_luts(plane_state); +} + int intel_plane_color_init(struct drm_plane *plane) { struct drm_i915_private *dev_priv = to_i915(plane->dev);
Add a blob property for plane CSC usage.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 +++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++++++++++ drivers/gpu/drm/drm_color_mgmt.c | 11 +++++++++++ include/drm/drm_plane.h | 15 +++++++++++++++ 4 files changed, 39 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 6e358067cb7a..fafb8af1c9cb 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -314,6 +314,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
if (state->degamma_lut) drm_property_blob_get(state->degamma_lut); + if (state->ctm) + drm_property_blob_get(state->ctm);
state->color_mgmt_changed = false; } @@ -363,6 +365,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
drm_property_blob_put(state->fb_damage_clips); drm_property_blob_put(state->degamma_lut); + drm_property_blob_put(state->ctm); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 904291b96ba9..e736fd7c1d5b 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -605,6 +605,14 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, &replaced); state->color_mgmt_changed |= replaced; return ret; + } else if (property == plane->ctm_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + &state->ctm, + val, + sizeof(struct drm_color_ctm), -1, + &replaced); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, @@ -676,6 +684,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, } else if (property == plane->degamma_lut_property) { *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; + } else if (property == plane->ctm_property) { + *val = (state->ctm) ? state->ctm->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 29d0fc1e52b5..83832adf3adf 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -602,6 +602,10 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * engine, thereby making the content as linear for further color * processing. * + * ctm_property: + * Blob property which allows a userspace to provide CTM coefficients + * to do color space conversion or any other enhancement by doing a + * matrix multiplication using the h/w CTM processing engine */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -623,6 +627,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev,
plane->degamma_lut_property = prop;
+ prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_CTM", 0); + if (!prop) + return -ENOMEM; + + plane->ctm_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index fbfada0b990d..c4ed1799ecaf 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -255,6 +255,14 @@ struct drm_plane_state { */ struct drm_property_blob *degamma_lut;
+ /** + * @ctm: + * + * Color transformation matrix. See drm_plane_enable_color_mgmt(). The + * blob (if not NULL) is a &struct drm_color_ctm. + */ + struct drm_property_blob *ctm; + u8 color_mgmt_changed : 1; };
@@ -779,6 +787,13 @@ struct drm_plane { * used to convert the framebuffer's colors to linear gamma. */ struct drm_property *degamma_lut_property; + + /** + * @plane_ctm_property: Optional Plane property to set the + * matrix used to convert colors after the lookup in the + * degamma LUT. + */ + struct drm_property *ctm_property; };
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
Add a DRM helper to attach ctm property.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/drm_color_mgmt.c | 10 ++++++++++ include/drm/drm_plane.h | 1 + 2 files changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 83832adf3adf..5c3138497b9c 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -654,6 +654,16 @@ void drm_plane_attach_degamma_properties(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_degamma_properties);
+void drm_plane_attach_ctm_property(struct drm_plane *plane) +{ + if (!plane->ctm_property) + return; + + drm_object_attach_property(&plane->base, + plane->ctm_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_ctm_property); + int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index c4ed1799ecaf..3d329f71d287 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -889,6 +889,7 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, int num_values); void drm_plane_attach_degamma_properties(struct drm_plane *plane); +void drm_plane_attach_ctm_property(struct drm_plane *plane); int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges,
Define Register macros for plane CSC.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0c36a330734f..20c1b8ddded8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7440,6 +7440,49 @@ enum { #define PLANE_COLOR_CTL(pipe, plane) \ _MMIO_PLANE(plane, _PLANE_COLOR_CTL_1(pipe), _PLANE_COLOR_CTL_2(pipe))
+/* Plane CSC Registers */ +#define _PLANE_CSC_RY_GY_1_A 0x70210 +#define _PLANE_CSC_RY_GY_2_A 0x70310 + +#define _PLANE_CSC_RY_GY_1_B 0x71210 +#define _PLANE_CSC_RY_GY_2_B 0x71310 + +#define _PLANE_CSC_RY_GY_1(pipe) _PIPE(pipe, _PLANE_CSC_RY_GY_1_A, \ + _PLANE_CSC_RY_GY_1_B) +#define _PLANE_CSC_RY_GY_2(pipe) _PIPE(pipe, _PLANE_INPUT_CSC_RY_GY_2_A, \ + _PLANE_INPUT_CSC_RY_GY_2_B) +#define PLANE_CSC_COEFF(pipe, plane, index) _MMIO_PLANE(plane, \ + _PLANE_CSC_RY_GY_1(pipe) + (index) * 4, \ + _PLANE_CSC_RY_GY_2(pipe) + (index) * 4) + +#define _PLANE_CSC_PREOFF_HI_1_A 0x70228 +#define _PLANE_CSC_PREOFF_HI_2_A 0x70328 + +#define _PLANE_CSC_PREOFF_HI_1_B 0x71228 +#define _PLANE_CSC_PREOFF_HI_2_B 0x71328 + +#define _PLANE_CSC_PREOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_1_A, \ + _PLANE_CSC_PREOFF_HI_1_B) +#define _PLANE_CSC_PREOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_2_A, \ + _PLANE_CSC_PREOFF_HI_2_B) +#define PLANE_CSC_PREOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_PREOFF_HI_1(pipe) + \ + (index) * 4, _PLANE_CSC_PREOFF_HI_2(pipe) + \ + (index) * 4) + +#define _PLANE_CSC_POSTOFF_HI_1_A 0x70234 +#define _PLANE_CSC_POSTOFF_HI_2_A 0x70334 + +#define _PLANE_CSC_POSTOFF_HI_1_B 0x71234 +#define _PLANE_CSC_POSTOFF_HI_2_B 0x71334 + +#define _PLANE_CSC_POSTOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_1_A, \ + _PLANE_CSC_POSTOFF_HI_1_B) +#define _PLANE_CSC_POSTOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_2_A, \ + _PLANE_CSC_POSTOFF_HI_2_B) +#define PLANE_CSC_POSTOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_POSTOFF_HI_1(pipe) + \ + (index) * 4, _PLANE_CSC_POSTOFF_HI_2(pipe) + \ + (index) * 4) + #define _SEL_FETCH_PLANE_BASE_1_A 0x70890 #define _SEL_FETCH_PLANE_BASE_2_A 0x708B0 #define _SEL_FETCH_PLANE_BASE_3_A 0x708D0
Implement plane CSC for ICL+
Signed-off-by: Uma Shankar uma.shankar@intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 5 +- drivers/gpu/drm/i915/display/intel_color.c | 82 +++++++++++++++++++ .../drm/i915/display/skl_universal_plane.c | 4 + drivers/gpu/drm/i915/i915_reg.h | 1 + 4 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 8796fc86b2e5..1637f7890f42 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -499,6 +499,7 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct skl_ddb_entry entries_y[I915_MAX_PLANES]; struct skl_ddb_entry entries_uv[I915_MAX_PLANES]; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 update_mask = new_crtc_state->update_planes; struct intel_plane *plane;
@@ -513,8 +514,10 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane);
- if (new_plane_state->uapi.color_mgmt_changed) + if (new_plane_state->uapi.color_mgmt_changed) { intel_color_load_plane_luts(&new_plane_state->uapi); + dev_priv->display.load_plane_csc_matrix(&new_plane_state->uapi); + }
if (new_plane_state->uapi.visible || new_plane_state->planar_slave) { diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index f5a9af858d1b..e9c80ed41466 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2118,6 +2118,83 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } }
+static void icl_load_plane_csc_matrix(const struct drm_plane_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + struct drm_color_ctm *ctm; + const u64 *input; + u16 coeffs[9] = {}; + u16 postoff = 0; + int i; + + if (!icl_is_hdr_plane(dev_priv, plane) || !state->ctm) + return; + + ctm = state->ctm->data; + input = ctm->matrix; + + /* + * Convert fixed point S31.32 input to format supported by the + * hardware. + */ + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + u64 abs_coeff = ((1ULL << 63) - 1) & input[i]; + + /* + * Clamp input value to min/max supported by + * hardware. + */ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1); + + /* sign bit */ + if (CTM_COEFF_NEGATIVE(input[i])) + coeffs[i] |= 1 << 15; + + if (abs_coeff < CTM_COEFF_0_125) + coeffs[i] |= (3 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 12); + else if (abs_coeff < CTM_COEFF_0_25) + coeffs[i] |= (2 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 11); + else if (abs_coeff < CTM_COEFF_0_5) + coeffs[i] |= (1 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 10); + else if (abs_coeff < CTM_COEFF_1_0) + coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9); + else if (abs_coeff < CTM_COEFF_2_0) + coeffs[i] |= (7 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 8); + else + coeffs[i] |= (6 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 7); + } + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), + coeffs[0] << 16 | coeffs[1]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), + coeffs[2] << 16); + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), + coeffs[3] << 16 | coeffs[4]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), + coeffs[5] << 16); + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), + coeffs[6] << 16 | coeffs[7]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), + coeffs[8] << 16); + + intel_de_write(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0); + intel_de_write(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 1), 0); + intel_de_write(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 2), 0); + + intel_de_write(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 0), postoff); + intel_de_write(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 1), postoff); + intel_de_write(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 2), postoff); +} + /* FIXME input bpc? */ static const struct drm_color_lut_range d13_degamma_hdr[] = { /* segment 1 */ @@ -2342,7 +2419,12 @@ int intel_plane_color_init(struct drm_plane *plane) LUT_TYPE_DEGAMMA);
dev_priv->display.load_plane_luts = d13_plane_load_luts; + dev_priv->display.load_plane_csc_matrix = icl_load_plane_csc_matrix; + drm_plane_attach_degamma_properties(plane); + + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + drm_plane_attach_ctm_property(plane); }
return ret; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index c4e01ae4343c..61eff22a3503 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -965,6 +965,10 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, if (plane_state->uapi.degamma_lut) plane_color_ctl |= PLANE_PRE_CSC_GAMMA_ENABLE;
+ /* FIXME needs hw.ctm */ + if (plane_state->uapi.ctm) + plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 20c1b8ddded8..ceee500e64d7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7230,6 +7230,7 @@ enum { #define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-ICL */ #define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28) +#define PLANE_COLOR_PLANE_CSC_ENABLE (1 << 21) /* ICL+ */ #define PLANE_COLOR_INPUT_CSC_ENABLE (1 << 20) /* ICL+ */ #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) /* Pre-ICL */ #define PLANE_PRE_CSC_GAMMA_ENABLE (1 << 14)
Add Plane Gamma Mode as a blob property. This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property.
Lut values will be sent through a separate GAMMA_LUT blob property.
Signed-off-by: Uma Shankar uma.shankar@intel.com Signed-off-by: Bhanuprakash Modem bhanuprakash.modem@intel.com --- drivers/gpu/drm/drm_atomic_uapi.c | 4 ++++ drivers/gpu/drm/drm_color_mgmt.c | 26 ++++++++++++++++++++++++++ include/drm/drm_plane.h | 14 ++++++++++++++ 3 files changed, 44 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index e736fd7c1d5b..b5abf03c5d51 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -613,6 +613,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, &replaced); state->color_mgmt_changed |= replaced; return ret; + } else if (property == plane->gamma_mode_property) { + state->gamma_mode = val; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, @@ -686,6 +688,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, state->degamma_lut->base.id : 0; } else if (property == plane->ctm_property) { *val = (state->ctm) ? state->ctm->base.id : 0; + } else if (property == plane->gamma_mode_property) { + *val = state->gamma_mode; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 5c3138497b9c..02367e691cf3 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -606,6 +606,13 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * Blob property which allows a userspace to provide CTM coefficients * to do color space conversion or any other enhancement by doing a * matrix multiplication using the h/w CTM processing engine + * + * gamma_mode_property: + * Blob property which advertizes the possible gamma modes and + * lut ranges supported by the platform. This allows userspace + * to query and get the plane gamma color caps and choose the + * appropriate gamma mode and create lut values accordingly + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -634,6 +641,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev,
plane->ctm_property = prop;
+ prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "PLANE_GAMMA_MODE", num_values); + if (!prop) + return -ENOMEM; + + plane->gamma_mode_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -664,6 +678,16 @@ void drm_plane_attach_ctm_property(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_ctm_property);
+void drm_plane_attach_gamma_properties(struct drm_plane *plane) +{ + if (!plane->gamma_mode_property) + return; + + drm_object_attach_property(&plane->base, + plane->gamma_mode_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_gamma_properties); + int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, @@ -676,6 +700,8 @@ int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane,
if (type == LUT_TYPE_DEGAMMA) prop = plane->degamma_mode_property; + else + prop = plane->gamma_mode_property;
if (!prop) return -EINVAL; diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 3d329f71d287..9081867ecbd1 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -263,6 +263,13 @@ struct drm_plane_state { */ struct drm_property_blob *ctm;
+ /** + * @gamma_mode: This is a blob_id and exposes the platform capabilities + * wrt to various gamma modes and the respective lut ranges. This also + * helps user select a gamma mode amongst the supported ones. + */ + u32 gamma_mode; + u8 color_mgmt_changed : 1; };
@@ -794,6 +801,12 @@ struct drm_plane { * degamma LUT. */ struct drm_property *ctm_property; + + /** + * @gamma_mode_property: Optional Plane property to set the LUT + * used to convert the framebuffer's colors to non-linear gamma. + */ + struct drm_property *gamma_mode_property; };
#define obj_to_plane(x) container_of(x, struct drm_plane, base) @@ -890,6 +903,7 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, int num_values); void drm_plane_attach_degamma_properties(struct drm_plane *plane); void drm_plane_attach_ctm_property(struct drm_plane *plane); +void drm_plane_attach_gamma_properties(struct drm_plane *plane); int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges,
Add Plane Gamma Lut as a blob property.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 +++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++++++++++ drivers/gpu/drm/drm_color_mgmt.c | 18 ++++++++++++++++++ include/drm/drm_plane.h | 14 ++++++++++++++ 4 files changed, 45 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index fafb8af1c9cb..7ddf6e4b956b 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -316,6 +316,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, drm_property_blob_get(state->degamma_lut); if (state->ctm) drm_property_blob_get(state->ctm); + if (state->gamma_lut) + drm_property_blob_get(state->gamma_lut);
state->color_mgmt_changed = false; } @@ -366,6 +368,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_property_blob_put(state->fb_damage_clips); drm_property_blob_put(state->degamma_lut); drm_property_blob_put(state->ctm); + drm_property_blob_put(state->gamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index b5abf03c5d51..a32557a4e0d3 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -615,6 +615,13 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, return ret; } else if (property == plane->gamma_mode_property) { state->gamma_mode = val; + } else if (property == plane->gamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + &state->gamma_lut, + val, -1, sizeof(struct drm_color_lut_ext), + &replaced); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, @@ -690,6 +697,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = (state->ctm) ? state->ctm->base.id : 0; } else if (property == plane->gamma_mode_property) { *val = state->gamma_mode; + } else if (property == plane->gamma_lut_property) { + *val = (state->gamma_lut) ? + state->gamma_lut->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 02367e691cf3..b5b3ff7f654d 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -613,6 +613,11 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * to query and get the plane gamma color caps and choose the * appropriate gamma mode and create lut values accordingly * + * gamma_lut_property: + * Blob property which allows a userspace to provide LUT values + * to apply gamma curve using the h/w plane degamma processing + * engine, thereby making the content as non-linear. + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -648,6 +653,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev,
plane->gamma_mode_property = prop;
+ prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_GAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + + plane->gamma_lut_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -685,6 +697,12 @@ void drm_plane_attach_gamma_properties(struct drm_plane *plane)
drm_object_attach_property(&plane->base, plane->gamma_mode_property, 0); + + if (!plane->gamma_lut_property) + return; + + drm_object_attach_property(&plane->base, + plane->gamma_lut_property, 0); } EXPORT_SYMBOL(drm_plane_attach_gamma_properties);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 9081867ecbd1..8b1f506bc5d3 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -270,6 +270,14 @@ struct drm_plane_state { */ u32 gamma_mode;
+ /* @gamma_lut: + * + * Lookup table for converting framebuffer pixel data after applying the + * color conversion matrix @ctm. See drm_plane_enable_color_mgmt(). The + * blob (if not NULL) is an array of &struct drm_color_lut_ext. + */ + struct drm_property_blob *gamma_lut; + u8 color_mgmt_changed : 1; };
@@ -807,6 +815,12 @@ struct drm_plane { * used to convert the framebuffer's colors to non-linear gamma. */ struct drm_property *gamma_mode_property; + + /** + * @gamma_lut_property: Optional Plane property to set the LUT + * used to convert the framebuffer's colors to non-linear gamma. + */ + struct drm_property *gamma_lut_property; };
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
Define the structure with XE_LPD gamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes. Degamma and GAMMA has same Lut caps for SDR planes, extended the same.
Initialize the mode range caps as well.
Signed-off-by: Uma Shankar uma.shankar@intel.com Signed-off-by: Bhanuprakash Modem bhanuprakash.modem@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 112 ++++++++++++++++++--- 1 file changed, 99 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e9c80ed41466..b4cad5c92c85 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2247,7 +2247,7 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { };
/* FIXME input bpc? */ -static const struct drm_color_lut_range d13_degamma_sdr[] = { +static const struct drm_color_lut_range d13_gamma_degamma_sdr[] = { /* segment 1 */ { .flags = (DRM_MODE_LUT_GAMMA | @@ -2297,6 +2297,63 @@ static const struct drm_color_lut_range d13_degamma_sdr[] = { }, };
+ /* FIXME input bpc? */ +static const struct drm_color_lut_range d13_gamma_hdr[] = { + /* + * ToDo: Add Segment 1 + * There is an optional fine segment added with 9 lut values + * Will be added later + */ + + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = 1 << 24, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (3 << 24), + }, + /* Segment 5 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (7 << 24), + }, +}; + static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, struct drm_color_lut_ext *degamma_lut, u32 offset) @@ -2406,26 +2463,55 @@ int intel_plane_color_init(struct drm_plane *plane) ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", NULL, 0, LUT_TYPE_DEGAMMA); - if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + if (ret) + return ret; + + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no gamma", + NULL, 0, + LUT_TYPE_GAMMA); + if (ret) + return ret; + + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) { ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", d13_degamma_hdr, sizeof(d13_degamma_hdr), LUT_TYPE_DEGAMMA); - else - ret = drm_plane_color_add_gamma_degamma_mode_range(plane, - "plane degamma", - d13_degamma_sdr, - sizeof(d13_degamma_sdr), + if (ret) + return ret; + + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane gamma", + d13_gamma_hdr, + sizeof(d13_gamma_hdr), + LUT_TYPE_GAMMA); + if (ret) + return ret; + } else { + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", + d13_gamma_degamma_sdr, + sizeof(d13_gamma_degamma_sdr), LUT_TYPE_DEGAMMA); + if (ret) + return ret; + + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane gamma", + d13_gamma_degamma_sdr, + sizeof(d13_gamma_degamma_sdr), + LUT_TYPE_GAMMA); + if (ret) + return ret; + } + }
- dev_priv->display.load_plane_luts = d13_plane_load_luts; - dev_priv->display.load_plane_csc_matrix = icl_load_plane_csc_matrix; + dev_priv->display.load_plane_luts = d13_plane_load_luts; + dev_priv->display.load_plane_csc_matrix = icl_load_plane_csc_matrix;
- drm_plane_attach_degamma_properties(plane); + drm_plane_attach_degamma_properties(plane);
- if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) - drm_plane_attach_ctm_property(plane); - } + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + drm_plane_attach_ctm_property(plane); + + drm_plane_attach_gamma_properties(plane);
return ret; }
Add macros to define Plane Gamma registers
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 73 +++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ceee500e64d7..fc4f8b430518 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -11464,6 +11464,79 @@ enum skl_power_gate { _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ _PLANE_PRE_CSC_GAMC_DATA_2(pipe))
+/* Display13 Plane Gamma Reg */ +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A 0x70160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B 0x71160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A 0x70260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B 0x71260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A 0x70164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B 0x71164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A 0x70264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B 0x71264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A 0x701d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B 0x711d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A 0x702d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B 0x712d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_A 0x701dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_B 0x711dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_A 0x702dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_B 0x712dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_1_A 0x704d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1_B 0x714d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_A 0x705d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_B 0x715d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_2_B) +#define PLANE_POST_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_1_A 0x704dc +#define _PLANE_POST_CSC_GAMC_DATA_1_B 0x714dc +#define _PLANE_POST_CSC_GAMC_DATA_2_A 0x705dc +#define _PLANE_POST_CSC_GAMC_DATA_2_B 0x715dc +#define _PLANE_POST_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_1_A, \ + _PLANE_POST_CSC_GAMC_DATA_1_B) +#define _PLANE_POST_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_2_A, \ + _PLANE_POST_CSC_GAMC_DATA_2_B) +#define PLANE_POST_CSC_GAMC_DATA(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_1(pipe), \ + _PLANE_POST_CSC_GAMC_DATA_2(pipe)) + /* pipe CSC & degamma/gamma LUTs on CHV */ #define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900) #define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904)
Extract the LUT and program plane gamma registers. Enabled multi segmented lut as well.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 89 ++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 9 ++- 2 files changed, 94 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index b4cad5c92c85..e5f168a32932 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -27,6 +27,9 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_sprite.h" + +#include "skl_universal_plane.h" + #include <drm/drm_plane.h>
#define CTM_COEFF_SIGN (1ULL << 63) @@ -2433,16 +2436,102 @@ static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, } }
+static void d13_program_plane_gamma_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *gamma_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + if (gamma_lut) { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(gamma_lut[i].green, 24); + u32 lut_val = (word & 0xffffff); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + do { + /* Program the max register to clamp values > 1.0. */ + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + gamma_lut[i].green); + } while (i++ < 34); + } else { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + /* + * First 3 planes are HDR, so reduce by 3 to get to the right + * SDR plane offset + */ + plane = plane - 3; + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (gamma_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + gamma_lut[i].green & 0xffff); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + gamma_lut[i++].green & 0x3ffff); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + (1 << 16)); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static void d13_plane_load_luts(const struct drm_plane_state *plane_state) { const struct drm_property_blob *degamma_lut_blob = plane_state->degamma_lut; + const struct drm_property_blob *gamma_lut_blob = + plane_state->gamma_lut; struct drm_color_lut_ext *degamma_lut = NULL; + struct drm_color_lut_ext *gamma_lut = NULL;
if (degamma_lut_blob) { degamma_lut = degamma_lut_blob->data; d13_program_plane_degamma_lut(plane_state, degamma_lut, 0); } + + if (gamma_lut_blob) { + gamma_lut = gamma_lut_blob->data; + d13_program_plane_gamma_lut(plane_state, gamma_lut, 0); + } }
void intel_color_load_plane_luts(const struct drm_plane_state *plane_state) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fc4f8b430518..037b95153b86 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7230,10 +7230,11 @@ enum { #define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-ICL */ #define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28) -#define PLANE_COLOR_PLANE_CSC_ENABLE (1 << 21) /* ICL+ */ -#define PLANE_COLOR_INPUT_CSC_ENABLE (1 << 20) /* ICL+ */ -#define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) /* Pre-ICL */ -#define PLANE_PRE_CSC_GAMMA_ENABLE (1 << 14) +#define PLANE_COLOR_PLANE_CSC_ENABLE (1 << 21) /* ICL+ */ +#define PLANE_COLOR_INPUT_CSC_ENABLE (1 << 20) /* ICL+ */ +#define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) /* Pre-ICL */ +#define PLANE_POST_CSC_GAMMA_MULTI_SEGMENT_ENABLE (1 << 15) +#define PLANE_PRE_CSC_GAMMA_ENABLE (1 << 14) #define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17) #define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601 (1 << 17) #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17)
Enable plane gamma feature in check callbacks. Decide based on the user input.
Signed-off-by: Uma Shankar uma.shankar@intel.com --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 61eff22a3503..139863d4e3a7 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -959,7 +959,9 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); u32 plane_color_ctl = 0;
- plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + /* FIXME needs hw.gamma_lut */ + if (!plane_state->uapi.gamma_lut) + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
/* FIXME needs hw.degamma_lut */ if (plane_state->uapi.degamma_lut)
On Tue, 7 Sep 2021 03:08:42 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ | | | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/ We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Hi,
thank you for this. I do believe the KMS UAPI should expose what hardware can do (prescribed operations) rather than how they would be often used (to realize a conversion from one space description to another). This proposal fits quite nicely with what I have envisioned for Weston.
I mainly went over the big picture by commenting in detail on the proposal document, and not looking too carefully at the other documentation or UAPI details at this time.
Unfortunately I was unable to decipher how userspace is supposed to use the XE_LPD special gamma features.
Thanks, pq
Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma
Documentation/gpu/drm-kms.rst | 90 +++ Documentation/gpu/rfc/drm_color_pipeline.rst | 167 ++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 12 + drivers/gpu/drm/drm_atomic_uapi.c | 38 ++ drivers/gpu/drm/drm_color_mgmt.c | 177 +++++- .../gpu/drm/i915/display/intel_atomic_plane.c | 6 + .../gpu/drm/i915/display/intel_atomic_plane.h | 2 + drivers/gpu/drm/i915/display/intel_color.c | 513 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 + .../drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 176 +++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 81 +++ include/uapi/drm/drm_mode.h | 58 ++ 16 files changed, 1337 insertions(+), 6 deletions(-) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:25 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 00/22] Add Support for Plane Color Lut and CSC features
On Tue, 7 Sep 2021 03:08:42 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ | | | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/ We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Hi,
thank you for this. I do believe the KMS UAPI should expose what hardware can do (prescribed operations) rather than how they would be often used (to realize a conversion from one space description to another). This proposal fits quite nicely with what I have envisioned for Weston.
I mainly went over the big picture by commenting in detail on the proposal document, and not looking too carefully at the other documentation or UAPI details at this time.
Thanks Pekka for the feedback.
Unfortunately I was unable to decipher how userspace is supposed to use the XE_LPD special gamma features.
I will include the details on how userspace should actually get this through a sample IGT reference, that should help make this clear.
Regards, Uma Shankar
Thanks, pq
Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma
Documentation/gpu/drm-kms.rst | 90 +++ Documentation/gpu/rfc/drm_color_pipeline.rst | 167 ++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 12 + drivers/gpu/drm/drm_atomic_uapi.c | 38 ++ drivers/gpu/drm/drm_color_mgmt.c | 177 +++++- .../gpu/drm/i915/display/intel_atomic_plane.c | 6 + .../gpu/drm/i915/display/intel_atomic_plane.h | 2 + drivers/gpu/drm/i915/display/intel_color.c | 513 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 + .../drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 176 +++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 81 +++ include/uapi/drm/drm_mode.h | 58 ++ 16 files changed, 1337 insertions(+), 6 deletions(-) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
On 2021-10-12 17:01, Shankar, Uma wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:25 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 00/22] Add Support for Plane Color Lut and CSC features
On Tue, 7 Sep 2021 03:08:42 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ | | | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/%3E%3E%3E%3E We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Hi,
thank you for this. I do believe the KMS UAPI should expose what hardware can do (prescribed operations) rather than how they would be often used (to realize a conversion from one space description to another). This proposal fits quite nicely with what I have envisioned for Weston.
It's taken me a while but I am starting to agree with the prescriptive approach to expose HW functionality. One thing we'll want to be careful of is to make sure this isn't tied to specific HW more than it needs to be. I'll comment in other places of this patchset to elaborate.
What's making me come around, i.e. change from a prescriptive (these are the input/output/blending spaces/formats) to a descriptive (these are the LUTs and CTMs) approach?
1) The prescriptive way has no good way of dealing with gamut and tone mapping. To do so we would need explicit OOTFs and CTMs or 3D LUTs anyways.
2) The prescriptive way provides no semblance of guarantee that transforms are equivalent when the compositor uses shaders transforms and composition vs when the compositor uses KMS transforms and composition.
3) Policy about treatment of surfaces/planes and blending is best left with the compositor (for the above reasons).
I mainly went over the big picture by commenting in detail on the proposal document, and not looking too carefully at the other documentation or UAPI details at this time.
Thanks Pekka for the feedback.
Unfortunately I was unable to decipher how userspace is supposed to use the XE_LPD special gamma features.
I will include the details on how userspace should actually get this through a sample IGT reference, that should help make this clear.
It looks like with your current definitions each userspace compositor (Weston, kwin, mutter, wlroots, Chrome's compositor, Android's compositor, etc.) would need to learn how to program the XE_LPD LUTs as well as AMD LUTs. Would these definitions change in future Intel HW generations? Would this mean all compositors would need to learn again how to program the future LUT format?
Other options would be to give userspace a generic LUT with 4k FP16 entries and then re-map that to the HW LUT in the kernel driver.
I might be missing some of the nuances of the XE_LPD LUT but it seems to me that the main difference between different PWL implementations is the distribution of the points used to define the LUT. Maybe a more generic PWL implementation could have a kernel driver report one (or more) PWL point distributions. We could encode these as enums and pre-defined arrays in a UAPI header. That way the compositor could have a single, generic implementation of programming PWL in FP16 and the kernel driver would only need to remap the FP16 to the HW-internal format, which is a trivial conversion. Using this approach compositors would implement PWL support once and won't have to touch it again in the future. Is there anything that would make this approach a bad idea for Intel HW (or other HW)? (Credit for this idea goes to Vitaly)
Harry
Regards, Uma Shankar
Thanks, pq
Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma
Documentation/gpu/drm-kms.rst | 90 +++ Documentation/gpu/rfc/drm_color_pipeline.rst | 167 ++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 12 + drivers/gpu/drm/drm_atomic_uapi.c | 38 ++ drivers/gpu/drm/drm_color_mgmt.c | 177 +++++- .../gpu/drm/i915/display/intel_atomic_plane.c | 6 + .../gpu/drm/i915/display/intel_atomic_plane.h | 2 + drivers/gpu/drm/i915/display/intel_color.c | 513 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 + .../drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 176 +++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 81 +++ include/uapi/drm/drm_mode.h | 58 ++ 16 files changed, 1337 insertions(+), 6 deletions(-) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
On Tue, 26 Oct 2021 11:02:31 -0400 Harry Wentland harry.wentland@amd.com wrote:
On 2021-10-12 17:01, Shankar, Uma wrote:
-----Original Message----- From: Pekka Paalanen ppaalanen@gmail.com Sent: Tuesday, October 12, 2021 5:25 PM To: Shankar, Uma uma.shankar@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentland@amd.com; ville.syrjala@linux.intel.com; brian.starkey@arm.com; sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 00/22] Add Support for Plane Color Lut and CSC features
On Tue, 7 Sep 2021 03:08:42 +0530 Uma Shankar uma.shankar@intel.com wrote:
This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ | | | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/%3E%3E%3E%3E We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Hi,
thank you for this. I do believe the KMS UAPI should expose what hardware can do (prescribed operations) rather than how they would be often used (to realize a conversion from one space description to another). This proposal fits quite nicely with what I have envisioned for Weston.
It's taken me a while but I am starting to agree with the prescriptive approach to expose HW functionality. One thing we'll want to be careful of is to make sure this isn't tied to specific HW more than it needs to be. I'll comment in other places of this patchset to elaborate.
What's making me come around, i.e. change from a prescriptive (these are the input/output/blending spaces/formats) to a descriptive (these are the LUTs and CTMs) approach?
The prescriptive way has no good way of dealing with gamut and tone mapping. To do so we would need explicit OOTFs and CTMs or 3D LUTs anyways.
The prescriptive way provides no semblance of guarantee that transforms are equivalent when the compositor uses shaders transforms and composition vs when the compositor uses KMS transforms and composition.
Policy about treatment of surfaces/planes and blending is best left with the compositor (for the above reasons).
Hi Harry,
I think we might have confusion there about prescriptive vs. descriptive, but I understand what you mean, and yes, those are my points too.
I mainly went over the big picture by commenting in detail on the proposal document, and not looking too carefully at the other documentation or UAPI details at this time.
Thanks Pekka for the feedback.
Unfortunately I was unable to decipher how userspace is supposed to use the XE_LPD special gamma features.
I will include the details on how userspace should actually get this through a sample IGT reference, that should help make this clear.
It looks like with your current definitions each userspace compositor (Weston, kwin, mutter, wlroots, Chrome's compositor, Android's compositor, etc.) would need to learn how to program the XE_LPD LUTs as well as AMD LUTs. Would these definitions change in future Intel HW generations? Would this mean all compositors would need to learn again how to program the future LUT format?
Other options would be to give userspace a generic LUT with 4k FP16 entries and then re-map that to the HW LUT in the kernel driver.
Do you want to run the optimisation algorithm to map the generic LUT to hardware specific optimised representation in the kernel driver? Wouldn't that be too much?
To me this seems like the perfect starting point for a libcamera equivalent to KMS. Feed the generic LUT to the lib, and get whatever the hardware-driver-specific KMS UAPI needs. Perhaps even with an error measure, so that a compositor can evaluate whether the mapping is accurate enough or if it needs to fall back.
I might be missing some of the nuances of the XE_LPD LUT but it seems to me that the main difference between different PWL implementations is the distribution of the points used to define the LUT. Maybe a more generic PWL implementation could have a kernel driver report one (or more) PWL point distributions. We could encode these as enums and pre-defined arrays in a UAPI header. That way the compositor could have a single, generic implementation of programming PWL in FP16 and the kernel driver would only need to remap the FP16 to the HW-internal format, which is a trivial conversion. Using this approach compositors would implement PWL support once and won't have to touch it again in the future. Is there anything that would make this approach a bad idea for Intel HW (or other HW)? (Credit for this idea goes to Vitaly)
I think that is also a workable solution. If that happens, it seems likely that a library for that optimisation will appear.
It has just one shortcoming: the compositor has no idea of the precision as there is no way to get an error measure for how much the FP16->internal conversion loses precision.
But maybe that is never significant? Or could we have some precision guarantees otherwise?
I'm thinking of hard-core professional color users who wouldn't normally trust off-loading to KMS at all, at least not on-demand off-loading where you are never sure if you are looking at SW or KMS composition.
Thanks, pq
On 2021-09-06 17:38, Uma Shankar wrote:
This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ |
We've had a number of discussions on naming for these properties but I don't think we've arrived at a consensus. It has come up repeatedly, though, that gamma/degamma might be misleading terms.
I've opened a ticket on gitlab to help track this item and would like it if we could discuss the merits of different naming schemes over there:
https://gitlab.freedesktop.org/pq/color-and-hdr/-/issues/7
Uma, I tried to tag you but don't see you on gitlab.freedesktop.org.
Harry
| | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/ We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma
Documentation/gpu/drm-kms.rst | 90 +++ Documentation/gpu/rfc/drm_color_pipeline.rst | 167 ++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 12 + drivers/gpu/drm/drm_atomic_uapi.c | 38 ++ drivers/gpu/drm/drm_color_mgmt.c | 177 +++++- .../gpu/drm/i915/display/intel_atomic_plane.c | 6 + .../gpu/drm/i915/display/intel_atomic_plane.h | 2 + drivers/gpu/drm/i915/display/intel_color.c | 513 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 + .../drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 176 +++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 81 +++ include/uapi/drm/drm_mode.h | 58 ++ 16 files changed, 1337 insertions(+), 6 deletions(-) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
-----Original Message----- From: dri-devel dri-devel-bounces@lists.freedesktop.org On Behalf Of Harry Wentland Sent: Wednesday, February 2, 2022 9:42 PM To: Shankar, Uma uma.shankar@intel.com; intel-gfx@lists.freedesktop.org; dri- devel@lists.freedesktop.org Cc: sebastian@sebastianwick.net; Shashank.Sharma@amd.com Subject: Re: [RFC v2 00/22] Add Support for Plane Color Lut and CSC features
On 2021-09-06 17:38, Uma Shankar wrote:
This is how a typical display color hardware pipeline looks like: +-------------------------------------------+ | RAM | | +------+ +---------+ +---------+ | | | FB 1 | | FB 2 | | FB N | | | +------+ +---------+ +---------+ | +-------------------------------------------+ | Plane Color Hardware Block | +--------------------------------------------+ | +---v-----+ +---v-------+ +---v------+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-----+ +---+-------+ +---+------+ | | | | | | | +---v-----+ +---v-------+ +---v------+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-----+ +----+------+ +----+-----+ | | | | | | | +---v-----+ +----v------+ +----v-----+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma | | | +---+-----+ +----+------+ +----+-----+ |
We've had a number of discussions on naming for these properties but I don't think we've arrived at a consensus. It has come up repeatedly, though, that gamma/degamma might be misleading terms.
I've opened a ticket on gitlab to help track this item and would like it if we could discuss the merits of different naming schemes over there:
https://gitlab.freedesktop.org/pq/color-and-hdr/-/issues/7
Uma, I tried to tag you but don't see you on gitlab.freedesktop.org.
Thanks Harry for creating the issue. I have replied there and we can discuss and finalize the UAPI.
Regards, Uma Shankar
Harry
| | | | | +--------------------------------------------+ +------v--------------v---------------v-------| || || || Pipe Blender || +--------------------+------------------------+ | | | | +-----------v----------+ | | | Pipe DeGamma | | | | | | | +-----------+----------+ | | | Pipe Color | | +-----------v----------+ Hardware | | | Pipe CSC/CTM | | | | | | | +-----------+----------+ | | | | | +-----------v----------+ | | | Pipe Gamma | | | | | | | +-----------+----------+ | | | | +---------------------------------------------+ | v Pipe Output
This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc.
Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware.
These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series.
Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea.
Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/ We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines.
ToDo: State readout for this feature will be added next.
v2: Added UAPI description and added change in the rfc section of kernel Documentation folder
Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma
Documentation/gpu/drm-kms.rst | 90 +++ Documentation/gpu/rfc/drm_color_pipeline.rst | 167 ++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 12 + drivers/gpu/drm/drm_atomic_uapi.c | 38 ++ drivers/gpu/drm/drm_color_mgmt.c | 177 +++++- .../gpu/drm/i915/display/intel_atomic_plane.c | 6 + .../gpu/drm/i915/display/intel_atomic_plane.h | 2 + drivers/gpu/drm/i915/display/intel_color.c | 513 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 + .../drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 176 +++++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 81 +++ include/uapi/drm/drm_mode.h | 58 ++ 16 files changed, 1337 insertions(+), 6 deletions(-) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst
dri-devel@lists.freedesktop.org