Chromium Code Reviews| 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 |