Commit f7483a5f authored by Miguel Casas's avatar Miguel Casas Committed by Commit Bot

Canvas2DLayerBridge: cleanups

This CL address multiple cleanups I found during
crrev.com/c/1452720:

- Removes unused member variables.
- Makes IsValid() non-const: const for no reason;
 but makes some member vars const.
- Prefers early return: fights arrow code.
- Removes unnecessary {}.
- Collapses if()+if() conditions.
- Removes unnecessary enum and uses constexpr next
 to the only use site: makes it clearer.

No new functionality intended.

Test:webkit_unit_tests --gtest_filter=Canvas2DLayerBridgeTest*:CanvasRenderingContext2DTest*

Bug: 927103
Change-Id: Ic2e6e26e3792d186a5d3f7671f0c7021315478a4
Reviewed-on: https://chromium-review.googlesource.com/c/1452618
Commit-Queue: Miguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629611}
parent 5c1a2b3e
...@@ -50,21 +50,12 @@ ...@@ -50,21 +50,12 @@
#include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurface.h"
namespace {
enum {
InvalidMailboxIndex = -1,
MaxCanvasAnimationBacklog = 2, // Make sure the the GPU is never more than
// two animation frames behind.
};
} // namespace
namespace blink { namespace blink {
Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size, Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
AccelerationMode acceleration_mode, AccelerationMode acceleration_mode,
const CanvasColorParams& color_params) const CanvasColorParams& color_params)
: logger_(std::make_unique<Logger>()), : logger_(std::make_unique<Logger>()),
bytes_allocated_(0),
have_recorded_draw_commands_(false), have_recorded_draw_commands_(false),
is_hidden_(false), is_hidden_(false),
is_deferral_enabled_(true), is_deferral_enabled_(true),
...@@ -86,33 +77,30 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size, ...@@ -86,33 +77,30 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
recorder_->getRecordingCanvas()->clear( recorder_->getRecordingCanvas()->clear(
color_params_.GetOpacityMode() == kOpaque ? SK_ColorBLACK color_params_.GetOpacityMode() == kOpaque ? SK_ColorBLACK
: SK_ColorTRANSPARENT); : SK_ColorTRANSPARENT);
DidDraw(FloatRect(FloatPoint(0, 0), FloatSize(size_))); DidDraw(FloatRect(0.f, 0.f, size_.Width(), size_.Height()));
} }
} }
Canvas2DLayerBridge::~Canvas2DLayerBridge() { Canvas2DLayerBridge::~Canvas2DLayerBridge() {
UMA_HISTOGRAM_BOOLEAN("Blink.Canvas.2DLayerBridgeIsDeferred", UMA_HISTOGRAM_BOOLEAN("Blink.Canvas.2DLayerBridgeIsDeferred",
is_deferral_enabled_); is_deferral_enabled_);
if (IsHibernating()) if (IsHibernating())
logger_->ReportHibernationEvent(kHibernationEndedWithTeardown); logger_->ReportHibernationEvent(kHibernationEndedWithTeardown);
ResetResourceProvider(); ResetResourceProvider();
if (layer_ && acceleration_mode_ != kDisableAcceleration) { if (!layer_)
return;
if (acceleration_mode_ != kDisableAcceleration) {
GraphicsLayer::UnregisterContentsLayer(layer_.get()); GraphicsLayer::UnregisterContentsLayer(layer_.get());
layer_->ClearTexture(); layer_->ClearTexture();
// Orphaning the layer is required to trigger the recration of a new layer // Orphaning the layer is required to trigger the recreation of a new layer
// in the case where destruction is caused by a canvas resize. Test: // in the case where destruction is caused by a canvas resize. Test:
// virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
layer_->RemoveFromParent(); layer_->RemoveFromParent();
} }
layer_->ClearClient();
DCHECK(!bytes_allocated_); layer_ = nullptr;
if (layer_) {
layer_->ClearClient();
layer_ = nullptr;
}
} }
void Canvas2DLayerBridge::StartRecording() { void Canvas2DLayerBridge::StartRecording() {
...@@ -124,21 +112,15 @@ void Canvas2DLayerBridge::StartRecording() { ...@@ -124,21 +112,15 @@ void Canvas2DLayerBridge::StartRecording() {
// and clip. // and clip.
canvas->save(); canvas->save();
if (resource_host_) { if (resource_host_)
resource_host_->RestoreCanvasMatrixClipStack(canvas); resource_host_->RestoreCanvasMatrixClipStack(canvas);
}
recording_pixel_count_ = 0; recording_pixel_count_ = 0;
} }
void Canvas2DLayerBridge::SetLoggerForTesting(std::unique_ptr<Logger> logger) {
logger_ = std::move(logger);
}
void Canvas2DLayerBridge::ResetResourceProvider() { void Canvas2DLayerBridge::ResetResourceProvider() {
if (resource_host_) { if (resource_host_)
resource_host_->ReplaceResourceProvider(nullptr); resource_host_->ReplaceResourceProvider(nullptr);
}
} }
bool Canvas2DLayerBridge::ShouldAccelerate(AccelerationHint hint) const { bool Canvas2DLayerBridge::ShouldAccelerate(AccelerationHint hint) const {
...@@ -162,8 +144,9 @@ bool Canvas2DLayerBridge::ShouldAccelerate(AccelerationHint hint) const { ...@@ -162,8 +144,9 @@ bool Canvas2DLayerBridge::ShouldAccelerate(AccelerationHint hint) const {
if (accelerate && (!context_provider_wrapper || if (accelerate && (!context_provider_wrapper ||
context_provider_wrapper->ContextProvider() context_provider_wrapper->ContextProvider()
->ContextGL() ->ContextGL()
->GetGraphicsResetStatusKHR() != GL_NO_ERROR)) ->GetGraphicsResetStatusKHR() != GL_NO_ERROR)) {
accelerate = false; accelerate = false;
}
return accelerate; return accelerate;
} }
...@@ -304,12 +287,14 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider( ...@@ -304,12 +287,14 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
AccelerationHint adjusted_hint = AccelerationHint adjusted_hint =
want_acceleration ? kPreferAcceleration : kPreferNoAcceleration; want_acceleration ? kPreferAcceleration : kPreferNoAcceleration;
// We call Impl directly here, to allow HTMLCanvasElement to call us // We call GetOrCreateCanvasResourceProviderImpl directly here to prevent a
// in GetOrCreateCanvasResourceProvider. // circular callstack from HTMLCanvasElement.
resource_provider = resource_provider =
resource_host_->GetOrCreateCanvasResourceProviderImpl(adjusted_hint); resource_host_->GetOrCreateCanvasResourceProviderImpl(adjusted_hint);
if (!resource_provider)
return nullptr;
if (resource_provider && IsAccelerated() && !layer_) { if (IsAccelerated() && !layer_) {
layer_ = cc::TextureLayer::CreateForMailbox(this); layer_ = cc::TextureLayer::CreateForMailbox(this);
layer_->SetIsDrawable(true); layer_->SetIsDrawable(true);
layer_->SetContentsOpaque(ColorParams().GetOpacityMode() == kOpaque); layer_->SetContentsOpaque(ColorParams().GetOpacityMode() == kOpaque);
...@@ -319,49 +304,46 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider( ...@@ -319,49 +304,46 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
GraphicsLayer::RegisterContentsLayer(layer_.get()); GraphicsLayer::RegisterContentsLayer(layer_.get());
} }
if (resource_provider && IsHibernating()) { if (!IsHibernating())
if (resource_provider->IsAccelerated()) { return resource_provider;
logger_->ReportHibernationEvent(kHibernationEndedNormally);
if (resource_provider->IsAccelerated()) {
logger_->ReportHibernationEvent(kHibernationEndedNormally);
} else {
if (IsHidden()) {
logger_->ReportHibernationEvent(
kHibernationEndedWithSwitchToBackgroundRendering);
} else { } else {
if (IsHidden()) { logger_->ReportHibernationEvent(kHibernationEndedWithFallbackToSW);
logger_->ReportHibernationEvent(
kHibernationEndedWithSwitchToBackgroundRendering);
} else {
logger_->ReportHibernationEvent(kHibernationEndedWithFallbackToSW);
}
} }
}
PaintFlags copy_paint; PaintFlags copy_paint;
copy_paint.setBlendMode(SkBlendMode::kSrc); copy_paint.setBlendMode(SkBlendMode::kSrc);
PaintImageBuilder builder = PaintImageBuilder::WithDefault(); PaintImageBuilder builder = PaintImageBuilder::WithDefault();
builder.set_image(hibernation_image_, PaintImage::GetNextContentId()); builder.set_image(hibernation_image_, PaintImage::GetNextContentId());
builder.set_id(PaintImage::GetNextId()); builder.set_id(PaintImage::GetNextId());
resource_provider->Canvas()->drawImage(builder.TakePaintImage(), 0, 0, resource_provider->Canvas()->drawImage(builder.TakePaintImage(), 0, 0,
&copy_paint); &copy_paint);
hibernation_image_.reset(); hibernation_image_.reset();
if (resource_host_) {
if (!is_deferral_enabled_) {
resource_host_->RestoreCanvasMatrixClipStack(
resource_provider->Canvas());
}
// shouldBeDirectComposited() may have changed. if (resource_host_) {
resource_host_->SetNeedsCompositingUpdate(); if (!is_deferral_enabled_)
} resource_host_->RestoreCanvasMatrixClipStack(resource_provider->Canvas());
}
// shouldBeDirectComposited() may have changed.
resource_host_->SetNeedsCompositingUpdate();
}
return resource_provider; return resource_provider;
} }
cc::PaintCanvas* Canvas2DLayerBridge::Canvas() { cc::PaintCanvas* Canvas2DLayerBridge::Canvas() {
DCHECK(resource_host_); DCHECK(resource_host_);
if (!is_deferral_enabled_) { if (is_deferral_enabled_)
if (GetOrCreateResourceProvider()) return recorder_->getRecordingCanvas();
return ResourceProvider()->Canvas(); if (GetOrCreateResourceProvider())
return nullptr; return ResourceProvider()->Canvas();
} return nullptr;
return recorder_->getRecordingCanvas();
} }
void Canvas2DLayerBridge::DisableDeferral(DisableDeferralReason reason) { void Canvas2DLayerBridge::DisableDeferral(DisableDeferralReason reason) {
...@@ -450,9 +432,8 @@ void Canvas2DLayerBridge::SetIsHidden(bool hidden) { ...@@ -450,9 +432,8 @@ void Canvas2DLayerBridge::SetIsHidden(bool hidden) {
resource_host_->ReplaceResourceProvider(std::move(old_resource_provider)); resource_host_->ReplaceResourceProvider(std::move(old_resource_provider));
} }
} }
if (!IsHidden() && IsHibernating()) { if (!IsHidden() && IsHibernating())
GetOrCreateResourceProvider(); // Rude awakening GetOrCreateResourceProvider(); // Rude awakening
}
} }
void Canvas2DLayerBridge::DrawFullImage(const cc::PaintImage& image) { void Canvas2DLayerBridge::DrawFullImage(const cc::PaintImage& image) {
...@@ -466,6 +447,7 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info, ...@@ -466,6 +447,7 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
int y) { int y) {
if (!GetOrCreateResourceProvider()) if (!GetOrCreateResourceProvider())
return false; return false;
if (x <= 0 && y <= 0 && x + orig_info.width() >= size_.Width() && if (x <= 0 && y <= 0 && x + orig_info.width() >= size_.Width() &&
y + orig_info.height() >= size_.Height()) { y + orig_info.height() >= size_.Height()) {
SkipQueuedDrawCommands(); SkipQueuedDrawCommands();
...@@ -477,7 +459,6 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info, ...@@ -477,7 +459,6 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
ResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x, y); ResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x, y);
DidDraw(FloatRect(x, y, orig_info.width(), orig_info.height())); DidDraw(FloatRect(x, y, orig_info.width(), orig_info.height()));
return true; return true;
} }
...@@ -488,37 +469,36 @@ void Canvas2DLayerBridge::SkipQueuedDrawCommands() { ...@@ -488,37 +469,36 @@ void Canvas2DLayerBridge::SkipQueuedDrawCommands() {
have_recorded_draw_commands_ = false; have_recorded_draw_commands_ = false;
} }
if (is_deferral_enabled_) { if (is_deferral_enabled_ && rate_limiter_)
if (rate_limiter_) rate_limiter_->Reset();
rate_limiter_->Reset();
}
} }
void Canvas2DLayerBridge::FlushRecording() { void Canvas2DLayerBridge::FlushRecording() {
if (have_recorded_draw_commands_ && GetOrCreateResourceProvider()) { if (!have_recorded_draw_commands_ || !GetOrCreateResourceProvider())
TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecording"); return;
cc::PaintCanvas* canvas = ResourceProvider()->Canvas();
{
sk_sp<PaintRecord> recording = recorder_->finishRecordingAsPicture();
canvas->drawPicture(recording);
}
// Rastering the recording would have locked images, since we've flushed TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecording");
// all recorded ops, we should relase all locked images as well.
// A new null check on the resource provider is necessary just in case
// the playback crashed the context.
if (GetOrCreateResourceProvider())
ResourceProvider()->ReleaseLockedImages();
if (is_deferral_enabled_) cc::PaintCanvas* canvas = ResourceProvider()->Canvas();
StartRecording(); {
have_recorded_draw_commands_ = false; sk_sp<PaintRecord> recording = recorder_->finishRecordingAsPicture();
canvas->drawPicture(recording);
} }
// Rastering the recording would have locked images, since we've flushed
// all recorded ops, we should release all locked images as well.
// A new null check on the resource provider is necessary just in case
// the playback crashed the context.
if (GetOrCreateResourceProvider())
ResourceProvider()->ReleaseLockedImages();
if (is_deferral_enabled_)
StartRecording();
have_recorded_draw_commands_ = false;
} }
bool Canvas2DLayerBridge::IsValid() const { bool Canvas2DLayerBridge::IsValid() {
return const_cast<Canvas2DLayerBridge*>(this)->CheckResourceProviderValid(); return CheckResourceProviderValid();
} }
bool Canvas2DLayerBridge::CheckResourceProviderValid() { bool Canvas2DLayerBridge::CheckResourceProviderValid() {
...@@ -582,12 +562,10 @@ bool Canvas2DLayerBridge::PrepareTransferableResource( ...@@ -582,12 +562,10 @@ bool Canvas2DLayerBridge::PrepareTransferableResource(
DCHECK(layer_); // This explodes if FinalizeFrame() was not called. DCHECK(layer_); // This explodes if FinalizeFrame() was not called.
frames_since_last_commit_ = 0; frames_since_last_commit_ = 0;
if (rate_limiter_) { if (rate_limiter_)
rate_limiter_->Reset(); rate_limiter_->Reset();
}
// if hibernating but not hidden, we want to wake up from // If hibernating but not hidden, we want to wake up from hibernation.
// hibernation
if ((IsHibernating() || software_rendering_while_hidden_) && IsHidden()) if ((IsHibernating() || software_rendering_while_hidden_) && IsHidden())
return false; return false;
...@@ -620,27 +598,27 @@ cc::Layer* Canvas2DLayerBridge::Layer() { ...@@ -620,27 +598,27 @@ cc::Layer* Canvas2DLayerBridge::Layer() {
void Canvas2DLayerBridge::DidDraw(const FloatRect& rect) { void Canvas2DLayerBridge::DidDraw(const FloatRect& rect) {
if (snapshot_state_ == kDidAcquireSnapshot) if (snapshot_state_ == kDidAcquireSnapshot)
snapshot_state_ = kDrawnToAfterSnapshot; snapshot_state_ = kDrawnToAfterSnapshot;
if (is_deferral_enabled_) { if (!is_deferral_enabled_)
have_recorded_draw_commands_ = true; return;
IntRect pixel_bounds = EnclosingIntRect(rect);
base::CheckedNumeric<int> pixel_bounds_size = pixel_bounds.Width(); have_recorded_draw_commands_ = true;
pixel_bounds_size *= pixel_bounds.Height(); IntRect pixel_bounds = EnclosingIntRect(rect);
recording_pixel_count_ += pixel_bounds_size; base::CheckedNumeric<int> pixel_bounds_size = pixel_bounds.Width();
if (!recording_pixel_count_.IsValid()) { pixel_bounds_size *= pixel_bounds.Height();
DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic); recording_pixel_count_ += pixel_bounds_size;
return; if (!recording_pixel_count_.IsValid()) {
} DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
base::CheckedNumeric<int> threshold_size = size_.Width(); return;
threshold_size *= size_.Height(); }
threshold_size *= canvas_heuristic_parameters::kExpensiveOverdrawThreshold; base::CheckedNumeric<int> threshold_size = size_.Width();
if (!threshold_size.IsValid()) { threshold_size *= size_.Height();
DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic); threshold_size *= canvas_heuristic_parameters::kExpensiveOverdrawThreshold;
return; if (!threshold_size.IsValid()) {
} DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
if (recording_pixel_count_.ValueOrDie() >= threshold_size.ValueOrDie()) { return;
DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
}
} }
if (recording_pixel_count_.ValueOrDie() >= threshold_size.ValueOrDie())
DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
} }
void Canvas2DLayerBridge::FinalizeFrame() { void Canvas2DLayerBridge::FinalizeFrame() {
...@@ -652,20 +630,18 @@ void Canvas2DLayerBridge::FinalizeFrame() { ...@@ -652,20 +630,18 @@ void Canvas2DLayerBridge::FinalizeFrame() {
return; return;
++frames_since_last_commit_; ++frames_since_last_commit_;
if (frames_since_last_commit_ >= 2) { if (frames_since_last_commit_ >= 2) {
ResourceProvider()->FlushSkia(); ResourceProvider()->FlushSkia();
if (IsAccelerated()) { if (IsAccelerated() && !rate_limiter_) {
if (!rate_limiter_) { // Make sure the GPU is never more than two animation frames behind.
rate_limiter_ = constexpr unsigned kMaxCanvasAnimationBacklog = 2;
SharedContextRateLimiter::Create(MaxCanvasAnimationBacklog); rate_limiter_ =
} SharedContextRateLimiter::Create(kMaxCanvasAnimationBacklog);
} }
} }
if (rate_limiter_) { if (rate_limiter_)
rate_limiter_->Tick(); rate_limiter_->Tick();
}
} }
void Canvas2DLayerBridge::DoPaintInvalidation(const FloatRect& dirty_rect) { void Canvas2DLayerBridge::DoPaintInvalidation(const FloatRect& dirty_rect) {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_2D_LAYER_BRIDGE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_2D_LAYER_BRIDGE_H_
#include <memory> #include <memory>
#include <utility>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
...@@ -109,7 +110,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient { ...@@ -109,7 +110,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
virtual bool IsAccelerated() const; virtual bool IsAccelerated() const;
cc::PaintCanvas* Canvas(); cc::PaintCanvas* Canvas();
bool IsValid() const; bool IsValid();
bool WritePixels(const SkImageInfo&, bool WritePixels(const SkImageInfo&,
const void* pixels, const void* pixels,
size_t row_bytes, size_t row_bytes,
...@@ -158,13 +159,19 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient { ...@@ -158,13 +159,19 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
virtual ~Logger() = default; virtual ~Logger() = default;
}; };
void SetLoggerForTesting(std::unique_ptr<Logger>); void SetLoggerForTesting(std::unique_ptr<Logger> logger) {
logger_ = std::move(logger);
}
CanvasResourceProvider* GetOrCreateResourceProvider( CanvasResourceProvider* GetOrCreateResourceProvider(
AccelerationHint = kPreferAcceleration); AccelerationHint = kPreferAcceleration);
CanvasResourceProvider* ResourceProvider() const; CanvasResourceProvider* ResourceProvider() const;
void FlushRecording(); void FlushRecording();
private: private:
friend class Canvas2DLayerBridgeTest;
friend class CanvasRenderingContext2DTest;
friend class HTMLCanvasPainterTestForCAP;
bool IsHidden() { return is_hidden_; } bool IsHidden() { return is_hidden_; }
bool CheckResourceProviderValid(); bool CheckResourceProviderValid();
void ResetResourceProvider(); void ResetResourceProvider();
...@@ -179,24 +186,19 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient { ...@@ -179,24 +186,19 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
scoped_refptr<cc::TextureLayer> layer_; scoped_refptr<cc::TextureLayer> layer_;
std::unique_ptr<SharedContextRateLimiter> rate_limiter_; std::unique_ptr<SharedContextRateLimiter> rate_limiter_;
std::unique_ptr<Logger> logger_; std::unique_ptr<Logger> logger_;
int msaa_sample_count_;
int frames_since_last_commit_ = 0; int frames_since_last_commit_ = 0;
size_t bytes_allocated_;
bool have_recorded_draw_commands_; bool have_recorded_draw_commands_;
bool is_hidden_; bool is_hidden_;
// See the implementation of DisableDeferral() for more information.
bool is_deferral_enabled_; bool is_deferral_enabled_;
bool software_rendering_while_hidden_; bool software_rendering_while_hidden_;
bool hibernation_scheduled_ = false; bool hibernation_scheduled_ = false;
bool dont_use_idle_scheduling_for_testing_ = false; bool dont_use_idle_scheduling_for_testing_ = false;
bool context_lost_ = false; bool context_lost_ = false;
friend class Canvas2DLayerBridgeTest; const AccelerationMode acceleration_mode_;
friend class CanvasRenderingContext2DTest; const CanvasColorParams color_params_;
friend class HTMLCanvasPainterTestForCAP; const IntSize size_;
AccelerationMode acceleration_mode_;
CanvasColorParams color_params_;
IntSize size_;
base::CheckedNumeric<int> recording_pixel_count_; base::CheckedNumeric<int> recording_pixel_count_;
enum SnapshotState { enum SnapshotState {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment