1 // Copyright 2017 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
5 #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
6
7 #include "cc/paint/skia_paint_canvas.h"
8 #include "components/viz/common/resources/resource_format_utils.h"
9 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
10 #include "third_party/khronos/GLES2/gl2.h"
11 #include "third_party/khronos/GLES2/gl2ext.h"
12 #include "third_party/khronos/GLES3/gl3.h"
13 #include "third_party/skia/include/core/SkSurfaceProps.h"
14 #include "ui/gfx/color_space.h"
15
16 namespace blink {
17
18 namespace {
19
GetPrimaryID(CanvasColorSpace color_space)20 gfx::ColorSpace::PrimaryID GetPrimaryID(CanvasColorSpace color_space) {
21 gfx::ColorSpace::PrimaryID primary_id = gfx::ColorSpace::PrimaryID::BT709;
22 switch (color_space) {
23 case CanvasColorSpace::kSRGB:
24 case CanvasColorSpace::kLinearRGB:
25 primary_id = gfx::ColorSpace::PrimaryID::BT709;
26 break;
27 case CanvasColorSpace::kRec2020:
28 primary_id = gfx::ColorSpace::PrimaryID::BT2020;
29 break;
30 case CanvasColorSpace::kP3:
31 primary_id = gfx::ColorSpace::PrimaryID::SMPTEST432_1;
32 break;
33 }
34 return primary_id;
35 }
36
37 } // namespace
38
39 CanvasColorParams::CanvasColorParams() = default;
40
CanvasColorParams(CanvasColorSpace color_space,CanvasPixelFormat pixel_format,OpacityMode opacity_mode)41 CanvasColorParams::CanvasColorParams(CanvasColorSpace color_space,
42 CanvasPixelFormat pixel_format,
43 OpacityMode opacity_mode)
44 : color_space_(color_space),
45 pixel_format_(pixel_format),
46 opacity_mode_(opacity_mode) {}
47
CanvasColorParams(const SkImageInfo & info)48 CanvasColorParams::CanvasColorParams(const SkImageInfo& info)
49 : CanvasColorParams(info.refColorSpace(), info.colorType()) {}
50
GetSkColorSpaceForSkSurfaces() const51 sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpaceForSkSurfaces() const {
52 return GetSkColorSpace();
53 }
54
NeedsColorConversion(const CanvasColorParams & dest_color_params) const55 bool CanvasColorParams::NeedsColorConversion(
56 const CanvasColorParams& dest_color_params) const {
57 if ((color_space_ == dest_color_params.ColorSpace() &&
58 pixel_format_ == dest_color_params.PixelFormat()))
59 return false;
60 return true;
61 }
62
GetSkColorType() const63 SkColorType CanvasColorParams::GetSkColorType() const {
64 switch (pixel_format_) {
65 case CanvasPixelFormat::kF16:
66 return kRGBA_F16_SkColorType;
67 case CanvasPixelFormat::kRGBA8:
68 return kRGBA_8888_SkColorType;
69 case CanvasPixelFormat::kBGRA8:
70 return kBGRA_8888_SkColorType;
71 }
72 NOTREACHED();
73 return kN32_SkColorType;
74 }
75
GetSkAlphaType() const76 SkAlphaType CanvasColorParams::GetSkAlphaType() const {
77 return opacity_mode_ == kOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
78 }
79
GetSkSurfaceProps() const80 const SkSurfaceProps* CanvasColorParams::GetSkSurfaceProps() const {
81 static const SkSurfaceProps disable_lcd_props(0, kUnknown_SkPixelGeometry);
82 if (opacity_mode_ == kOpaque)
83 return nullptr;
84 return &disable_lcd_props;
85 }
86
BytesPerPixel() const87 uint8_t CanvasColorParams::BytesPerPixel() const {
88 return SkColorTypeBytesPerPixel(GetSkColorType());
89 }
90
GetSamplerGfxColorSpace() const91 gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const {
92 gfx::ColorSpace::PrimaryID primary_id = GetPrimaryID(color_space_);
93
94 // TODO(ccameron): This needs to take into account whether or not this texture
95 // will be sampled in linear or nonlinear space.
96 gfx::ColorSpace::TransferID transfer_id =
97 gfx::ColorSpace::TransferID::IEC61966_2_1;
98 if (pixel_format_ == CanvasPixelFormat::kF16)
99 transfer_id = gfx::ColorSpace::TransferID::LINEAR_HDR;
100
101 return gfx::ColorSpace(primary_id, transfer_id);
102 }
103
GetStorageGfxColorSpace() const104 gfx::ColorSpace CanvasColorParams::GetStorageGfxColorSpace() const {
105 gfx::ColorSpace::PrimaryID primary_id = GetPrimaryID(color_space_);
106
107 gfx::ColorSpace::TransferID transfer_id =
108 gfx::ColorSpace::TransferID::IEC61966_2_1;
109 // Only sRGB and e-sRGB use sRGB transfer function. Other canvas color spaces,
110 // i.e., linear-rgb, p3 and rec2020 use linear transfer function.
111 if (color_space_ != CanvasColorSpace::kSRGB)
112 transfer_id = gfx::ColorSpace::TransferID::LINEAR_HDR;
113
114 return gfx::ColorSpace(primary_id, transfer_id);
115 }
116
GetSkColorSpace() const117 sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
118 static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
119 kN32_SkColorType == kBGRA_8888_SkColorType,
120 "Unexpected kN32_SkColorType value.");
121 skcms_Matrix3x3 gamut = SkNamedGamut::kSRGB;
122 skcms_TransferFunction transferFn = SkNamedTransferFn::kSRGB;
123 switch (color_space_) {
124 case CanvasColorSpace::kSRGB:
125 break;
126 case CanvasColorSpace::kLinearRGB:
127 transferFn = SkNamedTransferFn::kLinear;
128 break;
129 case CanvasColorSpace::kRec2020:
130 gamut = SkNamedGamut::kRec2020;
131 transferFn = SkNamedTransferFn::kLinear;
132 break;
133 case CanvasColorSpace::kP3:
134 gamut = SkNamedGamut::kDCIP3;
135 transferFn = SkNamedTransferFn::kLinear;
136 break;
137 }
138 return SkColorSpace::MakeRGB(transferFn, gamut);
139 }
140
GetBufferFormat() const141 gfx::BufferFormat CanvasColorParams::GetBufferFormat() const {
142 switch (GetSkColorType()) {
143 case kRGBA_8888_SkColorType:
144 return gfx::BufferFormat::RGBA_8888;
145 case kBGRA_8888_SkColorType:
146 return gfx::BufferFormat::BGRA_8888;
147 case kRGBA_F16_SkColorType:
148 return gfx::BufferFormat::RGBA_F16;
149 default:
150 NOTREACHED();
151 }
152
153 return gfx::BufferFormat::RGBA_8888;
154 }
155
GLUnsizedInternalFormat() const156 GLenum CanvasColorParams::GLUnsizedInternalFormat() const {
157 // TODO(junov): try GL_RGB when opacity_mode_ == kOpaque
158 switch (GetSkColorType()) {
159 case kRGBA_8888_SkColorType:
160 return GL_RGBA;
161 case kBGRA_8888_SkColorType:
162 return GL_BGRA_EXT;
163 case kRGBA_F16_SkColorType:
164 return GL_RGBA;
165 default:
166 NOTREACHED();
167 }
168
169 return GL_RGBA;
170 }
171
GLSizedInternalFormat() const172 GLenum CanvasColorParams::GLSizedInternalFormat() const {
173 switch (GetSkColorType()) {
174 case kRGBA_8888_SkColorType:
175 return GL_RGBA8;
176 case kBGRA_8888_SkColorType:
177 return GL_BGRA8_EXT;
178 case kRGBA_F16_SkColorType:
179 return GL_RGBA16F;
180 default:
181 NOTREACHED();
182 }
183
184 return GL_RGBA8;
185 }
186
GLType() const187 GLenum CanvasColorParams::GLType() const {
188 switch (GetSkColorType()) {
189 case kRGBA_8888_SkColorType:
190 case kBGRA_8888_SkColorType:
191 return GL_UNSIGNED_BYTE;
192 case kRGBA_F16_SkColorType:
193 return GL_HALF_FLOAT_OES;
194 default:
195 NOTREACHED();
196 }
197
198 return GL_UNSIGNED_BYTE;
199 }
200
TransferableResourceFormat() const201 viz::ResourceFormat CanvasColorParams::TransferableResourceFormat() const {
202 return viz::GetResourceFormat(GetBufferFormat());
203 }
204
CanvasColorParams(const sk_sp<SkColorSpace> color_space,SkColorType color_type)205 CanvasColorParams::CanvasColorParams(const sk_sp<SkColorSpace> color_space,
206 SkColorType color_type) {
207 color_space_ = CanvasColorSpace::kSRGB;
208 pixel_format_ = GetNativeCanvasPixelFormat();
209 // When there is no color space information, the SkImage is in legacy mode and
210 // the color type is kRGBA8 canvas pixel format.
211 if (!color_space)
212 return;
213
214 // CanvasColorSpace::kSRGB covers sRGB and e-sRGB. We need to check for
215 // linear-rgb, rec2020 and p3.
216 if (SkColorSpace::Equals(color_space.get(),
217 SkColorSpace::MakeSRGB()->makeLinearGamma().get())) {
218 color_space_ = CanvasColorSpace::kLinearRGB;
219 } else if (SkColorSpace::Equals(
220 color_space.get(),
221 SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear,
222 SkNamedGamut::kRec2020)
223 .get())) {
224 color_space_ = CanvasColorSpace::kRec2020;
225 } else if (SkColorSpace::Equals(
226 color_space.get(),
227 SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear,
228 SkNamedGamut::kDCIP3)
229 .get())) {
230 color_space_ = CanvasColorSpace::kP3;
231 }
232
233 if (color_type == kRGBA_F16_SkColorType)
234 pixel_format_ = CanvasPixelFormat::kF16;
235 else if (color_type == kRGBA_8888_SkColorType)
236 pixel_format_ = CanvasPixelFormat::kRGBA8;
237 }
238
239 } // namespace blink
240