display_icc_profiles.cc 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gfx/mac/display_icc_profiles.h"
  5. #include "base/no_destructor.h"
  6. #include "base/notreached.h"
  7. #include "ui/gfx/icc_profile.h"
  8. namespace gfx {
  9. DisplayICCProfiles* DisplayICCProfiles::GetInstance() {
  10. static base::NoDestructor<DisplayICCProfiles> profiles;
  11. return profiles.get();
  12. }
  13. base::ScopedCFTypeRef<CFDataRef> DisplayICCProfiles::GetDataForColorSpace(
  14. const ColorSpace& color_space) {
  15. UpdateIfNeeded();
  16. base::ScopedCFTypeRef<CFDataRef> result;
  17. auto found = map_.find(color_space);
  18. if (found != map_.end())
  19. result = found->second;
  20. return result;
  21. }
  22. DisplayICCProfiles::DisplayICCProfiles() {
  23. CGDisplayRegisterReconfigurationCallback(
  24. DisplayICCProfiles::DisplayReconfigurationCallBack, this);
  25. }
  26. DisplayICCProfiles::~DisplayICCProfiles() {
  27. NOTREACHED();
  28. }
  29. void DisplayICCProfiles::UpdateIfNeeded() {
  30. if (!needs_update_)
  31. return;
  32. needs_update_ = false;
  33. map_.clear();
  34. // Always add Apple's sRGB profile.
  35. base::ScopedCFTypeRef<CFDataRef> srgb_icc(
  36. CGColorSpaceCopyICCData(CGColorSpaceCreateWithName(kCGColorSpaceSRGB)));
  37. map_[ColorSpace::CreateSRGB()] = srgb_icc;
  38. // Add the profiles for all active displays.
  39. uint32_t display_count = 0;
  40. CGError error = kCGErrorSuccess;
  41. error = CGGetActiveDisplayList(0, nullptr, &display_count);
  42. if (error != kCGErrorSuccess)
  43. return;
  44. if (!display_count)
  45. return;
  46. std::vector<CGDirectDisplayID> displays(display_count);
  47. error =
  48. CGGetActiveDisplayList(displays.size(), displays.data(), &display_count);
  49. if (error != kCGErrorSuccess)
  50. return;
  51. for (uint32_t i = 0; i < display_count; ++i) {
  52. base::ScopedCFTypeRef<CGColorSpaceRef> cg_color_space(
  53. CGDisplayCopyColorSpace(displays[i]));
  54. if (!cg_color_space)
  55. continue;
  56. base::ScopedCFTypeRef<CFDataRef> icc_data(
  57. CGColorSpaceCopyICCData(cg_color_space));
  58. if (!icc_data)
  59. continue;
  60. ICCProfile icc_profile = ICCProfile::FromData(CFDataGetBytePtr(icc_data),
  61. CFDataGetLength(icc_data));
  62. ColorSpace color_space = icc_profile.GetColorSpace();
  63. // If the ICC profile isn't accurately parametrically approximated, then
  64. // don't store its data (we will assign the best parametric fit to
  65. // IOSurfaces, and rely on the system compositor to do conversion to the
  66. // display profile).
  67. if (color_space.IsValid() && icc_profile.IsColorSpaceAccurate())
  68. map_[color_space] = icc_data;
  69. }
  70. }
  71. // static
  72. void DisplayICCProfiles::DisplayReconfigurationCallBack(
  73. CGDirectDisplayID display,
  74. CGDisplayChangeSummaryFlags flags,
  75. void* user_info) {
  76. DisplayICCProfiles* profiles =
  77. reinterpret_cast<DisplayICCProfiles*>(user_info);
  78. profiles->needs_update_ = true;
  79. }
  80. } // namespace gfx