OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |