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 19 matching lines...) Expand all Loading... | |
30 #include "platform/TraceEvent.h" | 30 #include "platform/TraceEvent.h" |
31 #include "platform/graphics/CanvasMetrics.h" | 31 #include "platform/graphics/CanvasMetrics.h" |
32 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | 32 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" |
33 #include "platform/graphics/GraphicsLayer.h" | 33 #include "platform/graphics/GraphicsLayer.h" |
34 #include "platform/graphics/ImageBuffer.h" | 34 #include "platform/graphics/ImageBuffer.h" |
35 #include "platform/graphics/gpu/SharedContextRateLimiter.h" | 35 #include "platform/graphics/gpu/SharedContextRateLimiter.h" |
36 #include "public/platform/Platform.h" | 36 #include "public/platform/Platform.h" |
37 #include "public/platform/WebCompositorSupport.h" | 37 #include "public/platform/WebCompositorSupport.h" |
38 #include "public/platform/WebGraphicsContext3D.h" | 38 #include "public/platform/WebGraphicsContext3D.h" |
39 #include "public/platform/WebGraphicsContext3DProvider.h" | 39 #include "public/platform/WebGraphicsContext3DProvider.h" |
40 #include "public/platform/WebScheduler.h" | |
41 #include "public/platform/WebTraceLocation.h" | |
40 #include "third_party/skia/include/core/SkData.h" | 42 #include "third_party/skia/include/core/SkData.h" |
41 #include "third_party/skia/include/core/SkPictureRecorder.h" | 43 #include "third_party/skia/include/core/SkPictureRecorder.h" |
42 #include "third_party/skia/include/core/SkSurface.h" | 44 #include "third_party/skia/include/core/SkSurface.h" |
43 #include "third_party/skia/include/gpu/GrContext.h" | 45 #include "third_party/skia/include/gpu/GrContext.h" |
44 #include "wtf/RefCountedLeakCounter.h" | 46 #include "wtf/RefCountedLeakCounter.h" |
45 | 47 |
46 namespace { | 48 namespace { |
47 enum { | 49 enum { |
48 InvalidMailboxIndex = -1, | 50 InvalidMailboxIndex = -1, |
49 MaxCanvasAnimationBacklog = 2, // Make sure the the GPU is never more than t wo animation frames behind. | 51 MaxCanvasAnimationBacklog = 2, // Make sure the the GPU is never more than t wo animation frames behind. |
50 }; | 52 }; |
51 | 53 |
52 #ifndef NDEBUG | 54 #ifndef NDEBUG |
53 WTF::RefCountedLeakCounter& canvas2DLayerBridgeInstanceCounter() | 55 WTF::RefCountedLeakCounter& canvas2DLayerBridgeInstanceCounter() |
54 { | 56 { |
55 DEFINE_STATIC_LOCAL(WTF::RefCountedLeakCounter, staticCanvas2DLayerBridgeIns tanceCounter, ("Canvas2DLayerBridge")); | 57 DEFINE_STATIC_LOCAL(WTF::RefCountedLeakCounter, staticCanvas2DLayerBridgeIns tanceCounter, ("Canvas2DLayerBridge")); |
56 return staticCanvas2DLayerBridgeInstanceCounter; | 58 return staticCanvas2DLayerBridgeInstanceCounter; |
57 } | 59 } |
58 #endif | 60 #endif |
59 } | 61 |
62 } // unnamed | |
60 | 63 |
61 namespace blink { | 64 namespace blink { |
62 | 65 |
63 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount, OpacityMode opacityMode, bool* surfaceIsAccelerated) | 66 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount, OpacityMode opacityMode, bool* surfaceIsAccelerated) |
64 { | 67 { |
65 if (gr) | 68 if (gr) |
66 gr->resetContext(); | 69 gr->resetContext(); |
67 | 70 |
68 SkAlphaType alphaType = (Opaque == opacityMode) ? kOpaque_SkAlphaType : kPre mul_SkAlphaType; | 71 SkAlphaType alphaType = (Opaque == opacityMode) ? kOpaque_SkAlphaType : kPre mul_SkAlphaType; |
69 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaTy pe); | 72 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaTy pe); |
(...skipping 26 matching lines...) Expand all Loading... | |
96 OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::cu rrent()->createSharedOffscreenGraphicsContext3DProvider()); | 99 OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::cu rrent()->createSharedOffscreenGraphicsContext3DProvider()); |
97 if (!contextProvider) | 100 if (!contextProvider) |
98 return nullptr; | 101 return nullptr; |
99 RefPtr<Canvas2DLayerBridge> layerBridge; | 102 RefPtr<Canvas2DLayerBridge> layerBridge; |
100 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), si ze, msaaSampleCount, opacityMode, accelerationMode)); | 103 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), si ze, msaaSampleCount, opacityMode, accelerationMode)); |
101 return layerBridge.release(); | 104 return layerBridge.release(); |
102 } | 105 } |
103 | 106 |
104 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider > contextProvider, const IntSize& size, int msaaSampleCount, OpacityMode opacity Mode, AccelerationMode accelerationMode) | 107 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider > contextProvider, const IntSize& size, int msaaSampleCount, OpacityMode opacity Mode, AccelerationMode accelerationMode) |
105 : m_contextProvider(contextProvider) | 108 : m_contextProvider(contextProvider) |
109 , m_logger(adoptPtr(new Logger)) | |
110 , m_weakPtrFactory(this) | |
106 , m_imageBuffer(0) | 111 , m_imageBuffer(0) |
107 , m_msaaSampleCount(msaaSampleCount) | 112 , m_msaaSampleCount(msaaSampleCount) |
108 , m_bytesAllocated(0) | 113 , m_bytesAllocated(0) |
109 , m_haveRecordedDrawCommands(false) | 114 , m_haveRecordedDrawCommands(false) |
110 , m_destructionInProgress(false) | 115 , m_destructionInProgress(false) |
111 , m_filterQuality(kLow_SkFilterQuality) | 116 , m_filterQuality(kLow_SkFilterQuality) |
112 , m_isHidden(false) | 117 , m_isHidden(false) |
113 , m_isDeferralEnabled(true) | 118 , m_isDeferralEnabled(true) |
114 , m_isRegisteredTaskObserver(false) | 119 , m_isRegisteredTaskObserver(false) |
115 , m_renderingTaskCompletedForCurrentFrame(false) | 120 , m_renderingTaskCompletedForCurrentFrame(false) |
121 , m_softwareRenderingWhileHidden(false) | |
116 , m_lastImageId(0) | 122 , m_lastImageId(0) |
117 , m_lastFilter(GL_LINEAR) | 123 , m_lastFilter(GL_LINEAR) |
118 , m_accelerationMode(accelerationMode) | 124 , m_accelerationMode(accelerationMode) |
119 , m_opacityMode(opacityMode) | 125 , m_opacityMode(opacityMode) |
120 , m_size(size) | 126 , m_size(size) |
121 { | 127 { |
122 ASSERT(m_contextProvider); | 128 ASSERT(m_contextProvider); |
123 // Used by browser tests to detect the use of a Canvas2DLayerBridge. | 129 // Used by browser tests to detect the use of a Canvas2DLayerBridge. |
124 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL); | 130 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL); |
125 startRecording(); | 131 startRecording(); |
(...skipping 16 matching lines...) Expand all Loading... | |
142 { | 148 { |
143 ASSERT(m_isDeferralEnabled); | 149 ASSERT(m_isDeferralEnabled); |
144 m_recorder = adoptPtr(new SkPictureRecorder); | 150 m_recorder = adoptPtr(new SkPictureRecorder); |
145 m_recorder->beginRecording(m_size.width(), m_size.height(), nullptr); | 151 m_recorder->beginRecording(m_size.width(), m_size.height(), nullptr); |
146 if (m_imageBuffer) { | 152 if (m_imageBuffer) { |
147 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas()); | 153 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas()); |
148 } | 154 } |
149 m_recordingPixelCount = 0; | 155 m_recordingPixelCount = 0; |
150 } | 156 } |
151 | 157 |
158 void Canvas2DLayerBridge::setLoggerForTesting(PassOwnPtr<Logger> logger) | |
159 { | |
160 m_logger = logger; | |
161 } | |
162 | |
152 bool Canvas2DLayerBridge::shouldAccelerate(AccelerationHint hint) const | 163 bool Canvas2DLayerBridge::shouldAccelerate(AccelerationHint hint) const |
153 { | 164 { |
154 bool accelerate; | 165 bool accelerate; |
155 if (m_accelerationMode == ForceAccelerationForTesting) | 166 if (m_softwareRenderingWhileHidden) |
167 accelerate = false; | |
168 else if (m_accelerationMode == ForceAccelerationForTesting) | |
156 accelerate = true; | 169 accelerate = true; |
157 else if (m_accelerationMode == DisableAcceleration) | 170 else if (m_accelerationMode == DisableAcceleration) |
158 accelerate = false; | 171 accelerate = false; |
159 else | 172 else |
160 accelerate = hint == PreferAcceleration; | 173 accelerate = hint == PreferAcceleration; |
161 | 174 |
162 if (accelerate && (!m_contextProvider || m_contextProvider->context3d()->isC ontextLost())) | 175 if (accelerate && (!m_contextProvider || m_contextProvider->context3d()->isC ontextLost())) |
163 accelerate = false; | 176 accelerate = false; |
164 return accelerate; | 177 return accelerate; |
165 } | 178 } |
166 | 179 |
167 bool Canvas2DLayerBridge::isAccelerated() const | 180 bool Canvas2DLayerBridge::isAccelerated() const |
168 { | 181 { |
182 if (m_softwareRenderingWhileHidden) | |
183 return false; | |
169 if (m_layer) // We don't check m_surface, so this returns true if context wa s lost (m_surface is null) with restoration pending. | 184 if (m_layer) // We don't check m_surface, so this returns true if context wa s lost (m_surface is null) with restoration pending. |
170 return true; | 185 return true; |
171 if (m_surface) // && !m_layer is implied | 186 if (m_surface) // && !m_layer is implied |
172 return false; | 187 return false; |
173 | 188 |
174 // Whether or not to accelerate is not yet resolved, determine whether immed iate presentation | 189 // Whether or not to accelerate is not yet resolved, determine whether immed iate presentation |
175 // of the canvas would result in the canvas being accelerated. Presentation is assumed to be | 190 // of the canvas would result in the canvas being accelerated. Presentation is assumed to be |
176 // a 'PreferAcceleration' operation. | 191 // a 'PreferAcceleration' operation. |
177 return shouldAccelerate(PreferAcceleration); | 192 return shouldAccelerate(PreferAcceleration); |
178 } | 193 } |
179 | 194 |
195 static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleD eadline*/) | |
196 { | |
197 if (bridge) { | |
198 bridge->hibernate(); | |
199 } else { | |
200 Canvas2DLayerBridge::Logger localLogger; | |
201 localLogger.reportHibernationEvent(Canvas2DLayerBridge::HibernationAbort edDueToDestructionWhileHibernatePending); | |
202 } | |
203 } | |
204 | |
205 void Canvas2DLayerBridge::hibernate() | |
206 { | |
207 if (m_destructionInProgress) { | |
208 m_logger->reportHibernationEvent(HibernationAbortedDueToPendingDestructi on); | |
209 return; | |
210 } | |
211 | |
212 if (!isHidden()) { | |
213 m_logger->reportHibernationEvent(HibernationAbortedDueToVisibilityChange ); | |
214 return; | |
215 } | |
216 | |
217 if (!checkSurfaceValid()) { | |
218 m_logger->reportHibernationEvent(HibernationAbortedDueGpuContextLoss); | |
219 return; | |
220 } | |
221 | |
222 if (!isAccelerated()) { | |
223 m_logger->reportHibernationEvent(HibernationAbortedDueToSwitchToUnaccele ratedRendering); | |
224 return; | |
225 } | |
226 | |
227 TRACE_EVENT0("cc", "Canvas2DLayerBridge::hibernate"); | |
228 RefPtr<SkSurface> tempHibernationSurface = adoptRef(SkSurface::NewRasterN32P remul(m_size.width(), m_size.height())); | |
229 if (tempHibernationSurface) { | |
230 // No HibernationEvent reported on success. This is on purppose to avoid | |
231 // non-complementary stats. Each HibernationScheduled event is paired wi th | |
232 // exactly one faillure or exit event. | |
Stephen White
2015/12/10 16:13:10
Nit: s/faillure/failure/
| |
233 flushRecordingOnly(); | |
234 SkPaint copyPaint; | |
235 copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
236 m_surface->draw(tempHibernationSurface->getCanvas(), 0, 0, ©Paint); // GPU readback | |
237 m_hibernationImage = adoptRef(tempHibernationSurface->newImageSnapshot() ); | |
238 m_surface.clear(); // destroy the GPU-backed buffer | |
239 m_layer->clearTexture(); | |
240 m_logger->didStartHibernating(); | |
241 } else { | |
242 m_logger->reportHibernationEvent(HibernationAbortedDueToAllocationFailur e); | |
243 } | |
244 } | |
245 | |
180 SkSurface* Canvas2DLayerBridge::getOrCreateSurface(AccelerationHint hint) | 246 SkSurface* Canvas2DLayerBridge::getOrCreateSurface(AccelerationHint hint) |
181 { | 247 { |
182 if (!m_surface) { | 248 if (m_surface) |
183 if (m_layer) | 249 return m_surface.get(); |
184 return nullptr; // recreation will happen through restore() | |
185 | 250 |
186 bool wantAccelerated = shouldAccelerate(hint); | 251 if (m_layer && !isHibernating()) |
187 bool surfaceIsAccelerated; | 252 return nullptr; // recreation will happen through restore() |
Stephen White
2015/12/10 16:13:10
s/recreation/re-creation/ :)
| |
188 | 253 |
189 m_surface = createSkSurface(wantAccelerated ? m_contextProvider->grConte xt() : nullptr, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated) ; | 254 bool wantAccelerated = shouldAccelerate(hint); |
Stephen White
2015/12/10 16:13:10
naming uNit: wantAccelerated is awkward. wantAccel
| |
255 bool surfaceIsAccelerated; | |
190 | 256 |
191 if (m_surface && surfaceIsAccelerated && !m_layer) { | 257 if (isHidden() && wantAccelerated) { |
192 m_layer = adoptPtr(Platform::current()->compositorSupport()->createE xternalTextureLayer(this)); | 258 wantAccelerated = false; |
193 m_layer->setOpaque(m_opacityMode == Opaque); | 259 m_softwareRenderingWhileHidden = true; |
194 m_layer->setBlendBackgroundColor(m_opacityMode != Opaque); | 260 } |
195 GraphicsLayer::registerContentsLayer(m_layer->layer()); | 261 |
196 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality ); | 262 m_surface = createSkSurface(wantAccelerated ? m_contextProvider->grContext() : nullptr, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated); |
263 | |
264 if (m_surface && surfaceIsAccelerated && !m_layer) { | |
265 m_layer = adoptPtr(Platform::current()->compositorSupport()->createExter nalTextureLayer(this)); | |
266 m_layer->setOpaque(m_opacityMode == Opaque); | |
267 m_layer->setBlendBackgroundColor(m_opacityMode != Opaque); | |
268 GraphicsLayer::registerContentsLayer(m_layer->layer()); | |
269 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); | |
270 } | |
271 | |
272 if (m_surface && isHibernating()) { | |
273 if (surfaceIsAccelerated) { | |
274 m_logger->reportHibernationEvent(HibernationEndedNormally); | |
275 } else { | |
276 if (isHidden()) | |
277 m_logger->reportHibernationEvent(HibernationEndedWithSwitchToBac kgroundRendering); | |
278 else | |
279 m_logger->reportHibernationEvent(HibernationEndedWithFallbackToS W); | |
197 } | 280 } |
281 | |
282 SkPaint copyPaint; | |
283 copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
284 m_surface->getCanvas()->drawImage(m_hibernationImage.get(), 0, 0, ©P aint); | |
285 m_hibernationImage.clear(); | |
198 } | 286 } |
199 return m_surface.get(); | 287 return m_surface.get(); |
200 } | 288 } |
201 | 289 |
202 SkCanvas* Canvas2DLayerBridge::canvas() | 290 SkCanvas* Canvas2DLayerBridge::canvas() |
203 { | 291 { |
204 if (!m_isDeferralEnabled) { | 292 if (!m_isDeferralEnabled) { |
205 SkSurface* s = getOrCreateSurface(); | 293 SkSurface* s = getOrCreateSurface(); |
206 return s ? s->getCanvas() : nullptr; | 294 return s ? s->getCanvas() : nullptr; |
207 } | 295 } |
(...skipping 11 matching lines...) Expand all Loading... | |
219 // required multiple times per frame, the repeated flushing of deferred | 307 // required multiple times per frame, the repeated flushing of deferred |
220 // commands would cause significant overhead, so it is better to just stop | 308 // commands would cause significant overhead, so it is better to just stop |
221 // trying to defer altogether. | 309 // trying to defer altogether. |
222 if (!m_isDeferralEnabled) | 310 if (!m_isDeferralEnabled) |
223 return; | 311 return; |
224 | 312 |
225 m_isDeferralEnabled = false; | 313 m_isDeferralEnabled = false; |
226 flushRecordingOnly(); | 314 flushRecordingOnly(); |
227 m_recorder.clear(); | 315 m_recorder.clear(); |
228 // install the current matrix/clip stack onto the immediate canvas | 316 // install the current matrix/clip stack onto the immediate canvas |
229 m_imageBuffer->resetCanvas(getOrCreateSurface()->getCanvas()); | 317 if (m_imageBuffer) |
318 m_imageBuffer->resetCanvas(getOrCreateSurface()->getCanvas()); | |
230 } | 319 } |
231 | 320 |
232 void Canvas2DLayerBridge::setImageBuffer(ImageBuffer* imageBuffer) | 321 void Canvas2DLayerBridge::setImageBuffer(ImageBuffer* imageBuffer) |
233 { | 322 { |
234 m_imageBuffer = imageBuffer; | 323 m_imageBuffer = imageBuffer; |
235 if (m_imageBuffer && m_isDeferralEnabled) { | 324 if (m_imageBuffer && m_isDeferralEnabled) { |
236 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas()); | 325 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas()); |
237 } | 326 } |
238 } | 327 } |
239 | 328 |
240 void Canvas2DLayerBridge::beginDestruction() | 329 void Canvas2DLayerBridge::beginDestruction() |
241 { | 330 { |
242 ASSERT(!m_destructionInProgress); | 331 if (m_destructionInProgress) |
332 return; | |
333 if (isHibernating()) | |
334 m_logger->reportHibernationEvent(HibernationEndedWithTeardown); | |
335 m_hibernationImage.clear(); | |
243 m_recorder.clear(); | 336 m_recorder.clear(); |
244 m_imageBuffer = nullptr; | 337 m_imageBuffer = nullptr; |
245 m_destructionInProgress = true; | 338 m_destructionInProgress = true; |
246 setIsHidden(true); | 339 setIsHidden(true); |
247 m_surface.clear(); | 340 m_surface.clear(); |
248 | 341 |
249 unregisterTaskObserver(); | 342 unregisterTaskObserver(); |
250 | 343 |
251 if (m_layer) { | 344 if (m_layer) { |
252 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); | 345 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |
253 m_layer->clearTexture(); | 346 m_layer->clearTexture(); |
254 // Orphaning the layer is required to trigger the recration of a new lay er | 347 // Orphaning the layer is required to trigger the recration of a new lay er |
255 // in the case where destruction is caused by a canvas resize. Test: | 348 // in the case where destruction is caused by a canvas resize. Test: |
256 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html | 349 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html |
257 m_layer->layer()->removeFromParent(); | 350 m_layer->layer()->removeFromParent(); |
258 } | 351 } |
352 | |
259 ASSERT(!m_bytesAllocated); | 353 ASSERT(!m_bytesAllocated); |
260 } | 354 } |
261 | 355 |
262 void Canvas2DLayerBridge::unregisterTaskObserver() | 356 void Canvas2DLayerBridge::unregisterTaskObserver() |
263 { | 357 { |
264 if (m_isRegisteredTaskObserver) { | 358 if (m_isRegisteredTaskObserver) { |
265 Platform::current()->currentThread()->removeTaskObserver(this); | 359 Platform::current()->currentThread()->removeTaskObserver(this); |
266 m_isRegisteredTaskObserver = false; | 360 m_isRegisteredTaskObserver = false; |
267 } | 361 } |
268 } | 362 } |
269 | 363 |
270 void Canvas2DLayerBridge::setFilterQuality(SkFilterQuality filterQuality) | 364 void Canvas2DLayerBridge::setFilterQuality(SkFilterQuality filterQuality) |
271 { | 365 { |
272 ASSERT(!m_destructionInProgress); | 366 ASSERT(!m_destructionInProgress); |
273 m_filterQuality = filterQuality; | 367 m_filterQuality = filterQuality; |
274 if (m_layer) | 368 if (m_layer) |
275 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); | 369 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); |
276 } | 370 } |
277 | 371 |
278 void Canvas2DLayerBridge::setIsHidden(bool hidden) | 372 void Canvas2DLayerBridge::setIsHidden(bool hidden) |
279 { | 373 { |
280 bool newHiddenValue = hidden || m_destructionInProgress; | 374 bool newHiddenValue = hidden || m_destructionInProgress; |
281 if (m_isHidden == newHiddenValue) | 375 if (m_isHidden == newHiddenValue) |
282 return; | 376 return; |
283 | 377 |
284 m_isHidden = newHiddenValue; | 378 m_isHidden = newHiddenValue; |
285 if (isHidden() && !m_destructionInProgress) | 379 if (m_surface && isHidden() && !m_destructionInProgress) { |
286 flush(); | 380 if (m_layer) |
381 m_layer->clearTexture(); | |
382 m_logger->reportHibernationEvent(HibernationScheduled); | |
383 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FR OM_HERE, WTF::bind<double>(&hibernateWrapper, m_weakPtrFactory.createWeakPtr())) ; | |
384 } | |
385 if (!isHidden() && m_softwareRenderingWhileHidden) { | |
386 flushRecordingOnly(); | |
387 SkPaint copyPaint; | |
388 copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
389 RefPtr<SkSurface> oldSurface = m_surface.release(); | |
390 m_softwareRenderingWhileHidden = false; | |
391 SkSurface* newSurface = getOrCreateSurface(); | |
392 if (newSurface) { | |
393 oldSurface->draw(newSurface->getCanvas(), 0, 0, ©Paint); | |
394 } | |
395 } | |
396 if (!isHidden() && isHibernating()) { | |
397 getOrCreateSurface(); // Rude awakening | |
398 } | |
287 } | 399 } |
288 | 400 |
289 bool Canvas2DLayerBridge::writePixels(const SkImageInfo& origInfo, const void* p ixels, size_t rowBytes, int x, int y) | 401 bool Canvas2DLayerBridge::writePixels(const SkImageInfo& origInfo, const void* p ixels, size_t rowBytes, int x, int y) |
290 { | 402 { |
291 if (!getOrCreateSurface()) | 403 if (!getOrCreateSurface()) |
292 return false; | 404 return false; |
293 if (x <= 0 && y <= 0 && x + origInfo.width() >= m_size.width() && y + origIn fo.height() >= m_size.height()) { | 405 if (x <= 0 && y <= 0 && x + origInfo.width() >= m_size.width() && y + origIn fo.height() >= m_size.height()) { |
294 skipQueuedDrawCommands(); | 406 skipQueuedDrawCommands(); |
295 } else { | 407 } else { |
296 flush(); | 408 flush(); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 m_surface = surface.release(); | 517 m_surface = surface.release(); |
406 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 | 518 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 |
407 } | 519 } |
408 } | 520 } |
409 | 521 |
410 return m_surface; | 522 return m_surface; |
411 } | 523 } |
412 | 524 |
413 bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap) | 525 bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap) |
414 { | 526 { |
415 ASSERT(isAccelerated()); | |
416 if (m_destructionInProgress) { | 527 if (m_destructionInProgress) { |
417 // It can be hit in the following sequence. | 528 // It can be hit in the following sequence. |
418 // 1. Canvas draws something. | 529 // 1. Canvas draws something. |
419 // 2. The compositor begins the frame. | 530 // 2. The compositor begins the frame. |
420 // 3. Javascript makes a context be lost. | 531 // 3. Javascript makes a context be lost. |
421 // 4. Here. | 532 // 4. Here. |
422 return false; | 533 return false; |
423 } | 534 } |
535 ASSERT(isAccelerated() || isHibernating()); | |
536 | |
537 // if hibernating but not hidden, we want to wake up from | |
538 // hibernation | |
539 if (isHibernating() && isHidden()) | |
540 return false; | |
541 | |
424 if (bitmap) { | 542 if (bitmap) { |
425 // Using accelerated 2d canvas with software renderer, which | 543 // Using accelerated 2d canvas with software renderer, which |
426 // should only happen in tests that use fake graphics contexts | 544 // should only happen in tests that use fake graphics contexts |
427 // or in Android WebView in software mode. In this case, we do | 545 // or in Android WebView in software mode. In this case, we do |
428 // not care about producing any results for this canvas. | 546 // not care about producing any results for this canvas. |
429 skipQueuedDrawCommands(); | 547 skipQueuedDrawCommands(); |
430 m_lastImageId = 0; | 548 m_lastImageId = 0; |
431 return false; | 549 return false; |
432 } | 550 } |
433 if (!checkSurfaceValid()) | 551 if (!checkSurfaceValid()) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 // Because we are changing the texture binding without going through skia, | 617 // Because we are changing the texture binding without going through skia, |
500 // we must dirty the context. | 618 // we must dirty the context. |
501 grContext->resetContext(kTextureBinding_GrGLBackendState); | 619 grContext->resetContext(kTextureBinding_GrGLBackendState); |
502 | 620 |
503 *outMailbox = mailboxInfo.m_mailbox; | 621 *outMailbox = mailboxInfo.m_mailbox; |
504 return true; | 622 return true; |
505 } | 623 } |
506 | 624 |
507 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb ox, bool lostResource) | 625 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb ox, bool lostResource) |
508 { | 626 { |
509 ASSERT(isAccelerated()); | 627 ASSERT(isAccelerated() || isHibernating()); |
510 bool contextLost = !m_surface || m_contextProvider->context3d()->isContextLo st(); | 628 bool contextLost = !isHibernating() && (!m_surface || m_contextProvider->con text3d()->isContextLost()); |
511 ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); | 629 ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); |
512 | 630 |
513 // Mailboxes are typically released in FIFO order, so we iterate | 631 // Mailboxes are typically released in FIFO order, so we iterate |
514 // from the end of m_mailboxes. | 632 // from the end of m_mailboxes. |
515 auto releasedMailboxInfo = m_mailboxes.end(); | 633 auto releasedMailboxInfo = m_mailboxes.end(); |
516 auto firstMailbox = m_mailboxes.begin(); | 634 auto firstMailbox = m_mailboxes.begin(); |
517 | 635 |
518 while (true) { | 636 while (true) { |
519 --releasedMailboxInfo; | 637 --releasedMailboxInfo; |
520 if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) { | 638 if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
644 skipQueuedDrawCommands(); | 762 skipQueuedDrawCommands(); |
645 } | 763 } |
646 | 764 |
647 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) | 765 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) |
648 { | 766 { |
649 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); | 767 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); |
650 m_image = other.m_image; | 768 m_image = other.m_image; |
651 m_parentLayerBridge = other.m_parentLayerBridge; | 769 m_parentLayerBridge = other.m_parentLayerBridge; |
652 } | 770 } |
653 | 771 |
772 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event) | |
773 { | |
774 blink::Platform::current()->histogramEnumeration("Canvas.HibernationEvents", event, HibernationEventCount); | |
775 } | |
776 | |
654 } // namespace blink | 777 } // namespace blink |
OLD | NEW |