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 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 |