diff --git a/CMakeLists.txt b/CMakeLists.txt index 4298d7e5..db1fcfe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -502,8 +502,6 @@ protocolnew("protocols" "kde-server-decoration" true) protocolnew("protocols" "wlr-data-control-unstable-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) -protocolnew("protocols" "xx-color-management-v4" true) -protocolnew("protocols" "frog-color-management-v1" true) protocolnew("protocols" "wayland-drm" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true) diff --git a/protocols/frog-color-management-v1.xml b/protocols/frog-color-management-v1.xml deleted file mode 100644 index aab235a7..00000000 --- a/protocols/frog-color-management-v1.xml +++ /dev/null @@ -1,366 +0,0 @@ - - - - - Copyright © 2023 Joshua Ashton for Valve Software - Copyright © 2023 Xaver Hugl - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - The aim of this color management extension is to get HDR games working quickly, - and have an easy way to test implementations in the wild before the upstream - protocol is ready to be merged. - For that purpose it's intentionally limited and cut down and does not serve - all uses cases. - - - - - The color management factory singleton creates color managed surface objects. - - - - - - - - - - - - - - - - Interface for changing surface color management and HDR state. - - An implementation must: support every part of the version - of the frog_color_managed_surface interface it exposes. - Including all known enums associated with a given version. - - - - - Destroying the color managed surface resets all known color - state for the surface back to 'undefined' implementation-specific - values. - - - - - - Extended information on the transfer functions described - here can be found in the Khronos Data Format specification: - https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html - - - - - - - - - - - - - - - - - - - - - - - - - - - - Extended information on render intents described - here can be found in ICC.1:2022: - - https://www.color.org/specification/ICC.1-2022-05.pdf - - - - - - - NOTE: On a surface with "perceptual" (default) render intent, handling of the container's - color volume - is implementation-specific, and may differ between different transfer functions it is paired - with: - ie. sRGB + 709 rendering may have it's primaries widened to more of the available display's - gamut - to be be more pleasing for the viewer. - Compared to scRGB Linear + 709 being treated faithfully as 709 - (including utilizing negatives out of the 709 gamut triangle) - - - - - - - Forwards HDR metadata from the client to the compositor. - - HDR Metadata Infoframe as per CTA 861.G spec. - - Usage of this HDR metadata is implementation specific and - outside of the scope of this protocol. - - - - Mastering Red Color Primary X Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering Red Color Primary Y Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering Green Color Primary X Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering Green Color Primary Y Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering Blue Color Primary X Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering Blue Color Primary Y Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering White Point X Coordinate of the Data. - - These are coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Mastering White Point Y Coordinate of the Data. - - These are coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Max Mastering Display Luminance. - This value is coded as an unsigned 16-bit value in units of 1 cd/m2, - where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. - - - - - Min Mastering Display Luminance. - This value is coded as an unsigned 16-bit value in units of - 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF - represents 6.5535 cd/m2. - - - - - Max Content Light Level. - This value is coded as an unsigned 16-bit value in units of 1 cd/m2, - where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. - - - - - Max Frame Average Light Level. - This value is coded as an unsigned 16-bit value in units of 1 cd/m2, - where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. - - - - - - - Current preferred metadata for a surface. - The application should use this information to tone-map its buffers - to this target before committing. - - This metadata does not necessarily correspond to any physical output, but - rather what the compositor thinks would be best for a given surface. - - - - Specifies a known transfer function that corresponds to the - output the surface is targeting. - - - - - Output Red Color Primary X Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output Red Color Primary Y Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output Green Color Primary X Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output Green Color Primary Y Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output Blue Color Primary X Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output Blue Color Primary Y Coordinate of the Data. - - Coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output White Point X Coordinate of the Data. - - These are coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Output White Point Y Coordinate of the Data. - - These are coded as unsigned 16-bit values in units of - 0.00002, where 0x0000 represents zero and 0xC350 - represents 1.0000. - - - - - Max Output Luminance - The max luminance in nits that the output is capable of rendering in small areas. - Content should: not exceed this value to avoid clipping. - - This value is coded as an unsigned 16-bit value in units of 1 cd/m2, - where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. - - - - - Min Output Luminance - The min luminance that the output is capable of rendering. - Content should: not exceed this value to avoid clipping. - - This value is coded as an unsigned 16-bit value in units of - 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF - represents 6.5535 cd/m2. - - - - - Max Full Frame Luminance - The max luminance in nits that the output is capable of rendering for the - full frame sustained. - - This value is coded as an unsigned 16-bit value in units of 1 cd/m2, - where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. - - - - - \ No newline at end of file diff --git a/protocols/xx-color-management-v4.xml b/protocols/xx-color-management-v4.xml deleted file mode 100644 index 23ff716e..00000000 --- a/protocols/xx-color-management-v4.xml +++ /dev/null @@ -1,1457 +0,0 @@ - - - - Copyright 2019 Sebastian Wick - Copyright 2019 Erwin Burema - Copyright 2020 AMD - Copyright 2020-2024 Collabora, Ltd. - Copyright 2024 Xaver Hugl - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - The aim of the color management extension is to allow clients to know - the color properties of outputs, and to tell the compositor about the color - properties of their content on surfaces. Doing this enables a compositor - to perform automatic color management of content for different outputs - according to how content is intended to look like. - - The color properties are represented as an image description object which - is immutable after it has been created. A wl_output always has an - associated image description that clients can observe. A wl_surface - always has an associated preferred image description as a hint chosen by - the compositor that clients can also observe. Clients can set an image - description on a wl_surface to denote the color characteristics of the - surface contents. - - An image description includes SDR and HDR colorimetry and encoding, HDR - metadata, and viewing environment parameters. An image description does - not include the properties set through color-representation extension. - It is expected that the color-representation extension is used in - conjunction with the color management extension when necessary, - particularly with the YUV family of pixel formats. - - Recommendation ITU-T H.273 - "Coding-independent code points for video signal type identification" - shall be referred to as simply H.273 here. - - The color-and-hdr repository - (https://gitlab.freedesktop.org/pq/color-and-hdr) contains - background information on the protocol design and legacy color management. - It also contains a glossary, learning resources for digital color, tools, - samples and more. - - The terminology used in this protocol is based on common color science and - color encoding terminology where possible. The glossary in the color-and-hdr - repository shall be the authority on the definition of terms in this - protocol. - - - - - A global interface used for getting color management extensions for - wl_surface and wl_output objects, and for creating client defined image - description objects. The extension interfaces allow - getting the image description of outputs and setting the image - description of surfaces. - - - - - Destroy the xx_color_manager_v4 object. This does not affect any other - objects in any way. - - - - - - - - - - - See the ICC.1:2022 specification from the International Color Consortium - for more details about rendering intents. - - The principles of ICC defined rendering intents apply with all types of - image descriptions, not only those with ICC file profiles. - - Compositors must support the perceptual rendering intent. Other - rendering intents are optional. - - - - - - - - - - - - - - - - - - - - The compositor supports set_mastering_display_primaries request with a - target color volume fully contained inside the primary color volume. - - - - - The compositor additionally supports target color volumes that - extend outside of the primary color volume. - - This can only be advertised if feature set_mastering_display_primaries - is supported as well. - - - - - - - Named color primaries used to encode well-known sets of primaries. H.273 - is the authority, when it comes to the exact values of primaries and - authoritative specifications, where an equivalent code point exists. - - Descriptions do list the specifications for convenience. - - - - - Color primaries as defined by - - Rec. ITU-R BT.709-6 - - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended - colour gamut system (historical) - - IEC 61966-2-1 sRGB or sYCC - - IEC 61966-2-4 - - Society of Motion Picture and Television Engineers (SMPTE) RP 177 - (1993) Annex B - Equivalent to H.273 ColourPrimaries code point 1. - - - - - Color primaries as defined by - - Rec. ITU-R BT.470-6 System M (historical) - - United States National Television System Committee 1953 - Recommendation for transmission standards for color television - - United States Federal Communications Commission (2003) Title 47 Code - of Federal Regulations 73.682 (a)(20) - Equivalent to H.273 ColourPrimaries code point 4. - - - - - Color primaries as defined by - - Rec. ITU-R BT.470-6 System B, G (historical) - - Rec. ITU-R BT.601-7 625 - - Rec. ITU-R BT.1358-0 625 (historical) - - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM - Equivalent to H.273 ColourPrimaries code point 5. - - - - - Color primaries as defined by - - Rec. ITU-R BT.601-7 525 - - Rec. ITU-R BT.1358-1 525 or 625 (historical) - - Rec. ITU-R BT.1700-0 NTSC - - SMPTE 170M (2004) - - SMPTE 240M (1999) (historical) - Equivalent to H.273 ColourPrimaries code point 6 and 7. - - - - - Color primaries as defined by H.273 for generic film. - Equivalent to H.273 ColourPrimaries code point 8. - - - - - Color primaries as defined by - - Rec. ITU-R BT.2020-2 - - Rec. ITU-R BT.2100-0 - Equivalent to H.273 ColourPrimaries code point 9. - - - - - Color primaries as defined as the maximum of the CIE 1931 XYZ color - space by - - SMPTE ST 428-1 - - (CIE 1931 XYZ as in ISO 11664-1) - Equivalent to H.273 ColourPrimaries code point 10. - - - - - Color primaries as defined by Digital Cinema System and published in - SMPTE RP 431-2 (2011). Equivalent to H.273 ColourPrimaries code point - 11. - - - - - Color primaries as defined by Digital Cinema System and published in - SMPTE EG 432-1 (2010). - Equivalent to H.273 ColourPrimaries code point 12. - - - - - Color primaries as defined by Adobe as "Adobe RGB" and later published - by ISO 12640-4 (2011). - - - - - - - Named transfer functions used to encode well-known transfer - characteristics. H.273 is the authority, when it comes to the exact - formulas and authoritative specifications, where an equivalent code - point exists. - - Descriptions do list the specifications for convenience. - - - - - Transfer characteristics as defined by - - Rec. ITU-R BT.709-6 - - Rec. ITU-R BT.1361-0 conventional colour gamut system (historical) - Equivalent to H.273 TransferCharacteristics code point 1, 6, 14, 15. - - - - - Transfer characteristics as defined by - - Rec. ITU-R BT.470-6 System M (historical) - - United States National Television System Committee 1953 - Recommendation for transmission standards for color television - - United States Federal Communications Commission (2003) Title 47 Code - of Federal Regulations 73.682 (a) (20) - - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM - Equivalent to H.273 TransferCharacteristics code point 4. - - - - - Transfer characteristics as defined by - - Rec. ITU-R BT.470-6 System B, G (historical) - Equivalent to H.273 TransferCharacteristics code point 5. - - - - - Transfer characteristics as defined by - - SMPTE ST 240 (1999) - Equivalent to H.273 TransferCharacteristics code point 7. - - - - - Linear transfer characteristics. - Equivalent to H.273 TransferCharacteristics code point 8. - - - - - Logarithmic transfer characteristic (100:1 range). - Equivalent to H.273 TransferCharacteristics code point 9. - - - - - Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range). - Equivalent to H.273 TransferCharacteristics code point 10. - - - - - Transfer characteristics as defined by - - IEC 61966-2-4 - Equivalent to H.273 TransferCharacteristics code point 11. - - - - - Transfer characteristics as defined by - - Rec. ITU-R BT.1361-0 extended colour gamut system (historical) - Equivalent to H.273 TransferCharacteristics code point 12. - - - - - Transfer characteristics as defined by - - IEC 61966-2-1 sRGB - Equivalent to H.273 TransferCharacteristics code point 13 with - MatrixCoefficients set to 0. - - - - - Transfer characteristics as defined by - - IEC 61966-2-1 sYCC - Equivalent to H.273 TransferCharacteristics code point 13 with - MatrixCoefficients set to anything but 0. - - - - - Transfer characteristics as defined by - - SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems - - Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system - Equivalent to H.273 TransferCharacteristics code point 16. - - This TF implies these default luminances - - primary color volume minimum: 0.005 cd/m² - - primary color volume maximum: 10000 cd/m² - - reference white: 203 cd/m² - - - - - Transfer characteristics as defined by - - SMPTE ST 428-1 (2019) - Equivalent to H.273 TransferCharacteristics code point 17. - - - - - Transfer characteristics as defined by - - ARIB STD-B67 (2015) - - Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system - Equivalent to H.273 TransferCharacteristics code point 18. - - This TF implies these default luminances - - primary color volume minimum: 0.005 cd/m² - - primary color volume maximum: 1000 cd/m² - - reference white: 203 cd/m² - Note: HLG is a scene referred signal. All absolute luminance values - used here for HLG assume a 1000 cd/m² display. - - - - - - - This creates a new xx_color_management_output_v4 object for the - given wl_output. - - See the xx_color_management_output_v4 interface for more details. - - - - - - - - - If a xx_color_management_surface_v4 object already exists for the given - wl_surface, the protocol error surface_exists is raised. - - This creates a new color xx_color_management_surface_v4 object for the - given wl_surface. - - See the xx_color_management_surface_v4 interface for more details. - - - - - - - - - This creates a new color xx_color_management_feedback_surface_v4 object - for the given wl_surface. - - See the xx_color_management_feedback_surface_v4 interface for more - details. - - - - - - - - - Makes a new ICC-based image description creator object with all - properties initially unset. The client can then use the object's - interface to define all the required properties for an image description - and finally create a xx_image_description_v4 object. - - This request can be used when the compositor advertises - xx_color_manager_v4.feature.icc_v2_v4. - Otherwise this request raises the protocol error unsupported_feature. - - - - - - - - Makes a new parametric image description creator object with all - properties initially unset. The client can then use the object's - interface to define all the required properties for an image description - and finally create a xx_image_description_v4 object. - - This request can be used when the compositor advertises - xx_color_manager_v4.feature.parametric. - Otherwise this request raises the protocol error unsupported_feature. - - - - - - - - When this object is created, it shall immediately send this event once - for each rendering intent the compositor supports. - - - - - - - - When this object is created, it shall immediately send this event once - for each compositor supported feature listed in the enumeration. - - - - - - - - When this object is created, it shall immediately send this event once - for each named transfer function the compositor supports with the - parametric image description creator. - - - - - - - - When this object is created, it shall immediately send this event once - for each named set of primaries the compositor supports with the - parametric image description creator. - - - - - - - - - A xx_color_management_output_v4 describes the color properties of an - output. - - The xx_color_management_output_v4 is associated with the wl_output global - underlying the wl_output object. Therefore the client destroying the - wl_output object has no impact, but the compositor removing the output - global makes the xx_color_management_output_v4 object inert. - - - - - Destroy the color xx_color_management_output_v4 object. This does not - affect any remaining protocol objects. - - - - - - This event is sent whenever the image description of the output changed, - followed by one wl_output.done event common to output events across all - extensions. - - If the client wants to use the updated image description, it needs to do - get_image_description again, because image description objects are - immutable. - - - - - - This creates a new xx_image_description_v4 object for the current image - description of the output. There always is exactly one image description - active for an output so the client should destroy the image description - created by earlier invocations of this request. This request is usually - sent as a reaction to the image_description_changed event or when - creating a xx_color_management_output_v4 object. - - The image description of an output represents the color encoding the - output expects. There might be performance and power advantages, as well - as improved color reproduction, if a content update matches the image - description of the output it is being shown on. If a content update is - shown on any other output than the one it matches the image description - of, then the color reproduction on those outputs might be considerably - worse. - - The created xx_image_description_v4 object preserves the image - description of the output from the time the object was created. - - The resulting image description object allows get_information request. - - If this protocol object is inert, the resulting image description object - shall immediately deliver the xx_image_description_v4.failed event with - the no_output cause. - - If the interface version is inadequate for the output's image - description, meaning that the client does not support all the events - needed to deliver the crucial information, the resulting image - description object shall immediately deliver the - xx_image_description_v4.failed event with the low_version cause. - - Otherwise the object shall immediately deliver the ready event. - - - - - - - - - A xx_color_management_surface_v4 allows the client to set the color - space and HDR properties of a surface. - - If the wl_surface associated with the xx_color_management_surface_v4 is - destroyed, the xx_color_management_surface_v4 object becomes inert. - - - - - Destroy the xx_color_management_surface_v4 object and do the same as - unset_image_description. - - - - - - - - - - - - Set the image description of the underlying surface. The image - description and rendering intent are double-buffered state, see - wl_surface.commit. - - It is the client's responsibility to understand the image description - it sets on a surface, and to provide content that matches that image - description. Compositors might convert images to match their own or any - other image descriptions. - - Image description whose creation gracefully failed (received - xx_image_description_v4.failed) are forbidden in this request, and in - such case the protocol error image_description is raised. - - All image descriptions whose creation succeeded (received - xx_image_description_v4.ready) are allowed and must always be accepted - by the compositor. - - A rendering intent provides the client's preference on how content - colors should be mapped to each output. The render_intent value must - be one advertised by the compositor with - xx_color_manager_v4.render_intent event, otherwise the protocol error - render_intent is raised. - - By default, a surface does not have an associated image description - nor a rendering intent. The handling of color on such surfaces is - compositor implementation defined. Compositors should handle such - surfaces as sRGB but may handle them differently if they have specific - requirements. - - - - - - - - - This request removes any image description from the surface. See - set_image_description for how a compositor handles a surface without - an image description. This is double-buffered state, see - wl_surface.commit. - - - - - - - A xx_color_management_feedback_surface_v4 allows the client to get the - preferred color description of a surface. - - If the wl_surface associated with this object is destroyed, the - xx_color_management_feedback_surface_v4 object becomes inert. - - - - - Destroy the xx_color_management_feedback_surface_v4 object. - - - - - - - - - - - The preferred image description is the one which likely has the most - performance and/or quality benefits for the compositor if used by the - client for its wl_surface contents. This event is sent whenever the - compositor changes the wl_surface's preferred image description. - - This event is merely a notification. When the client wants to know - what the preferred image description is, it shall use the get_preferred - request. - - The preferred image description is not automatically used for anything. - It is only a hint, and clients may set any valid image description with - set_image_description but there might be performance and color accuracy - improvements by providing the wl_surface contents in the preferred - image description. Therefore clients that can, should render according - to the preferred image description - - - - - - If this protocol object is inert, the protocol error inert is raised. - - The preferred image description represents the compositor's preferred - color encoding for this wl_surface at the current time. There might be - performance and power advantages, as well as improved color - reproduction, if the image description of a content update matches the - preferred image description. - - This creates a new xx_image_description_v4 object for the currently - preferred image description for the wl_surface. The client should - stop using and destroy the image descriptions created by earlier - invocations of this request for the associated wl_surface. - This request is usually sent as a reaction to the preferred_changed - event or when creating a xx_color_management_feedback_surface_v4 object - if the client is capable of adapting to image descriptions. - - The created xx_image_description_v4 object preserves the preferred image - description of the wl_surface from the time the object was created. - - The resulting image description object allows get_information request. - - If the interface version is inadequate for the preferred image - description, meaning that the client does not support all the - events needed to deliver the crucial information, the resulting image - description object shall immediately deliver the - xx_image_description_v4.failed event with the low_version cause, - otherwise the object shall immediately deliver the ready event. - - - - - - - - - This type of object is used for collecting all the information required - to create a xx_image_description_v4 object from an ICC file. A complete - set of required parameters consists of these properties: - - ICC file - - Each required property must be set exactly once if the client is to create - an image description. The set requests verify that a property was not - already set. The create request verifies that all required properties are - set. There may be several alternative requests for setting each property, - and in that case the client must choose one of them. - - Once all properties have been set, the create request must be used to - create the image description object, destroying the creator in the - process. - - - - - - - - - - - - - - - Create an image description object based on the ICC information - previously set on this object. A compositor must parse the ICC data in - some undefined but finite amount of time. - - The completeness of the parameter set is verified. If the set is not - complete, the protocol error incomplete_set is raised. For the - definition of a complete set, see the description of this interface. - - If the particular combination of the information is not supported - by the compositor, the resulting image description object shall - immediately deliver the xx_image_description_v4.failed event with the - 'unsupported' cause. If a valid image description was created from the - information, the xx_image_description_v4.ready event will eventually - be sent instead. - - This request destroys the xx_image_description_creator_icc_v4 object. - - The resulting image description object does not allow get_information - request. - - - - - - - - Sets the ICC profile file to be used as the basis of the image - description. - - The data shall be found through the given fd at the given offset, having - the given length. The fd must seekable and readable. Violating these - requirements raises the bad_fd protocol error. - - If reading the data fails due to an error independent of the client, the - compositor shall send the xx_image_description_v4.failed event on the - created xx_image_description_v4 with the 'operating_system' cause. - - The maximum size of the ICC profile is 4 MB. If length is greater than - that or zero, the protocol error bad_size is raised. If offset + length - exceeds the file size, the protocol error out_of_file is raised. - - A compositor may read the file at any time starting from this request - and only until whichever happens first: - - If create request was issued, the xx_image_description_v4 object - delivers either failed or ready event; or - - if create request was not issued, this - xx_image_description_creator_icc_v4 object is destroyed. - - A compositor shall not modify the contents of the file, and the fd may - be sealed for writes and size changes. The client must ensure to its - best ability that the data does not change while the compositor is - reading it. - - The data must represent a valid ICC profile. The ICC profile version - must be 2 or 4, it must be a 3 channel profile and the class must be - Display or ColorSpace. Violating these requirements will not result in a - protocol error but will eventually send the - xx_image_description_v4.failed event on the created - xx_image_description_v4 with the 'unsupported' cause. - - See the International Color Consortium specification ICC.1:2022 for more - details about ICC profiles. - - If ICC file has already been set on this object, the protocol error - already_set is raised. - - - - - - - - - - - This type of object is used for collecting all the parameters required - to create a xx_image_description_v4 object. A complete set of required - parameters consists of these properties: - - transfer characteristic function (tf) - - chromaticities of primaries and white point (primary color volume) - - The following properties are optional and have a well-defined default - if not explicitly set: - - primary color volume luminance range - - reference white luminance level - - mastering display primaries and white point (target color volume) - - mastering luminance range - - maximum content light level - - maximum frame-average light level - - Each required property must be set exactly once if the client is to create - an image description. The set requests verify that a property was not - already set. The create request verifies that all required properties are - set. There may be several alternative requests for setting each property, - and in that case the client must choose one of them. - - Once all properties have been set, the create request must be used to - create the image description object, destroying the creator in the - process. - - - - - - - - - - - - - - - - - - Create an image description object based on the parameters previously - set on this object. - - The completeness of the parameter set is verified. If the set is not - complete, the protocol error incomplete_set is raised. For the - definition of a complete set, see the description of this interface. - - Also, the combination of the parameter set is verified. If the set is - not consistent, the protocol error inconsistent_set is raised. - - If the particular combination of the parameter set is not supported - by the compositor, the resulting image description object shall - immediately deliver the xx_image_description_v4.failed event with the - 'unsupported' cause. If a valid image description was created from the - parameter set, the xx_image_description_v4.ready event will eventually - be sent instead. - - This request destroys the xx_image_description_creator_params_v4 - object. - - The resulting image description object does not allow get_information - request. - - - - - - - - Sets the transfer characteristic using explicitly enumerated named - functions. - - When the resulting image description is attached to an image, the - content should be encoded and decoded according to the industry standard - practices for the transfer characteristic. - - Only names advertised with xx_color_manager_v4 event supported_tf_named - are allowed. Other values shall raise the protocol error invalid_tf. - - If transfer characteristic has already been set on this object, the - protocol error already_set is raised. - - - - - - - - Sets the color component transfer characteristic to a power curve with - the given exponent. This curve represents the conversion from electrical - to optical pixel or color values. - - When the resulting image description is attached to an image, the - content should be encoded with the inverse of the power curve. - - The curve exponent shall be multiplied by 10000 to get the argument eexp - value to carry the precision of 4 decimals. - - The curve exponent must be at least 1.0 and at most 10.0. Otherwise the - protocol error invalid_tf is raised. - - If transfer characteristic has already been set on this object, the - protocol error already_set is raised. - - This request can be used when the compositor advertises - xx_color_manager_v4.feature.set_tf_power. Otherwise this request raises - the protocol error unsupported_feature. - - - - - - - - Sets the color primaries and white point using explicitly named sets. - This describes the primary color volume which is the basis for color - value encoding. - - Only names advertised with xx_color_manager_v4 event - supported_primaries_named are allowed. Other values shall raise the - protocol error invalid_primaries. - - If primaries have already been set on this object, the protocol error - already_set is raised. - - - - - - - - Sets the color primaries and white point using CIE 1931 xy chromaticity - coordinates. This describes the primary color volume which is the basis - for color value encoding. - - Each coordinate value is multiplied by 10000 to get the argument value - to carry precision of 4 decimals. - - If primaries have already been set on this object, the protocol error - already_set is raised. - - This request can be used if the compositor advertises - xx_color_manager_v4.feature.set_primaries. Otherwise this request raises - the protocol error unsupported_feature. - - - - - - - - - - - - - - - Sets the primary color volume luminance range and the reference white - luminance level. - - The default luminances are - - primary color volume minimum: 0.2 cd/m² - - primary color volume maximum: 80 cd/m² - - reference white: 80 cd/m² - - Setting a named transfer characteristic can imply other default - luminances. - - The default luminances get overwritten when this request is used. - - 'min_lum' and 'max_lum' specify the minimum and maximum luminances of - the primary color volume as reproduced by the targeted display. - - 'reference_lum' specifies the luminance of the reference white as - reproduced by the targeted display, and reflects the targeted viewing - environment. - - Compositors should make sure that all content is anchored, meaning that - an input signal level of 'reference_lum' on one image description and - another input signal level of 'reference_lum' on another image - description should produce the same output level, even though the - 'reference_lum' on both image representations can be different. - - If 'max_lum' is less than the 'reference_lum', or 'reference_lum' is - less than or equal to 'min_lum', the protocol error invalid_luminance is - raised. - - The minimum luminance is multiplied by 10000 to get the argument - 'min_lum' value and carries precision of 4 decimals. The maximum - luminance and reference white luminance values are unscaled. - - If the primary color volume luminance range and the reference white - luminance level have already been set on this object, the protocol error - already_set is raised. - - This request can be used if the compositor advertises - xx_color_manager_v4.feature.set_luminances. Otherwise this request - raises the protocol error unsupported_feature. - - - - - - - - - - Provides the color primaries and white point of the mastering display - using CIE 1931 xy chromaticity coordinates. This is compatible with the - SMPTE ST 2086 definition of HDR static metadata. - - The mastering display primaries define the target color volume. - - If mastering display primaries are not explicitly set, the target color - volume is assumed to be equal to the primary color volume. - - The target color volume is defined by all tristimulus values between 0.0 - and 1.0 (inclusive) of the color space defined by the given mastering - display primaries and white point. The colorimetry is identical between - the container color space and the mastering display color space, - including that no chromatic adaptation is applied even if the white - points differ. - - The target color volume can exceed the primary color volume to allow for - a greater color volume with an existing color space definition (for - example scRGB). It can be smaller than the primary color volume to - minimize gamut and tone mapping distances for big color spaces (HDR - metadata). - - To make use of the entire target color volume a suitable pixel format - has to be chosen (e.g. floating point to exceed the primary color - volume, or abusing limited quantization range as with xvYCC). - - Each coordinate value is multiplied by 10000 to get the argument value - to carry precision of 4 decimals. - - If mastering display primaries have already been set on this object, the - protocol error already_set is raised. - - This request can be used if the compositor advertises - xx_color_manager_v4.feature.set_mastering_display_primaries. Otherwise - this request raises the protocol error unsupported_feature. The - advertisement implies support only for target color volumes fully - contained within the primary color volume. - - If a compositor additionally supports target color volume exceeding the - primary color volume, it must advertise - xx_color_manager_v4.feature.extended_target_volume. If a client uses - target color volume exceeding the primary color volume and the - compositor does not support it, the result is implementation defined. - Compositors are recommended to detect this case and fail the image - description gracefully, but it may as well result in color artifacts. - - - - - - - - - - - - - - - Sets the luminance range that was used during the content mastering - process as the minimum and maximum absolute luminance L. This is - compatible with the SMPTE ST 2086 definition of HDR static metadata. - - The mastering luminance range is undefined by default. - - If max L is less than or equal to min L, the protocol error - invalid_luminance is raised. - - Min L value is multiplied by 10000 to get the argument min_lum value - and carry precision of 4 decimals. Max L value is unscaled for max_lum. - - - - - - - - - Sets the maximum content light level (max_cll) as defined by CTA-861-H. - - This can only be set when set_tf_cicp is used to set the transfer - characteristic to Rec. ITU-R BT.2100-2 perceptual quantization system. - Otherwise, 'create' request shall raise inconsistent_set protocol - error. - - max_cll is undefined by default. - - - - - - - - Sets the maximum frame-average light level (max_fall) as defined by - CTA-861-H. - - This can only be set when set_tf_cicp is used to set the transfer - characteristic to Rec. ITU-R BT.2100-2 perceptual quantization system. - Otherwise, 'create' request shall raise inconsistent_set protocol error. - - max_fall is undefined by default. - - - - - - - - - An image description carries information about the color encoding used on - a surface when attached to a wl_surface via - xx_color_management_surface_v4.set_image_description. A compositor can use - this information to decode pixel values into colorimetrically meaningful - quantities. - - Note, that the xx_image_description_v4 object is not ready to be used - immediately after creation. The object eventually delivers either the - 'ready' or the 'failed' event, specified in all requests creating it. The - object is deemed "ready" after receiving the 'ready' event. - - An object which is not ready is illegal to use, it can only be destroyed. - Any other request in this interface shall result in the 'not_ready' - protocol error. Attempts to use an object which is not ready through other - interfaces shall raise protocol errors defined there. - - Once created and regardless of how it was created, a - xx_image_description_v4 object always refers to one fixed image - description. It cannot change after creation. - - - - - Destroy this object. It is safe to destroy an object which is not ready. - - Destroying a xx_image_description_v4 object has no side-effects, not - even if a xx_color_management_surface_v4.set_image_description has not - yet been followed by a wl_surface.commit. - - - - - - - - - - - - - - - - - - - - - - If creating a xx_image_description_v4 object fails for a reason that is - not defined as a protocol error, this event is sent. - - The requests that create image description objects define whether and - when this can occur. Only such creation requests can trigger this event. - This event cannot be triggered after the image description was - successfully formed. - - Once this event has been sent, the xx_image_description_v4 object will - never become ready and it can only be destroyed. - - - - - - - - - Once this event has been sent, the xx_image_description_v4 object is - deemed "ready". Ready objects can be used to send requests and can be - used through other interfaces. - - Every ready xx_image_description_v4 protocol object refers to an - underlying image description record in the compositor. Multiple protocol - objects may end up referring to the same record. Clients may identify - these "copies" by comparing their id numbers: if the numbers from two - protocol objects are identical, the protocol objects refer to the same - image description record. Two different image description records - cannot have the same id number simultaneously. The id number does not - change during the lifetime of the image description record. - - The id number is valid only as long as the protocol object is alive. If - all protocol objects referring to the same image description record are - destroyed, the id number may be recycled for a different image - description record. - - Image description id number is not a protocol object id. Zero is - reserved as an invalid id number. It shall not be possible for a client - to refer to an image description by its id number in protocol. The id - numbers might not be portable between Wayland connections. - - This identity allows clients to de-duplicate image description records - and avoid get_information request if they already have the image - description information. - - - - - - - - Creates a xx_image_description_info_v4 object which delivers the - information that makes up the image description. - - Not all image description protocol objects allow get_information - request. Whether it is allowed or not is defined by the request that - created the object. If get_information is not allowed, the protocol - error no_information is raised. - - - - - - - - - Sends all matching events describing an image description object exactly - once and finally sends the 'done' event. - - Once a xx_image_description_info_v4 object has delivered a 'done' event it - is automatically destroyed. - - Every xx_image_description_info_v4 created from the same - xx_image_description_v4 shall always return the exact same data. - - - - - Signals the end of information events and destroys the object. - - - - - - The icc argument provides a file descriptor to the client which may be - memory-mapped to provide the ICC profile matching the image description. - The fd is read-only, and if mapped then it must be mapped with - MAP_PRIVATE by the client. - - The ICC profile version and other details are determined by the - compositor. There is no provision for a client to ask for a specific - kind of a profile. - - - - - - - - - - Delivers the primary color volume primaries and white point using CIE - 1931 xy chromaticity coordinates. - - Each coordinate value is multiplied by 10000 to get the argument value - to carry precision of 4 decimals. - - - - - - - - - - - - - - - Delivers the primary color volume primaries and white point using an - explicitly enumerated named set. - - - - - - - - The color component transfer characteristic of this image description is - a pure power curve. This event provides the exponent of the power - function. This curve represents the conversion from electrical to - optical pixel or color values. - - The curve exponent has been multiplied by 10000 to get the argument eexp - value to carry the precision of 4 decimals. - - - - - - - - Delivers the transfer characteristic using an explicitly enumerated - named function. - - - - - - - - Delivers the primary color volume luminance range and the reference - white luminance level. - - The minimum luminance is multiplied by 10000 to get the argument - 'min_lum' value and carries precision of 4 decimals. The maximum - luminance and reference white luminance values are unscaled. - - - - - - - - - - Provides the color primaries and white point of the target color volume - using CIE 1931 xy chromaticity coordinates. This is compatible with the - SMPTE ST 2086 definition of HDR static metadata for mastering displays. - - While primary color volume is about how color is encoded, the target - color volume is the actually displayable color volume. If target color - volume is equal to the primary color volume, then this event is not - sent. - - Each coordinate value is multiplied by 10000 to get the argument value - to carry precision of 4 decimals. - - - - - - - - - - - - - - - Provides the luminance range that the image description is targeting as - the minimum and maximum absolute luminance L. This is compatible with - the SMPTE ST 2086 definition of HDR static metadata. - - This luminance range is only theoretical and may not correspond to the - luminance of light emitted on an actual display. - - Min L value is multiplied by 10000 to get the argument min_lum value and - carry precision of 4 decimals. Max L value is unscaled for max_lum. - - - - - - - - - Provides the targeted max_cll of the image description. max_cll is - defined by CTA-861-H. - - This luminance is only theoretical and may not correspond to the - luminance of light emitted on an actual display. - - - - - - - - Provides the targeted max_fall of the image description. max_fall is - defined by CTA-861-H. - - This luminance is only theoretical and may not correspond to the - luminance of light emitted on an actual display. - - - - - - \ No newline at end of file diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9c806fdd..772f87fe 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2956,35 +2956,31 @@ void CCompositor::onNewMonitor(SP output) { } } -SImageDescription CCompositor::getPreferredImageDescription() { +PImageDescription CCompositor::getPreferredImageDescription() { if (!PROTO::colorManagement) { Log::logger->log(Log::ERR, "FIXME: color management protocol is not enabled, returning empty image description"); - return SImageDescription{}; + return DEFAULT_IMAGE_DESCRIPTION; } Log::logger->log(Log::WARN, "FIXME: color management protocol is enabled, determine correct preferred image description"); // should determine some common settings to avoid unnecessary transformations while keeping maximum displayable precision - return m_monitors.size() == 1 ? m_monitors[0]->m_imageDescription : SImageDescription{.primaries = NColorPrimaries::BT709}; + return m_monitors.size() == 1 ? m_monitors[0]->m_imageDescription : CImageDescription::from(SImageDescription{.primaries = NColorPrimaries::BT709}); } -SImageDescription CCompositor::getHDRImageDescription() { +PImageDescription CCompositor::getHDRImageDescription() { if (!PROTO::colorManagement) { Log::logger->log(Log::ERR, "FIXME: color management protocol is not enabled, returning empty image description"); - return SImageDescription{}; + return DEFAULT_IMAGE_DESCRIPTION; } return m_monitors.size() == 1 && m_monitors[0]->m_output && m_monitors[0]->m_output->parsedEDID.hdrMetadata.has_value() ? - SImageDescription{.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), - .luminances = {.min = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredContentMinLuminance, - .max = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredContentMaxLuminance, - .reference = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredMaxFrameAverageLuminance}} : - SImageDescription{.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), - .luminances = {.min = 0, .max = 10000, .reference = 203}}; + CImageDescription::from(SImageDescription{.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), + .luminances = {.min = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredContentMinLuminance, + .max = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredContentMaxLuminance, + .reference = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredMaxFrameAverageLuminance}}) : + DEFAULT_HDR_IMAGE_DESCRIPTION; } bool CCompositor::shouldChangePreferredImageDescription() { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7671d8f0..abcf7ec6 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -162,8 +162,8 @@ class CCompositor { void ensurePersistentWorkspacesPresent(const std::vector& rules, PHLWORKSPACE pWorkspace = nullptr); std::optional getVTNr(); - NColorManagement::SImageDescription getPreferredImageDescription(); - NColorManagement::SImageDescription getHDRImageDescription(); + NColorManagement::PImageDescription getPreferredImageDescription(); + NColorManagement::PImageDescription getHDRImageDescription(); bool shouldChangePreferredImageDescription(); bool supportsDrmSyncobjTimeline() const; diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 187d0d05..132b4789 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1562,10 +1562,10 @@ inline static const std::vector CONFIG_OPTIONS = { }, SConfigOptionDescription{ .value = "render:cm_sdr_eotf", - .description = "Default transfer function for displaying SDR apps. 0 - Treat unspecified as sRGB, 1 - Treat unspecified as Gamma 2.2, 2 - Treat " - "unspecified and sRGB as Gamma 2.2", + .description = "Default transfer function for displaying SDR apps. 0 - Use default value (Gamma 2.2), 1 - Treat unspecified as Gamma 2.2, 2 - Treat " + "unspecified and sRGB as Gamma 2.2, 3 - Treat unspecified as sRGB", .type = CONFIG_OPTION_CHOICE, - .data = SConfigOptionDescription::SChoiceData{0, "srgb,gamma22,gamma22force"}, + .data = SConfigOptionDescription::SChoiceData{0, "default,gamma22,gamma22force,srgb"}, }, /* @@ -2001,17 +2001,6 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SBoolData{false}, }, - /* - * Experimental - */ - - SConfigOptionDescription{ - .value = "experimental:xx_color_management_v4", - .description = "enable color management protocol", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, - }, - /* * Quirks */ diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index bb2cc845..d82983a1 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -771,8 +771,6 @@ CConfigManager::CConfigManager() { registerConfigVar("ecosystem:no_donation_nag", Hyprlang::INT{0}); registerConfigVar("ecosystem:enforce_permissions", Hyprlang::INT{0}); - registerConfigVar("experimental:xx_color_management_v4", Hyprlang::INT{0}); - registerConfigVar("quirks:prefer_hdr", Hyprlang::INT{0}); // devices diff --git a/src/desktop/view/WLSurface.hpp b/src/desktop/view/WLSurface.hpp index 944e863b..3c5e3a38 100644 --- a/src/desktop/view/WLSurface.hpp +++ b/src/desktop/view/WLSurface.hpp @@ -112,6 +112,5 @@ namespace Desktop::View { } m_listeners; friend class ::CPointerConstraint; - friend class CXxColorManagerV4; }; } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 3508e84a..af8ed0c7 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -476,81 +476,76 @@ void CMonitor::onDisconnect(bool destroy) { void CMonitor::applyCMType(NCMType::eCMType cmType, int cmSdrEotf) { auto oldImageDescription = m_imageDescription; static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); - auto chosenSdrEotf = cmSdrEotf == 0 ? (*PSDREOTF > 0 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB) : + auto chosenSdrEotf = cmSdrEotf == 0 ? (*PSDREOTF != 3 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB) : (cmSdrEotf == 1 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22); switch (cmType) { - case NCMType::CM_SRGB: m_imageDescription = {.transferFunction = chosenSdrEotf}; break; // assumes SImageDescription defaults to sRGB + case NCMType::CM_SRGB: m_imageDescription = CImageDescription::from({.transferFunction = chosenSdrEotf}); break; // assumes SImageDescription defaults to sRGB case NCMType::CM_WIDE: - m_imageDescription = {.transferFunction = chosenSdrEotf, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)}; + m_imageDescription = CImageDescription::from({.transferFunction = chosenSdrEotf, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)}); break; case NCMType::CM_DCIP3: - m_imageDescription = {.transferFunction = chosenSdrEotf, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_DCI_P3, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DCI_P3)}; + m_imageDescription = CImageDescription::from({.transferFunction = chosenSdrEotf, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_DCI_P3, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DCI_P3)}); break; case NCMType::CM_DP3: - m_imageDescription = {.transferFunction = chosenSdrEotf, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_DISPLAY_P3, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DISPLAY_P3)}; + m_imageDescription = CImageDescription::from({.transferFunction = chosenSdrEotf, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_DISPLAY_P3, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DISPLAY_P3)}); break; case NCMType::CM_ADOBE: - m_imageDescription = {.transferFunction = chosenSdrEotf, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_ADOBE_RGB, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_ADOBE_RGB)}; + m_imageDescription = CImageDescription::from({.transferFunction = chosenSdrEotf, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_ADOBE_RGB, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_ADOBE_RGB)}); break; case NCMType::CM_EDID: - m_imageDescription = {.transferFunction = chosenSdrEotf, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, - .primaries = { - .red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y}, - .green = {.x = m_output->parsedEDID.chromaticityCoords->green.x, .y = m_output->parsedEDID.chromaticityCoords->green.y}, - .blue = {.x = m_output->parsedEDID.chromaticityCoords->blue.x, .y = m_output->parsedEDID.chromaticityCoords->blue.y}, - .white = {.x = m_output->parsedEDID.chromaticityCoords->white.x, .y = m_output->parsedEDID.chromaticityCoords->white.y}, - }}; - break; - case NCMType::CM_HDR: - m_imageDescription = {.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, - .primariesNameSet = true, - .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, - .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), - .luminances = {.min = 0, .max = 10000, .reference = 203}}; + m_imageDescription = + CImageDescription::from({.transferFunction = chosenSdrEotf, + .primariesNameSet = false, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = { + .red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y}, + .green = {.x = m_output->parsedEDID.chromaticityCoords->green.x, .y = m_output->parsedEDID.chromaticityCoords->green.y}, + .blue = {.x = m_output->parsedEDID.chromaticityCoords->blue.x, .y = m_output->parsedEDID.chromaticityCoords->blue.y}, + .white = {.x = m_output->parsedEDID.chromaticityCoords->white.x, .y = m_output->parsedEDID.chromaticityCoords->white.y}, + }}); break; + case NCMType::CM_HDR: m_imageDescription = DEFAULT_HDR_IMAGE_DESCRIPTION; break; case NCMType::CM_HDR_EDID: - m_imageDescription = {.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, - .primariesNameSet = false, - .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, - .primaries = m_output->parsedEDID.chromaticityCoords.has_value() ? - NColorManagement::SPCPRimaries{ - .red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y}, - .green = {.x = m_output->parsedEDID.chromaticityCoords->green.x, .y = m_output->parsedEDID.chromaticityCoords->green.y}, - .blue = {.x = m_output->parsedEDID.chromaticityCoords->blue.x, .y = m_output->parsedEDID.chromaticityCoords->blue.y}, - .white = {.x = m_output->parsedEDID.chromaticityCoords->white.x, .y = m_output->parsedEDID.chromaticityCoords->white.y}, - } : - NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), - .luminances = {.min = m_output->parsedEDID.hdrMetadata->desiredContentMinLuminance, - .max = m_output->parsedEDID.hdrMetadata->desiredContentMaxLuminance, - .reference = m_output->parsedEDID.hdrMetadata->desiredMaxFrameAverageLuminance}}; + m_imageDescription = + CImageDescription::from({.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, + .primariesNameSet = false, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = m_output->parsedEDID.chromaticityCoords.has_value() ? + NColorManagement::SPCPRimaries{ + .red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y}, + .green = {.x = m_output->parsedEDID.chromaticityCoords->green.x, .y = m_output->parsedEDID.chromaticityCoords->green.y}, + .blue = {.x = m_output->parsedEDID.chromaticityCoords->blue.x, .y = m_output->parsedEDID.chromaticityCoords->blue.y}, + .white = {.x = m_output->parsedEDID.chromaticityCoords->white.x, .y = m_output->parsedEDID.chromaticityCoords->white.y}, + } : + NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), + .luminances = {.min = m_output->parsedEDID.hdrMetadata->desiredContentMinLuminance, + .max = m_output->parsedEDID.hdrMetadata->desiredContentMaxLuminance, + .reference = m_output->parsedEDID.hdrMetadata->desiredMaxFrameAverageLuminance}}); break; default: UNREACHABLE(); } - if (m_minLuminance >= 0) - m_imageDescription.luminances.min = m_minLuminance; - if (m_maxLuminance >= 0) - m_imageDescription.luminances.max = m_maxLuminance; - if (m_maxAvgLuminance >= 0) - m_imageDescription.luminances.reference = m_maxAvgLuminance; + if (m_minLuminance >= 0 || m_maxLuminance >= 0 || m_maxAvgLuminance >= 0) + m_imageDescription = m_imageDescription->with({ + .min = m_minLuminance >= 0 ? m_minLuminance : m_imageDescription->value().luminances.min, // + .max = m_maxLuminance >= 0 ? m_maxLuminance : m_imageDescription->value().luminances.max, // + .reference = m_maxAvgLuminance >= 0 ? m_maxAvgLuminance : m_imageDescription->value().luminances.reference // + }); if (oldImageDescription != m_imageDescription) { - m_imageDescription.updateId(); if (PROTO::colorManagement) PROTO::colorManagement->onMonitorImageDescriptionChanged(m_self); } @@ -1999,7 +1994,7 @@ int CMonitor::maxAvgLuminance(int defaultValue) { } bool CMonitor::wantsWideColor() { - return supportsWideColor() && (wantsHDR() || m_imageDescription.primariesNamed == CM_PRIMARIES_BT2020); + return supportsWideColor() && (wantsHDR() || m_imageDescription->value().primariesNamed == CM_PRIMARIES_BT2020); } bool CMonitor::wantsHDR() { @@ -2014,7 +2009,7 @@ bool CMonitor::inFullscreenMode() { return m_activeWorkspace && m_activeWorkspace->m_hasFullscreenWindow && m_activeWorkspace->m_fullscreenMode == FSMODE_FULLSCREEN; } -std::optional CMonitor::getFSImageDescription() { +std::optional CMonitor::getFSImageDescription() { if (!inFullscreenMode()) return {}; @@ -2024,7 +2019,7 @@ std::optional CMonitor::getFSImageDescripti const auto ROOT_SURF = FS_WINDOW->wlSurface()->resource(); const auto SURF = ROOT_SURF->findWithCM(); - return SURF ? SURF->m_colorManagement->imageDescription() : SImageDescription{}; + return SURF ? NColorManagement::CImageDescription::from(SURF->m_colorManagement->imageDescription()) : DEFAULT_IMAGE_DESCRIPTION; } bool CMonitor::needsCM() { @@ -2045,19 +2040,20 @@ bool CMonitor::canNoShaderCM() { if (SRC_DESC.value() == m_imageDescription) return true; // no CM needed - if (SRC_DESC->icc.fd >= 0 || m_imageDescription.icc.fd >= 0) + const auto SRC_DESC_VALUE = SRC_DESC.value()->value(); + + if (SRC_DESC_VALUE.icc.fd >= 0 || m_imageDescription->value().icc.fd >= 0) return false; // no ICC support static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); // only primaries differ - if ((SRC_DESC->transferFunction == m_imageDescription.transferFunction || - (*PSDREOTF == 2 && SRC_DESC->transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_SRGB && - m_imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22)) && - SRC_DESC->transferFunctionPower == m_imageDescription.transferFunctionPower && (!inHDR() || SRC_DESC->luminances == m_imageDescription.luminances) && - SRC_DESC->masteringLuminances == m_imageDescription.masteringLuminances && SRC_DESC->maxCLL == m_imageDescription.maxCLL && SRC_DESC->maxFALL == m_imageDescription.maxFALL) - return true; - - return false; + return ((SRC_DESC_VALUE.transferFunction == m_imageDescription->value().transferFunction || + (*PSDREOTF == 2 && SRC_DESC_VALUE.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_SRGB && + m_imageDescription->value().transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22)) && + SRC_DESC_VALUE.transferFunctionPower == m_imageDescription->value().transferFunctionPower && + (!inHDR() || SRC_DESC_VALUE.luminances == m_imageDescription->value().luminances) && + SRC_DESC_VALUE.masteringLuminances == m_imageDescription->value().masteringLuminances && SRC_DESC_VALUE.maxCLL == m_imageDescription->value().maxCLL && + SRC_DESC_VALUE.maxFALL == m_imageDescription->value().maxFALL); } bool CMonitor::doesNoShaderCM() { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index ea2cf185..4c27d1b3 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -329,7 +329,7 @@ class CMonitor { /// Has an active workspace with a real fullscreen window bool inFullscreenMode(); - std::optional getFSImageDescription(); + std::optional getFSImageDescription(); bool needsCM(); /// Can do CM without shader @@ -342,7 +342,7 @@ class CMonitor { PHLWINDOWREF m_previousFSWindow; bool m_needsHDRupdate = false; - NColorManagement::SImageDescription m_imageDescription; + NColorManagement::PImageDescription m_imageDescription; bool m_noShaderCTM = false; // sets drm CTM, restore needed // For the list lookup diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index b41fc37f..ce77e2fe 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -57,8 +57,6 @@ #include "../protocols/core/Output.hpp" #include "../protocols/core/Shm.hpp" #include "../protocols/ColorManagement.hpp" -#include "../protocols/XXColorManagement.hpp" -#include "../protocols/FrogColorManagement.hpp" #include "../protocols/ContentType.hpp" #include "../protocols/XDGTag.hpp" #include "../protocols/XDGBell.hpp" @@ -106,9 +104,8 @@ void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) { CProtocolManager::CProtocolManager() { - static const auto PENABLECM = CConfigValue("render:cm_enabled"); - static const auto PENABLEXXCM = CConfigValue("experimental:xx_color_management_v4"); - static const auto PDEBUGCM = CConfigValue("debug:full_cm_proto"); + static const auto PENABLECM = CConfigValue("render:cm_enabled"); + static const auto PDEBUGCM = CConfigValue("debug:full_cm_proto"); // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { @@ -202,11 +199,6 @@ CProtocolManager::CProtocolManager() { if (*PENABLECM) PROTO::colorManagement = makeUnique(&wp_color_manager_v1_interface, 1, "ColorManagement", *PDEBUGCM); - if (*PENABLEXXCM && *PENABLECM) { - PROTO::xxColorManagement = makeUnique(&xx_color_manager_v4_interface, 1, "XXColorManagement"); - PROTO::frogColorManagement = makeUnique(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement"); - } - // ! please read the top of this file before adding another protocol for (auto const& b : g_pCompositor->m_aqBackend->getImplementations()) { @@ -295,8 +287,6 @@ CProtocolManager::~CProtocolManager() { PROTO::hyprlandSurface.reset(); PROTO::contentType.reset(); PROTO::colorManagement.reset(); - PROTO::xxColorManagement.reset(); - PROTO::frogColorManagement.reset(); PROTO::xdgTag.reset(); PROTO::xdgBell.reset(); PROTO::extWorkspace.reset(); diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp index 4215a5e7..84280c71 100644 --- a/src/protocols/ColorManagement.cpp +++ b/src/protocols/ColorManagement.cpp @@ -18,12 +18,12 @@ CColorManager::CColorManager(SP resource) : m_resource(resour m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_PRIMARIES); m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES); m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_WINDOWS_SCRGB); + m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES); + m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_EXTENDED_TARGET_VOLUME); if (PROTO::colorManagement->m_debug) { m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_ICC_V2_V4); m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_TF_POWER); - m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES); - m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_EXTENDED_TARGET_VOLUME); } m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_SRGB); @@ -35,10 +35,7 @@ CColorManager::CColorManager(SP resource) : m_resource(resour m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_DCI_P3); m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_DISPLAY_P3); m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_ADOBE_RGB); - - if (PROTO::colorManagement->m_debug) { - m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_CIE1931_XYZ); - } + m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_CIE1931_XYZ); m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB); m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22); @@ -171,14 +168,10 @@ CColorManager::CColorManager(SP resource) : m_resource(resour return; } - RESOURCE->m_self = RESOURCE; - RESOURCE->m_settings.windowsScRGB = true; - RESOURCE->m_settings.primariesNamed = NColorManagement::CM_PRIMARIES_SRGB; - RESOURCE->m_settings.primariesNameSet = true; - RESOURCE->m_settings.primaries = NColorPrimaries::BT709; - RESOURCE->m_settings.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_EXT_LINEAR; - RESOURCE->m_settings.luminances.reference = 203; - RESOURCE->resource()->sendReady(RESOURCE->m_settings.updateId()); + RESOURCE->m_self = RESOURCE; + RESOURCE->m_settings = SCRGB_IMAGE_DESCRIPTION; + + RESOURCE->resource()->sendReady(RESOURCE->m_settings->id()); }); m_resource->setOnDestroy([this](CWpColorManagerV1* r) { PROTO::colorManagement->destroyResource(this); }); @@ -223,7 +216,7 @@ CColorManagementOutput::CColorManagementOutput(SP re RESOURCE->m_resource->sendFailed(WP_IMAGE_DESCRIPTION_V1_CAUSE_NO_OUTPUT, "No output"); else { RESOURCE->m_settings = m_output->m_monitor->m_imageDescription; - RESOURCE->m_resource->sendReady(RESOURCE->m_settings.updateId()); + RESOURCE->m_resource->sendReady(RESOURCE->m_settings->id()); } }); } @@ -236,10 +229,6 @@ wl_client* CColorManagementOutput::client() { return m_client; } -CColorManagementSurface::CColorManagementSurface(SP surface_) : m_surface(surface_) { - // only for frog cm until wayland cm is adopted -} - CColorManagementSurface::CColorManagementSurface(SP resource, SP surface_) : m_surface(surface_), m_resource(resource) { if UNLIKELY (!good()) return; @@ -280,7 +269,7 @@ CColorManagementSurface::CColorManagementSurface(SP }); m_resource->setUnsetImageDescription([this](CWpColorManagementSurfaceV1* r) { LOGM(Log::TRACE, "Unset image description for surface={}", (uintptr_t)r); - m_imageDescription = SImageDescription{}; + m_imageDescription = DEFAULT_IMAGE_DESCRIPTION; setHasImageDescription(false); }); } @@ -296,7 +285,8 @@ wl_client* CColorManagementSurface::client() { const SImageDescription& CColorManagementSurface::imageDescription() { if (!hasImageDescription()) LOGM(Log::WARN, "Reading imageDescription while none set. Returns default or empty values"); - return m_imageDescription; + + return m_imageDescription->value(); } bool CColorManagementSurface::hasImageDescription() { @@ -327,13 +317,14 @@ bool CColorManagementSurface::needsHdrMetadataUpdate() { } bool CColorManagementSurface::isHDR() { - return m_imageDescription.transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ || m_imageDescription.transferFunction == CM_TRANSFER_FUNCTION_HLG || isWindowsScRGB(); + return m_imageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ || m_imageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_HLG || + isWindowsScRGB(); } bool CColorManagementSurface::isWindowsScRGB() { - return m_imageDescription.windowsScRGB || + return m_imageDescription->value().windowsScRGB || // autodetect scRGB, might be incorrect - (m_imageDescription.primariesNamed == CM_PRIMARIES_SRGB && m_imageDescription.transferFunction == CM_TRANSFER_FUNCTION_EXT_LINEAR); + (m_imageDescription->value().primariesNamed == CM_PRIMARIES_SRGB && m_imageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_EXT_LINEAR); } CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP resource, SP surface_) : @@ -372,7 +363,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPm_self = RESOURCE; RESOURCE->m_settings = m_surface->getPreferredImageDescription(); - RESOURCE->resource()->sendReady(RESOURCE->m_settings.updateId()); + RESOURCE->resource()->sendReady(RESOURCE->m_settings->id()); }); m_resource->setGetPreferredParametric([this](CWpColorManagementSurfaceFeedbackV1* r, uint32_t id) { @@ -394,9 +385,9 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPm_self = RESOURCE; RESOURCE->m_settings = m_surface->getPreferredImageDescription(); - m_currentPreferredId = RESOURCE->m_settings.updateId(); + m_currentPreferredId = RESOURCE->m_settings->id(); - if (!PROTO::colorManagement->m_debug && RESOURCE->m_settings.icc.fd >= 0) { + if (!PROTO::colorManagement->m_debug && RESOURCE->m_settings->value().icc.fd >= 0) { LOGM(Log::ERR, "FIXME: parse icc profile"); r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported"); return; @@ -411,7 +402,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPm_enteredOutputs.size() == 1) { - const auto newId = m_surface->getPreferredImageDescription().updateId(); + const auto newId = m_surface->getPreferredImageDescription()->id(); if (m_currentPreferredId != newId) m_resource->sendPreferredChanged(newId); } @@ -460,8 +451,8 @@ CColorManagementIccCreator::CColorManagementIccCreator(SPm_self = RESOURCE; - RESOURCE->m_settings = m_settings; - RESOURCE->resource()->sendReady(m_settings.updateId()); + RESOURCE->m_settings = CImageDescription::from(m_settings); + RESOURCE->resource()->sendReady(RESOURCE->m_settings->id()); PROTO::colorManagement->destroyResource(this); }); @@ -514,8 +505,8 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SPm_self = RESOURCE; - RESOURCE->m_settings = m_settings; - RESOURCE->resource()->sendReady(m_settings.updateId()); + RESOURCE->m_settings = CImageDescription::from(m_settings); + RESOURCE->resource()->sendReady(RESOURCE->m_settings->id()); PROTO::colorManagement->destroyResource(this); }); @@ -577,6 +568,7 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SPerror(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Mastering primaries already set"); return; } - if (!PROTO::colorManagement->m_debug) { - r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Mastering primaries are not supported"); - return; - } + m_settings.masteringPrimaries = SPCPRimaries{.red = {.x = r_x / PRIMARIES_SCALE, .y = r_y / PRIMARIES_SCALE}, .green = {.x = g_x / PRIMARIES_SCALE, .y = g_y / PRIMARIES_SCALE}, .blue = {.x = b_x / PRIMARIES_SCALE, .y = b_y / PRIMARIES_SCALE}, @@ -653,10 +642,7 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SPerror(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_LUMINANCE, "Invalid luminances"); return; } - if (!PROTO::colorManagement->m_debug) { - r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Mastering luminances are not supported"); - return; - } + m_settings.masteringLuminances = SImageDescription::SPCMasteringLuminances{.min = min, .max = max_lum}; m_valuesSet |= PC_MASTERING_LUMINANCES; }); @@ -705,7 +691,7 @@ CColorManagementImageDescription::CColorManagementImageDescription(SP(makeShared(r->client(), r->version(), id), m_settings); + auto RESOURCE = makeShared(makeShared(r->client(), r->version(), id), m_settings->value()); if UNLIKELY (!RESOURCE->good()) r->noMemory(); diff --git a/src/protocols/ColorManagement.hpp b/src/protocols/ColorManagement.hpp index dea9f74c..d43d5c12 100644 --- a/src/protocols/ColorManagement.hpp +++ b/src/protocols/ColorManagement.hpp @@ -46,7 +46,6 @@ class CColorManagementOutput { class CColorManagementSurface { public: - CColorManagementSurface(SP surface_); // temporary interface for frog CM CColorManagementSurface(SP resource, SP surface_); bool good(); @@ -67,14 +66,11 @@ class CColorManagementSurface { private: SP m_resource; wl_client* m_client = nullptr; - NColorManagement::SImageDescription m_imageDescription; - NColorManagement::SImageDescription m_lastImageDescription; + NColorManagement::PImageDescription m_imageDescription; + NColorManagement::PImageDescription m_lastImageDescription; bool m_hasImageDescription = false; bool m_needsNewMetadata = false; hdr_output_metadata m_hdrMetadata; - - friend class CXXColorManagementSurface; - friend class CFrogColorManagementSurface; }; class CColorManagementFeedbackSurface { @@ -157,7 +153,7 @@ class CColorManagementImageDescription { WP m_self; - NColorManagement::SImageDescription m_settings; + NColorManagement::PImageDescription m_settings; private: SP m_resource; @@ -216,9 +212,6 @@ class CColorManagementProtocol : public IWaylandProtocol { friend class CColorManagementIccCreator; friend class CColorManagementParametricCreator; friend class CColorManagementImageDescription; - - friend class CXXColorManagementSurface; - friend class CFrogColorManagementSurface; }; namespace PROTO { diff --git a/src/protocols/FrogColorManagement.cpp b/src/protocols/FrogColorManagement.cpp deleted file mode 100644 index 8506ce7b..00000000 --- a/src/protocols/FrogColorManagement.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "FrogColorManagement.hpp" -#include "color-management-v1.hpp" -#include "macros.hpp" -#include "protocols/ColorManagement.hpp" -#include "protocols/core/Subcompositor.hpp" -#include "protocols/types/ColorManagement.hpp" - -using namespace NColorManagement; - -static wpColorManagerV1TransferFunction getWPTransferFunction(frogColorManagedSurfaceTransferFunction tf) { - switch (tf) { - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_UNDEFINED: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_BT1886; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SRGB: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SCRGB_LINEAR: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR; - default: UNREACHABLE(); - } -} - -static wpColorManagerV1Primaries getWPPrimaries(frogColorManagedSurfacePrimaries primaries) { - return sc(primaries + 1); -} - -CFrogColorManager::CFrogColorManager(SP resource_) : m_resource(resource_) { - if UNLIKELY (!good()) - return; - - m_resource->setDestroy([](CFrogColorManagementFactoryV1* r) { LOGM(Log::TRACE, "Destroy frog_color_management at {:x} (generated default)", (uintptr_t)r); }); - m_resource->setOnDestroy([this](CFrogColorManagementFactoryV1* r) { PROTO::frogColorManagement->destroyResource(this); }); - - m_resource->setGetColorManagedSurface([](CFrogColorManagementFactoryV1* r, wl_resource* surface, uint32_t id) { - LOGM(Log::TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface); - auto SURF = CWLSurfaceResource::fromResource(surface); - - if (!SURF) { - LOGM(Log::ERR, "No surface for resource {}", (uintptr_t)surface); - r->error(-1, "Invalid surface (2)"); - return; - } - - const auto RESOURCE = - PROTO::frogColorManagement->m_surfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), SURF)); - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::frogColorManagement->m_surfaces.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - }); -} - -bool CFrogColorManager::good() { - return m_resource->resource(); -} - -CFrogColorManagementSurface::CFrogColorManagementSurface(SP resource_, SP surface_) : m_surface(surface_), m_resource(resource_) { - if UNLIKELY (!good()) - return; - - m_client = m_resource->client(); - - if (!m_surface->m_colorManagement.valid()) { - const auto RESOURCE = PROTO::colorManagement->m_surfaces.emplace_back(makeShared(surface_)); - if UNLIKELY (!RESOURCE) { - m_resource->noMemory(); - PROTO::colorManagement->m_surfaces.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - - m_surface->m_colorManagement = RESOURCE; - - m_resource->setOnDestroy([this](CFrogColorManagedSurface* r) { - LOGM(Log::TRACE, "Destroy frog cm and xx cm for surface {}", (uintptr_t)m_surface); - if (m_surface.valid()) - PROTO::colorManagement->destroyResource(m_surface->m_colorManagement.get()); - PROTO::frogColorManagement->destroyResource(this); - }); - } else - m_resource->setOnDestroy([this](CFrogColorManagedSurface* r) { - LOGM(Log::TRACE, "Destroy frog cm surface {}", (uintptr_t)m_surface); - PROTO::frogColorManagement->destroyResource(this); - }); - - m_resource->setDestroy([this](CFrogColorManagedSurface* r) { - LOGM(Log::TRACE, "Destroy frog cm surface {}", (uintptr_t)m_surface); - PROTO::frogColorManagement->destroyResource(this); - }); - - m_resource->setSetKnownTransferFunction([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceTransferFunction tf) { - LOGM(Log::TRACE, "Set frog cm transfer function {} for {}", (uint32_t)tf, m_surface->id()); - switch (tf) { - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ: - m_surface->m_colorManagement->m_imageDescription.transferFunction = - convertTransferFunction(getWPTransferFunction(FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ)); - break; - ; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22: - if (m_pqIntentSent) { - LOGM(Log::TRACE, - "FIXME: assuming broken enum value 2 (FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22) referring to eotf value 2 (TRANSFER_FUNCTION_ST2084_PQ)"); - m_surface->m_colorManagement->m_imageDescription.transferFunction = - convertTransferFunction(getWPTransferFunction(FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ)); - break; - }; - [[fallthrough]]; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_UNDEFINED: - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SCRGB_LINEAR: LOGM(Log::TRACE, "FIXME: add tf support for {}", (uint32_t)tf); [[fallthrough]]; - case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SRGB: - m_surface->m_colorManagement->m_imageDescription.transferFunction = convertTransferFunction(getWPTransferFunction(tf)); - - m_surface->m_colorManagement->setHasImageDescription(true); - } - }); - m_resource->setSetKnownContainerColorVolume([this](CFrogColorManagedSurface* r, frogColorManagedSurfacePrimaries primariesName) { - LOGM(Log::TRACE, "Set frog cm primaries {}", (uint32_t)primariesName); - switch (primariesName) { - case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_UNDEFINED: - case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_REC709: m_surface->m_colorManagement->m_imageDescription.primaries = NColorPrimaries::BT709; break; - case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_REC2020: m_surface->m_colorManagement->m_imageDescription.primaries = NColorPrimaries::BT2020; break; - } - m_surface->m_colorManagement->m_imageDescription.primariesNamed = convertPrimaries(getWPPrimaries(primariesName)); - - m_surface->m_colorManagement->setHasImageDescription(true); - }); - m_resource->setSetRenderIntent([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceRenderIntent intent) { - LOGM(Log::TRACE, "Set frog cm intent {}", (uint32_t)intent); - m_pqIntentSent = intent == FROG_COLOR_MANAGED_SURFACE_RENDER_INTENT_PERCEPTUAL; - m_surface->m_colorManagement->setHasImageDescription(true); - }); - m_resource->setSetHdrMetadata([this](CFrogColorManagedSurface* r, uint32_t r_x, uint32_t r_y, uint32_t g_x, uint32_t g_y, uint32_t b_x, uint32_t b_y, uint32_t w_x, - uint32_t w_y, uint32_t max_lum, uint32_t min_lum, uint32_t cll, uint32_t fall) { - LOGM(Log::TRACE, "Set frog primaries r:{},{} g:{},{} b:{},{} w:{},{} luminances {} - {} cll {} fall {}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y, min_lum, max_lum, cll, - fall); - m_surface->m_colorManagement->m_imageDescription.masteringPrimaries = SPCPRimaries{.red = {.x = r_x / 50000.0f, .y = r_y / 50000.0f}, - .green = {.x = g_x / 50000.0f, .y = g_y / 50000.0f}, - .blue = {.x = b_x / 50000.0f, .y = b_y / 50000.0f}, - .white = {.x = w_x / 50000.0f, .y = w_y / 50000.0f}}; - m_surface->m_colorManagement->m_imageDescription.masteringLuminances.min = min_lum / 10000.0f; - m_surface->m_colorManagement->m_imageDescription.masteringLuminances.max = max_lum; - m_surface->m_colorManagement->m_imageDescription.maxCLL = cll; - m_surface->m_colorManagement->m_imageDescription.maxFALL = fall; - - m_surface->m_colorManagement->setHasImageDescription(true); - }); -} - -bool CFrogColorManagementSurface::good() { - return m_resource->resource(); -} - -wl_client* CFrogColorManagementSurface::client() { - return m_client; -} - -CFrogColorManagementProtocol::CFrogColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - ; -} - -void CFrogColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_managers.emplace_back(makeShared(makeShared(client, ver, id))); - - if UNLIKELY (!RESOURCE->good()) { - wl_client_post_no_memory(client); - m_managers.pop_back(); - return; - } - - LOGM(Log::TRACE, "New frog_color_management at {:x}", (uintptr_t)RESOURCE.get()); -} - -void CFrogColorManagementProtocol::destroyResource(CFrogColorManager* resource) { - std::erase_if(m_managers, [&](const auto& other) { return other.get() == resource; }); -} - -void CFrogColorManagementProtocol::destroyResource(CFrogColorManagementSurface* resource) { - std::erase_if(m_surfaces, [&](const auto& other) { return other.get() == resource; }); -} diff --git a/src/protocols/FrogColorManagement.hpp b/src/protocols/FrogColorManagement.hpp deleted file mode 100644 index 32e2202c..00000000 --- a/src/protocols/FrogColorManagement.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include "WaylandProtocol.hpp" -#include "protocols/core/Compositor.hpp" -#include "frog-color-management-v1.hpp" - -class CFrogColorManager { - public: - CFrogColorManager(SP resource_); - - bool good(); - - private: - SP m_resource; -}; - -class CFrogColorManagementSurface { - public: - CFrogColorManagementSurface(SP resource_, SP surface_); - - bool good(); - wl_client* client(); - - WP m_self; - WP m_surface; - - bool m_pqIntentSent = false; - - private: - SP m_resource; - wl_client* m_client = nullptr; -}; - -class CFrogColorManagementProtocol : public IWaylandProtocol { - public: - CFrogColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name); - - virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - - private: - void destroyResource(CFrogColorManager* resource); - void destroyResource(CFrogColorManagementSurface* resource); - - std::vector> m_managers; - std::vector> m_surfaces; - - friend class CFrogColorManager; - friend class CFrogColorManagementSurface; -}; - -namespace PROTO { - inline UP frogColorManagement; -}; diff --git a/src/protocols/XXColorManagement.cpp b/src/protocols/XXColorManagement.cpp deleted file mode 100644 index 92b30f7a..00000000 --- a/src/protocols/XXColorManagement.cpp +++ /dev/null @@ -1,666 +0,0 @@ -#include "XXColorManagement.hpp" -#include "../Compositor.hpp" -#include "ColorManagement.hpp" -#include "color-management-v1.hpp" -#include "types/ColorManagement.hpp" -#include "xx-color-management-v4.hpp" - -using namespace NColorManagement; - -static wpColorManagerV1TransferFunction getWPTransferFunction(xxColorManagerV4TransferFunction tf) { - switch (tf) { - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT709: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT1361: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_BT1886; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA28; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST240: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST240; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_100: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_LOG_100; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_316: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_LOG_316; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_XVYCC: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_XVYCC; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_EXT_SRGB: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_SRGB; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST428: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST428; - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_HLG: return WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_HLG; - default: UNREACHABLE(); - } -} - -static wpColorManagerV1Primaries getWPPrimaries(xxColorManagerV4Primaries primaries) { - return sc(primaries + 1); -} - -CXXColorManager::CXXColorManager(SP resource_) : m_resource(resource_) { - if UNLIKELY (!good()) - return; - - m_resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC); - m_resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_EXTENDED_TARGET_VOLUME); - m_resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES); - m_resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES); - m_resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES); - - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_SRGB); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_NTSC); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_BT2020); - // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_CIE1931_XYZ); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3); - m_resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB); - - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_HLG); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT709); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT1361); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST240); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_100); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_316); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_XVYCC); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_EXT_SRGB); - m_resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST428); - - m_resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL); - // resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE); - // resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE); - // resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC); - - m_resource->setDestroy([](CXxColorManagerV4* r) { LOGM(Log::TRACE, "Destroy xx_color_manager at {:x} (generated default)", (uintptr_t)r); }); - m_resource->setGetOutput([](CXxColorManagerV4* r, uint32_t id, wl_resource* output) { - LOGM(Log::TRACE, "Get output for id={}, output={}", id, (uintptr_t)output); - const auto RESOURCE = - PROTO::xxColorManagement->m_outputs.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_outputs.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - }); - m_resource->setGetSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) { - LOGM(Log::TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface); - auto SURF = CWLSurfaceResource::fromResource(surface); - - if (!SURF) { - LOGM(Log::ERR, "No surface for resource {}", (uintptr_t)surface); - r->error(-1, "Invalid surface (2)"); - return; - } - - if (SURF->m_colorManagement) { - r->error(XX_COLOR_MANAGER_V4_ERROR_SURFACE_EXISTS, "CM Surface already exists"); - return; - } - - const auto RESOURCE = - PROTO::xxColorManagement->m_surfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), SURF)); - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_surfaces.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - }); - m_resource->setGetFeedbackSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) { - LOGM(Log::TRACE, "Get feedback surface for id={}, surface={}", id, (uintptr_t)surface); - auto SURF = CWLSurfaceResource::fromResource(surface); - - if (!SURF) { - LOGM(Log::ERR, "No surface for resource {}", (uintptr_t)surface); - r->error(-1, "Invalid surface (2)"); - return; - } - - const auto RESOURCE = PROTO::xxColorManagement->m_feedbackSurfaces.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), SURF)); - - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_feedbackSurfaces.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - }); - m_resource->setNewIccCreator([](CXxColorManagerV4* r, uint32_t id) { - LOGM(Log::WARN, "New ICC creator for id={} (unsupported)", id); - r->error(XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported"); - }); - m_resource->setNewParametricCreator([](CXxColorManagerV4* r, uint32_t id) { - LOGM(Log::TRACE, "New parametric creator for id={}", id); - - const auto RESOURCE = PROTO::xxColorManagement->m_parametricCreators.emplace_back( - makeShared(makeShared(r->client(), r->version(), id))); - - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_parametricCreators.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - }); - - m_resource->setOnDestroy([this](CXxColorManagerV4* r) { PROTO::xxColorManagement->destroyResource(this); }); -} - -bool CXXColorManager::good() { - return m_resource->resource(); -} - -CXXColorManagementOutput::CXXColorManagementOutput(SP resource_) : m_resource(resource_) { - if UNLIKELY (!good()) - return; - - m_client = m_resource->client(); - - m_resource->setDestroy([this](CXxColorManagementOutputV4* r) { PROTO::xxColorManagement->destroyResource(this); }); - m_resource->setOnDestroy([this](CXxColorManagementOutputV4* r) { PROTO::xxColorManagement->destroyResource(this); }); - - m_resource->setGetImageDescription([this](CXxColorManagementOutputV4* r, uint32_t id) { - LOGM(Log::TRACE, "Get image description for output={}, id={}", (uintptr_t)r, id); - if (m_imageDescription.valid()) - PROTO::xxColorManagement->destroyResource(m_imageDescription.get()); - - const auto RESOURCE = PROTO::xxColorManagement->m_imageDescriptions.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), true)); - - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_imageDescriptions.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - }); -} - -bool CXXColorManagementOutput::good() { - return m_resource->resource(); -} - -wl_client* CXXColorManagementOutput::client() { - return m_client; -} - -CXXColorManagementSurface::CXXColorManagementSurface(SP surface_) : m_surface(surface_) { - // only for frog cm until wayland cm is adopted -} - -CXXColorManagementSurface::CXXColorManagementSurface(SP resource_, SP surface_) : m_surface(surface_), m_resource(resource_) { - if UNLIKELY (!good()) - return; - - m_client = m_resource->client(); - - if (!m_surface->m_colorManagement.valid()) { - const auto RESOURCE = PROTO::colorManagement->m_surfaces.emplace_back(makeShared(surface_)); - if UNLIKELY (!RESOURCE) { - m_resource->noMemory(); - PROTO::colorManagement->m_surfaces.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - - m_surface->m_colorManagement = RESOURCE; - - m_resource->setOnDestroy([this](CXxColorManagementSurfaceV4* r) { - LOGM(Log::TRACE, "Destroy wp cm and xx cm for surface {}", (uintptr_t)m_surface); - if (m_surface.valid()) - PROTO::colorManagement->destroyResource(m_surface->m_colorManagement.get()); - PROTO::xxColorManagement->destroyResource(this); - }); - } else - m_resource->setOnDestroy([this](CXxColorManagementSurfaceV4* r) { - LOGM(Log::TRACE, "Destroy xx cm surface {}", (uintptr_t)m_surface); - PROTO::xxColorManagement->destroyResource(this); - }); - - m_resource->setDestroy([this](CXxColorManagementSurfaceV4* r) { - LOGM(Log::TRACE, "Destroy xx cm surface {}", (uintptr_t)m_surface); - PROTO::xxColorManagement->destroyResource(this); - }); - - m_resource->setSetImageDescription([this](CXxColorManagementSurfaceV4* r, wl_resource* image_description, uint32_t render_intent) { - LOGM(Log::TRACE, "Set image description for surface={}, desc={}, intent={}", (uintptr_t)r, (uintptr_t)image_description, render_intent); - - const auto PO = sc(wl_resource_get_user_data(image_description)); - if (!PO) { // FIXME check validity - r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description creation failed"); - return; - } - if (render_intent != XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL) { - r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_RENDER_INTENT, "Unsupported render intent"); - return; - } - - const auto imageDescription = - std::ranges::find_if(PROTO::xxColorManagement->m_imageDescriptions, [&](const auto& other) { return other->resource()->resource() == image_description; }); - if (imageDescription == PROTO::xxColorManagement->m_imageDescriptions.end()) { - r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description not found"); - return; - } - - if (m_surface.valid()) { - m_surface->m_colorManagement->m_imageDescription = imageDescription->get()->m_settings; - m_surface->m_colorManagement->setHasImageDescription(true); - } else - LOGM(Log::ERR, "Set image description for invalid surface"); - }); - m_resource->setUnsetImageDescription([this](CXxColorManagementSurfaceV4* r) { - LOGM(Log::TRACE, "Unset image description for surface={}", (uintptr_t)r); - if (m_surface.valid()) { - m_surface->m_colorManagement->m_imageDescription = SImageDescription{}; - m_surface->m_colorManagement->setHasImageDescription(false); - } else - LOGM(Log::ERR, "Unset image description for invalid surface"); - }); -} - -bool CXXColorManagementSurface::good() { - return m_resource && m_resource->resource(); -} - -wl_client* CXXColorManagementSurface::client() { - return m_client; -} - -const SImageDescription& CXXColorManagementSurface::imageDescription() { - if (!hasImageDescription()) - LOGM(Log::WARN, "Reading imageDescription while none set. Returns default or empty values"); - return m_imageDescription; -} - -bool CXXColorManagementSurface::hasImageDescription() { - return m_hasImageDescription; -} - -void CXXColorManagementSurface::setHasImageDescription(bool has) { - m_hasImageDescription = has; - m_needsNewMetadata = true; -} - -const hdr_output_metadata& CXXColorManagementSurface::hdrMetadata() { - return m_hdrMetadata; -} - -void CXXColorManagementSurface::setHDRMetadata(const hdr_output_metadata& metadata) { - m_hdrMetadata = metadata; - m_needsNewMetadata = false; -} - -bool CXXColorManagementSurface::needsHdrMetadataUpdate() { - return m_needsNewMetadata; -} - -CXXColorManagementFeedbackSurface::CXXColorManagementFeedbackSurface(SP resource_, SP surface_) : - m_surface(surface_), m_resource(resource_) { - if UNLIKELY (!good()) - return; - - m_client = m_resource->client(); - - m_resource->setDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) { - LOGM(Log::TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)m_surface); - if (m_currentPreferred.valid()) - PROTO::xxColorManagement->destroyResource(m_currentPreferred.get()); - PROTO::xxColorManagement->destroyResource(this); - }); - m_resource->setOnDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) { - LOGM(Log::TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)m_surface); - if (m_currentPreferred.valid()) - PROTO::xxColorManagement->destroyResource(m_currentPreferred.get()); - PROTO::xxColorManagement->destroyResource(this); - }); - - m_resource->setGetPreferred([this](CXxColorManagementFeedbackSurfaceV4* r, uint32_t id) { - LOGM(Log::TRACE, "Get preferred for id {}", id); - - if (m_currentPreferred.valid()) - PROTO::xxColorManagement->destroyResource(m_currentPreferred.get()); - - const auto RESOURCE = PROTO::xxColorManagement->m_imageDescriptions.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), true)); - - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_imageDescriptions.pop_back(); - return; - } - - RESOURCE->m_self = RESOURCE; - m_currentPreferred = RESOURCE; - - m_currentPreferred->m_settings = g_pCompositor->getPreferredImageDescription(); - - RESOURCE->resource()->sendReady(id); - }); -} - -bool CXXColorManagementFeedbackSurface::good() { - return m_resource->resource(); -} - -wl_client* CXXColorManagementFeedbackSurface::client() { - return m_client; -} - -CXXColorManagementParametricCreator::CXXColorManagementParametricCreator(SP resource_) : m_resource(resource_) { - if UNLIKELY (!good()) - return; - // - m_client = m_resource->client(); - - m_resource->setOnDestroy([this](CXxImageDescriptionCreatorParamsV4* r) { PROTO::xxColorManagement->destroyResource(this); }); - - m_resource->setCreate([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t id) { - LOGM(Log::TRACE, "Create image description from params for id {}", id); - - // FIXME actually check completeness - if (!m_valuesSet) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCOMPLETE_SET, "Missing required settings"); - return; - } - - // FIXME actually check consistency - if (!m_valuesSet) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCONSISTENT_SET, "Set is not consistent"); - return; - } - - const auto RESOURCE = PROTO::xxColorManagement->m_imageDescriptions.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), false)); - - if UNLIKELY (!RESOURCE->good()) { - r->noMemory(); - PROTO::xxColorManagement->m_imageDescriptions.pop_back(); - return; - } - - // FIXME actually check support - if (!m_valuesSet) { - RESOURCE->resource()->sendFailed(XX_IMAGE_DESCRIPTION_V4_CAUSE_UNSUPPORTED, "unsupported"); - return; - } - - RESOURCE->m_self = RESOURCE; - RESOURCE->m_settings = m_settings; - RESOURCE->resource()->sendReady(id); - - PROTO::xxColorManagement->destroyResource(this); - }); - m_resource->setSetTfNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t tf) { - LOGM(Log::TRACE, "Set image description transfer function to {}", tf); - if (m_valuesSet & PC_TF) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function already set"); - return; - } - - switch (tf) { - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_HLG: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT709: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT1361: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST240: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_100: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_316: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_XVYCC: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_EXT_SRGB: - case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST428: break; - default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_TF, "Unsupported transfer function"); return; - } - - m_settings.transferFunction = convertTransferFunction(getWPTransferFunction(sc(tf))); - m_valuesSet |= PC_TF; - }); - m_resource->setSetTfPower([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t eexp) { - LOGM(Log::TRACE, "Set image description tf power to {}", eexp); - if (m_valuesSet & PC_TF_POWER) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function power already set"); - return; - } - m_settings.transferFunctionPower = eexp / 10000.0f; - m_valuesSet |= PC_TF_POWER; - }); - m_resource->setSetPrimariesNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t primaries) { - LOGM(Log::TRACE, "Set image description primaries by name {}", primaries); - if (m_valuesSet & PC_PRIMARIES) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set"); - return; - } - - switch (primaries) { - case XX_COLOR_MANAGER_V4_PRIMARIES_SRGB: - case XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M: - case XX_COLOR_MANAGER_V4_PRIMARIES_PAL: - case XX_COLOR_MANAGER_V4_PRIMARIES_NTSC: - case XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM: - case XX_COLOR_MANAGER_V4_PRIMARIES_BT2020: - case XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3: - case XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3: - case XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB: - m_settings.primariesNameSet = true; - m_settings.primariesNamed = convertPrimaries(getWPPrimaries(sc(primaries))); - m_settings.primaries = getPrimaries(m_settings.primariesNamed); - m_valuesSet |= PC_PRIMARIES; - break; - default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_PRIMARIES, "Unsupported primaries"); - } - }); - m_resource->setSetPrimaries( - [this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) { - LOGM(Log::TRACE, "Set image description primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y); - if (m_valuesSet & PC_PRIMARIES) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set"); - return; - } - m_settings.primariesNameSet = false; - m_settings.primaries = SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}}; - m_valuesSet |= PC_PRIMARIES; - }); - m_resource->setSetLuminances([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) { - auto min = min_lum / 10000.0f; - LOGM(Log::TRACE, "Set image description luminances to {} - {} ({})", min, max_lum, reference_lum); - if (m_valuesSet & PC_LUMINANCES) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Luminances already set"); - return; - } - if (max_lum < reference_lum || reference_lum <= min) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances"); - return; - } - m_settings.luminances = SImageDescription::SPCLuminances{.min = min, .max = max_lum, .reference = reference_lum}; - m_valuesSet |= PC_LUMINANCES; - }); - m_resource->setSetMasteringDisplayPrimaries( - [this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) { - LOGM(Log::TRACE, "Set image description mastering primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y); - // if (valuesSet & PC_MASTERING_PRIMARIES) { - // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering primaries already set"); - // return; - // } - m_settings.masteringPrimaries = SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}}; - m_valuesSet |= PC_MASTERING_PRIMARIES; - }); - m_resource->setSetMasteringLuminance([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum) { - auto min = min_lum / 10000.0f; - LOGM(Log::TRACE, "Set image description mastering luminances to {} - {}", min, max_lum); - // if (valuesSet & PC_MASTERING_LUMINANCES) { - // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering luminances already set"); - // return; - // } - if (min > 0 && max_lum > 0 && max_lum <= min) { - r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances"); - return; - } - m_settings.masteringLuminances = SImageDescription::SPCMasteringLuminances{.min = min, .max = max_lum}; - m_valuesSet |= PC_MASTERING_LUMINANCES; - }); - m_resource->setSetMaxCll([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_cll) { - LOGM(Log::TRACE, "Set image description max content light level to {}", max_cll); - // if (valuesSet & PC_CLL) { - // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max CLL already set"); - // return; - // } - m_settings.maxCLL = max_cll; - m_valuesSet |= PC_CLL; - }); - m_resource->setSetMaxFall([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_fall) { - LOGM(Log::TRACE, "Set image description max frame-average light level to {}", max_fall); - // if (valuesSet & PC_FALL) { - // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max FALL already set"); - // return; - // } - m_settings.maxFALL = max_fall; - m_valuesSet |= PC_FALL; - }); -} - -bool CXXColorManagementParametricCreator::good() { - return m_resource->resource(); -} - -wl_client* CXXColorManagementParametricCreator::client() { - return m_client; -} - -CXXColorManagementImageDescription::CXXColorManagementImageDescription(SP resource_, bool allowGetInformation) : - m_resource(resource_), m_allowGetInformation(allowGetInformation) { - if UNLIKELY (!good()) - return; - - m_client = m_resource->client(); - - m_resource->setDestroy([this](CXxImageDescriptionV4* r) { PROTO::xxColorManagement->destroyResource(this); }); - m_resource->setOnDestroy([this](CXxImageDescriptionV4* r) { PROTO::xxColorManagement->destroyResource(this); }); - - m_resource->setGetInformation([this](CXxImageDescriptionV4* r, uint32_t id) { - LOGM(Log::TRACE, "Get image information for image={}, id={}", (uintptr_t)r, id); - if (!m_allowGetInformation) { - r->error(XX_IMAGE_DESCRIPTION_V4_ERROR_NO_INFORMATION, "Image descriptions doesn't allow get_information request"); - return; - } - - auto RESOURCE = makeShared(makeShared(r->client(), r->version(), id), m_settings); - - if UNLIKELY (!RESOURCE->good()) - r->noMemory(); - - // CXXColorManagementImageDescriptionInfo should send everything in the constructor and be ready for destroying at this point - RESOURCE.reset(); - }); -} - -bool CXXColorManagementImageDescription::good() { - return m_resource->resource(); -} - -wl_client* CXXColorManagementImageDescription::client() { - return m_client; -} - -SP CXXColorManagementImageDescription::resource() { - return m_resource; -} - -CXXColorManagementImageDescriptionInfo::CXXColorManagementImageDescriptionInfo(SP resource_, const SImageDescription& settings_) : - m_resource(resource_), m_settings(settings_) { - if UNLIKELY (!good()) - return; - - m_client = m_resource->client(); - - const auto toProto = [](float value) { return sc(std::round(value * 10000)); }; - - if (m_settings.icc.fd >= 0) - m_resource->sendIccFile(m_settings.icc.fd, m_settings.icc.length); - - // send preferred client paramateres - m_resource->sendPrimaries(toProto(m_settings.primaries.red.x), toProto(m_settings.primaries.red.y), toProto(m_settings.primaries.green.x), - toProto(m_settings.primaries.green.y), toProto(m_settings.primaries.blue.x), toProto(m_settings.primaries.blue.y), - toProto(m_settings.primaries.white.x), toProto(m_settings.primaries.white.y)); - if (m_settings.primariesNameSet) - m_resource->sendPrimariesNamed(m_settings.primariesNamed); - m_resource->sendTfPower(std::round(m_settings.transferFunctionPower * 10000)); - m_resource->sendTfNamed(m_settings.transferFunction); - m_resource->sendLuminances(std::round(m_settings.luminances.min * 10000), m_settings.luminances.max, m_settings.luminances.reference); - - // send expected display paramateres - m_resource->sendTargetPrimaries(toProto(m_settings.masteringPrimaries.red.x), toProto(m_settings.masteringPrimaries.red.y), toProto(m_settings.masteringPrimaries.green.x), - toProto(m_settings.masteringPrimaries.green.y), toProto(m_settings.masteringPrimaries.blue.x), toProto(m_settings.masteringPrimaries.blue.y), - toProto(m_settings.masteringPrimaries.white.x), toProto(m_settings.masteringPrimaries.white.y)); - m_resource->sendTargetLuminance(std::round(m_settings.masteringLuminances.min * 10000), m_settings.masteringLuminances.max); - m_resource->sendTargetMaxCll(m_settings.maxCLL); - m_resource->sendTargetMaxFall(m_settings.maxFALL); - - m_resource->sendDone(); -} - -bool CXXColorManagementImageDescriptionInfo::good() { - return m_resource->resource(); -} - -wl_client* CXXColorManagementImageDescriptionInfo::client() { - return m_client; -} - -CXXColorManagementProtocol::CXXColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - ; -} - -void CXXColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_managers.emplace_back(makeShared(makeShared(client, ver, id))); - - if UNLIKELY (!RESOURCE->good()) { - wl_client_post_no_memory(client); - m_managers.pop_back(); - return; - } - - LOGM(Log::TRACE, "New xx_color_manager at {:x}", (uintptr_t)RESOURCE.get()); -} - -void CXXColorManagementProtocol::onImagePreferredChanged() { - for (auto const& feedback : m_feedbackSurfaces) { - feedback->m_resource->sendPreferredChanged(); - } -} - -void CXXColorManagementProtocol::destroyResource(CXXColorManager* resource) { - std::erase_if(m_managers, [&](const auto& other) { return other.get() == resource; }); -} - -void CXXColorManagementProtocol::destroyResource(CXXColorManagementOutput* resource) { - std::erase_if(m_outputs, [&](const auto& other) { return other.get() == resource; }); -} - -void CXXColorManagementProtocol::destroyResource(CXXColorManagementSurface* resource) { - std::erase_if(m_surfaces, [&](const auto& other) { return other.get() == resource; }); -} - -void CXXColorManagementProtocol::destroyResource(CXXColorManagementFeedbackSurface* resource) { - std::erase_if(m_feedbackSurfaces, [&](const auto& other) { return other.get() == resource; }); -} - -void CXXColorManagementProtocol::destroyResource(CXXColorManagementParametricCreator* resource) { - std::erase_if(m_parametricCreators, [&](const auto& other) { return other.get() == resource; }); -} - -void CXXColorManagementProtocol::destroyResource(CXXColorManagementImageDescription* resource) { - std::erase_if(m_imageDescriptions, [&](const auto& other) { return other.get() == resource; }); -} diff --git a/src/protocols/XXColorManagement.hpp b/src/protocols/XXColorManagement.hpp deleted file mode 100644 index 0407730a..00000000 --- a/src/protocols/XXColorManagement.hpp +++ /dev/null @@ -1,188 +0,0 @@ -#pragma once - -#include -#include -#include -#include "WaylandProtocol.hpp" -#include "core/Compositor.hpp" -#include "xx-color-management-v4.hpp" -#include "types/ColorManagement.hpp" - -class CXXColorManager; -class CXXColorManagementOutput; -class CXXColorManagementImageDescription; -class CXXColorManagementProtocol; - -class CXXColorManager { - public: - CXXColorManager(SP resource_); - - bool good(); - - private: - SP m_resource; -}; - -class CXXColorManagementOutput { - public: - CXXColorManagementOutput(SP resource_); - - bool good(); - wl_client* client(); - - WP m_self; - WP m_imageDescription; - - private: - SP m_resource; - wl_client* m_client = nullptr; - - friend class CXXColorManagementProtocol; - friend class CXXColorManagementImageDescription; -}; - -class CXXColorManagementSurface { - public: - CXXColorManagementSurface(SP surface_); // temporary interface for frog CM - CXXColorManagementSurface(SP resource_, SP surface_); - - bool good(); - wl_client* client(); - - WP m_self; - WP m_surface; - - const NColorManagement::SImageDescription& imageDescription(); - bool hasImageDescription(); - void setHasImageDescription(bool has); - const hdr_output_metadata& hdrMetadata(); - void setHDRMetadata(const hdr_output_metadata& metadata); - bool needsHdrMetadataUpdate(); - - private: - SP m_resource; - wl_client* m_client = nullptr; - NColorManagement::SImageDescription m_imageDescription; - bool m_hasImageDescription = false; - bool m_needsNewMetadata = false; - hdr_output_metadata m_hdrMetadata; - - friend class CFrogColorManagementSurface; -}; - -class CXXColorManagementFeedbackSurface { - public: - CXXColorManagementFeedbackSurface(SP resource_, SP surface_); - - bool good(); - wl_client* client(); - - WP m_self; - WP m_surface; - - private: - SP m_resource; - wl_client* m_client = nullptr; - - WP m_currentPreferred; - - friend class CXXColorManagementProtocol; -}; - -class CXXColorManagementParametricCreator { - public: - CXXColorManagementParametricCreator(SP resource_); - - bool good(); - wl_client* client(); - - WP m_self; - - NColorManagement::SImageDescription m_settings; - - private: - enum eValuesSet : uint32_t { // NOLINT - PC_TF = (1 << 0), - PC_TF_POWER = (1 << 1), - PC_PRIMARIES = (1 << 2), - PC_LUMINANCES = (1 << 3), - PC_MASTERING_PRIMARIES = (1 << 4), - PC_MASTERING_LUMINANCES = (1 << 5), - PC_CLL = (1 << 6), - PC_FALL = (1 << 7), - }; - - SP m_resource; - wl_client* m_client = nullptr; - uint32_t m_valuesSet = 0; // enum eValuesSet -}; - -class CXXColorManagementImageDescription { - public: - CXXColorManagementImageDescription(SP resource_, bool allowGetInformation); - - bool good(); - wl_client* client(); - SP resource(); - - WP m_self; - - NColorManagement::SImageDescription m_settings; - - private: - SP m_resource; - wl_client* m_client = nullptr; - bool m_allowGetInformation = false; - - friend class CXXColorManagementOutput; -}; - -class CXXColorManagementImageDescriptionInfo { - public: - CXXColorManagementImageDescriptionInfo(SP resource_, const NColorManagement::SImageDescription& settings_); - - bool good(); - wl_client* client(); - - private: - SP m_resource; - wl_client* m_client = nullptr; - NColorManagement::SImageDescription m_settings; -}; - -class CXXColorManagementProtocol : public IWaylandProtocol { - public: - CXXColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name); - - virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - - void onImagePreferredChanged(); - - private: - void destroyResource(CXXColorManager* resource); - void destroyResource(CXXColorManagementOutput* resource); - void destroyResource(CXXColorManagementSurface* resource); - void destroyResource(CXXColorManagementFeedbackSurface* resource); - void destroyResource(CXXColorManagementParametricCreator* resource); - void destroyResource(CXXColorManagementImageDescription* resource); - - std::vector> m_managers; - std::vector> m_outputs; - std::vector> m_surfaces; - std::vector> m_feedbackSurfaces; - std::vector> m_parametricCreators; - std::vector> m_imageDescriptions; - - friend class CXXColorManager; - friend class CXXColorManagementOutput; - friend class CXXColorManagementSurface; - friend class CXXColorManagementFeedbackSurface; - friend class CXXColorManagementParametricCreator; - friend class CXXColorManagementImageDescription; - - friend class CFrogColorManagementSurface; -}; - -namespace PROTO { - inline UP xxColorManagement; -}; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index c2d99176..b9e677af 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -556,7 +556,7 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) { dropCurrentBuffer(); } -SImageDescription CWLSurfaceResource::getPreferredImageDescription() { +PImageDescription CWLSurfaceResource::getPreferredImageDescription() { static const auto PFORCE_HDR = CConfigValue("quirks:prefer_hdr"); const auto WINDOW = m_hlSurface ? Desktop::View::CWindow::fromView(m_hlSurface->view()) : nullptr; diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 7b295aa7..89bfb31b 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -33,7 +33,6 @@ class CDRMSyncobjSurfaceResource; class CFifoResource; class CCommitTimerResource; class CColorManagementSurface; -class CFrogColorManagementSurface; class CContentType; class CWLCallbackResource { @@ -126,7 +125,7 @@ class CWLSurfaceResource { void presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded = false); void scheduleState(WP state); void commitState(SSurfaceState& state); - NColorManagement::SImageDescription getPreferredImageDescription(); + NColorManagement::PImageDescription getPreferredImageDescription(); void sortSubsurfaces(); bool hasVisibleSubsurface(); diff --git a/src/protocols/types/ColorManagement.cpp b/src/protocols/types/ColorManagement.cpp index e6b470d0..5d23d1c9 100644 --- a/src/protocols/types/ColorManagement.cpp +++ b/src/protocols/types/ColorManagement.cpp @@ -1,11 +1,16 @@ #include "ColorManagement.hpp" +#include "../../macros.hpp" +#include #include +#include namespace NColorManagement { - static uint32_t lastImageID = 0; - static std::map knownDescriptionIds; // expected to be small + // expected to be small + static std::vector> knownPrimaries; + static std::vector> knownDescriptions; + static std::map, Hyprgraphics::CMatrix3> primariesConversion; - const SPCPRimaries& getPrimaries(ePrimaries name) { + const SPCPRimaries& getPrimaries(ePrimaries name) { switch (name) { case CM_PRIMARIES_SRGB: return NColorPrimaries::BT709; case CM_PRIMARIES_BT2020: return NColorPrimaries::BT2020; @@ -13,7 +18,7 @@ namespace NColorManagement { case CM_PRIMARIES_PAL: return NColorPrimaries::PAL; case CM_PRIMARIES_NTSC: return NColorPrimaries::NTSC; case CM_PRIMARIES_GENERIC_FILM: return NColorPrimaries::GENERIC_FILM; - case CM_PRIMARIES_CIE1931_XYZ: return NColorPrimaries::DEFAULT_PRIMARIES; // FIXME + case CM_PRIMARIES_CIE1931_XYZ: return NColorPrimaries::CIE1931_XYZ; case CM_PRIMARIES_DCI_P3: return NColorPrimaries::DCI_P3; case CM_PRIMARIES_DISPLAY_P3: return NColorPrimaries::DISPLAY_P3; case CM_PRIMARIES_ADOBE_RGB: return NColorPrimaries::ADOBE_RGB; @@ -21,26 +26,85 @@ namespace NColorManagement { } } - // TODO make image descriptions immutable and always set an id + CPrimaries::CPrimaries(const SPCPRimaries& primaries, const uint primariesId) : m_id(primariesId), m_primaries(primaries) { + m_primaries2XYZ = m_primaries.toXYZ(); + } - uint32_t SImageDescription::findId() const { - for (auto it = knownDescriptionIds.begin(); it != knownDescriptionIds.end(); ++it) { - if (it->second == *this) - return it->first; + WP CPrimaries::from(const SPCPRimaries& primaries) { + for (const auto& known : knownPrimaries) { + if (known->value() == primaries) + return known; } - const auto newId = ++lastImageID; - knownDescriptionIds.insert(std::make_pair(newId, *this)); - return newId; + knownPrimaries.emplace_back(CUniquePointer(new CPrimaries(primaries, knownPrimaries.size() + 1))); + return knownPrimaries.back(); } - uint32_t SImageDescription::getId() const { - return id > 0 ? id : findId(); + WP CPrimaries::from(const ePrimaries name) { + return from(getPrimaries(name)); } - uint32_t SImageDescription::updateId() { - id = 0; - id = findId(); - return id; + WP CPrimaries::from(const uint primariesId) { + ASSERT(primariesId <= knownPrimaries.size()); + return knownPrimaries[primariesId - 1]; } + + const SPCPRimaries& CPrimaries::value() const { + return m_primaries; + } + + uint CPrimaries::id() const { + return m_id; + } + + const Hyprgraphics::CMatrix3& CPrimaries::toXYZ() const { + return m_primaries2XYZ; + } + + const Hyprgraphics::CMatrix3& CPrimaries::convertMatrix(const WP dst) const { + const auto cacheKey = std::make_pair(m_id, dst->m_id); + if (!primariesConversion.contains(cacheKey)) + primariesConversion.insert(std::make_pair(cacheKey, m_primaries.convertMatrix(dst->m_primaries))); + + return primariesConversion[cacheKey]; + } + + CImageDescription::CImageDescription(const SImageDescription& imageDescription, const uint imageDescriptionId) : + m_id(imageDescriptionId), m_imageDescription(imageDescription) { + m_primariesId = CPrimaries::from(m_imageDescription.getPrimaries())->id(); + } + + PImageDescription CImageDescription::from(const SImageDescription& imageDescription) { + for (const auto& known : knownDescriptions) { + if (known->value() == imageDescription) + return known; + } + + knownDescriptions.emplace_back(CUniquePointer(new CImageDescription(imageDescription, knownDescriptions.size() + 1))); + return knownDescriptions.back(); + } + + PImageDescription CImageDescription::from(const uint imageDescriptionId) { + ASSERT(imageDescriptionId <= knownDescriptions.size()); + return knownDescriptions[imageDescriptionId - 1]; + } + + PImageDescription CImageDescription::with(const SImageDescription::SPCLuminances& luminances) const { + auto desc = m_imageDescription; + desc.luminances = luminances; + return CImageDescription::from(desc); + } + + const SImageDescription& CImageDescription::value() const { + return m_imageDescription; + } + + uint CImageDescription::id() const { + return m_id; + } + + WP CImageDescription::getPrimaries() const { + return CPrimaries::from(m_primariesId); + } + } \ No newline at end of file diff --git a/src/protocols/types/ColorManagement.hpp b/src/protocols/types/ColorManagement.hpp index 8bb30e8e..01077704 100644 --- a/src/protocols/types/ColorManagement.hpp +++ b/src/protocols/types/ColorManagement.hpp @@ -75,30 +75,35 @@ namespace NColorManagement { .blue = {.x = 0.15, .y = 0.06}, .white = {.x = 0.3127, .y = 0.3290}, }; + static const auto PAL_M = SPCPRimaries{ .red = {.x = 0.67, .y = 0.33}, .green = {.x = 0.21, .y = 0.71}, .blue = {.x = 0.14, .y = 0.08}, .white = {.x = 0.310, .y = 0.316}, }; + static const auto PAL = SPCPRimaries{ .red = {.x = 0.640, .y = 0.330}, .green = {.x = 0.290, .y = 0.600}, .blue = {.x = 0.150, .y = 0.060}, .white = {.x = 0.3127, .y = 0.3290}, }; + static const auto NTSC = SPCPRimaries{ .red = {.x = 0.630, .y = 0.340}, .green = {.x = 0.310, .y = 0.595}, .blue = {.x = 0.155, .y = 0.070}, .white = {.x = 0.3127, .y = 0.3290}, }; + static const auto GENERIC_FILM = SPCPRimaries{ .red = {.x = 0.243, .y = 0.692}, .green = {.x = 0.145, .y = 0.049}, .blue = {.x = 0.681, .y = 0.319}, // NOLINT(modernize-use-std-numbers) .white = {.x = 0.310, .y = 0.316}, }; + static const auto BT2020 = SPCPRimaries{ .red = {.x = 0.708, .y = 0.292}, .green = {.x = 0.170, .y = 0.797}, @@ -106,7 +111,12 @@ namespace NColorManagement { .white = {.x = 0.3127, .y = 0.3290}, }; - // FIXME CIE1931_XYZ + static const auto CIE1931_XYZ = SPCPRimaries{ + .red = {.x = 1.0, .y = 0.0}, + .green = {.x = 0.0, .y = 1.0}, + .blue = {.x = 0.0, .y = 0.0}, + .white = {.x = 1.0 / 3.0, .y = 1.0 / 3.0}, + }; static const auto DCI_P3 = SPCPRimaries{ .red = {.x = 0.680, .y = 0.320}, @@ -121,6 +131,7 @@ namespace NColorManagement { .blue = {.x = 0.150, .y = 0.060}, .white = {.x = 0.3127, .y = 0.3290}, }; + static const auto ADOBE_RGB = SPCPRimaries{ .red = {.x = 0.6400, .y = 0.3300}, .green = {.x = 0.2100, .y = 0.7100}, @@ -131,9 +142,27 @@ namespace NColorManagement { const SPCPRimaries& getPrimaries(ePrimaries name); - struct SImageDescription { - uint32_t id = 0; // FIXME needs id setting + class CPrimaries { + public: + static WP from(const SPCPRimaries& primaries); + static WP from(const ePrimaries name); + static WP from(const uint primariesId); + const SPCPRimaries& value() const; + uint id() const; + + const Hyprgraphics::CMatrix3& toXYZ() const; // toXYZ() * rgb -> xyz + const Hyprgraphics::CMatrix3& convertMatrix(const WP dst) const; // convertMatrix(dst) * rgb with "this" primaries -> rgb with dst primaries + + private: + CPrimaries(const SPCPRimaries& primaries, const uint primariesId); + uint m_id; + SPCPRimaries m_primaries; + + Hyprgraphics::CMatrix3 m_primaries2XYZ; + }; + + struct SImageDescription { struct SIccFile { int fd = -1; uint32_t length = 0; @@ -145,16 +174,14 @@ namespace NColorManagement { bool windowsScRGB = false; - eTransferFunction transferFunction = CM_TRANSFER_FUNCTION_SRGB; + eTransferFunction transferFunction = CM_TRANSFER_FUNCTION_GAMMA22; float transferFunctionPower = 1.0f; bool primariesNameSet = false; ePrimaries primariesNamed = CM_PRIMARIES_SRGB; // primaries are stored as FP values with the same scale as standard defines (0.0 - 1.0) // wayland protocol expects int32_t values multiplied by 1000000 - // xx protocol expects int32_t values multiplied by 10000 // drm expects uint16_t values multiplied by 50000 - // frog protocol expects drm values SPCPRimaries primaries, masteringPrimaries; // luminances in cd/m² @@ -179,11 +206,10 @@ namespace NColorManagement { uint32_t maxFALL = 0; bool operator==(const SImageDescription& d2) const { - return (id != 0 && id == d2.id) || - (icc == d2.icc && windowsScRGB == d2.windowsScRGB && transferFunction == d2.transferFunction && transferFunctionPower == d2.transferFunctionPower && - (primariesNameSet == d2.primariesNameSet && (primariesNameSet ? primariesNamed == d2.primariesNamed : primaries == d2.primaries)) && - masteringPrimaries == d2.masteringPrimaries && luminances == d2.luminances && masteringLuminances == d2.masteringLuminances && maxCLL == d2.maxCLL && - maxFALL == d2.maxFALL); + return icc == d2.icc && windowsScRGB == d2.windowsScRGB && transferFunction == d2.transferFunction && transferFunctionPower == d2.transferFunctionPower && + (primariesNameSet == d2.primariesNameSet && (primariesNameSet ? primariesNamed == d2.primariesNamed : primaries == d2.primaries)) && + masteringPrimaries == d2.masteringPrimaries && luminances == d2.luminances && masteringLuminances == d2.masteringLuminances && maxCLL == d2.maxCLL && + maxFALL == d2.maxFALL; } const SPCPRimaries& getPrimaries() const { @@ -249,9 +275,44 @@ namespace NColorManagement { default: return sdrRefLuminance >= 0 ? sdrRefLuminance : SDR_REF_LUMINANCE; } }; - - uint32_t findId() const; - uint32_t getId() const; - uint32_t updateId(); }; + + class CImageDescription { + public: + static WP from(const SImageDescription& imageDescription); + static WP from(const uint imageDescriptionId); + + WP with(const SImageDescription::SPCLuminances& luminances) const; + + const SImageDescription& value() const; + uint id() const; + + WP getPrimaries() const; + + private: + CImageDescription(const SImageDescription& imageDescription, const uint imageDescriptionId); + uint m_id; + uint m_primariesId; + SImageDescription m_imageDescription; + }; + + using PImageDescription = WP; + + static const auto DEFAULT_IMAGE_DESCRIPTION = CImageDescription::from(SImageDescription{}); + static const auto DEFAULT_HDR_IMAGE_DESCRIPTION = CImageDescription::from(SImageDescription{.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), + .luminances = {.min = 0, .max = 10000, .reference = 203}}); + ; + static const auto SCRGB_IMAGE_DESCRIPTION = CImageDescription::from(SImageDescription{ + .windowsScRGB = true, + .transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_EXT_LINEAR, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_SRGB, + .primaries = NColorPrimaries::BT709, + .luminances = {.reference = 203}, + }); + ; + } \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index fd83090f..9a5d6ad0 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1560,52 +1560,52 @@ static bool isHDR2SDR(const NColorManagement::SImageDescription& imageDescriptio targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22); } -void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::SImageDescription& imageDescription, - const NColorManagement::SImageDescription& targetImageDescription, bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) { +void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, + bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) { static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); if (m_renderData.surface.valid() && ((!m_renderData.surface->m_colorManagement.valid() && *PSDREOTF >= 1) || (*PSDREOTF == 2 && m_renderData.surface->m_colorManagement.valid() && - imageDescription.transferFunction == NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_SRGB))) { + imageDescription->value().transferFunction == NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_SRGB))) { shader.setUniformInt(SHADER_SOURCE_TF, NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_GAMMA22); } else - shader.setUniformInt(SHADER_SOURCE_TF, imageDescription.transferFunction); + shader.setUniformInt(SHADER_SOURCE_TF, imageDescription->value().transferFunction); - shader.setUniformInt(SHADER_TARGET_TF, targetImageDescription.transferFunction); + shader.setUniformInt(SHADER_TARGET_TF, targetImageDescription->value().transferFunction); - const auto targetPrimaries = targetImageDescription.primariesNameSet || targetImageDescription.primaries == SPCPRimaries{} ? - getPrimaries(targetImageDescription.primariesNamed) : - targetImageDescription.primaries; + const auto targetPrimaries = targetImageDescription->getPrimaries(); const std::array glTargetPrimaries = { - targetPrimaries.red.x, targetPrimaries.red.y, targetPrimaries.green.x, targetPrimaries.green.y, - targetPrimaries.blue.x, targetPrimaries.blue.y, targetPrimaries.white.x, targetPrimaries.white.y, + targetPrimaries->value().red.x, targetPrimaries->value().red.y, targetPrimaries->value().green.x, targetPrimaries->value().green.y, + targetPrimaries->value().blue.x, targetPrimaries->value().blue.y, targetPrimaries->value().white.x, targetPrimaries->value().white.y, }; shader.setUniformMatrix4x2fv(SHADER_TARGET_PRIMARIES, 1, false, glTargetPrimaries); - const bool needsSDRmod = modifySDR && isSDR2HDR(imageDescription, targetImageDescription); - const bool needsHDRmod = !needsSDRmod && isHDR2SDR(imageDescription, targetImageDescription); + const bool needsSDRmod = modifySDR && isSDR2HDR(imageDescription->value(), targetImageDescription->value()); + const bool needsHDRmod = !needsSDRmod && isHDR2SDR(imageDescription->value(), targetImageDescription->value()); - shader.setUniformFloat2(SHADER_SRC_TF_RANGE, imageDescription.getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), - imageDescription.getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); - shader.setUniformFloat2(SHADER_DST_TF_RANGE, targetImageDescription.getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), - targetImageDescription.getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); + shader.setUniformFloat2(SHADER_SRC_TF_RANGE, imageDescription->value().getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), + imageDescription->value().getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); + shader.setUniformFloat2(SHADER_DST_TF_RANGE, targetImageDescription->value().getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), + targetImageDescription->value().getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); - shader.setUniformFloat(SHADER_SRC_REF_LUMINANCE, imageDescription.getTFRefLuminance(-1)); - shader.setUniformFloat(SHADER_DST_REF_LUMINANCE, targetImageDescription.getTFRefLuminance(-1)); + shader.setUniformFloat(SHADER_SRC_REF_LUMINANCE, imageDescription->value().getTFRefLuminance(-1)); + shader.setUniformFloat(SHADER_DST_REF_LUMINANCE, targetImageDescription->value().getTFRefLuminance(-1)); - const float maxLuminance = - needsHDRmod ? imageDescription.getTFMaxLuminance(-1) : (imageDescription.luminances.max > 0 ? imageDescription.luminances.max : imageDescription.luminances.reference); + const float maxLuminance = needsHDRmod ? + imageDescription->value().getTFMaxLuminance(-1) : + (imageDescription->value().luminances.max > 0 ? imageDescription->value().luminances.max : imageDescription->value().luminances.reference); shader.setUniformFloat(SHADER_MAX_LUMINANCE, - maxLuminance * targetImageDescription.luminances.reference / - (needsHDRmod ? imageDescription.getTFRefLuminance(-1) : imageDescription.luminances.reference)); - shader.setUniformFloat(SHADER_DST_MAX_LUMINANCE, targetImageDescription.luminances.max > 0 ? targetImageDescription.luminances.max : 10000); + maxLuminance * targetImageDescription->value().luminances.reference / + (needsHDRmod ? imageDescription->value().getTFRefLuminance(-1) : imageDescription->value().luminances.reference)); + shader.setUniformFloat(SHADER_DST_MAX_LUMINANCE, targetImageDescription->value().luminances.max > 0 ? targetImageDescription->value().luminances.max : 10000); shader.setUniformFloat(SHADER_SDR_SATURATION, needsSDRmod && m_renderData.pMonitor->m_sdrSaturation > 0 ? m_renderData.pMonitor->m_sdrSaturation : 1.0f); shader.setUniformFloat(SHADER_SDR_BRIGHTNESS, needsSDRmod && m_renderData.pMonitor->m_sdrBrightness > 0 ? m_renderData.pMonitor->m_sdrBrightness : 1.0f); - const auto cacheKey = std::make_pair(imageDescription.getId(), targetImageDescription.getId()); + const auto cacheKey = std::make_pair(imageDescription->id(), targetImageDescription->id()); if (!primariesConversionCache.contains(cacheKey)) { - const auto mat = imageDescription.getPrimaries().convertMatrix(targetImageDescription.getPrimaries()).mat(); + auto conversion = imageDescription->getPrimaries()->convertMatrix(targetImageDescription->getPrimaries()); + const auto mat = conversion.mat(); const std::array glConvertMatrix = { mat[0][0], mat[1][0], mat[2][0], // mat[0][1], mat[1][1], mat[2][1], // @@ -1616,7 +1616,7 @@ void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::SI shader.setUniformMatrix3fv(SHADER_CONVERT_MATRIX, 1, false, primariesConversionCache[cacheKey]); } -void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const SImageDescription& imageDescription) { +void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const PImageDescription imageDescription) { passCMUniforms(shader, imageDescription, m_renderData.pMonitor->m_imageDescription, true, m_renderData.pMonitor->m_sdrMinLuminance, m_renderData.pMonitor->m_sdrMaxLuminance); } @@ -1699,13 +1699,13 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c const bool isHDRSurface = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? m_renderData.surface->m_colorManagement->isHDR() : false; const bool canPassHDRSurface = isHDRSurface && !m_renderData.surface->m_colorManagement->isWindowsScRGB(); // windows scRGB requires CM shader - auto imageDescription = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? - m_renderData.surface->m_colorManagement->imageDescription() : - (data.cmBackToSRGB ? data.cmBackToSRGBSource->m_imageDescription : SImageDescription{}); + const auto imageDescription = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? + CImageDescription::from(m_renderData.surface->m_colorManagement->imageDescription()) : + (data.cmBackToSRGB ? data.cmBackToSRGBSource->m_imageDescription : DEFAULT_IMAGE_DESCRIPTION); - const bool skipCM = !*PENABLECM || !m_cmSupported /* CM unsupported or disabled */ - || m_renderData.pMonitor->doesNoShaderCM() /* no shader needed */ - || (imageDescription == m_renderData.pMonitor->m_imageDescription && !data.cmBackToSRGB) /* Source and target have the same image description */ + const bool skipCM = !*PENABLECM || !m_cmSupported /* CM unsupported or disabled */ + || m_renderData.pMonitor->doesNoShaderCM() /* no shader needed */ + || (imageDescription->id() == m_renderData.pMonitor->m_imageDescription->id() && !data.cmBackToSRGB) /* Source and target have the same image description */ || (((*PPASS && canPassHDRSurface) || (*PPASS == 1 && !isHDRSurface && m_renderData.pMonitor->m_cmType != NCMType::CM_HDR && m_renderData.pMonitor->m_cmType != NCMType::CM_HDR_EDID)) && m_renderData.pMonitor->inFullscreenMode()) /* Fullscreen window with pass cm enabled */; @@ -1719,8 +1719,8 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c shader->setUniformInt(SHADER_TEX_TYPE, texType); if (data.cmBackToSRGB) { static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); - auto chosenSdrEotf = *PSDREOTF > 0 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB; - passCMUniforms(*shader, imageDescription, NColorManagement::SImageDescription{.transferFunction = chosenSdrEotf}, true, -1, -1); + auto chosenSdrEotf = *PSDREOTF != 3 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB; + passCMUniforms(*shader, imageDescription, CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = chosenSdrEotf}), true, -1, -1); } else passCMUniforms(*shader, imageDescription); } @@ -2028,18 +2028,20 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi useProgram(m_shaders->m_shBLURPREPARE.program); // From FB to sRGB - const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; + const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); m_shaders->m_shBLURPREPARE.setUniformInt(SHADER_SKIP_CM, skipCM); if (!skipCM) { - passCMUniforms(m_shaders->m_shBLURPREPARE, m_renderData.pMonitor->m_imageDescription, SImageDescription{}); + passCMUniforms(m_shaders->m_shBLURPREPARE, m_renderData.pMonitor->m_imageDescription, DEFAULT_IMAGE_DESCRIPTION); m_shaders->m_shBLURPREPARE.setUniformFloat(SHADER_SDR_SATURATION, m_renderData.pMonitor->m_sdrSaturation > 0 && - m_renderData.pMonitor->m_imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? + m_renderData.pMonitor->m_imageDescription->value().transferFunction == + NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? m_renderData.pMonitor->m_sdrSaturation : 1.0f); m_shaders->m_shBLURPREPARE.setUniformFloat(SHADER_SDR_BRIGHTNESS, m_renderData.pMonitor->m_sdrBrightness > 0 && - m_renderData.pMonitor->m_imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? + m_renderData.pMonitor->m_imageDescription->value().transferFunction == + NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? m_renderData.pMonitor->m_sdrBrightness : 1.0f); } @@ -2509,10 +2511,10 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr useProgram(m_shaders->m_shBORDER1.program); - const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; + const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); m_shaders->m_shBORDER1.setUniformInt(SHADER_SKIP_CM, skipCM); if (!skipCM) - passCMUniforms(m_shaders->m_shBORDER1, SImageDescription{}); + passCMUniforms(m_shaders->m_shBORDER1, DEFAULT_IMAGE_DESCRIPTION); m_shaders->m_shBORDER1.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); m_shaders->m_shBORDER1.setUniform4fv(SHADER_GRADIENT, grad.m_colorsOkLabA.size() / 4, grad.m_colorsOkLabA); @@ -2593,10 +2595,10 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr useProgram(m_shaders->m_shBORDER1.program); - const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; + const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); m_shaders->m_shBORDER1.setUniformInt(SHADER_SKIP_CM, skipCM); if (!skipCM) - passCMUniforms(m_shaders->m_shBORDER1, SImageDescription{}); + passCMUniforms(m_shaders->m_shBORDER1, DEFAULT_IMAGE_DESCRIPTION); m_shaders->m_shBORDER1.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); m_shaders->m_shBORDER1.setUniform4fv(SHADER_GRADIENT, grad1.m_colorsOkLabA.size() / 4, grad1.m_colorsOkLabA); @@ -2670,10 +2672,10 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun blend(true); useProgram(m_shaders->m_shSHADOW.program); - const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; + const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); m_shaders->m_shSHADOW.setUniformInt(SHADER_SKIP_CM, skipCM); if (!skipCM) - passCMUniforms(m_shaders->m_shSHADOW, SImageDescription{}); + passCMUniforms(m_shaders->m_shSHADOW, DEFAULT_IMAGE_DESCRIPTION); m_shaders->m_shSHADOW.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); m_shaders->m_shSHADOW.setUniformFloat4(SHADER_COLOR, col.r, col.g, col.b, col.a * a); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 855a9439..e71429b7 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -403,9 +403,9 @@ class CHyprOpenGLImpl { CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); CFramebuffer* blurFramebufferWithDamage(float a, CRegion* damage, CFramebuffer& source); - void passCMUniforms(SShader&, const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription, + void passCMUniforms(SShader&, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1); - void passCMUniforms(SShader&, const NColorManagement::SImageDescription& imageDescription); + void passCMUniforms(SShader&, const NColorManagement::PImageDescription imageDescription); void renderTexturePrimitive(SP tex, const CBox& box); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); void renderRectInternal(const CBox&, const CHyprColor&, const SRectRenderData& data); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ee4f66a8..1aa85f15 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1515,6 +1515,7 @@ static const hdr_output_metadata NO_HDR_METADATA = {.hdmi_metadata_type1 = hdr_m static hdr_output_metadata createHDRMetadata(SImageDescription settings, SP monitor) { uint8_t eotf = 0; switch (settings.transferFunction) { + case CM_TRANSFER_FUNCTION_GAMMA22: case CM_TRANSFER_FUNCTION_SRGB: eotf = 0; break; // used to send primaries and luminances to AQ. ignored for now case CM_TRANSFER_FUNCTION_ST2084_PQ: eotf = 2; break; case CM_TRANSFER_FUNCTION_EXT_LINEAR: @@ -1527,9 +1528,11 @@ static hdr_output_metadata createHDRMetadata(SImageDescription settings, S const auto toNits = [](uint32_t value) { return sc(std::round(value)); }; const auto to16Bit = [](float value) { return sc(std::round(value * 50000)); }; - auto colorimetry = settings.primariesNameSet || settings.primaries == SPCPRimaries{} ? getPrimaries(settings.primariesNamed) : settings.primaries; + auto colorimetry = settings.getPrimaries(); auto luminances = settings.masteringLuminances.max > 0 ? settings.masteringLuminances : - SImageDescription::SPCMasteringLuminances{.min = monitor->minLuminance(), .max = monitor->maxLuminance(10000)}; + (settings.luminances != SImageDescription::SPCLuminances{} ? + SImageDescription::SPCMasteringLuminances{.min = settings.luminances.min, .max = settings.luminances.max} : + SImageDescription::SPCMasteringLuminances{.min = monitor->minLuminance(), .max = monitor->maxLuminance(10000)}); Log::logger->log(Log::TRACE, "ColorManagement primaries {},{} {},{} {},{} {},{}", colorimetry.red.x, colorimetry.red.y, colorimetry.green.x, colorimetry.green.y, colorimetry.blue.x, colorimetry.blue.y, colorimetry.white.x, colorimetry.white.y); @@ -1617,7 +1620,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { pMonitor->m_previousFSWindow.reset(); // trigger CTM update } Log::logger->log(Log::INFO, wantHDR ? "[CM] Updating HDR metadata from monitor" : "[CM] Restoring SDR mode"); - pMonitor->m_output->state->setHDRMetadata(wantHDR ? createHDRMetadata(pMonitor->m_imageDescription, pMonitor) : NO_HDR_METADATA); + pMonitor->m_output->state->setHDRMetadata(wantHDR ? createHDRMetadata(pMonitor->m_imageDescription->value(), pMonitor) : NO_HDR_METADATA); } pMonitor->m_needsHDRupdate = true; } @@ -1655,9 +1658,10 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { const auto FS_DESC = pMonitor->getFSImageDescription(); if (FS_DESC.has_value()) { Log::logger->log(Log::INFO, "[CM] Updating fullscreen CTM"); - pMonitor->m_noShaderCTM = true; - const auto mat = FS_DESC->getPrimaries().convertMatrix(pMonitor->m_imageDescription.getPrimaries()).mat(); - const std::array CTM = { + pMonitor->m_noShaderCTM = true; + auto conversion = FS_DESC.value()->getPrimaries()->convertMatrix(pMonitor->m_imageDescription->getPrimaries()); + const auto mat = conversion.mat(); + const std::array CTM = { mat[0][0], mat[0][1], mat[0][2], // mat[1][0], mat[1][1], mat[1][2], // mat[2][0], mat[2][1], mat[2][2], // diff --git a/src/render/shaders/glsl/border.frag b/src/render/shaders/glsl/border.frag index d93773fd..223b4b29 100644 --- a/src/render/shaders/glsl/border.frag +++ b/src/render/shaders/glsl/border.frag @@ -36,7 +36,7 @@ vec4 okLabAToSrgb(vec4 lab) { l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292, l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965), l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010 - ), CM_TRANSFER_FUNCTION_SRGB + ), CM_TRANSFER_FUNCTION_GAMMA22 ), lab[3]); }