summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc168
1 files changed, 108 insertions, 60 deletions
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
index 05291896076..2af7de9bf05 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
@@ -5,8 +5,8 @@
#include "third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h"
#include "base/metrics/histogram_functions.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/bindings/modules/v8/offscreen_rendering_context.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
@@ -34,6 +34,8 @@ namespace {
const size_t kHardMaxCachedFonts = 250;
const size_t kMaxCachedFonts = 25;
const float kUMASampleProbability = 0.01;
+// Max delay to fire context lost for context in iframes.
+static const unsigned kMaxIframeContextLoseDelay = 100;
class OffscreenFontCache {
public:
@@ -84,8 +86,6 @@ CanvasRenderingContext* OffscreenCanvasRenderingContext2D::Factory::Create(
MakeGarbageCollected<OffscreenCanvasRenderingContext2D>(
static_cast<OffscreenCanvas*>(host), attrs);
DCHECK(rendering_context);
- rendering_context->RecordUKMCanvasRenderingAPI(
- CanvasRenderingContext::CanvasRenderingAPI::k2D);
return rendering_context;
}
@@ -95,15 +95,17 @@ OffscreenCanvasRenderingContext2D::~OffscreenCanvasRenderingContext2D() =
OffscreenCanvasRenderingContext2D::OffscreenCanvasRenderingContext2D(
OffscreenCanvas* canvas,
const CanvasContextCreationAttributesCore& attrs)
- : CanvasRenderingContext(canvas, attrs),
- random_generator_((uint32_t)base::RandUint64()),
+ : CanvasRenderingContext(canvas, attrs, CanvasRenderingAPI::k2D),
+ random_generator_(static_cast<uint32_t>(base::RandUint64())),
bernoulli_distribution_(kUMASampleProbability),
color_params_(attrs.color_space, attrs.pixel_format, attrs.alpha) {
+ identifiability_study_helper_.SetExecutionContext(
+ canvas->GetTopExecutionContext());
is_valid_size_ = IsValidImageSize(Host()->Size());
// Clear the background transparent or opaque.
if (IsCanvas2DBufferValid())
- DidDraw();
+ DidDraw(CanvasPerformanceMonitor::DrawType::kOther);
ExecutionContext* execution_context = canvas->GetTopExecutionContext();
if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
@@ -190,11 +192,15 @@ CanvasResourceProvider*
OffscreenCanvasRenderingContext2D::GetCanvasResourceProvider() const {
return Host()->ResourceProvider();
}
+
void OffscreenCanvasRenderingContext2D::Reset() {
Host()->DiscardResourceProvider();
BaseRenderingContext2D::reset();
// Because the host may have changed to a zero size
is_valid_size_ = IsValidImageSize(Host()->Size());
+ // We must resize the damage rect to avoid a potentially larger damage than
+ // actual canvas size. See: crbug.com/1227165
+ dirty_rect_for_commit_ = SkIRect::MakeWH(Width(), Height());
}
scoped_refptr<CanvasResource>
@@ -222,6 +228,11 @@ bool OffscreenCanvasRenderingContext2D::PushFrame() {
return ret;
}
+CanvasRenderingContextHost*
+OffscreenCanvasRenderingContext2D::GetCanvasRenderingContextHost() {
+ return Host();
+}
+
ImageBitmap* OffscreenCanvasRenderingContext2D::TransferToImageBitmap(
ScriptState* script_state) {
WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmap2D;
@@ -252,8 +263,6 @@ scoped_refptr<StaticBitmapImage> OffscreenCanvasRenderingContext2D::GetImage() {
return image;
}
-#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
V8RenderingContext* OffscreenCanvasRenderingContext2D::AsV8RenderingContext() {
return nullptr;
}
@@ -263,15 +272,6 @@ OffscreenCanvasRenderingContext2D::AsV8OffscreenRenderingContext() {
return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}
-#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
-void OffscreenCanvasRenderingContext2D::SetOffscreenCanvasGetContextResult(
- OffscreenRenderingContext& result) {
- result.SetOffscreenCanvasRenderingContext2D(this);
-}
-
-#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
-
bool OffscreenCanvasRenderingContext2D::ParseColorOrCurrentColor(
Color& color,
const String& color_string) const {
@@ -290,22 +290,17 @@ cc::PaintCanvas* OffscreenCanvasRenderingContext2D::GetPaintCanvas() const {
return GetCanvasResourceProvider()->Canvas();
}
-void OffscreenCanvasRenderingContext2D::DidDraw() {
- dirty_rect_for_commit_.setWH(Width(), Height());
- Host()->DidDraw();
- if (GetCanvasResourceProvider() && GetCanvasResourceProvider()->needs_flush())
- FinalizeFrame();
-}
-
-void OffscreenCanvasRenderingContext2D::DidDraw(const SkIRect& dirty_rect) {
+cc::PaintCanvas* OffscreenCanvasRenderingContext2D::GetPaintCanvasForDraw(
+ const SkIRect& dirty_rect,
+ CanvasPerformanceMonitor::DrawType draw_type) {
+ if (!is_valid_size_ || !GetCanvasResourceProvider())
+ return nullptr;
dirty_rect_for_commit_.join(dirty_rect);
- Host()->DidDraw(SkRect::Make(dirty_rect_for_commit_));
+ GetCanvasPerformanceMonitor().DidDraw(draw_type);
+ Host()->DidDraw(dirty_rect_for_commit_);
if (GetCanvasResourceProvider() && GetCanvasResourceProvider()->needs_flush())
FinalizeFrame();
-}
-
-bool OffscreenCanvasRenderingContext2D::StateHasFilter() {
- return GetState().HasFilterForOffscreenCanvas(Host()->Size(), this);
+ return GetCanvasResourceProvider()->Canvas();
}
sk_sp<PaintFilter> OffscreenCanvasRenderingContext2D::StateGetFilter() {
@@ -327,7 +322,19 @@ void OffscreenCanvasRenderingContext2D::ValidateStateStackWithCanvas(
}
bool OffscreenCanvasRenderingContext2D::isContextLost() const {
- return false;
+ return context_lost_mode_ != kNotLostContext;
+}
+
+void OffscreenCanvasRenderingContext2D::LoseContext(LostContextMode lost_mode) {
+ if (context_lost_mode_ != kNotLostContext)
+ return;
+ context_lost_mode_ = lost_mode;
+ if (context_lost_mode_ == kSyntheticLostContext && Host()) {
+ Host()->DiscardResourceProvider();
+ }
+ uint32_t delay = base::RandInt(1, kMaxIframeContextLoseDelay);
+ dispatch_context_lost_event_timer_.StartOneShot(
+ base::TimeDelta::FromMilliseconds(delay), FROM_HERE);
}
bool OffscreenCanvasRenderingContext2D::IsPaintable() const {
@@ -399,8 +406,10 @@ String OffscreenCanvasRenderingContext2D::font() const {
void OffscreenCanvasRenderingContext2D::setFont(const String& new_font) {
if (GetState().HasRealizedFont() && new_font == GetState().UnparsedFont())
return;
- identifiability_study_helper_.MaybeUpdateBuilder(
- CanvasOps::kSetFont, IdentifiabilityBenignStringToken(new_font));
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ CanvasOps::kSetFont, IdentifiabilityBenignStringToken(new_font));
+ }
base::TimeTicks start_time = base::TimeTicks::Now();
OffscreenFontCache& font_cache = GetOffscreenFontCache();
@@ -410,21 +419,10 @@ void OffscreenCanvasRenderingContext2D::setFont(const String& new_font) {
GetState().SetFont(*cached_font, Host()->GetFontSelector());
} else {
auto* style =
- MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);
+ CSSParser::ParseFont(new_font, Host()->GetTopExecutionContext());
if (!style)
return;
- CSSParser::ParseValue(style, CSSPropertyID::kFont, new_font, true,
- Host()->GetTopExecutionContext());
-
- // According to
- // http://lists.w3.org/Archives/Public/public-html/2009Jul/0947.html,
- // the "inherit", "initial" and "unset" values must be ignored.
- const CSSValue* font_value =
- style->GetPropertyCSSValue(CSSPropertyID::kFontSize);
- if (!font_value || font_value->IsCSSWideKeyword())
- return;
-
FontDescription desc =
FontStyleResolver::ComputeFont(*style, Host()->GetFontSelector());
@@ -434,8 +432,8 @@ void OffscreenCanvasRenderingContext2D::setFont(const String& new_font) {
GetState().SetUnparsedFont(new_font);
if (bernoulli_distribution_(random_generator_)) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
- base::UmaHistogramMicrosecondsTimesUnderTenMilliseconds(
- "OffscreenCanvas.TextMetrics.SetFont", elapsed);
+ base::UmaHistogramMicrosecondsTimes("OffscreenCanvas.TextMetrics.SetFont2",
+ elapsed);
}
}
@@ -458,33 +456,38 @@ String OffscreenCanvasRenderingContext2D::direction() const {
? kRtlDirectionString
: kLtrDirectionString;
}
-void OffscreenCanvasRenderingContext2D::setTextLetterSpacing(
+void OffscreenCanvasRenderingContext2D::setLetterSpacing(
const double letter_spacing) {
if (UNLIKELY(!std::isfinite(letter_spacing)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
float letter_spacing_float = clampTo<float>(letter_spacing);
- GetState().SetTextLetterSpacing(letter_spacing_float,
- Host()->GetFontSelector());
+ GetState().SetLetterSpacing(letter_spacing_float, Host()->GetFontSelector());
}
-void OffscreenCanvasRenderingContext2D::setTextWordSpacing(
+void OffscreenCanvasRenderingContext2D::setWordSpacing(
const double word_spacing) {
if (UNLIKELY(!std::isfinite(word_spacing)))
return;
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
float word_spacing_float = clampTo<float>(word_spacing);
- GetState().SetTextWordSpacing(word_spacing_float, Host()->GetFontSelector());
+ GetState().SetWordSpacing(word_spacing_float, Host()->GetFontSelector());
}
void OffscreenCanvasRenderingContext2D::setTextRendering(
const String& text_rendering_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -526,6 +529,8 @@ void OffscreenCanvasRenderingContext2D::setDirection(
void OffscreenCanvasRenderingContext2D::setFontKerning(
const String& font_kerning_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
FontDescription::Kerning kerning;
@@ -547,6 +552,8 @@ void OffscreenCanvasRenderingContext2D::setFontKerning(
void OffscreenCanvasRenderingContext2D::setFontStretch(
const String& font_stretch) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
@@ -581,6 +588,8 @@ void OffscreenCanvasRenderingContext2D::setFontStretch(
void OffscreenCanvasRenderingContext2D::setFontVariantCaps(
const String& font_variant_caps_string) {
+ // TODO(crbug.com/1234113): Instrument new canvas APIs.
+ identifiability_study_helper_.set_encountered_skipped_ops();
if (!GetState().HasRealizedFont())
setFont(font());
FontDescription::FontVariantCaps variant_caps;
@@ -651,13 +660,15 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
if (max_width && (!std::isfinite(*max_width) || *max_width <= 0))
return;
- identifiability_study_helper_.MaybeUpdateBuilder(
- paint_type == CanvasRenderingContext2DState::kFillPaintType
- ? CanvasOps::kFillText
- : CanvasOps::kStrokeText,
- IdentifiabilitySensitiveStringToken(text), x, y,
- max_width ? *max_width : -1);
- identifiability_study_helper_.set_encountered_sensitive_ops();
+ if (identifiability_study_helper_.ShouldUpdateBuilder()) {
+ identifiability_study_helper_.UpdateBuilder(
+ paint_type == CanvasRenderingContext2DState::kFillPaintType
+ ? CanvasOps::kFillText
+ : CanvasOps::kStrokeText,
+ IdentifiabilitySensitiveStringToken(text), x, y,
+ max_width ? *max_width : -1);
+ identifiability_study_helper_.set_encountered_sensitive_ops();
+ }
const Font& font = AccessFont();
const SimpleFontData* font_data = font.PrimaryFont();
@@ -728,7 +739,8 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
},
[](const SkIRect& rect) // overdraw test lambda
{ return false; },
- bounds, paint_type, CanvasRenderingContext2DState::kNoImage);
+ bounds, paint_type, CanvasRenderingContext2DState::kNoImage,
+ CanvasPerformanceMonitor::DrawType::kText);
// |paint_canvas| maybe rese during Draw. If that happens,
// GetOrCreatePaintCanvas will create a new |paint_canvas| and return a new
@@ -762,4 +774,40 @@ bool OffscreenCanvasRenderingContext2D::IsCanvas2DBufferValid() const {
return false;
}
+void OffscreenCanvasRenderingContext2D::TryRestoreContextEvent(
+ TimerBase* timer) {
+ if (context_lost_mode_ == kNotLostContext) {
+ // Canvas was already restored (possibly thanks to a resize), so stop
+ // trying.
+ try_restore_context_event_timer_.Stop();
+ return;
+ }
+
+ DCHECK(context_lost_mode_ != kWebGLLoseContextLostContext);
+
+ // If lost mode is |kSyntheticLostContext| and |context_restorable_| is set to
+ // true, it means context is forced to be lost for testing purpose. Restore
+ // the context.
+ if (context_lost_mode_ == kSyntheticLostContext) {
+ try_restore_context_event_timer_.Stop();
+ Host()->GetOrCreateCanvasResourceProvider(RasterModeHint::kPreferGPU);
+ DispatchContextRestoredEvent(nullptr);
+
+ // If lost mode is |kRealLostContext|, it means the context was not lost due
+ // to surface failure but rather due to a an eviction, which means image
+ // buffer exists.
+ } else if (context_lost_mode_ == kRealLostContext &&
+ GetOrCreatePaintCanvas()) {
+ try_restore_context_event_timer_.Stop();
+ DispatchContextRestoredEvent(nullptr);
+ }
+
+ // It gets here if lost mode is |kRealLostContext| and it fails to create a
+ // new PaintCanvas. Discard the old resource and allocating a new one here.
+ Host()->DiscardResourceProvider();
+ try_restore_context_event_timer_.Stop();
+ if (GetOrCreatePaintCanvas())
+ DispatchContextRestoredEvent(nullptr);
+}
+
} // namespace blink