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

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

Issue 1507863005: [2D Canvas] Send GPU resources into hibernation when page is not visible (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: tests + histogram Created 5 years 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
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 19 matching lines...) Expand all
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
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
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, &copyPaint); // 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, &copyP 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
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, &copyPaint);
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698