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), | |
145 m_renderingTaskCompletedForCurrentFrame(false), | |
146 m_softwareRenderingWhileHidden(false), | 144 m_softwareRenderingWhileHidden(false), |
147 m_lastImageId(0), | 145 m_lastImageId(0), |
148 m_lastFilter(GL_LINEAR), | 146 m_lastFilter(GL_LINEAR), |
149 m_accelerationMode(accelerationMode), | 147 m_accelerationMode(accelerationMode), |
150 m_opacityMode(opacityMode), | 148 m_opacityMode(opacityMode), |
151 m_size(size), | 149 m_size(size), |
152 m_colorSpace(colorSpace), | 150 m_colorSpace(colorSpace), |
153 m_skSurfacesUseColorSpace(skSurfacesUseColorSpace), | 151 m_skSurfacesUseColorSpace(skSurfacesUseColorSpace), |
154 m_colorType(colorType) { | 152 m_colorType(colorType) { |
155 DCHECK(m_contextProvider); | 153 DCHECK(m_contextProvider); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 m_logger->reportHibernationEvent(HibernationAbortedDueGpuContextLoss); | 488 m_logger->reportHibernationEvent(HibernationAbortedDueGpuContextLoss); |
491 return; | 489 return; |
492 } | 490 } |
493 | 491 |
494 if (!isAccelerated()) { | 492 if (!isAccelerated()) { |
495 m_logger->reportHibernationEvent( | 493 m_logger->reportHibernationEvent( |
496 HibernationAbortedDueToSwitchToUnacceleratedRendering); | 494 HibernationAbortedDueToSwitchToUnacceleratedRendering); |
497 return; | 495 return; |
498 } | 496 } |
499 | 497 |
500 TRACE_EVENT0("cc", "Canvas2DLayerBridge::hibernate"); | 498 TRACE_EVENT0("blink", "Canvas2DLayerBridge::hibernate"); |
501 sk_sp<PaintSurface> tempHibernationSurface = | 499 sk_sp<PaintSurface> tempHibernationSurface = |
502 PaintSurface::MakeRasterN32Premul(m_size.width(), m_size.height()); | 500 PaintSurface::MakeRasterN32Premul(m_size.width(), m_size.height()); |
503 if (!tempHibernationSurface) { | 501 if (!tempHibernationSurface) { |
504 m_logger->reportHibernationEvent(HibernationAbortedDueToAllocationFailure); | 502 m_logger->reportHibernationEvent(HibernationAbortedDueToAllocationFailure); |
505 return; | 503 return; |
506 } | 504 } |
507 // No HibernationEvent reported on success. This is on purppose to avoid | 505 // No HibernationEvent reported on success. This is on purppose to avoid |
508 // non-complementary stats. Each HibernationScheduled event is paired with | 506 // non-complementary stats. Each HibernationScheduled event is paired with |
509 // exactly one failure or exit event. | 507 // exactly one failure or exit event. |
510 flushRecordingOnly(); | 508 flushRecordingOnly(); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 return; | 660 return; |
663 if (isHibernating()) | 661 if (isHibernating()) |
664 m_logger->reportHibernationEvent(HibernationEndedWithTeardown); | 662 m_logger->reportHibernationEvent(HibernationEndedWithTeardown); |
665 m_hibernationImage.reset(); | 663 m_hibernationImage.reset(); |
666 m_recorder.reset(); | 664 m_recorder.reset(); |
667 m_imageBuffer = nullptr; | 665 m_imageBuffer = nullptr; |
668 m_destructionInProgress = true; | 666 m_destructionInProgress = true; |
669 setIsHidden(true); | 667 setIsHidden(true); |
670 m_surface.reset(); | 668 m_surface.reset(); |
671 | 669 |
672 unregisterTaskObserver(); | |
673 | |
674 if (m_layer && m_accelerationMode != DisableAcceleration) { | 670 if (m_layer && m_accelerationMode != DisableAcceleration) { |
675 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); | 671 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |
676 m_layer->clearTexture(); | 672 m_layer->clearTexture(); |
677 // Orphaning the layer is required to trigger the recration of a new layer | 673 // 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: | 674 // in the case where destruction is caused by a canvas resize. Test: |
679 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html | 675 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html |
680 m_layer->layer()->removeFromParent(); | 676 m_layer->layer()->removeFromParent(); |
681 } | 677 } |
682 | 678 |
683 DCHECK(!m_bytesAllocated); | 679 DCHECK(!m_bytesAllocated); |
684 } | 680 } |
685 | 681 |
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) { | 682 void Canvas2DLayerBridge::setFilterQuality(SkFilterQuality filterQuality) { |
694 DCHECK(!m_destructionInProgress); | 683 DCHECK(!m_destructionInProgress); |
695 m_filterQuality = filterQuality; | 684 m_filterQuality = filterQuality; |
696 if (m_layer) | 685 if (m_layer) |
697 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); | 686 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); |
698 } | 687 } |
699 | 688 |
700 void Canvas2DLayerBridge::setIsHidden(bool hidden) { | 689 void Canvas2DLayerBridge::setIsHidden(bool hidden) { |
701 bool newHiddenValue = hidden || m_destructionInProgress; | 690 bool newHiddenValue = hidden || m_destructionInProgress; |
702 if (m_isHidden == newHiddenValue) | 691 if (m_isHidden == newHiddenValue) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 } | 754 } |
766 | 755 |
767 void Canvas2DLayerBridge::skipQueuedDrawCommands() { | 756 void Canvas2DLayerBridge::skipQueuedDrawCommands() { |
768 if (m_haveRecordedDrawCommands) { | 757 if (m_haveRecordedDrawCommands) { |
769 m_recorder->finishRecordingAsPicture(); | 758 m_recorder->finishRecordingAsPicture(); |
770 startRecording(); | 759 startRecording(); |
771 m_haveRecordedDrawCommands = false; | 760 m_haveRecordedDrawCommands = false; |
772 } | 761 } |
773 | 762 |
774 if (m_isDeferralEnabled) { | 763 if (m_isDeferralEnabled) { |
775 unregisterTaskObserver(); | |
776 if (m_rateLimiter) | 764 if (m_rateLimiter) |
777 m_rateLimiter->reset(); | 765 m_rateLimiter->reset(); |
778 } | 766 } |
779 } | 767 } |
780 | 768 |
781 void Canvas2DLayerBridge::flushRecordingOnly() { | 769 void Canvas2DLayerBridge::flushRecordingOnly() { |
782 DCHECK(!m_destructionInProgress); | 770 DCHECK(!m_destructionInProgress); |
783 | 771 |
784 if (m_haveRecordedDrawCommands && getOrCreateSurface()) { | 772 if (m_haveRecordedDrawCommands && getOrCreateSurface()) { |
785 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecordingOnly"); | 773 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) { | 881 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) { |
894 if (m_destructionInProgress) { | 882 if (m_destructionInProgress) { |
895 // It can be hit in the following sequence. | 883 // It can be hit in the following sequence. |
896 // 1. Canvas draws something. | 884 // 1. Canvas draws something. |
897 // 2. The compositor begins the frame. | 885 // 2. The compositor begins the frame. |
898 // 3. Javascript makes a context be lost. | 886 // 3. Javascript makes a context be lost. |
899 // 4. Here. | 887 // 4. Here. |
900 return false; | 888 return false; |
901 } | 889 } |
902 | 890 |
| 891 m_framesSinceLastCommit = 0; |
| 892 if (m_rateLimiter) { |
| 893 m_rateLimiter->reset(); |
| 894 } |
| 895 |
903 // If the context is lost, we don't know if we should be producing GPU or | 896 // 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 | 897 // software frames, until we get a new context, since the compositor will |
905 // be trying to get a new context and may change modes. | 898 // be trying to get a new context and may change modes. |
906 if (!m_contextProvider || | 899 if (!m_contextProvider || |
907 m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() != | 900 m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() != |
908 GL_NO_ERROR) | 901 GL_NO_ERROR) |
909 return false; | 902 return false; |
910 | 903 |
911 DCHECK(isAccelerated() || isHibernating() || m_softwareRenderingWhileHidden); | 904 DCHECK(isAccelerated() || isHibernating() || m_softwareRenderingWhileHidden); |
912 | 905 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 if (m_isDeferralEnabled) { | 1021 if (m_isDeferralEnabled) { |
1029 m_haveRecordedDrawCommands = true; | 1022 m_haveRecordedDrawCommands = true; |
1030 IntRect pixelBounds = enclosingIntRect(rect); | 1023 IntRect pixelBounds = enclosingIntRect(rect); |
1031 m_recordingPixelCount += pixelBounds.width() * pixelBounds.height(); | 1024 m_recordingPixelCount += pixelBounds.width() * pixelBounds.height(); |
1032 if (m_recordingPixelCount >= | 1025 if (m_recordingPixelCount >= |
1033 (m_size.width() * m_size.height() * | 1026 (m_size.width() * m_size.height() * |
1034 ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) { | 1027 ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) { |
1035 disableDeferral(DisableDeferralReasonExpensiveOverdrawHeuristic); | 1028 disableDeferral(DisableDeferralReasonExpensiveOverdrawHeuristic); |
1036 } | 1029 } |
1037 } | 1030 } |
1038 if (!m_isRegisteredTaskObserver) { | |
1039 Platform::current()->currentThread()->addTaskObserver(this); | |
1040 m_isRegisteredTaskObserver = true; | |
1041 } | |
1042 m_didDrawSinceLastFlush = true; | 1031 m_didDrawSinceLastFlush = true; |
1043 m_didDrawSinceLastGpuFlush = true; | 1032 m_didDrawSinceLastGpuFlush = true; |
1044 } | 1033 } |
1045 | 1034 |
1046 void Canvas2DLayerBridge::finalizeFrame() { | 1035 void Canvas2DLayerBridge::finalizeFrame() { |
| 1036 TRACE_EVENT0("blink", "Canvas2DLayerBridge::finalizeFrame"); |
1047 DCHECK(!m_destructionInProgress); | 1037 DCHECK(!m_destructionInProgress); |
1048 | 1038 |
1049 // Make sure surface is ready for painting: fix the rendering mode now | 1039 // Make sure surface is ready for painting: fix the rendering mode now |
1050 // because it will be too late during the paint invalidation phase. | 1040 // because it will be too late during the paint invalidation phase. |
1051 getOrCreateSurface(PreferAcceleration); | 1041 getOrCreateSurface(PreferAcceleration); |
1052 | 1042 |
1053 if (m_rateLimiter) | 1043 ++m_framesSinceLastCommit; |
1054 m_rateLimiter->reset(); | |
1055 m_renderingTaskCompletedForCurrentFrame = false; | |
1056 } | |
1057 | 1044 |
1058 void Canvas2DLayerBridge::doPaintInvalidation(const FloatRect& dirtyRect) { | 1045 if (m_framesSinceLastCommit >= 2) { |
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 } |
1081 } | 1055 } |
1082 | 1056 |
1083 if (m_rateLimiter) { | 1057 if (m_rateLimiter) { |
1084 m_rateLimiter->tick(); | 1058 m_rateLimiter->tick(); |
1085 } | 1059 } |
1086 | |
1087 m_renderingTaskCompletedForCurrentFrame = true; | |
1088 unregisterTaskObserver(); | |
1089 } | 1060 } |
1090 | 1061 |
1091 void Canvas2DLayerBridge::willProcessTask() { | 1062 void Canvas2DLayerBridge::doPaintInvalidation(const FloatRect& dirtyRect) { |
1092 NOTREACHED(); | 1063 DCHECK(!m_destructionInProgress); |
| 1064 if (m_layer && m_accelerationMode != DisableAcceleration) |
| 1065 m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect)); |
1093 } | 1066 } |
1094 | 1067 |
1095 sk_sp<SkImage> Canvas2DLayerBridge::newImageSnapshot(AccelerationHint hint, | 1068 sk_sp<SkImage> Canvas2DLayerBridge::newImageSnapshot(AccelerationHint hint, |
1096 SnapshotReason) { | 1069 SnapshotReason) { |
1097 if (isHibernating()) | 1070 if (isHibernating()) |
1098 return m_hibernationImage; | 1071 return m_hibernationImage; |
1099 if (!checkSurfaceValid()) | 1072 if (!checkSurfaceValid()) |
1100 return nullptr; | 1073 return nullptr; |
1101 if (!getOrCreateSurface(hint)) | 1074 if (!getOrCreateSurface(hint)) |
1102 return nullptr; | 1075 return nullptr; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 default; | 1108 default; |
1136 | 1109 |
1137 void Canvas2DLayerBridge::Logger::reportHibernationEvent( | 1110 void Canvas2DLayerBridge::Logger::reportHibernationEvent( |
1138 HibernationEvent event) { | 1111 HibernationEvent event) { |
1139 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, | 1112 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, |
1140 ("Canvas.HibernationEvents", HibernationEventCount)); | 1113 ("Canvas.HibernationEvents", HibernationEventCount)); |
1141 hibernationHistogram.count(event); | 1114 hibernationHistogram.count(event); |
1142 } | 1115 } |
1143 | 1116 |
1144 } // namespace blink | 1117 } // namespace blink |
OLD | NEW |