Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp

Issue 2700833002: Simplify rate limiter logic in Canvas2DLayerBridge (Closed)
Patch Set: add trace Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 m_logger(WTF::wrapUnique(new Logger)), 134 m_logger(WTF::wrapUnique(new Logger)),
135 m_weakPtrFactory(this), 135 m_weakPtrFactory(this),
136 m_imageBuffer(0), 136 m_imageBuffer(0),
137 m_msaaSampleCount(msaaSampleCount), 137 m_msaaSampleCount(msaaSampleCount),
138 m_bytesAllocated(0), 138 m_bytesAllocated(0),
139 m_haveRecordedDrawCommands(false), 139 m_haveRecordedDrawCommands(false),
140 m_destructionInProgress(false), 140 m_destructionInProgress(false),
141 m_filterQuality(kLow_SkFilterQuality), 141 m_filterQuality(kLow_SkFilterQuality),
142 m_isHidden(false), 142 m_isHidden(false),
143 m_isDeferralEnabled(true), 143 m_isDeferralEnabled(true),
144 m_isRegisteredTaskObserver(false), 144 m_previousFrameWasPresented(
xlai (Olivia) 2017/02/17 19:39:53 Will it be better to rename this as "m_nextFrameNe
Justin Novosad 2017/02/21 15:49:26 Acknowledged.
145 m_renderingTaskCompletedForCurrentFrame(false), 145 true), // true to prevent rate limiting at startup
146 m_softwareRenderingWhileHidden(false), 146 m_softwareRenderingWhileHidden(false),
147 m_lastImageId(0), 147 m_lastImageId(0),
148 m_lastFilter(GL_LINEAR), 148 m_lastFilter(GL_LINEAR),
149 m_accelerationMode(accelerationMode), 149 m_accelerationMode(accelerationMode),
150 m_opacityMode(opacityMode), 150 m_opacityMode(opacityMode),
151 m_size(size), 151 m_size(size),
152 m_colorSpace(colorSpace), 152 m_colorSpace(colorSpace),
153 m_skSurfacesUseColorSpace(skSurfacesUseColorSpace), 153 m_skSurfacesUseColorSpace(skSurfacesUseColorSpace),
154 m_colorType(colorType) { 154 m_colorType(colorType) {
155 DCHECK(m_contextProvider); 155 DCHECK(m_contextProvider);
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 m_logger->reportHibernationEvent(HibernationAbortedDueGpuContextLoss); 490 m_logger->reportHibernationEvent(HibernationAbortedDueGpuContextLoss);
491 return; 491 return;
492 } 492 }
493 493
494 if (!isAccelerated()) { 494 if (!isAccelerated()) {
495 m_logger->reportHibernationEvent( 495 m_logger->reportHibernationEvent(
496 HibernationAbortedDueToSwitchToUnacceleratedRendering); 496 HibernationAbortedDueToSwitchToUnacceleratedRendering);
497 return; 497 return;
498 } 498 }
499 499
500 TRACE_EVENT0("cc", "Canvas2DLayerBridge::hibernate"); 500 TRACE_EVENT0("blink", "Canvas2DLayerBridge::hibernate");
501 sk_sp<PaintSurface> tempHibernationSurface = 501 sk_sp<PaintSurface> tempHibernationSurface =
502 PaintSurface::MakeRasterN32Premul(m_size.width(), m_size.height()); 502 PaintSurface::MakeRasterN32Premul(m_size.width(), m_size.height());
503 if (!tempHibernationSurface) { 503 if (!tempHibernationSurface) {
504 m_logger->reportHibernationEvent(HibernationAbortedDueToAllocationFailure); 504 m_logger->reportHibernationEvent(HibernationAbortedDueToAllocationFailure);
505 return; 505 return;
506 } 506 }
507 // No HibernationEvent reported on success. This is on purppose to avoid 507 // No HibernationEvent reported on success. This is on purppose to avoid
508 // non-complementary stats. Each HibernationScheduled event is paired with 508 // non-complementary stats. Each HibernationScheduled event is paired with
509 // exactly one failure or exit event. 509 // exactly one failure or exit event.
510 flushRecordingOnly(); 510 flushRecordingOnly();
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 return; 662 return;
663 if (isHibernating()) 663 if (isHibernating())
664 m_logger->reportHibernationEvent(HibernationEndedWithTeardown); 664 m_logger->reportHibernationEvent(HibernationEndedWithTeardown);
665 m_hibernationImage.reset(); 665 m_hibernationImage.reset();
666 m_recorder.reset(); 666 m_recorder.reset();
667 m_imageBuffer = nullptr; 667 m_imageBuffer = nullptr;
668 m_destructionInProgress = true; 668 m_destructionInProgress = true;
669 setIsHidden(true); 669 setIsHidden(true);
670 m_surface.reset(); 670 m_surface.reset();
671 671
672 unregisterTaskObserver();
673
674 if (m_layer && m_accelerationMode != DisableAcceleration) { 672 if (m_layer && m_accelerationMode != DisableAcceleration) {
675 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 673 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
676 m_layer->clearTexture(); 674 m_layer->clearTexture();
677 // Orphaning the layer is required to trigger the recration of a new layer 675 // Orphaning the layer is required to trigger the recration of a new layer
678 // in the case where destruction is caused by a canvas resize. Test: 676 // in the case where destruction is caused by a canvas resize. Test:
679 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html 677 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
680 m_layer->layer()->removeFromParent(); 678 m_layer->layer()->removeFromParent();
681 } 679 }
682 680
683 DCHECK(!m_bytesAllocated); 681 DCHECK(!m_bytesAllocated);
684 } 682 }
685 683
686 void Canvas2DLayerBridge::unregisterTaskObserver() {
687 if (m_isRegisteredTaskObserver) {
688 Platform::current()->currentThread()->removeTaskObserver(this);
689 m_isRegisteredTaskObserver = false;
690 }
691 }
692
693 void Canvas2DLayerBridge::setFilterQuality(SkFilterQuality filterQuality) { 684 void Canvas2DLayerBridge::setFilterQuality(SkFilterQuality filterQuality) {
694 DCHECK(!m_destructionInProgress); 685 DCHECK(!m_destructionInProgress);
695 m_filterQuality = filterQuality; 686 m_filterQuality = filterQuality;
696 if (m_layer) 687 if (m_layer)
697 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); 688 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
698 } 689 }
699 690
700 void Canvas2DLayerBridge::setIsHidden(bool hidden) { 691 void Canvas2DLayerBridge::setIsHidden(bool hidden) {
701 bool newHiddenValue = hidden || m_destructionInProgress; 692 bool newHiddenValue = hidden || m_destructionInProgress;
702 if (m_isHidden == newHiddenValue) 693 if (m_isHidden == newHiddenValue)
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 } 756 }
766 757
767 void Canvas2DLayerBridge::skipQueuedDrawCommands() { 758 void Canvas2DLayerBridge::skipQueuedDrawCommands() {
768 if (m_haveRecordedDrawCommands) { 759 if (m_haveRecordedDrawCommands) {
769 m_recorder->finishRecordingAsPicture(); 760 m_recorder->finishRecordingAsPicture();
770 startRecording(); 761 startRecording();
771 m_haveRecordedDrawCommands = false; 762 m_haveRecordedDrawCommands = false;
772 } 763 }
773 764
774 if (m_isDeferralEnabled) { 765 if (m_isDeferralEnabled) {
775 unregisterTaskObserver();
776 if (m_rateLimiter) 766 if (m_rateLimiter)
777 m_rateLimiter->reset(); 767 m_rateLimiter->reset();
778 } 768 }
779 } 769 }
780 770
781 void Canvas2DLayerBridge::flushRecordingOnly() { 771 void Canvas2DLayerBridge::flushRecordingOnly() {
782 DCHECK(!m_destructionInProgress); 772 DCHECK(!m_destructionInProgress);
783 773
784 if (m_haveRecordedDrawCommands && getOrCreateSurface()) { 774 if (m_haveRecordedDrawCommands && getOrCreateSurface()) {
785 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecordingOnly"); 775 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecordingOnly");
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) { 883 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
894 if (m_destructionInProgress) { 884 if (m_destructionInProgress) {
895 // It can be hit in the following sequence. 885 // It can be hit in the following sequence.
896 // 1. Canvas draws something. 886 // 1. Canvas draws something.
897 // 2. The compositor begins the frame. 887 // 2. The compositor begins the frame.
898 // 3. Javascript makes a context be lost. 888 // 3. Javascript makes a context be lost.
899 // 4. Here. 889 // 4. Here.
900 return false; 890 return false;
901 } 891 }
902 892
893 m_previousFrameWasPresented = true;
894 if (m_rateLimiter) {
895 m_rateLimiter->reset();
xlai (Olivia) 2017/02/17 19:39:53 Are you sure that this is the only place when the
Justin Novosad 2017/02/21 15:49:26 For non-offscreen gpu-accelerated 2D canvases, it
896 }
897
903 // If the context is lost, we don't know if we should be producing GPU or 898 // If the context is lost, we don't know if we should be producing GPU or
904 // software frames, until we get a new context, since the compositor will 899 // software frames, until we get a new context, since the compositor will
905 // be trying to get a new context and may change modes. 900 // be trying to get a new context and may change modes.
906 if (!m_contextProvider || 901 if (!m_contextProvider ||
907 m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() != 902 m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() !=
908 GL_NO_ERROR) 903 GL_NO_ERROR)
909 return false; 904 return false;
910 905
911 DCHECK(isAccelerated() || isHibernating() || m_softwareRenderingWhileHidden); 906 DCHECK(isAccelerated() || isHibernating() || m_softwareRenderingWhileHidden);
912 907
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 if (m_isDeferralEnabled) { 1023 if (m_isDeferralEnabled) {
1029 m_haveRecordedDrawCommands = true; 1024 m_haveRecordedDrawCommands = true;
1030 IntRect pixelBounds = enclosingIntRect(rect); 1025 IntRect pixelBounds = enclosingIntRect(rect);
1031 m_recordingPixelCount += pixelBounds.width() * pixelBounds.height(); 1026 m_recordingPixelCount += pixelBounds.width() * pixelBounds.height();
1032 if (m_recordingPixelCount >= 1027 if (m_recordingPixelCount >=
1033 (m_size.width() * m_size.height() * 1028 (m_size.width() * m_size.height() *
1034 ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) { 1029 ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) {
1035 disableDeferral(DisableDeferralReasonExpensiveOverdrawHeuristic); 1030 disableDeferral(DisableDeferralReasonExpensiveOverdrawHeuristic);
1036 } 1031 }
1037 } 1032 }
1038 if (!m_isRegisteredTaskObserver) {
1039 Platform::current()->currentThread()->addTaskObserver(this);
1040 m_isRegisteredTaskObserver = true;
1041 }
1042 m_didDrawSinceLastFlush = true; 1033 m_didDrawSinceLastFlush = true;
1043 m_didDrawSinceLastGpuFlush = true; 1034 m_didDrawSinceLastGpuFlush = true;
1044 } 1035 }
1045 1036
1046 void Canvas2DLayerBridge::finalizeFrame() { 1037 void Canvas2DLayerBridge::finalizeFrame() {
1038 TRACE_EVENT0("blink", "Canvas2DLayerBridge::finalizeFrame");
1047 DCHECK(!m_destructionInProgress); 1039 DCHECK(!m_destructionInProgress);
1048 1040
1049 // Make sure surface is ready for painting: fix the rendering mode now 1041 // Make sure surface is ready for painting: fix the rendering mode now
1050 // because it will be too late during the paint invalidation phase. 1042 // because it will be too late during the paint invalidation phase.
1051 getOrCreateSurface(PreferAcceleration); 1043 getOrCreateSurface(PreferAcceleration);
1052 1044
1053 if (m_rateLimiter) 1045 if (!m_previousFrameWasPresented) {
1054 m_rateLimiter->reset();
1055 m_renderingTaskCompletedForCurrentFrame = false;
1056 }
1057
1058 void Canvas2DLayerBridge::doPaintInvalidation(const FloatRect& dirtyRect) {
1059 DCHECK(!m_destructionInProgress);
1060 if (m_layer && m_accelerationMode != DisableAcceleration)
1061 m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect));
1062 }
1063
1064 void Canvas2DLayerBridge::didProcessTask() {
1065 TRACE_EVENT0("cc", "Canvas2DLayerBridge::didProcessTask");
1066 DCHECK(m_isRegisteredTaskObserver);
1067 // If m_renderTaskProcessedForCurrentFrame is already set to true,
1068 // it means that rendering tasks are not synchronized with the compositor
1069 // (i.e. not using requestAnimationFrame), so we are at risk of posting
1070 // a multi-frame backlog to the GPU
1071 if (m_renderingTaskCompletedForCurrentFrame) {
1072 if (isAccelerated()) { 1046 if (isAccelerated()) {
1073 flushGpu(); 1047 flushGpu();
1074 if (!m_rateLimiter) { 1048 if (!m_rateLimiter) {
1075 m_rateLimiter = 1049 m_rateLimiter =
1076 SharedContextRateLimiter::create(MaxCanvasAnimationBacklog); 1050 SharedContextRateLimiter::create(MaxCanvasAnimationBacklog);
1077 } 1051 }
1078 } else { 1052 } else {
1079 flush(); 1053 flush();
1080 } 1054 }
1055 } else {
1056 m_previousFrameWasPresented = false;
xlai (Olivia) 2017/02/17 19:39:53 If the previous frame was successfully committed (
Justin Novosad 2017/02/21 15:49:26 The basic idea is to activate rate limiting when f
1081 } 1057 }
1082 1058
1083 if (m_rateLimiter) { 1059 if (m_rateLimiter) {
1084 m_rateLimiter->tick(); 1060 m_rateLimiter->tick();
1085 } 1061 }
1086
1087 m_renderingTaskCompletedForCurrentFrame = true;
1088 unregisterTaskObserver();
1089 } 1062 }
1090 1063
1091 void Canvas2DLayerBridge::willProcessTask() { 1064 void Canvas2DLayerBridge::doPaintInvalidation(const FloatRect& dirtyRect) {
1092 NOTREACHED(); 1065 DCHECK(!m_destructionInProgress);
1066 if (m_layer && m_accelerationMode != DisableAcceleration)
1067 m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect));
1093 } 1068 }
1094 1069
1095 sk_sp<SkImage> Canvas2DLayerBridge::newImageSnapshot(AccelerationHint hint, 1070 sk_sp<SkImage> Canvas2DLayerBridge::newImageSnapshot(AccelerationHint hint,
1096 SnapshotReason) { 1071 SnapshotReason) {
1097 if (isHibernating()) 1072 if (isHibernating())
1098 return m_hibernationImage; 1073 return m_hibernationImage;
1099 if (!checkSurfaceValid()) 1074 if (!checkSurfaceValid())
1100 return nullptr; 1075 return nullptr;
1101 if (!getOrCreateSurface(hint)) 1076 if (!getOrCreateSurface(hint))
1102 return nullptr; 1077 return nullptr;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 default; 1110 default;
1136 1111
1137 void Canvas2DLayerBridge::Logger::reportHibernationEvent( 1112 void Canvas2DLayerBridge::Logger::reportHibernationEvent(
1138 HibernationEvent event) { 1113 HibernationEvent event) {
1139 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, 1114 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram,
1140 ("Canvas.HibernationEvents", HibernationEventCount)); 1115 ("Canvas.HibernationEvents", HibernationEventCount));
1141 hibernationHistogram.count(event); 1116 hibernationHistogram.count(event);
1142 } 1117 }
1143 1118
1144 } // namespace blink 1119 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698