| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/canvas2d/CanvasRenderingContext2D.h" | 5 #include "modules/canvas2d/CanvasRenderingContext2D.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include "bindings/core/v8/V8BindingForCore.h" | 8 #include "bindings/core/v8/V8BindingForCore.h" |
| 9 #include "bindings/core/v8/V8BindingForTesting.h" | 9 #include "bindings/core/v8/V8BindingForTesting.h" |
| 10 #include "core/dom/Document.h" | 10 #include "core/dom/Document.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
| 37 #include "third_party/skia/include/core/SkColorSpaceXform.h" | 37 #include "third_party/skia/include/core/SkColorSpaceXform.h" |
| 38 #include "third_party/skia/include/core/SkImage.h" | 38 #include "third_party/skia/include/core/SkImage.h" |
| 39 #include "third_party/skia/include/core/SkSurface.h" | 39 #include "third_party/skia/include/core/SkSurface.h" |
| 40 #include "third_party/skia/include/core/SkSwizzle.h" | 40 #include "third_party/skia/include/core/SkSwizzle.h" |
| 41 | 41 |
| 42 using ::testing::Mock; | 42 using ::testing::Mock; |
| 43 | 43 |
| 44 namespace blink { | 44 namespace blink { |
| 45 | 45 |
| 46 namespace { | |
| 47 | |
| 48 gfx::ColorSpace AdobeRGBColorSpace() { | |
| 49 return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::ADOBE_RGB, | |
| 50 gfx::ColorSpace::TransferID::GAMMA22); | |
| 51 } | |
| 52 | |
| 53 } // namespace | |
| 54 | |
| 55 enum BitmapOpacity { kOpaqueBitmap, kTransparentBitmap }; | 46 enum BitmapOpacity { kOpaqueBitmap, kTransparentBitmap }; |
| 56 | 47 |
| 57 class FakeImageSource : public CanvasImageSource { | 48 class FakeImageSource : public CanvasImageSource { |
| 58 public: | 49 public: |
| 59 FakeImageSource(IntSize, BitmapOpacity); | 50 FakeImageSource(IntSize, BitmapOpacity); |
| 60 | 51 |
| 61 PassRefPtr<Image> GetSourceImageForCanvas(SourceImageStatus*, | 52 PassRefPtr<Image> GetSourceImageForCanvas(SourceImageStatus*, |
| 62 AccelerationHint, | 53 AccelerationHint, |
| 63 SnapshotReason, | 54 SnapshotReason, |
| 64 const FloatSize&) override; | 55 const FloatSize&) override; |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 CanvasElement().GetImageBuffer()->DisableAcceleration(); | 1054 CanvasElement().GetImageBuffer()->DisableAcceleration(); |
| 1064 EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); | 1055 EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); |
| 1065 | 1056 |
| 1066 context->fillRect(10, 10, 100, 100); | 1057 context->fillRect(10, 10, 100, 100); |
| 1067 | 1058 |
| 1068 EXPECT_EQ(0, GetCurrentGPUMemoryUsage()); | 1059 EXPECT_EQ(0, GetCurrentGPUMemoryUsage()); |
| 1069 EXPECT_EQ(0, GetGlobalGPUMemoryUsage()); | 1060 EXPECT_EQ(0, GetGlobalGPUMemoryUsage()); |
| 1070 EXPECT_EQ(0u, GetGlobalAcceleratedImageBufferCount()); | 1061 EXPECT_EQ(0u, GetGlobalAcceleratedImageBufferCount()); |
| 1071 } | 1062 } |
| 1072 | 1063 |
| 1073 TEST_F(CanvasRenderingContext2DTest, | |
| 1074 LegacyColorSpaceUsesGlobalTargetColorBehavior) { | |
| 1075 // Set the global target color space to something distinctly recognizable (not | |
| 1076 // srgb) | |
| 1077 gfx::ColorSpace saved_global_target_color_space = | |
| 1078 ColorBehavior::GlobalTargetColorSpace(); | |
| 1079 ColorBehavior::SetGlobalTargetColorSpaceForTesting(AdobeRGBColorSpace()); | |
| 1080 bool saved_color_correct_rendering_enabled = | |
| 1081 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | |
| 1082 | |
| 1083 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(false); | |
| 1084 CreateContext(kNonOpaque, "legacy-srgb"); | |
| 1085 ColorBehavior behavior = Context2d()->DrawImageColorBehavior(); | |
| 1086 EXPECT_TRUE(behavior.IsTransformToTargetColorSpace()); | |
| 1087 EXPECT_TRUE(ColorBehavior::GlobalTargetColorSpace() == | |
| 1088 behavior.TargetColorSpace()); | |
| 1089 | |
| 1090 // Restore global state to avoid interfering with other tests | |
| 1091 ColorBehavior::SetGlobalTargetColorSpaceForTesting( | |
| 1092 saved_global_target_color_space); | |
| 1093 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( | |
| 1094 saved_color_correct_rendering_enabled); | |
| 1095 } | |
| 1096 | |
| 1097 TEST_F(CanvasRenderingContext2DTest, | |
| 1098 LegacyColorSpaceUsesSRGBWhenColorCorrectRenderingEnabled) { | |
| 1099 // Set the global target color space to something distinctly recognizable (not | |
| 1100 // srgb) | |
| 1101 gfx::ColorSpace saved_global_target_color_space = | |
| 1102 ColorBehavior::GlobalTargetColorSpace(); | |
| 1103 ColorBehavior::SetGlobalTargetColorSpaceForTesting(AdobeRGBColorSpace()); | |
| 1104 bool saved_color_correct_rendering_enabled = | |
| 1105 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | |
| 1106 | |
| 1107 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(true); | |
| 1108 CreateContext(kNonOpaque, "legacy-srgb"); | |
| 1109 ColorBehavior behavior = Context2d()->DrawImageColorBehavior(); | |
| 1110 EXPECT_TRUE(behavior.IsTransformToTargetColorSpace()); | |
| 1111 EXPECT_TRUE(gfx::ColorSpace::CreateSRGB() == behavior.TargetColorSpace()); | |
| 1112 | |
| 1113 // Restore global state to avoid interfering with other tests | |
| 1114 ColorBehavior::SetGlobalTargetColorSpaceForTesting( | |
| 1115 saved_global_target_color_space); | |
| 1116 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( | |
| 1117 saved_color_correct_rendering_enabled); | |
| 1118 } | |
| 1119 | |
| 1120 TEST_F(CanvasRenderingContext2DTest, | |
| 1121 SRGBColorSpaceUsesTransformToSRGBColorBehavior) { | |
| 1122 // Set the global target color space to something distinctly recognizable (not | |
| 1123 // srgb) | |
| 1124 gfx::ColorSpace saved_global_target_color_space = | |
| 1125 ColorBehavior::GlobalTargetColorSpace(); | |
| 1126 ColorBehavior::SetGlobalTargetColorSpaceForTesting(AdobeRGBColorSpace()); | |
| 1127 | |
| 1128 CreateContext(kNonOpaque, "srgb"); | |
| 1129 ColorBehavior behavior = Context2d()->DrawImageColorBehavior(); | |
| 1130 EXPECT_TRUE(behavior.IsTransformToTargetColorSpace()); | |
| 1131 EXPECT_TRUE(gfx::ColorSpace::CreateSRGB() == behavior.TargetColorSpace()); | |
| 1132 | |
| 1133 // Restore global state to avoid interfering with other tests | |
| 1134 ColorBehavior::SetGlobalTargetColorSpaceForTesting( | |
| 1135 saved_global_target_color_space); | |
| 1136 } | |
| 1137 | |
| 1138 TEST_F(CanvasRenderingContext2DTest, | |
| 1139 LinearRGBColorSpaceUsesTransformToLinearSRGBColorBehavior) { | |
| 1140 // Set the global target color space to something distinctly recognizable (not | |
| 1141 // srgb) | |
| 1142 gfx::ColorSpace saved_global_target_color_space = | |
| 1143 ColorBehavior::GlobalTargetColorSpace(); | |
| 1144 ColorBehavior::SetGlobalTargetColorSpaceForTesting(AdobeRGBColorSpace()); | |
| 1145 | |
| 1146 CreateContext(kNonOpaque, "srgb", kLinearPixelMathEnabled); | |
| 1147 ColorBehavior behavior = Context2d()->DrawImageColorBehavior(); | |
| 1148 EXPECT_TRUE(behavior.IsTransformToTargetColorSpace()); | |
| 1149 EXPECT_TRUE(gfx::ColorSpace::CreateSCRGBLinear() == | |
| 1150 behavior.TargetColorSpace()); | |
| 1151 | |
| 1152 // Restore global state to avoid interfering with other tests | |
| 1153 ColorBehavior::SetGlobalTargetColorSpaceForTesting( | |
| 1154 saved_global_target_color_space); | |
| 1155 } | |
| 1156 | |
| 1157 enum class ColorSpaceConversion : uint8_t { | 1064 enum class ColorSpaceConversion : uint8_t { |
| 1158 NONE = 0, | 1065 NONE = 0, |
| 1159 DEFAULT_NOT_COLOR_CORRECTED = 1, | 1066 DEFAULT_NOT_COLOR_CORRECTED = 1, |
| 1160 DEFAULT_COLOR_CORRECTED = 2, | 1067 DEFAULT_COLOR_CORRECTED = 2, |
| 1161 SRGB = 3, | 1068 SRGB = 3, |
| 1162 LINEAR_RGB = 4, | 1069 LINEAR_RGB = 4, |
| 1163 | 1070 |
| 1164 LAST = LINEAR_RGB | 1071 LAST = LINEAR_RGB |
| 1165 }; | 1072 }; |
| 1166 | 1073 |
| 1167 static ImageBitmapOptions PrepareBitmapOptionsAndSetRuntimeFlags( | 1074 static ImageBitmapOptions PrepareBitmapOptionsAndSetRuntimeFlags( |
| 1168 const ColorSpaceConversion& color_space_conversion) { | 1075 const ColorSpaceConversion& color_space_conversion) { |
| 1169 // Set the color space conversion in ImageBitmapOptions | 1076 // Set the color space conversion in ImageBitmapOptions |
| 1170 ImageBitmapOptions options; | 1077 ImageBitmapOptions options; |
| 1171 static const Vector<String> kConversions = {"none", "default", "default", | 1078 static const Vector<String> kConversions = {"none", "default", "default", |
| 1172 "srgb", "linear-rgb"}; | 1079 "srgb", "linear-rgb"}; |
| 1173 options.setColorSpaceConversion( | 1080 options.setColorSpaceConversion( |
| 1174 kConversions[static_cast<uint8_t>(color_space_conversion)]); | 1081 kConversions[static_cast<uint8_t>(color_space_conversion)]); |
| 1175 | 1082 |
| 1176 // Set the runtime flags | 1083 // Set the runtime flags |
| 1177 bool flag = (color_space_conversion != | 1084 bool flag = (color_space_conversion != |
| 1178 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); | 1085 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); |
| 1179 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); | 1086 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); |
| 1180 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(flag); | 1087 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(flag); |
| 1181 RuntimeEnabledFeatures::setColorCorrectRenderingDefaultModeEnabled(!flag); | 1088 RuntimeEnabledFeatures::setColorCanvasExtensionsEnabled(true); |
| 1182 | |
| 1183 return options; | 1089 return options; |
| 1184 } | 1090 } |
| 1185 | 1091 |
| 1186 TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) { | 1092 TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) { |
| 1187 bool experimental_canvas_features_runtime_flag = | 1093 bool experimental_canvas_features_runtime_flag = |
| 1188 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); | 1094 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); |
| 1189 bool color_correct_rendering_runtime_flag = | 1095 bool color_correct_rendering_runtime_flag = |
| 1190 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | 1096 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
| 1191 bool color_correct_rendering_default_mode_runtime_flag = | 1097 bool color_canvas_extensions_flag = |
| 1192 RuntimeEnabledFeatures::colorCorrectRenderingDefaultModeEnabled(); | 1098 RuntimeEnabledFeatures::colorCanvasExtensionsEnabled(); |
| 1193 | 1099 |
| 1194 Persistent<HTMLCanvasElement> canvas = | 1100 Persistent<HTMLCanvasElement> canvas = |
| 1195 Persistent<HTMLCanvasElement>(CanvasElement()); | 1101 Persistent<HTMLCanvasElement>(CanvasElement()); |
| 1196 CanvasContextCreationAttributes attributes; | 1102 CanvasContextCreationAttributes attributes; |
| 1197 attributes.setAlpha(true); | 1103 attributes.setAlpha(true); |
| 1198 attributes.setColorSpace("srgb"); | 1104 attributes.setColorSpace("srgb"); |
| 1199 CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>( | 1105 CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>( |
| 1200 canvas->GetCanvasRenderingContext("2d", attributes)); | 1106 canvas->GetCanvasRenderingContext("2d", attributes)); |
| 1201 StringOrCanvasGradientOrCanvasPattern fill_style; | 1107 StringOrCanvasGradientOrCanvasPattern fill_style; |
| 1202 fill_style.setString("#FF0000"); | 1108 fill_style.setString("#FF0000"); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 | 1179 |
| 1274 int compare = std::memcmp(converted_pixel.get(), transformed_pixel.get(), | 1180 int compare = std::memcmp(converted_pixel.get(), transformed_pixel.get(), |
| 1275 image_info.bytesPerPixel()); | 1181 image_info.bytesPerPixel()); |
| 1276 ASSERT_EQ(compare, 0); | 1182 ASSERT_EQ(compare, 0); |
| 1277 } | 1183 } |
| 1278 | 1184 |
| 1279 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( | 1185 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( |
| 1280 experimental_canvas_features_runtime_flag); | 1186 experimental_canvas_features_runtime_flag); |
| 1281 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( | 1187 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( |
| 1282 color_correct_rendering_runtime_flag); | 1188 color_correct_rendering_runtime_flag); |
| 1283 RuntimeEnabledFeatures::setColorCorrectRenderingDefaultModeEnabled( | 1189 RuntimeEnabledFeatures::setColorCanvasExtensionsEnabled( |
| 1284 color_correct_rendering_default_mode_runtime_flag); | 1190 color_canvas_extensions_flag); |
| 1285 } | 1191 } |
| 1286 | 1192 |
| 1287 bool ConvertPixelsToColorSpaceAndPixelFormatForTest( | 1193 bool ConvertPixelsToColorSpaceAndPixelFormatForTest( |
| 1288 DOMArrayBufferView* data_array, | 1194 DOMArrayBufferView* data_array, |
| 1289 CanvasColorSpace src_color_space, | 1195 CanvasColorSpace src_color_space, |
| 1290 CanvasColorSpace dst_color_space, | 1196 CanvasColorSpace dst_color_space, |
| 1291 CanvasPixelFormat dst_pixel_format, | 1197 CanvasPixelFormat dst_pixel_format, |
| 1292 std::unique_ptr<uint8_t[]>& converted_pixels) { | 1198 std::unique_ptr<uint8_t[]>& converted_pixels) { |
| 1293 // Setting SkColorSpaceXform::apply parameters | 1199 // Setting SkColorSpaceXform::apply parameters |
| 1294 SkColorSpaceXform::ColorFormat src_color_format = | 1200 SkColorSpaceXform::ColorFormat src_color_format = |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1375 // This test verifies the correct behavior of putImageData member function in | 1281 // This test verifies the correct behavior of putImageData member function in |
| 1376 // color managed mode. | 1282 // color managed mode. |
| 1377 void TestPutImageDataOnCanvasWithColorSpaceSettings( | 1283 void TestPutImageDataOnCanvasWithColorSpaceSettings( |
| 1378 HTMLCanvasElement& canvas_element, | 1284 HTMLCanvasElement& canvas_element, |
| 1379 CanvasColorSpaceSettings canvas_colorspace_setting, | 1285 CanvasColorSpaceSettings canvas_colorspace_setting, |
| 1380 float color_tolerance) { | 1286 float color_tolerance) { |
| 1381 bool experimental_canvas_features_runtime_flag = | 1287 bool experimental_canvas_features_runtime_flag = |
| 1382 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); | 1288 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); |
| 1383 bool color_correct_rendering_runtime_flag = | 1289 bool color_correct_rendering_runtime_flag = |
| 1384 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | 1290 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
| 1291 bool color_canvas_extensions_flag = |
| 1292 RuntimeEnabledFeatures::colorCanvasExtensionsEnabled(); |
| 1385 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); | 1293 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); |
| 1386 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(true); | 1294 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(true); |
| 1295 RuntimeEnabledFeatures::setColorCanvasExtensionsEnabled(true); |
| 1387 | 1296 |
| 1388 bool test_passed = true; | 1297 bool test_passed = true; |
| 1389 unsigned num_image_data_color_spaces = 3; | 1298 unsigned num_image_data_color_spaces = 3; |
| 1390 CanvasColorSpace image_data_color_spaces[] = { | 1299 CanvasColorSpace image_data_color_spaces[] = { |
| 1391 kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace, | 1300 kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace, |
| 1392 }; | 1301 }; |
| 1393 | 1302 |
| 1394 unsigned num_image_data_storage_formats = 3; | 1303 unsigned num_image_data_storage_formats = 3; |
| 1395 ImageDataStorageFormat image_data_storage_formats[] = { | 1304 ImageDataStorageFormat image_data_storage_formats[] = { |
| 1396 kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat, | 1305 kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat, |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 } | 1448 } |
| 1540 } | 1449 } |
| 1541 } | 1450 } |
| 1542 delete[] u16_pixels; | 1451 delete[] u16_pixels; |
| 1543 delete[] f32_pixels; | 1452 delete[] f32_pixels; |
| 1544 | 1453 |
| 1545 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( | 1454 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( |
| 1546 experimental_canvas_features_runtime_flag); | 1455 experimental_canvas_features_runtime_flag); |
| 1547 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( | 1456 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( |
| 1548 color_correct_rendering_runtime_flag); | 1457 color_correct_rendering_runtime_flag); |
| 1458 RuntimeEnabledFeatures::setColorCanvasExtensionsEnabled( |
| 1459 color_canvas_extensions_flag); |
| 1549 } | 1460 } |
| 1550 | 1461 |
| 1551 TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnSRGBCanvas) { | 1462 TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnSRGBCanvas) { |
| 1552 TestPutImageDataOnCanvasWithColorSpaceSettings( | 1463 TestPutImageDataOnCanvasWithColorSpaceSettings( |
| 1553 CanvasElement(), CanvasColorSpaceSettings::CANVAS_SRGB, 0); | 1464 CanvasElement(), CanvasColorSpaceSettings::CANVAS_SRGB, 0); |
| 1554 } | 1465 } |
| 1555 | 1466 |
| 1556 TEST_F(CanvasRenderingContext2DTest, | 1467 TEST_F(CanvasRenderingContext2DTest, |
| 1557 ColorManagedPutImageDataOnLinearSRGBCanvas) { | 1468 ColorManagedPutImageDataOnLinearSRGBCanvas) { |
| 1558 TestPutImageDataOnCanvasWithColorSpaceSettings( | 1469 TestPutImageDataOnCanvasWithColorSpaceSettings( |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1639 | 1550 |
| 1640 // Wake up again, which should request a compositing update synchronously. | 1551 // Wake up again, which should request a compositing update synchronously. |
| 1641 GetDocument().GetPage()->SetVisibilityState(kPageVisibilityStateVisible, | 1552 GetDocument().GetPage()->SetVisibilityState(kPageVisibilityStateVisible, |
| 1642 false); | 1553 false); |
| 1643 EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED, | 1554 EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED, |
| 1644 layer->NeedsCompositingInputsUpdate()); | 1555 layer->NeedsCompositingInputsUpdate()); |
| 1645 RunUntilIdle(); // Clear task queue. | 1556 RunUntilIdle(); // Clear task queue. |
| 1646 } | 1557 } |
| 1647 | 1558 |
| 1648 } // namespace blink | 1559 } // namespace blink |
| OLD | NEW |