display_color_spaces.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Copyright 2020 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/display_color_spaces.h"
  5. #include "build/build_config.h"
  6. #include "build/chromeos_buildflags.h"
  7. #include "third_party/skia/include/core/SkColorSpace.h"
  8. namespace gfx {
  9. namespace {
  10. const ContentColorUsage kAllColorUsages[] = {
  11. ContentColorUsage::kSRGB,
  12. ContentColorUsage::kWideColorGamut,
  13. ContentColorUsage::kHDR,
  14. };
  15. gfx::BufferFormat DefaultBufferFormat() {
  16. // ChromeOS expects the default buffer format be BGRA_8888 in several places.
  17. // https://crbug.com/1057501, https://crbug.com/1073237
  18. #if BUILDFLAG(IS_CHROMEOS_ASH)
  19. return gfx::BufferFormat::BGRA_8888;
  20. #else
  21. return gfx::BufferFormat::RGBA_8888;
  22. #endif
  23. }
  24. size_t GetIndex(ContentColorUsage color_usage, bool needs_alpha) {
  25. switch (color_usage) {
  26. case ContentColorUsage::kSRGB:
  27. return 0 + needs_alpha;
  28. case ContentColorUsage::kWideColorGamut:
  29. return 2 + needs_alpha;
  30. case ContentColorUsage::kHDR:
  31. return 4 + needs_alpha;
  32. }
  33. }
  34. } // namespace
  35. DisplayColorSpaces::DisplayColorSpaces() {
  36. // TODO(crbug/1309228): Revert back to range-based for loops if possible
  37. for (size_t i = 0; i < kConfigCount; i++) {
  38. color_spaces_[i] = gfx::ColorSpace::CreateSRGB();
  39. buffer_formats_[i] = DefaultBufferFormat();
  40. }
  41. }
  42. DisplayColorSpaces::DisplayColorSpaces(const gfx::DisplayColorSpaces&) =
  43. default;
  44. DisplayColorSpaces& DisplayColorSpaces::operator=(
  45. const gfx::DisplayColorSpaces&) = default;
  46. DisplayColorSpaces::DisplayColorSpaces(const gfx::ColorSpace& c)
  47. : DisplayColorSpaces() {
  48. if (!c.IsValid())
  49. return;
  50. for (size_t i = 0; i < kConfigCount; i++) // NOLINT (modernize-loop-convert)
  51. color_spaces_[i] = c;
  52. }
  53. DisplayColorSpaces::DisplayColorSpaces(const ColorSpace& c, BufferFormat f) {
  54. for (size_t i = 0; i < kConfigCount; i++) {
  55. color_spaces_[i] = c.IsValid() ? c : gfx::ColorSpace::CreateSRGB();
  56. buffer_formats_[i] = f;
  57. }
  58. }
  59. void DisplayColorSpaces::SetOutputBufferFormats(
  60. gfx::BufferFormat buffer_format_no_alpha,
  61. gfx::BufferFormat buffer_format_needs_alpha) {
  62. for (const auto& color_usage : kAllColorUsages) {
  63. size_t i_no_alpha = GetIndex(color_usage, false);
  64. size_t i_needs_alpha = GetIndex(color_usage, true);
  65. buffer_formats_[i_no_alpha] = buffer_format_no_alpha;
  66. buffer_formats_[i_needs_alpha] = buffer_format_needs_alpha;
  67. }
  68. }
  69. void DisplayColorSpaces::SetOutputColorSpaceAndBufferFormat(
  70. ContentColorUsage color_usage,
  71. bool needs_alpha,
  72. const gfx::ColorSpace& color_space,
  73. gfx::BufferFormat buffer_format) {
  74. size_t i = GetIndex(color_usage, needs_alpha);
  75. color_spaces_[i] = color_space;
  76. buffer_formats_[i] = buffer_format;
  77. }
  78. ColorSpace DisplayColorSpaces::GetOutputColorSpace(
  79. ContentColorUsage color_usage,
  80. bool needs_alpha) const {
  81. return color_spaces_[GetIndex(color_usage, needs_alpha)];
  82. }
  83. BufferFormat DisplayColorSpaces::GetOutputBufferFormat(
  84. ContentColorUsage color_usage,
  85. bool needs_alpha) const {
  86. return buffer_formats_[GetIndex(color_usage, needs_alpha)];
  87. }
  88. gfx::ColorSpace DisplayColorSpaces::GetRasterColorSpace() const {
  89. return GetOutputColorSpace(ContentColorUsage::kHDR, false /* needs_alpha */);
  90. }
  91. gfx::ColorSpace DisplayColorSpaces::GetCompositingColorSpace(
  92. bool needs_alpha,
  93. ContentColorUsage color_usage) const {
  94. gfx::ColorSpace result = GetOutputColorSpace(color_usage, needs_alpha);
  95. if (!result.IsSuitableForBlending())
  96. result = gfx::ColorSpace::CreateExtendedSRGB();
  97. return result;
  98. }
  99. bool DisplayColorSpaces::SupportsHDR() const {
  100. return GetOutputColorSpace(ContentColorUsage::kHDR, false).IsHDR() ||
  101. GetOutputColorSpace(ContentColorUsage::kHDR, true).IsHDR();
  102. }
  103. SkColorSpacePrimaries DisplayColorSpaces::GetPrimaries() const {
  104. // TODO(https://crbug.com/1274220): Store this directly, rather than inferring
  105. // it from the raster color space.
  106. return GetRasterColorSpace().GetColorSpacePrimaries();
  107. }
  108. ColorSpace DisplayColorSpaces::GetScreenInfoColorSpace() const {
  109. return GetOutputColorSpace(ContentColorUsage::kHDR, false /* needs_alpha */);
  110. }
  111. void DisplayColorSpaces::ToStrings(
  112. std::vector<std::string>* out_names,
  113. std::vector<gfx::ColorSpace>* out_color_spaces,
  114. std::vector<gfx::BufferFormat>* out_buffer_formats) const {
  115. // The names of the configurations.
  116. const char* config_names[kConfigCount] = {
  117. "sRGB/no-alpha", "sRGB/alpha", "WCG/no-alpha",
  118. "WCG/alpha", "HDR/no-alpha", "HDR/alpha",
  119. };
  120. // Names for special configuration subsets (e.g, all sRGB, all WCG, etc).
  121. constexpr size_t kSpecialConfigCount = 5;
  122. const char* special_config_names[kSpecialConfigCount] = {
  123. "sRGB", "WCG", "SDR", "HDR", "all",
  124. };
  125. const size_t special_config_indices[kSpecialConfigCount][2] = {
  126. {0, 2}, {2, 4}, {0, 4}, {4, 6}, {0, 6},
  127. };
  128. // We don't want to take up 6 lines (one for each config) if we don't need to.
  129. // To avoid this, build up half-open intervals [i, j) which have the same
  130. // color space and buffer formats, and group them together. The above "special
  131. // configs" give groups that have a common name.
  132. size_t i = 0;
  133. size_t j = 0;
  134. while (i != kConfigCount) {
  135. // Keep growing the interval [i, j) until entry j is different, or past the
  136. // end.
  137. if (color_spaces_[i] == color_spaces_[j] &&
  138. buffer_formats_[i] == buffer_formats_[j] && j != kConfigCount) {
  139. j += 1;
  140. continue;
  141. }
  142. // Populate the name for the group from the "special config" names.
  143. std::string name;
  144. for (size_t k = 0; k < kSpecialConfigCount; ++k) {
  145. if (i == special_config_indices[k][0] &&
  146. j == special_config_indices[k][1]) {
  147. name = special_config_names[k];
  148. break;
  149. }
  150. }
  151. // If that didn't work, just list the configs.
  152. if (name.empty()) {
  153. for (size_t k = i; k < j; ++k) {
  154. name += std::string(config_names[k]);
  155. if (k != j - 1)
  156. name += ",";
  157. }
  158. }
  159. // Add an entry, and continue with the interval [j, j).
  160. out_names->push_back(name);
  161. out_buffer_formats->push_back(buffer_formats_[i]);
  162. out_color_spaces->push_back(color_spaces_[i]);
  163. i = j;
  164. };
  165. }
  166. bool DisplayColorSpaces::operator==(const DisplayColorSpaces& other) const {
  167. for (size_t i = 0; i < kConfigCount; ++i) {
  168. if (color_spaces_[i] != other.color_spaces_[i])
  169. return false;
  170. if (buffer_formats_[i] != other.buffer_formats_[i])
  171. return false;
  172. }
  173. if (sdr_max_luminance_nits_ != other.sdr_max_luminance_nits_)
  174. return false;
  175. if (hdr_max_luminance_relative_ != other.hdr_max_luminance_relative_)
  176. return false;
  177. return true;
  178. }
  179. bool DisplayColorSpaces::operator!=(const DisplayColorSpaces& other) const {
  180. return !(*this == other);
  181. }
  182. } // namespace gfx