| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_DISPLAY_DISPLAY_COLOR_MANAGER_H_ |
| #define ASH_DISPLAY_DISPLAY_COLOR_MANAGER_H_ |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "ash/ash_export.h" |
| #include "base/containers/flat_map.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/sequence_checker.h" |
| #include "third_party/skia/include/core/SkM44.h" |
| #include "ui/display/display_observer.h" |
| #include "ui/display/manager/display_configurator.h" |
| #include "ui/display/types/display_color_management.h" |
| #include "ui/display/types/display_constants.h" |
| |
| namespace base { |
| class SequencedTaskRunner; |
| } |
| |
| namespace display { |
| class DisplaySnapshot; |
| } // namespace display |
| |
| namespace ash { |
| |
| // An object that observes changes in display configuration applies any color |
| // calibration where needed. |
| class ASH_EXPORT DisplayColorManager |
| : public display::DisplayConfigurator::Observer, |
| public display::DisplayObserver { |
| public: |
| // The type of CRTC color transform matrix (CTM) support for the currently |
| // connected displays. |
| // WARNING: These values are persisted to logs. Entries should not be |
| // renumbered and numeric values should never be reused. |
| enum class DisplayCtmSupport { |
| // All connected displays don't support CRTC CTMs. |
| kNone = 0, |
| // Mixed support; some displays support CRTC CTMs while others don't. |
| kMixed = 1, |
| // All connected displays support CRTC CTMs. |
| kAll = 2, |
| kMaxValue = kAll, |
| }; |
| |
| explicit DisplayColorManager(display::DisplayConfigurator* configurator); |
| |
| DisplayColorManager(const DisplayColorManager&) = delete; |
| DisplayColorManager& operator=(const DisplayColorManager&) = delete; |
| |
| ~DisplayColorManager() override; |
| |
| DisplayCtmSupport displays_ctm_support() const { |
| return displays_ctm_support_; |
| } |
| |
| // Sets the given |color_matrix| on the display hardware of |display_id|, |
| // combining the given matrix with any available color calibration matrix for |
| // this display. This doesn't affect gamma or degamma values. |
| // Returns true if the hardware supports this operation and the matrix was |
| // successfully sent to the GPU. |
| bool SetDisplayColorMatrix(int64_t display_id, const SkM44& color_matrix); |
| |
| // Similar to the above but can be used when a display snapshot is known to |
| // the caller. |
| bool SetDisplayColorMatrix(const display::DisplaySnapshot* display_snapshot, |
| const SkM44& color_matrix); |
| |
| // display::DisplayConfigurator::Observer |
| void OnDisplayModeChanged( |
| const display::DisplayConfigurator::DisplayStateList& outputs) override; |
| void OnDisplayModeChangeFailed( |
| const display::DisplayConfigurator::DisplayStateList& displays, |
| display::MultipleDisplayState failed_new_state) override {} |
| |
| // display::DisplayObserver: |
| void OnDisplayRemoved(const display::Display& old_display) override; |
| |
| struct ColorCalibrationData { |
| ColorCalibrationData(); |
| ~ColorCalibrationData(); |
| |
| display::GammaCurve degamma_curve; |
| display::GammaCurve gamma_curve; |
| // Initialized to identity to reset color correction. |
| std::vector<float> correction_matrix; |
| }; |
| |
| protected: |
| virtual void FinishLoadCalibrationForDisplay( |
| int64_t display_id, |
| int64_t product_code, |
| bool has_color_correction_matrix, |
| display::DisplayConnectionType type, |
| const base::FilePath& path, |
| bool file_downloaded); |
| virtual void UpdateCalibrationData( |
| int64_t display_id, |
| int64_t product_code, |
| std::unique_ptr<ColorCalibrationData> data); |
| |
| private: |
| friend class DisplayColorManagerTest; |
| |
| void ApplyDisplayColorCalibration( |
| int64_t display_id, |
| const ColorCalibrationData& calibration_data); |
| |
| // Attempts to start requesting the ICC profile for |display|. Returns true if |
| // it was successful at initiating the request, false otherwise. |
| // TODO(jchinlee): Investigate if we need this return value, or if we can |
| // switch to a callback model. |
| bool LoadCalibrationForDisplay(const display::DisplaySnapshot* display); |
| |
| // Display-specific calibration methods. |
| // Look for VPD display profiles entry. |
| bool HasVpdDisplayProfilesEntry(int64_t product_code) const; |
| // Look for VPD-written calibration. |
| void QueryVpdForCalibration(int64_t display_id, |
| int64_t product_code, |
| bool has_color_correction_matrix, |
| display::DisplayConnectionType type); |
| void FinishQueryVpdForCalibration(int64_t display_id, |
| int64_t product_code, |
| bool has_color_correction_matrix, |
| display::DisplayConnectionType type, |
| const base::FilePath& expected_icc_path, |
| bool found_icc); |
| // Look for calibration for this display in Quirks. |
| void QueryQuirksForCalibration(int64_t display_id, |
| const std::string& display_name, |
| int64_t product_code, |
| bool has_color_correction_matrix, |
| display::DisplayConnectionType type); |
| |
| // Applies an empty color calibration data, potentially with a color |
| // matrix from |displays_color_matrix_map_| (if any for this display is |
| // available). This is needed in cases we fail to load ICC profiles for |
| // displays and we won't be getting any calibration data for them. We must |
| // reset their configuration because some drivers hold on to it across screen |
| // changes, https://crrev.com/1914343003. |
| void ResetDisplayColorCalibration(int64_t display_id); |
| |
| raw_ptr<display::DisplayConfigurator, ExperimentalAsh> configurator_; |
| |
| // This is a pre-allocated storage in order to avoid re-allocating the |
| // matrix array every time when converting a skia matrix to a matrix array. |
| std::vector<float> matrix_buffer_; |
| |
| // Contains a per display color transform matrix that can be post-multiplied |
| // by any available color calibration matrix for the corresponding display. |
| // The key is the display ID. |
| base::flat_map<int64_t, SkM44> displays_color_matrix_map_; |
| |
| // Maps a display's color calibration data by the display's product code as |
| // the key. |
| base::flat_map<int64_t, std::unique_ptr<ColorCalibrationData>> |
| calibration_map_; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; |
| |
| DisplayCtmSupport displays_ctm_support_; |
| |
| display::ScopedOptionalDisplayObserver display_observer_{this}; |
| |
| // Factory for callbacks. |
| base::WeakPtrFactory<DisplayColorManager> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_DISPLAY_DISPLAY_COLOR_MANAGER_H_ |