| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/BaseRenderingContext2D.h" | 5 #include "modules/canvas2d/BaseRenderingContext2D.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ExceptionMessages.h" | 7 #include "bindings/core/v8/ExceptionMessages.h" |
| 8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
| 9 #include "core/css/cssom/CSSURLImageValue.h" | 9 #include "core/css/cssom/CSSURLImageValue.h" |
| 10 #include "core/css/parser/CSSParser.h" | 10 #include "core/css/parser/CSSParser.h" |
| 11 #include "core/dom/ArrayBufferViewHelpers.h" | 11 #include "core/dom/ArrayBufferViewHelpers.h" |
| 12 #include "core/dom/ExecutionContext.h" | 12 #include "core/dom/ExecutionContext.h" |
| 13 #include "core/frame/ImageBitmap.h" | 13 #include "core/frame/ImageBitmap.h" |
| 14 #include "core/html/HTMLCanvasElement.h" | 14 #include "core/html/HTMLCanvasElement.h" |
| 15 #include "core/html/HTMLImageElement.h" | 15 #include "core/html/HTMLImageElement.h" |
| 16 #include "core/html/HTMLVideoElement.h" | 16 #include "core/html/HTMLVideoElement.h" |
| 17 #include "core/html/ImageData.h" | 17 #include "core/html/ImageData.h" |
| 18 #include "core/offscreencanvas/OffscreenCanvas.h" | 18 #include "core/offscreencanvas/OffscreenCanvas.h" |
| 19 #include "core/svg/SVGImageElement.h" | 19 #include "core/svg/SVGImageElement.h" |
| 20 #include "modules/canvas2d/CanvasGradient.h" | 20 #include "modules/canvas2d/CanvasGradient.h" |
| 21 #include "modules/canvas2d/CanvasPattern.h" | 21 #include "modules/canvas2d/CanvasPattern.h" |
| 22 #include "modules/canvas2d/CanvasStyle.h" | 22 #include "modules/canvas2d/CanvasStyle.h" |
| 23 #include "modules/canvas2d/Path2D.h" | 23 #include "modules/canvas2d/Path2D.h" |
| 24 #include "platform/Histogram.h" | 24 #include "platform/Histogram.h" |
| 25 #include "platform/RuntimeEnabledFeatures.h" | 25 #include "platform/RuntimeEnabledFeatures.h" |
| 26 #include "platform/bindings/ScriptState.h" | 26 #include "platform/bindings/ScriptState.h" |
| 27 #include "platform/geometry/FloatQuad.h" | 27 #include "platform/geometry/FloatQuad.h" |
| 28 #include "platform/graphics/CanvasHeuristicParameters.h" |
| 28 #include "platform/graphics/Color.h" | 29 #include "platform/graphics/Color.h" |
| 29 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | |
| 30 #include "platform/graphics/Image.h" | 30 #include "platform/graphics/Image.h" |
| 31 #include "platform/graphics/ImageBuffer.h" | 31 #include "platform/graphics/ImageBuffer.h" |
| 32 #include "platform/graphics/StrokeData.h" | 32 #include "platform/graphics/StrokeData.h" |
| 33 #include "platform/graphics/paint/PaintCanvas.h" | 33 #include "platform/graphics/paint/PaintCanvas.h" |
| 34 #include "platform/graphics/paint/PaintFlags.h" | 34 #include "platform/graphics/paint/PaintFlags.h" |
| 35 #include "platform/graphics/skia/SkiaUtils.h" | 35 #include "platform/graphics/skia/SkiaUtils.h" |
| 36 #include "platform/wtf/CheckedNumeric.h" | 36 #include "platform/wtf/CheckedNumeric.h" |
| 37 | 37 |
| 38 namespace blink { | 38 namespace blink { |
| 39 | 39 |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 bool BaseRenderingContext2D::IsFullCanvasCompositeMode(SkBlendMode op) { | 597 bool BaseRenderingContext2D::IsFullCanvasCompositeMode(SkBlendMode op) { |
| 598 // See 4.8.11.1.3 Compositing | 598 // See 4.8.11.1.3 Compositing |
| 599 // CompositeSourceAtop and CompositeDestinationOut are not listed here as the | 599 // CompositeSourceAtop and CompositeDestinationOut are not listed here as the |
| 600 // platforms already implement the specification's behavior. | 600 // platforms already implement the specification's behavior. |
| 601 return op == SkBlendMode::kSrcIn || op == SkBlendMode::kSrcOut || | 601 return op == SkBlendMode::kSrcIn || op == SkBlendMode::kSrcOut || |
| 602 op == SkBlendMode::kDstIn || op == SkBlendMode::kDstATop; | 602 op == SkBlendMode::kDstIn || op == SkBlendMode::kDstATop; |
| 603 } | 603 } |
| 604 | 604 |
| 605 static bool IsPathExpensive(const Path& path) { | 605 static bool IsPathExpensive(const Path& path) { |
| 606 const SkPath& sk_path = path.GetSkPath(); | 606 const SkPath& sk_path = path.GetSkPath(); |
| 607 if (ExpensiveCanvasHeuristicParameters::kConcavePathsAreExpensive && | 607 if (CanvasHeuristicParameters::kConcavePathsAreExpensive && |
| 608 !sk_path.isConvex()) | 608 !sk_path.isConvex()) |
| 609 return true; | 609 return true; |
| 610 | 610 |
| 611 if (sk_path.countPoints() > | 611 if (sk_path.countPoints() > |
| 612 ExpensiveCanvasHeuristicParameters::kExpensivePathPointCount) | 612 CanvasHeuristicParameters::kExpensivePathPointCount) |
| 613 return true; | 613 return true; |
| 614 | 614 |
| 615 return false; | 615 return false; |
| 616 } | 616 } |
| 617 | 617 |
| 618 void BaseRenderingContext2D::DrawPathInternal( | 618 void BaseRenderingContext2D::DrawPathInternal( |
| 619 const Path& path, | 619 const Path& path, |
| 620 CanvasRenderingContext2DState::PaintType paint_type, | 620 CanvasRenderingContext2DState::PaintType paint_type, |
| 621 SkPath::FillType fill_type) { | 621 SkPath::FillType fill_type) { |
| 622 if (path.IsEmpty()) | 622 if (path.IsEmpty()) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 649 if (winding_rule_string == "nonzero") | 649 if (winding_rule_string == "nonzero") |
| 650 return SkPath::kWinding_FillType; | 650 return SkPath::kWinding_FillType; |
| 651 if (winding_rule_string == "evenodd") | 651 if (winding_rule_string == "evenodd") |
| 652 return SkPath::kEvenOdd_FillType; | 652 return SkPath::kEvenOdd_FillType; |
| 653 | 653 |
| 654 NOTREACHED(); | 654 NOTREACHED(); |
| 655 return SkPath::kEvenOdd_FillType; | 655 return SkPath::kEvenOdd_FillType; |
| 656 } | 656 } |
| 657 | 657 |
| 658 void BaseRenderingContext2D::fill(const String& winding_rule_string) { | 658 void BaseRenderingContext2D::fill(const String& winding_rule_string) { |
| 659 TrackDrawCall(kFillPath); | |
| 660 DrawPathInternal(path_, CanvasRenderingContext2DState::kFillPaintType, | 659 DrawPathInternal(path_, CanvasRenderingContext2DState::kFillPaintType, |
| 661 ParseWinding(winding_rule_string)); | 660 ParseWinding(winding_rule_string)); |
| 662 } | 661 } |
| 663 | 662 |
| 664 void BaseRenderingContext2D::fill(Path2D* dom_path, | 663 void BaseRenderingContext2D::fill(Path2D* dom_path, |
| 665 const String& winding_rule_string) { | 664 const String& winding_rule_string) { |
| 666 TrackDrawCall(kFillPath, dom_path); | |
| 667 DrawPathInternal(dom_path->GetPath(), | 665 DrawPathInternal(dom_path->GetPath(), |
| 668 CanvasRenderingContext2DState::kFillPaintType, | 666 CanvasRenderingContext2DState::kFillPaintType, |
| 669 ParseWinding(winding_rule_string)); | 667 ParseWinding(winding_rule_string)); |
| 670 } | 668 } |
| 671 | 669 |
| 672 void BaseRenderingContext2D::stroke() { | 670 void BaseRenderingContext2D::stroke() { |
| 673 TrackDrawCall(kStrokePath); | |
| 674 DrawPathInternal(path_, CanvasRenderingContext2DState::kStrokePaintType); | 671 DrawPathInternal(path_, CanvasRenderingContext2DState::kStrokePaintType); |
| 675 } | 672 } |
| 676 | 673 |
| 677 void BaseRenderingContext2D::stroke(Path2D* dom_path) { | 674 void BaseRenderingContext2D::stroke(Path2D* dom_path) { |
| 678 TrackDrawCall(kStrokePath, dom_path); | |
| 679 DrawPathInternal(dom_path->GetPath(), | 675 DrawPathInternal(dom_path->GetPath(), |
| 680 CanvasRenderingContext2DState::kStrokePaintType); | 676 CanvasRenderingContext2DState::kStrokePaintType); |
| 681 } | 677 } |
| 682 | 678 |
| 683 void BaseRenderingContext2D::fillRect(double x, | 679 void BaseRenderingContext2D::fillRect(double x, |
| 684 double y, | 680 double y, |
| 685 double width, | 681 double width, |
| 686 double height) { | 682 double height) { |
| 687 TrackDrawCall(kFillRect, nullptr, width, height); | |
| 688 if (!ValidateRectForCanvas(x, y, width, height)) | 683 if (!ValidateRectForCanvas(x, y, width, height)) |
| 689 return; | 684 return; |
| 690 | 685 |
| 691 if (!DrawingCanvas()) | 686 if (!DrawingCanvas()) |
| 692 return; | 687 return; |
| 693 | 688 |
| 694 SkRect rect = SkRect::MakeXYWH(x, y, width, height); | 689 SkRect rect = SkRect::MakeXYWH(x, y, width, height); |
| 695 Draw([&rect](PaintCanvas* c, const PaintFlags* flags) // draw lambda | 690 Draw([&rect](PaintCanvas* c, const PaintFlags* flags) // draw lambda |
| 696 { c->drawRect(rect, *flags); }, | 691 { c->drawRect(rect, *flags); }, |
| 697 [&rect, this](const SkIRect& clip_bounds) // overdraw test lambda | 692 [&rect, this](const SkIRect& clip_bounds) // overdraw test lambda |
| (...skipping 14 matching lines...) Expand all Loading... |
| 712 canvas->drawPath(path, *flags); | 707 canvas->drawPath(path, *flags); |
| 713 return; | 708 return; |
| 714 } | 709 } |
| 715 canvas->drawRect(rect, *flags); | 710 canvas->drawRect(rect, *flags); |
| 716 } | 711 } |
| 717 | 712 |
| 718 void BaseRenderingContext2D::strokeRect(double x, | 713 void BaseRenderingContext2D::strokeRect(double x, |
| 719 double y, | 714 double y, |
| 720 double width, | 715 double width, |
| 721 double height) { | 716 double height) { |
| 722 TrackDrawCall(kStrokeRect, nullptr, width, height); | |
| 723 if (!ValidateRectForCanvas(x, y, width, height)) | 717 if (!ValidateRectForCanvas(x, y, width, height)) |
| 724 return; | 718 return; |
| 725 | 719 |
| 726 if (!DrawingCanvas()) | 720 if (!DrawingCanvas()) |
| 727 return; | 721 return; |
| 728 | 722 |
| 729 SkRect rect = SkRect::MakeXYWH(x, y, width, height); | 723 SkRect rect = SkRect::MakeXYWH(x, y, width, height); |
| 730 FloatRect bounds = rect; | 724 FloatRect bounds = rect; |
| 731 InflateStrokeRect(bounds); | 725 InflateStrokeRect(bounds); |
| 732 Draw([&rect](PaintCanvas* c, const PaintFlags* flags) // draw lambda | 726 Draw([&rect](PaintCanvas* c, const PaintFlags* flags) // draw lambda |
| (...skipping 11 matching lines...) Expand all Loading... |
| 744 } | 738 } |
| 745 if (!GetState().IsTransformInvertible()) { | 739 if (!GetState().IsTransformInvertible()) { |
| 746 return; | 740 return; |
| 747 } | 741 } |
| 748 | 742 |
| 749 SkPath sk_path = path.GetSkPath(); | 743 SkPath sk_path = path.GetSkPath(); |
| 750 sk_path.setFillType(ParseWinding(winding_rule_string)); | 744 sk_path.setFillType(ParseWinding(winding_rule_string)); |
| 751 ModifiableState().ClipPath(sk_path, clip_antialiasing_); | 745 ModifiableState().ClipPath(sk_path, clip_antialiasing_); |
| 752 c->clipPath(sk_path, SkClipOp::kIntersect, | 746 c->clipPath(sk_path, SkClipOp::kIntersect, |
| 753 clip_antialiasing_ == kAntiAliased); | 747 clip_antialiasing_ == kAntiAliased); |
| 754 if (ExpensiveCanvasHeuristicParameters::kComplexClipsAreExpensive && | 748 if (CanvasHeuristicParameters::kComplexClipsAreExpensive && |
| 755 !sk_path.isRect(0) && HasImageBuffer()) { | 749 !sk_path.isRect(0) && HasImageBuffer()) { |
| 756 GetImageBuffer()->SetHasExpensiveOp(); | 750 GetImageBuffer()->SetHasExpensiveOp(); |
| 757 } | 751 } |
| 758 } | 752 } |
| 759 | 753 |
| 760 void BaseRenderingContext2D::clip(const String& winding_rule_string) { | 754 void BaseRenderingContext2D::clip(const String& winding_rule_string) { |
| 761 ClipInternal(path_, winding_rule_string); | 755 ClipInternal(path_, winding_rule_string); |
| 762 } | 756 } |
| 763 | 757 |
| 764 void BaseRenderingContext2D::clip(Path2D* dom_path, | 758 void BaseRenderingContext2D::clip(Path2D* dom_path, |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 dst_rect.Height() * dst_rect.Height() * y_scale_squared < | 1038 dst_rect.Height() * dst_rect.Height() * y_scale_squared < |
| 1045 src_rect.Height() * src_rect.Height(); | 1039 src_rect.Height() * src_rect.Height(); |
| 1046 } | 1040 } |
| 1047 | 1041 |
| 1048 void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c, | 1042 void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c, |
| 1049 CanvasImageSource* image_source, | 1043 CanvasImageSource* image_source, |
| 1050 Image* image, | 1044 Image* image, |
| 1051 const FloatRect& src_rect, | 1045 const FloatRect& src_rect, |
| 1052 const FloatRect& dst_rect, | 1046 const FloatRect& dst_rect, |
| 1053 const PaintFlags* flags) { | 1047 const PaintFlags* flags) { |
| 1054 if (image_source->IsSVGSource()) { | |
| 1055 TrackDrawCall(kDrawVectorImage, nullptr, dst_rect.Width(), | |
| 1056 dst_rect.Height()); | |
| 1057 } else { | |
| 1058 TrackDrawCall(kDrawBitmapImage, nullptr, dst_rect.Width(), | |
| 1059 dst_rect.Height()); | |
| 1060 } | |
| 1061 | |
| 1062 int initial_save_count = c->getSaveCount(); | 1048 int initial_save_count = c->getSaveCount(); |
| 1063 PaintFlags image_flags = *flags; | 1049 PaintFlags image_flags = *flags; |
| 1064 | 1050 |
| 1065 if (flags->getImageFilter()) { | 1051 if (flags->getImageFilter()) { |
| 1066 SkMatrix ctm = c->getTotalMatrix(); | 1052 SkMatrix ctm = c->getTotalMatrix(); |
| 1067 SkMatrix inv_ctm; | 1053 SkMatrix inv_ctm; |
| 1068 if (!ctm.invert(&inv_ctm)) { | 1054 if (!ctm.invert(&inv_ctm)) { |
| 1069 // There is an earlier check for invertibility, but the arithmetic | 1055 // There is an earlier check for invertibility, but the arithmetic |
| 1070 // in AffineTransform is not exactly identical, so it is possible | 1056 // in AffineTransform is not exactly identical, so it is possible |
| 1071 // for SkMatrix to find the transform to be non-invertible at this stage. | 1057 // for SkMatrix to find the transform to be non-invertible at this stage. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 DisableDeferral(kDisableDeferralDrawImageWithTextureBackedSourceImage); | 1178 DisableDeferral(kDisableDeferralDrawImageWithTextureBackedSourceImage); |
| 1193 | 1179 |
| 1194 ValidateStateStack(); | 1180 ValidateStateStack(); |
| 1195 | 1181 |
| 1196 WillDrawImage(image_source); | 1182 WillDrawImage(image_source); |
| 1197 | 1183 |
| 1198 ValidateStateStack(); | 1184 ValidateStateStack(); |
| 1199 | 1185 |
| 1200 // Heuristic for disabling acceleration based on anticipated texture upload | 1186 // Heuristic for disabling acceleration based on anticipated texture upload |
| 1201 // overhead. | 1187 // overhead. |
| 1202 // See comments in ExpensiveCanvasHeuristicParameters.h for explanation. | 1188 // See comments in CanvasHeuristicParameters.h for explanation. |
| 1203 ImageBuffer* buffer = GetImageBuffer(); | 1189 ImageBuffer* buffer = GetImageBuffer(); |
| 1204 if (buffer && buffer->IsAccelerated() && !image_source->IsAccelerated()) { | 1190 if (buffer && buffer->IsAccelerated() && !image_source->IsAccelerated()) { |
| 1205 float src_area = src_rect.Width() * src_rect.Height(); | 1191 float src_area = src_rect.Width() * src_rect.Height(); |
| 1206 if (src_area > ExpensiveCanvasHeuristicParameters:: | 1192 if (src_area > |
| 1207 kDrawImageTextureUploadHardSizeLimit) { | 1193 CanvasHeuristicParameters::kDrawImageTextureUploadHardSizeLimit) { |
| 1208 buffer->DisableAcceleration(); | 1194 buffer->DisableAcceleration(); |
| 1209 } else if (src_area > ExpensiveCanvasHeuristicParameters:: | 1195 } else if (src_area > CanvasHeuristicParameters:: |
| 1210 kDrawImageTextureUploadSoftSizeLimit) { | 1196 kDrawImageTextureUploadSoftSizeLimit) { |
| 1211 SkRect bounds = dst_rect; | 1197 SkRect bounds = dst_rect; |
| 1212 SkMatrix ctm = DrawingCanvas()->getTotalMatrix(); | 1198 SkMatrix ctm = DrawingCanvas()->getTotalMatrix(); |
| 1213 ctm.mapRect(&bounds); | 1199 ctm.mapRect(&bounds); |
| 1214 float dst_area = dst_rect.Width() * dst_rect.Height(); | 1200 float dst_area = dst_rect.Width() * dst_rect.Height(); |
| 1215 if (src_area > | 1201 if (src_area > |
| 1216 dst_area * ExpensiveCanvasHeuristicParameters:: | 1202 dst_area * CanvasHeuristicParameters:: |
| 1217 kDrawImageTextureUploadSoftSizeLimitScaleThreshold) { | 1203 kDrawImageTextureUploadSoftSizeLimitScaleThreshold) { |
| 1218 buffer->DisableAcceleration(); | 1204 buffer->DisableAcceleration(); |
| 1219 } | 1205 } |
| 1220 } | 1206 } |
| 1221 } | 1207 } |
| 1222 | 1208 |
| 1223 ValidateStateStack(); | 1209 ValidateStateStack(); |
| 1224 | 1210 |
| 1225 // TODO(xidachen): After collecting some data, come back and prune off | 1211 // TODO(xidachen): After collecting some data, come back and prune off |
| 1226 // the ones that is not needed. | 1212 // the ones that is not needed. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 { return RectContainsTransformedRect(dst_rect, clip_bounds); }, | 1321 { return RectContainsTransformedRect(dst_rect, clip_bounds); }, |
| 1336 dst_rect, CanvasRenderingContext2DState::kImagePaintType, | 1322 dst_rect, CanvasRenderingContext2DState::kImagePaintType, |
| 1337 image_source->IsOpaque() | 1323 image_source->IsOpaque() |
| 1338 ? CanvasRenderingContext2DState::kOpaqueImage | 1324 ? CanvasRenderingContext2DState::kOpaqueImage |
| 1339 : CanvasRenderingContext2DState::kNonOpaqueImage); | 1325 : CanvasRenderingContext2DState::kNonOpaqueImage); |
| 1340 | 1326 |
| 1341 ValidateStateStack(); | 1327 ValidateStateStack(); |
| 1342 | 1328 |
| 1343 bool is_expensive = false; | 1329 bool is_expensive = false; |
| 1344 | 1330 |
| 1345 if (ExpensiveCanvasHeuristicParameters::kSVGImageSourcesAreExpensive && | 1331 if (CanvasHeuristicParameters::kSVGImageSourcesAreExpensive && |
| 1346 image_source->IsSVGSource()) | 1332 image_source->IsSVGSource()) |
| 1347 is_expensive = true; | 1333 is_expensive = true; |
| 1348 | 1334 |
| 1349 if (image_size.Width() * image_size.Height() > | 1335 if (image_size.Width() * image_size.Height() > |
| 1350 Width() * Height() * | 1336 Width() * Height() * CanvasHeuristicParameters::kExpensiveImageSizeRatio) |
| 1351 ExpensiveCanvasHeuristicParameters::kExpensiveImageSizeRatio) | |
| 1352 is_expensive = true; | 1337 is_expensive = true; |
| 1353 | 1338 |
| 1354 if (is_expensive) { | 1339 if (is_expensive) { |
| 1355 ImageBuffer* buffer = GetImageBuffer(); | 1340 ImageBuffer* buffer = GetImageBuffer(); |
| 1356 if (buffer) | 1341 if (buffer) |
| 1357 buffer->SetHasExpensiveOp(); | 1342 buffer->SetHasExpensiveOp(); |
| 1358 } | 1343 } |
| 1359 | 1344 |
| 1360 if (OriginClean() && | 1345 if (OriginClean() && |
| 1361 WouldTaintOrigin(image_source, ExecutionContext::From(script_state))) | 1346 WouldTaintOrigin(image_source, ExecutionContext::From(script_state))) |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1882 // With source over, we need to certify that alpha == 0xFF for all pixels | 1867 // With source over, we need to certify that alpha == 0xFF for all pixels |
| 1883 if (image_type == CanvasRenderingContext2DState::kNonOpaqueImage) | 1868 if (image_type == CanvasRenderingContext2DState::kNonOpaqueImage) |
| 1884 return; | 1869 return; |
| 1885 if (alpha < 0xFF) | 1870 if (alpha < 0xFF) |
| 1886 return; | 1871 return; |
| 1887 } | 1872 } |
| 1888 | 1873 |
| 1889 GetImageBuffer()->WillOverwriteCanvas(); | 1874 GetImageBuffer()->WillOverwriteCanvas(); |
| 1890 } | 1875 } |
| 1891 | 1876 |
| 1892 void BaseRenderingContext2D::TrackDrawCall(DrawCallType call_type, | |
| 1893 Path2D* path2d, | |
| 1894 int width, | |
| 1895 int height) { | |
| 1896 if (!RuntimeEnabledFeatures:: | |
| 1897 enableCanvas2dDynamicRenderingModeSwitchingEnabled()) { | |
| 1898 // Rendering mode switching is disabled so no need to track the usage | |
| 1899 return; | |
| 1900 } | |
| 1901 | |
| 1902 usage_counters_.num_draw_calls[call_type]++; | |
| 1903 | |
| 1904 float bounding_rect_width = static_cast<float>(width); | |
| 1905 float bounding_rect_height = static_cast<float>(height); | |
| 1906 float bounding_rect_area = bounding_rect_width * bounding_rect_height; | |
| 1907 float bounding_rect_perimeter = | |
| 1908 (2.0 * bounding_rect_width) + (2.0 * bounding_rect_height); | |
| 1909 | |
| 1910 if (call_type == kFillText || call_type == kFillPath || | |
| 1911 call_type == kStrokeText || call_type == kStrokePath || | |
| 1912 call_type == kFillRect || call_type == kStrokeRect) { | |
| 1913 SkPath sk_path; | |
| 1914 if (path2d) { | |
| 1915 sk_path = path2d->GetPath().GetSkPath(); | |
| 1916 } else { | |
| 1917 sk_path = path_.GetSkPath(); | |
| 1918 } | |
| 1919 | |
| 1920 if (!(call_type == kFillRect || call_type == kStrokeRect || | |
| 1921 call_type == kDrawVectorImage || call_type == kDrawBitmapImage)) { | |
| 1922 // The correct width and height were not passed as parameters | |
| 1923 const SkRect& bounding_rect = sk_path.getBounds(); | |
| 1924 bounding_rect_width = static_cast<float>(std::abs(bounding_rect.width())); | |
| 1925 bounding_rect_height = | |
| 1926 static_cast<float>(std::abs(bounding_rect.height())); | |
| 1927 bounding_rect_area = bounding_rect_width * bounding_rect_height; | |
| 1928 bounding_rect_perimeter = | |
| 1929 2.0 * bounding_rect_width + 2.0 * bounding_rect_height; | |
| 1930 } | |
| 1931 | |
| 1932 if (call_type == kFillPath && | |
| 1933 sk_path.getConvexity() != SkPath::kConvex_Convexity) { | |
| 1934 usage_counters_.num_non_convex_fill_path_calls++; | |
| 1935 usage_counters_.non_convex_fill_path_area += bounding_rect_area; | |
| 1936 } | |
| 1937 | |
| 1938 usage_counters_.bounding_box_perimeter_draw_calls[call_type] += | |
| 1939 bounding_rect_perimeter; | |
| 1940 usage_counters_.bounding_box_area_draw_calls[call_type] += | |
| 1941 bounding_rect_area; | |
| 1942 | |
| 1943 CanvasStyle* canvas_style; | |
| 1944 if (call_type == kFillText || call_type == kFillPath || | |
| 1945 call_type == kFillRect) { | |
| 1946 canvas_style = GetState().FillStyle(); | |
| 1947 } else { | |
| 1948 canvas_style = GetState().StrokeStyle(); | |
| 1949 } | |
| 1950 | |
| 1951 CanvasGradient* gradient = canvas_style->GetCanvasGradient(); | |
| 1952 if (gradient) { | |
| 1953 switch (gradient->GetGradient()->GetType()) { | |
| 1954 case Gradient::Type::kLinear: | |
| 1955 usage_counters_.num_linear_gradients++; | |
| 1956 usage_counters_.bounding_box_area_fill_type | |
| 1957 [BaseRenderingContext2D::kLinearGradientFillType] += | |
| 1958 bounding_rect_area; | |
| 1959 break; | |
| 1960 case Gradient::Type::kRadial: | |
| 1961 usage_counters_.num_radial_gradients++; | |
| 1962 usage_counters_.bounding_box_area_fill_type | |
| 1963 [BaseRenderingContext2D::kRadialGradientFillType] += | |
| 1964 bounding_rect_area; | |
| 1965 break; | |
| 1966 default: | |
| 1967 NOTREACHED(); | |
| 1968 } | |
| 1969 } else if (canvas_style->GetCanvasPattern()) { | |
| 1970 usage_counters_.num_patterns++; | |
| 1971 usage_counters_.bounding_box_area_fill_type | |
| 1972 [BaseRenderingContext2D::kPatternFillType] += bounding_rect_area; | |
| 1973 } else { | |
| 1974 usage_counters_.bounding_box_area_fill_type | |
| 1975 [BaseRenderingContext2D::kColorFillType] += bounding_rect_area; | |
| 1976 } | |
| 1977 } | |
| 1978 | |
| 1979 if (call_type == kDrawVectorImage || call_type == kDrawBitmapImage) { | |
| 1980 usage_counters_.bounding_box_perimeter_draw_calls[call_type] += | |
| 1981 bounding_rect_perimeter; | |
| 1982 usage_counters_.bounding_box_area_draw_calls[call_type] += | |
| 1983 bounding_rect_area; | |
| 1984 } | |
| 1985 | |
| 1986 if (call_type == kFillText || call_type == kFillPath || | |
| 1987 call_type == kStrokeText || call_type == kStrokePath || | |
| 1988 call_type == kFillRect || call_type == kStrokeRect || | |
| 1989 call_type == kDrawVectorImage || call_type == kDrawBitmapImage) { | |
| 1990 if (GetState().ShadowBlur() > 0.0 && | |
| 1991 SkColorGetA(GetState().ShadowColor()) > 0) { | |
| 1992 usage_counters_.num_blurred_shadows++; | |
| 1993 usage_counters_.bounding_box_area_times_shadow_blur_squared += | |
| 1994 bounding_rect_area * GetState().ShadowBlur() * | |
| 1995 GetState().ShadowBlur(); | |
| 1996 usage_counters_.bounding_box_perimeter_times_shadow_blur_squared += | |
| 1997 bounding_rect_perimeter * GetState().ShadowBlur() * | |
| 1998 GetState().ShadowBlur(); | |
| 1999 } | |
| 2000 } | |
| 2001 | |
| 2002 if (GetState().HasComplexClip()) { | |
| 2003 usage_counters_.num_draw_with_complex_clips++; | |
| 2004 } | |
| 2005 | |
| 2006 if (StateHasFilter()) { | |
| 2007 usage_counters_.num_filters++; | |
| 2008 } | |
| 2009 } | |
| 2010 | |
| 2011 const BaseRenderingContext2D::UsageCounters& | 1877 const BaseRenderingContext2D::UsageCounters& |
| 2012 BaseRenderingContext2D::GetUsage() { | 1878 BaseRenderingContext2D::GetUsage() { |
| 2013 return usage_counters_; | 1879 return usage_counters_; |
| 2014 } | 1880 } |
| 2015 | 1881 |
| 2016 DEFINE_TRACE(BaseRenderingContext2D) { | 1882 DEFINE_TRACE(BaseRenderingContext2D) { |
| 2017 visitor->Trace(state_stack_); | 1883 visitor->Trace(state_stack_); |
| 2018 } | 1884 } |
| 2019 | 1885 |
| 2020 BaseRenderingContext2D::UsageCounters::UsageCounters() | 1886 BaseRenderingContext2D::UsageCounters::UsageCounters() |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2034 bounding_box_perimeter_times_shadow_blur_squared(0.0f), | 1900 bounding_box_perimeter_times_shadow_blur_squared(0.0f), |
| 2035 num_filters(0), | 1901 num_filters(0), |
| 2036 num_get_image_data_calls(0), | 1902 num_get_image_data_calls(0), |
| 2037 area_get_image_data_calls(0.0), | 1903 area_get_image_data_calls(0.0), |
| 2038 num_put_image_data_calls(0), | 1904 num_put_image_data_calls(0), |
| 2039 area_put_image_data_calls(0.0), | 1905 area_put_image_data_calls(0.0), |
| 2040 num_clear_rect_calls(0), | 1906 num_clear_rect_calls(0), |
| 2041 num_draw_focus_calls(0), | 1907 num_draw_focus_calls(0), |
| 2042 num_frames_since_reset(0) {} | 1908 num_frames_since_reset(0) {} |
| 2043 | 1909 |
| 2044 float BaseRenderingContext2D::EstimateRenderingCost( | |
| 2045 ExpensiveCanvasHeuristicParameters::RenderingModeCostIndex index) const { | |
| 2046 float basic_cost_of_draw_calls = | |
| 2047 ExpensiveCanvasHeuristicParameters::kFillRectFixedCost[index] * | |
| 2048 usage_counters_.num_draw_calls[BaseRenderingContext2D::kFillRect] + | |
| 2049 ExpensiveCanvasHeuristicParameters::kFillConvexPathFixedCost[index] * | |
| 2050 (usage_counters_.num_draw_calls[BaseRenderingContext2D::kFillPath] - | |
| 2051 usage_counters_.num_non_convex_fill_path_calls) + | |
| 2052 ExpensiveCanvasHeuristicParameters::kFillNonConvexPathFixedCost[index] * | |
| 2053 usage_counters_.num_non_convex_fill_path_calls + | |
| 2054 ExpensiveCanvasHeuristicParameters::kFillTextFixedCost[index] * | |
| 2055 usage_counters_.num_draw_calls[BaseRenderingContext2D::kFillText] + | |
| 2056 | |
| 2057 ExpensiveCanvasHeuristicParameters::kStrokeRectFixedCost[index] * | |
| 2058 usage_counters_.num_draw_calls[BaseRenderingContext2D::kStrokeRect] + | |
| 2059 ExpensiveCanvasHeuristicParameters::kStrokePathFixedCost[index] * | |
| 2060 usage_counters_.num_draw_calls[BaseRenderingContext2D::kStrokePath] + | |
| 2061 ExpensiveCanvasHeuristicParameters::kStrokeTextFixedCost[index] * | |
| 2062 usage_counters_.num_draw_calls[BaseRenderingContext2D::kStrokeText] + | |
| 2063 | |
| 2064 ExpensiveCanvasHeuristicParameters::kFillRectVariableCostPerArea[index] * | |
| 2065 usage_counters_ | |
| 2066 .bounding_box_area_draw_calls[BaseRenderingContext2D::kFillRect] + | |
| 2067 ExpensiveCanvasHeuristicParameters::kFillConvexPathVariableCostPerArea | |
| 2068 [index] * | |
| 2069 (usage_counters_.bounding_box_area_draw_calls | |
| 2070 [BaseRenderingContext2D::kFillPath] - | |
| 2071 usage_counters_.non_convex_fill_path_area) + | |
| 2072 ExpensiveCanvasHeuristicParameters::kFillNonConvexPathVariableCostPerArea | |
| 2073 [index] * | |
| 2074 usage_counters_.non_convex_fill_path_area + | |
| 2075 ExpensiveCanvasHeuristicParameters::kFillTextVariableCostPerArea[index] * | |
| 2076 usage_counters_ | |
| 2077 .bounding_box_area_draw_calls[BaseRenderingContext2D::kFillText] + | |
| 2078 | |
| 2079 ExpensiveCanvasHeuristicParameters::kStrokeRectVariableCostPerArea | |
| 2080 [index] * | |
| 2081 usage_counters_.bounding_box_area_draw_calls | |
| 2082 [BaseRenderingContext2D::kStrokeRect] + | |
| 2083 ExpensiveCanvasHeuristicParameters::kStrokePathVariableCostPerArea | |
| 2084 [index] * | |
| 2085 usage_counters_.bounding_box_area_draw_calls | |
| 2086 [BaseRenderingContext2D::kStrokePath] + | |
| 2087 ExpensiveCanvasHeuristicParameters::kStrokeTextVariableCostPerArea | |
| 2088 [index] * | |
| 2089 usage_counters_.bounding_box_area_draw_calls | |
| 2090 [BaseRenderingContext2D::kStrokeText] + | |
| 2091 | |
| 2092 ExpensiveCanvasHeuristicParameters::kPutImageDataFixedCost[index] * | |
| 2093 usage_counters_.num_put_image_data_calls + | |
| 2094 ExpensiveCanvasHeuristicParameters::kPutImageDataVariableCostPerArea | |
| 2095 [index] * | |
| 2096 usage_counters_.area_put_image_data_calls + | |
| 2097 | |
| 2098 ExpensiveCanvasHeuristicParameters::kDrawSVGImageFixedCost[index] * | |
| 2099 usage_counters_ | |
| 2100 .num_draw_calls[BaseRenderingContext2D::kDrawVectorImage] + | |
| 2101 ExpensiveCanvasHeuristicParameters::kDrawPNGImageFixedCost[index] * | |
| 2102 usage_counters_ | |
| 2103 .num_draw_calls[BaseRenderingContext2D::kDrawBitmapImage] + | |
| 2104 | |
| 2105 ExpensiveCanvasHeuristicParameters::kDrawSVGImageVariableCostPerArea | |
| 2106 [index] * | |
| 2107 usage_counters_.bounding_box_area_draw_calls | |
| 2108 [BaseRenderingContext2D::kDrawVectorImage] + | |
| 2109 ExpensiveCanvasHeuristicParameters::kDrawPNGImageVariableCostPerArea | |
| 2110 [index] * | |
| 2111 usage_counters_.bounding_box_area_draw_calls | |
| 2112 [BaseRenderingContext2D::kDrawBitmapImage]; | |
| 2113 | |
| 2114 float fill_type_adjustment = | |
| 2115 ExpensiveCanvasHeuristicParameters::kPatternFillTypeFixedCost[index] * | |
| 2116 usage_counters_.num_patterns + | |
| 2117 ExpensiveCanvasHeuristicParameters::kLinearGradientFillTypeFixedCost | |
| 2118 [index] * | |
| 2119 usage_counters_.num_linear_gradients + | |
| 2120 ExpensiveCanvasHeuristicParameters::kRadialGradientFillTypeFixedCost | |
| 2121 [index] * | |
| 2122 usage_counters_.num_radial_gradients + | |
| 2123 | |
| 2124 ExpensiveCanvasHeuristicParameters::kPatternFillTypeVariableCostPerArea | |
| 2125 [index] * | |
| 2126 usage_counters_.bounding_box_area_fill_type | |
| 2127 [BaseRenderingContext2D::kPatternFillType] + | |
| 2128 ExpensiveCanvasHeuristicParameters::kLinearGradientFillVariableCostPerArea | |
| 2129 [index] * | |
| 2130 usage_counters_.bounding_box_area_fill_type | |
| 2131 [BaseRenderingContext2D::kLinearGradientFillType] + | |
| 2132 ExpensiveCanvasHeuristicParameters::kRadialGradientFillVariableCostPerArea | |
| 2133 [index] * | |
| 2134 usage_counters_.bounding_box_area_fill_type | |
| 2135 [BaseRenderingContext2D::kRadialGradientFillType]; | |
| 2136 | |
| 2137 float shadow_adjustment = | |
| 2138 ExpensiveCanvasHeuristicParameters::kShadowFixedCost[index] * | |
| 2139 usage_counters_.num_blurred_shadows + | |
| 2140 ExpensiveCanvasHeuristicParameters:: | |
| 2141 kShadowVariableCostPerAreaTimesShadowBlurSquared[index] * | |
| 2142 usage_counters_.bounding_box_area_times_shadow_blur_squared; | |
| 2143 | |
| 2144 return basic_cost_of_draw_calls + fill_type_adjustment + shadow_adjustment; | |
| 2145 } | |
| 2146 | |
| 2147 } // namespace blink | 1910 } // namespace blink |
| OLD | NEW |