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

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

Issue 1307143005: Make 2D canvas smarter about chosing whether or not to use GPU acceleration (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: migrated to chromium repo Created 5 years, 3 months 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 | Annotate | Revision Log
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 enum { 49 enum {
50 InvalidMailboxIndex = -1, 50 InvalidMailboxIndex = -1,
51 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.
52 }; 52 };
53 53
54 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstance Counter, ("Canvas2DLayerBridge")); 54 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstance Counter, ("Canvas2DLayerBridge"));
55 } 55 }
56 56
57 namespace blink { 57 namespace blink {
58 58
59 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount, OpacityMode opacityMode) 59 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount, OpacityMode opacityMode, bool* surfaceIsAccelerated)
60 { 60 {
61 if (!gr) 61 if (gr)
62 return nullptr; 62 gr->resetContext();
63 gr->resetContext(); 63
64 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); 64 SkAlphaType alphaType = (Opaque == opacityMode) ? kOpaque_SkAlphaType : kPre mul_SkAlphaType;
65 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaTy pe);
65 SkSurfaceProps disableLCDProps(0, kUnknown_SkPixelGeometry); 66 SkSurfaceProps disableLCDProps(0, kUnknown_SkPixelGeometry);
66 RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRenderTarget(gr, SkSurfac e::kNo_Budgeted, info, msaaSampleCount, 67 RefPtr<SkSurface> surface;
67 Opaque == opacityMode ? 0 : &disableLCDProps)); 68
69 if (gr) {
70 *surfaceIsAccelerated = true;
71 surface = adoptRef(SkSurface::NewRenderTarget(gr, SkSurface::kNo_Budgete d, info, msaaSampleCount, Opaque == opacityMode ? 0 : &disableLCDProps));
72 }
73
74 if (!surface) {
75 *surfaceIsAccelerated = false;
76 surface = adoptRef(SkSurface::NewRaster(info, Opaque == opacityMode ? 0 : &disableLCDProps));
77 }
78
68 if (surface) { 79 if (surface) {
69 if (opacityMode == Opaque) { 80 if (opacityMode == Opaque) {
70 surface->getCanvas()->clear(SK_ColorBLACK); 81 surface->getCanvas()->clear(SK_ColorBLACK);
71 } else { 82 } else {
72 surface->getCanvas()->clear(SK_ColorTRANSPARENT); 83 surface->getCanvas()->clear(SK_ColorTRANSPARENT);
73 } 84 }
74 } 85 }
75 return surface; 86 return surface;
76 } 87 }
77 88
78 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount) 89 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size, int msaaSampleCount, OpacityMode opacityMode, AccelerationMode accelerationMode )
79 { 90 {
80 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL); 91 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL);
81 OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::cu rrent()->createSharedOffscreenGraphicsContext3DProvider()); 92 OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::cu rrent()->createSharedOffscreenGraphicsContext3DProvider());
82 if (!contextProvider) 93 if (!contextProvider)
83 return nullptr; 94 return nullptr;
84 RefPtr<SkSurface> surface(createSkSurface(contextProvider->grContext(), size , msaaSampleCount, opacityMode));
85 if (!surface)
86 return nullptr;
87 RefPtr<Canvas2DLayerBridge> layerBridge; 95 RefPtr<Canvas2DLayerBridge> layerBridge;
88 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), su rface.release(), msaaSampleCount, opacityMode)); 96 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), si ze, msaaSampleCount, opacityMode, accelerationMode));
89 return layerBridge.release(); 97 return layerBridge.release();
90 } 98 }
91 99
92 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider > contextProvider, PassRefPtr<SkSurface> surface, int msaaSampleCount, OpacityMo de opacityMode) 100 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider > contextProvider, const IntSize& size, int msaaSampleCount, OpacityMode opacity Mode, AccelerationMode accelerationMode)
93 : m_surface(surface) 101 : m_contextProvider(contextProvider)
94 , m_contextProvider(contextProvider)
95 , m_imageBuffer(0) 102 , m_imageBuffer(0)
96 , m_msaaSampleCount(msaaSampleCount) 103 , m_msaaSampleCount(msaaSampleCount)
97 , m_bytesAllocated(0) 104 , m_bytesAllocated(0)
98 , m_haveRecordedDrawCommands(false) 105 , m_haveRecordedDrawCommands(false)
99 , m_destructionInProgress(false) 106 , m_destructionInProgress(false)
100 , m_filterQuality(kLow_SkFilterQuality) 107 , m_filterQuality(kLow_SkFilterQuality)
101 , m_isHidden(false) 108 , m_isHidden(false)
102 , m_isDeferralEnabled(true) 109 , m_isDeferralEnabled(true)
103 , m_isRegisteredTaskObserver(false) 110 , m_isRegisteredTaskObserver(false)
104 , m_renderingTaskCompletedForCurrentFrame(false) 111 , m_renderingTaskCompletedForCurrentFrame(false)
105 , m_lastImageId(0) 112 , m_lastImageId(0)
106 , m_lastFilter(GL_LINEAR) 113 , m_lastFilter(GL_LINEAR)
114 , m_accelerationMode(accelerationMode)
107 , m_opacityMode(opacityMode) 115 , m_opacityMode(opacityMode)
108 , m_size(m_surface->width(), m_surface->height()) 116 , m_size(size)
109 { 117 {
110 ASSERT(m_surface);
111 ASSERT(m_contextProvider); 118 ASSERT(m_contextProvider);
112 m_initialSurfaceSaveCount = m_surface->getCanvas()->getSaveCount();
113 // Used by browser tests to detect the use of a Canvas2DLayerBridge. 119 // Used by browser tests to detect the use of a Canvas2DLayerBridge.
114 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL); 120 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL);
115 m_layer = adoptPtr(Platform::current()->compositorSupport()->createExternalT extureLayer(this));
116 m_layer->setOpaque(opacityMode == Opaque);
117 m_layer->setBlendBackgroundColor(opacityMode != Opaque);
118 GraphicsLayer::registerContentsLayer(m_layer->layer());
119 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
120 startRecording(); 121 startRecording();
121 #ifndef NDEBUG 122 #ifndef NDEBUG
122 canvas2DLayerBridgeInstanceCounter.increment(); 123 canvas2DLayerBridgeInstanceCounter.increment();
123 #endif 124 #endif
124 } 125 }
125 126
126 Canvas2DLayerBridge::~Canvas2DLayerBridge() 127 Canvas2DLayerBridge::~Canvas2DLayerBridge()
127 { 128 {
128 ASSERT(m_destructionInProgress); 129 ASSERT(m_destructionInProgress);
129 m_layer.clear(); 130 m_layer.clear();
130 ASSERT(m_mailboxes.size() == 0); 131 ASSERT(m_mailboxes.size() == 0);
131 #ifndef NDEBUG 132 #ifndef NDEBUG
132 canvas2DLayerBridgeInstanceCounter.decrement(); 133 canvas2DLayerBridgeInstanceCounter.decrement();
133 #endif 134 #endif
134 } 135 }
135 136
136 void Canvas2DLayerBridge::startRecording() 137 void Canvas2DLayerBridge::startRecording()
137 { 138 {
138 ASSERT(m_isDeferralEnabled); 139 ASSERT(m_isDeferralEnabled);
139 m_recorder = adoptPtr(new SkPictureRecorder); 140 m_recorder = adoptPtr(new SkPictureRecorder);
140 m_recorder->beginRecording(m_size.width(), m_size.height(), nullptr); 141 m_recorder->beginRecording(m_size.width(), m_size.height(), nullptr);
141 if (m_imageBuffer) { 142 if (m_imageBuffer) {
142 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas()); 143 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas());
143 } 144 }
144 m_recordingPixelCount = 0; 145 m_recordingPixelCount = 0;
145 } 146 }
146 147
148 bool Canvas2DLayerBridge::shouldAccelerate(AccelerationHint hint) const
149 {
150 bool accelerate;
151 if (m_accelerationMode == ForceAccelerationForTesting)
152 accelerate = true;
153 else if (m_accelerationMode == DisableAcceleration)
154 accelerate = false;
155 else
156 accelerate = hint == PreferAcceleration;
157
158 if (accelerate && (!m_contextProvider || m_contextProvider->context3d()->isC ontextLost()))
159 accelerate = false;
160 return accelerate;
161 }
162
163 bool Canvas2DLayerBridge::isAccelerated() const
164 {
165 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.
166 return true;
167 if (m_surface) // && !m_layer is implied
168 return false;
169
170 // Whether or not to accelerate is not yet resolved, determine whether immed iate presentation
171 // of the canvas would result in the canvas being accelerated. Presentation is assumed to be
172 // a 'PreferAcceleration' operation.
173 return shouldAccelerate(PreferAcceleration);
174 }
175
176 SkSurface* Canvas2DLayerBridge::getOrCreateSurface(AccelerationHint hint)
177 {
178 if (!m_surface) {
179 if (m_layer)
180 return nullptr; // recreation will happen through restore()
181
182 bool wantAccelerated = shouldAccelerate(hint);
183 bool surfaceIsAccelerated;
184
185 m_surface = createSkSurface(wantAccelerated ? m_contextProvider->grConte xt() : nullptr, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated) ;
186
187 if (m_surface && surfaceIsAccelerated && !m_layer) {
188 m_layer = adoptPtr(Platform::current()->compositorSupport()->createE xternalTextureLayer(this));
189 m_layer->setOpaque(m_opacityMode == Opaque);
190 m_layer->setBlendBackgroundColor(m_opacityMode != Opaque);
191 GraphicsLayer::registerContentsLayer(m_layer->layer());
192 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality );
193 }
194 }
195 return m_surface.get();
196 }
197
147 SkCanvas* Canvas2DLayerBridge::canvas() 198 SkCanvas* Canvas2DLayerBridge::canvas()
148 { 199 {
149 if (!m_isDeferralEnabled) 200 if (!m_isDeferralEnabled) {
150 return m_surface->getCanvas(); 201 SkSurface* s = getOrCreateSurface();
202 return s ? s->getCanvas() : nullptr;
203 }
151 return m_recorder->getRecordingCanvas(); 204 return m_recorder->getRecordingCanvas();
152 } 205 }
153 206
154 void Canvas2DLayerBridge::disableDeferral() 207 void Canvas2DLayerBridge::disableDeferral()
155 { 208 {
156 // Disabling deferral is permanent: once triggered by disableDeferral() 209 // Disabling deferral is permanent: once triggered by disableDeferral()
157 // we stay in immediate mode indefinitely. This is a performance heuristic 210 // we stay in immediate mode indefinitely. This is a performance heuristic
158 // that significantly helps a number of use cases. The rationale is that if 211 // that significantly helps a number of use cases. The rationale is that if
159 // immediate rendering was needed once, it is likely to be needed at least 212 // immediate rendering was needed once, it is likely to be needed at least
160 // once per frame, which eliminates the possibility for inter-frame 213 // once per frame, which eliminates the possibility for inter-frame
161 // overdraw optimization. Furthermore, in cases where immediate mode is 214 // overdraw optimization. Furthermore, in cases where immediate mode is
162 // required multiple times per frame, the repeated flushing of deferred 215 // required multiple times per frame, the repeated flushing of deferred
163 // commands would cause significant overhead, so it is better to just stop 216 // commands would cause significant overhead, so it is better to just stop
164 // trying to defer altogether. 217 // trying to defer altogether.
165 if (!m_isDeferralEnabled) 218 if (!m_isDeferralEnabled)
166 return; 219 return;
167 220
168 m_isDeferralEnabled = false; 221 m_isDeferralEnabled = false;
169 flushRecordingOnly(); 222 flushRecordingOnly();
170 m_recorder.clear(); 223 m_recorder.clear();
171 // install the current matrix/clip stack onto the immediate canvas 224 // install the current matrix/clip stack onto the immediate canvas
172 m_imageBuffer->resetCanvas(m_surface->getCanvas()); 225 m_imageBuffer->resetCanvas(getOrCreateSurface()->getCanvas());
173 } 226 }
174 227
175 void Canvas2DLayerBridge::setImageBuffer(ImageBuffer* imageBuffer) 228 void Canvas2DLayerBridge::setImageBuffer(ImageBuffer* imageBuffer)
176 { 229 {
177 m_imageBuffer = imageBuffer; 230 m_imageBuffer = imageBuffer;
178 if (m_imageBuffer && m_isDeferralEnabled) { 231 if (m_imageBuffer && m_isDeferralEnabled) {
179 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas()); 232 m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas());
180 } 233 }
181 } 234 }
182 235
183 void Canvas2DLayerBridge::beginDestruction() 236 void Canvas2DLayerBridge::beginDestruction()
184 { 237 {
185 ASSERT(!m_destructionInProgress); 238 ASSERT(!m_destructionInProgress);
186 m_recorder.clear(); 239 m_recorder.clear();
187 m_imageBuffer = nullptr; 240 m_imageBuffer = nullptr;
188 m_destructionInProgress = true; 241 m_destructionInProgress = true;
189 setIsHidden(true); 242 setIsHidden(true);
190 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
191 m_surface.clear(); 243 m_surface.clear();
192 m_layer->clearTexture(); 244
193 // Orphaning the layer is required to trigger the recration of a new layer
194 // in the case where destruction is caused by a canvas resize. Test:
195 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
196 m_layer->layer()->removeFromParent();
197 // To anyone who ever hits this assert: Please update crbug.com/344666
198 // with repro steps.
199 unregisterTaskObserver(); 245 unregisterTaskObserver();
246
247 if (m_layer) {
248 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
249 m_layer->clearTexture();
250 // Orphaning the layer is required to trigger the recration of a new lay er
251 // in the case where destruction is caused by a canvas resize. Test:
252 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
253 m_layer->layer()->removeFromParent();
254 }
200 ASSERT(!m_bytesAllocated); 255 ASSERT(!m_bytesAllocated);
201 } 256 }
202 257
203 void Canvas2DLayerBridge::unregisterTaskObserver() 258 void Canvas2DLayerBridge::unregisterTaskObserver()
204 { 259 {
205 if (m_isRegisteredTaskObserver) { 260 if (m_isRegisteredTaskObserver) {
206 Platform::current()->currentThread()->removeTaskObserver(this); 261 Platform::current()->currentThread()->removeTaskObserver(this);
207 m_isRegisteredTaskObserver = false; 262 m_isRegisteredTaskObserver = false;
208 } 263 }
209 } 264 }
(...skipping 11 matching lines...) Expand all
221 if (m_isHidden == newHiddenValue) 276 if (m_isHidden == newHiddenValue)
222 return; 277 return;
223 278
224 m_isHidden = newHiddenValue; 279 m_isHidden = newHiddenValue;
225 if (isHidden() && !m_destructionInProgress) 280 if (isHidden() && !m_destructionInProgress)
226 flush(); 281 flush();
227 } 282 }
228 283
229 bool Canvas2DLayerBridge::writePixels(const SkImageInfo& origInfo, const void* p ixels, size_t rowBytes, int x, int y) 284 bool Canvas2DLayerBridge::writePixels(const SkImageInfo& origInfo, const void* p ixels, size_t rowBytes, int x, int y)
230 { 285 {
231 if (!m_surface) 286 if (!getOrCreateSurface())
232 return false; 287 return false;
233 if (x <= 0 && y <= 0 && x + origInfo.width() >= m_size.width() && y + origIn fo.height() >= m_size.height()) { 288 if (x <= 0 && y <= 0 && x + origInfo.width() >= m_size.width() && y + origIn fo.height() >= m_size.height()) {
234 skipQueuedDrawCommands(); 289 skipQueuedDrawCommands();
235 } else { 290 } else {
236 flush(); 291 flush();
237 } 292 }
238 ASSERT(!m_haveRecordedDrawCommands); 293 ASSERT(!m_haveRecordedDrawCommands);
239 // call write pixels on the surface, not the recording canvas. 294 // call write pixels on the surface, not the recording canvas.
240 // No need to call beginDirectSurfaceAccessModeIfNeeded() because writePixel s 295 // No need to call beginDirectSurfaceAccessModeIfNeeded() because writePixel s
241 // ignores the matrix and clip state. 296 // ignores the matrix and clip state.
242 return m_surface->getCanvas()->writePixels(origInfo, pixels, rowBytes, x, y) ; 297 return getOrCreateSurface()->getCanvas()->writePixels(origInfo, pixels, rowB ytes, x, y);
243 } 298 }
244 299
245 void Canvas2DLayerBridge::skipQueuedDrawCommands() 300 void Canvas2DLayerBridge::skipQueuedDrawCommands()
246 { 301 {
247 if (m_haveRecordedDrawCommands) { 302 if (m_haveRecordedDrawCommands) {
248 adoptRef(m_recorder->endRecording()); 303 adoptRef(m_recorder->endRecording());
249 startRecording(); 304 startRecording();
250 m_haveRecordedDrawCommands = false; 305 m_haveRecordedDrawCommands = false;
251 } 306 }
252 307
253 if (m_isDeferralEnabled) { 308 if (m_isDeferralEnabled) {
254 unregisterTaskObserver(); 309 unregisterTaskObserver();
255 if (m_rateLimiter) 310 if (m_rateLimiter)
256 m_rateLimiter->reset(); 311 m_rateLimiter->reset();
257 } 312 }
258 } 313 }
259 314
260 void Canvas2DLayerBridge::flushRecordingOnly() 315 void Canvas2DLayerBridge::flushRecordingOnly()
261 { 316 {
262 ASSERT(!m_destructionInProgress); 317 ASSERT(!m_destructionInProgress);
263 if (m_haveRecordedDrawCommands && m_surface) { 318
319 if (m_haveRecordedDrawCommands && getOrCreateSurface()) {
320 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecordingOnly");
264 RefPtr<SkPicture> picture = adoptRef(m_recorder->endRecording()); 321 RefPtr<SkPicture> picture = adoptRef(m_recorder->endRecording());
265 picture->playback(m_surface->getCanvas()); 322 picture->playback(getOrCreateSurface()->getCanvas());
266 if (m_isDeferralEnabled) 323 if (m_isDeferralEnabled)
267 startRecording(); 324 startRecording();
268 m_haveRecordedDrawCommands = false; 325 m_haveRecordedDrawCommands = false;
269 } 326 }
270 } 327 }
271 328
272 void Canvas2DLayerBridge::flush() 329 void Canvas2DLayerBridge::flush()
273 { 330 {
274 if (!m_surface) 331 if (!getOrCreateSurface())
275 return; 332 return;
276 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); 333 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
277 flushRecordingOnly(); 334 flushRecordingOnly();
278 m_surface->getCanvas()->flush(); 335 getOrCreateSurface()->getCanvas()->flush();
279 } 336 }
280 337
281 void Canvas2DLayerBridge::flushGpu() 338 void Canvas2DLayerBridge::flushGpu()
282 { 339 {
340 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushGpu");
283 flush(); 341 flush();
284 WebGraphicsContext3D* webContext = context(); 342 WebGraphicsContext3D* webContext = context();
285 if (isAccelerated() && webContext) 343 if (isAccelerated() && webContext)
286 webContext->flush(); 344 webContext->flush();
287 } 345 }
288 346
289 347
290 WebGraphicsContext3D* Canvas2DLayerBridge::context() 348 WebGraphicsContext3D* Canvas2DLayerBridge::context()
291 { 349 {
292 // Check on m_layer is necessary because context() may be called during 350 // Check on m_layer is necessary because context() may be called during
293 // the destruction of m_layer 351 // the destruction of m_layer
294 if (m_layer && !m_destructionInProgress) 352 if (m_layer && !m_destructionInProgress)
295 checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost. 353 checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost.
296 return m_contextProvider ? m_contextProvider->context3d() : 0; 354 return m_contextProvider ? m_contextProvider->context3d() : 0;
297 } 355 }
298 356
299 bool Canvas2DLayerBridge::checkSurfaceValid() 357 bool Canvas2DLayerBridge::checkSurfaceValid()
300 { 358 {
301 ASSERT(!m_destructionInProgress); 359 ASSERT(!m_destructionInProgress);
302 if (m_destructionInProgress || !m_surface) 360 if (m_destructionInProgress)
361 return false;
362 if (!m_layer)
363 return true;
364 if (!m_surface)
303 return false; 365 return false;
304 if (m_contextProvider->context3d()->isContextLost()) { 366 if (m_contextProvider->context3d()->isContextLost()) {
305 m_surface.clear(); 367 m_surface.clear();
306 for (auto mailboxInfo = m_mailboxes.begin(); mailboxInfo != m_mailboxes. end(); ++mailboxInfo) { 368 for (auto mailboxInfo = m_mailboxes.begin(); mailboxInfo != m_mailboxes. end(); ++mailboxInfo) {
307 if (mailboxInfo->m_image) 369 if (mailboxInfo->m_image)
308 mailboxInfo->m_image.clear(); 370 mailboxInfo->m_image.clear();
309 } 371 }
310 if (m_imageBuffer) 372 if (m_imageBuffer)
311 m_imageBuffer->notifySurfaceInvalid(); 373 m_imageBuffer->notifySurfaceInvalid();
312 } 374 }
313 return m_surface; 375 return m_surface;
314 } 376 }
315 377
316 bool Canvas2DLayerBridge::restoreSurface() 378 bool Canvas2DLayerBridge::restoreSurface()
317 { 379 {
318 ASSERT(!m_destructionInProgress); 380 ASSERT(!m_destructionInProgress);
319 if (m_destructionInProgress) 381 if (m_destructionInProgress)
320 return false; 382 return false;
321 ASSERT(m_layer && !m_surface); 383 ASSERT(isAccelerated() && !m_surface);
322 384
323 WebGraphicsContext3D* sharedContext = 0; 385 WebGraphicsContext3D* sharedContext = 0;
324 m_layer->clearTexture(); 386 m_layer->clearTexture();
325 m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraph icsContext3DProvider()); 387 m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraph icsContext3DProvider());
326 if (m_contextProvider) 388 if (m_contextProvider)
327 sharedContext = m_contextProvider->context3d(); 389 sharedContext = m_contextProvider->context3d();
328 390
329 if (sharedContext && !sharedContext->isContextLost()) { 391 if (sharedContext && !sharedContext->isContextLost()) {
330 GrContext* grCtx = m_contextProvider->grContext(); 392 GrContext* grCtx = m_contextProvider->grContext();
331 RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCou nt, m_opacityMode)); 393 bool surfaceIsAccelerated;
332 if (surface.get()) { 394 RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCou nt, m_opacityMode, &surfaceIsAccelerated));
395 // Current paradigm does support switching from accelerated to non-accel erated, which would be tricky
396 // due to changes to the layer tree, which can only happen at specific t imes during the document lifecycle.
397 // Therefore, we can only accept the restored surface if it is accelerat ed.
398 if (surface.get() && surfaceIsAccelerated) {
333 m_surface = surface.release(); 399 m_surface = surface.release();
334 m_initialSurfaceSaveCount = m_surface->getCanvas()->getSaveCount();
335 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 400 // FIXME: draw sad canvas picture into new buffer crbug.com/243842
336 } 401 }
337 } 402 }
338 403
339 return m_surface; 404 return m_surface;
340 } 405 }
341 406
342 bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap) 407 bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap)
343 { 408 {
409 ASSERT(isAccelerated());
344 if (m_destructionInProgress) { 410 if (m_destructionInProgress) {
345 // It can be hit in the following sequence. 411 // It can be hit in the following sequence.
346 // 1. Canvas draws something. 412 // 1. Canvas draws something.
347 // 2. The compositor begins the frame. 413 // 2. The compositor begins the frame.
348 // 3. Javascript makes a context be lost. 414 // 3. Javascript makes a context be lost.
349 // 4. Here. 415 // 4. Here.
350 return false; 416 return false;
351 } 417 }
352 if (bitmap) { 418 if (bitmap) {
353 // Using accelerated 2d canvas with software renderer, which 419 // Using accelerated 2d canvas with software renderer, which
354 // should only happen in tests that use fake graphics contexts 420 // should only happen in tests that use fake graphics contexts
355 // or in Android WebView in software mode. In this case, we do 421 // or in Android WebView in software mode. In this case, we do
356 // not care about producing any results for this canvas. 422 // not care about producing any results for this canvas.
357 skipQueuedDrawCommands(); 423 skipQueuedDrawCommands();
358 m_lastImageId = 0; 424 m_lastImageId = 0;
359 return false; 425 return false;
360 } 426 }
361 if (!checkSurfaceValid()) 427 if (!checkSurfaceValid())
362 return false; 428 return false;
363 429
364 WebGraphicsContext3D* webContext = context(); 430 WebGraphicsContext3D* webContext = context();
365 431
366 RefPtr<SkImage> image = newImageSnapshot(); 432 RefPtr<SkImage> image = newImageSnapshot(PreferAcceleration);
367 433
368 // Early exit if canvas was not drawn to since last prepareMailbox 434 // Early exit if canvas was not drawn to since last prepareMailbox
369 GLenum filter = m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_L INEAR; 435 GLenum filter = m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_L INEAR;
370 if (image->uniqueID() == m_lastImageId && filter == m_lastFilter) 436 if (image->uniqueID() == m_lastImageId && filter == m_lastFilter)
371 return false; 437 return false;
372 m_lastImageId = image->uniqueID(); 438 m_lastImageId = image->uniqueID();
373 m_lastFilter = filter; 439 m_lastFilter = filter;
374 440
375 { 441 {
376 MailboxInfo tmp; 442 MailboxInfo tmp;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 // Because we are changing the texture binding without going through skia, 493 // Because we are changing the texture binding without going through skia,
428 // we must dirty the context. 494 // we must dirty the context.
429 grContext->resetContext(kTextureBinding_GrGLBackendState); 495 grContext->resetContext(kTextureBinding_GrGLBackendState);
430 496
431 *outMailbox = mailboxInfo.m_mailbox; 497 *outMailbox = mailboxInfo.m_mailbox;
432 return true; 498 return true;
433 } 499 }
434 500
435 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb ox, bool lostResource) 501 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb ox, bool lostResource)
436 { 502 {
503 ASSERT(isAccelerated());
437 bool contextLost = !m_surface || m_contextProvider->context3d()->isContextLo st(); 504 bool contextLost = !m_surface || m_contextProvider->context3d()->isContextLo st();
438 ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); 505 ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this);
439 506
440 // Mailboxes are typically released in FIFO order, so we iterate 507 // Mailboxes are typically released in FIFO order, so we iterate
441 // from the end of m_mailboxes. 508 // from the end of m_mailboxes.
442 auto releasedMailboxInfo = m_mailboxes.end(); 509 auto releasedMailboxInfo = m_mailboxes.end();
443 auto firstMailbox = m_mailboxes.begin(); 510 auto firstMailbox = m_mailboxes.begin();
444 511
445 while (true) { 512 while (true) {
446 --releasedMailboxInfo; 513 --releasedMailboxInfo;
447 if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) { 514 if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) {
448 break; 515 break;
449 } 516 }
450 if (releasedMailboxInfo == firstMailbox) { 517 ASSERT(releasedMailboxInfo == firstMailbox);
451 // Reached last entry without finding a match, should never happen.
452 // FIXME: This used to be an ASSERT, and was (temporarily?) changed to a
453 // CRASH to facilitate the investigation of crbug.com/443898.
454 CRASH();
455 }
456 } 518 }
457 519
458 if (!contextLost) { 520 if (!contextLost) {
459 // Invalidate texture state in case the compositor altered it since the copy-on-write. 521 // Invalidate texture state in case the compositor altered it since the copy-on-write.
460 if (releasedMailboxInfo->m_image) { 522 if (releasedMailboxInfo->m_image) {
461 if (mailbox.syncPoint) { 523 if (mailbox.syncPoint) {
462 context()->waitSyncPoint(mailbox.syncPoint); 524 context()->waitSyncPoint(mailbox.syncPoint);
463 } 525 }
464 GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); 526 GrTexture* texture = releasedMailboxInfo->m_image->getTexture();
465 if (texture) { 527 if (texture) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 if (m_recordingPixelCount >= (m_size.width() * m_size.height() * Expensi veCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) { 565 if (m_recordingPixelCount >= (m_size.width() * m_size.height() * Expensi veCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) {
504 disableDeferral(); 566 disableDeferral();
505 } 567 }
506 } 568 }
507 if (!m_isRegisteredTaskObserver) { 569 if (!m_isRegisteredTaskObserver) {
508 Platform::current()->currentThread()->addTaskObserver(this); 570 Platform::current()->currentThread()->addTaskObserver(this);
509 m_isRegisteredTaskObserver = true; 571 m_isRegisteredTaskObserver = true;
510 } 572 }
511 } 573 }
512 574
575 void Canvas2DLayerBridge::prepareSurfaceForPaintingIfNeeded()
576 {
577 getOrCreateSurface(PreferAcceleration);
578 }
579
513 void Canvas2DLayerBridge::finalizeFrame(const FloatRect &dirtyRect) 580 void Canvas2DLayerBridge::finalizeFrame(const FloatRect &dirtyRect)
514 { 581 {
515 ASSERT(!m_destructionInProgress); 582 ASSERT(!m_destructionInProgress);
516 m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect)); 583 m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect));
517 if (m_rateLimiter) 584 if (m_rateLimiter)
518 m_rateLimiter->reset(); 585 m_rateLimiter->reset();
519 m_renderingTaskCompletedForCurrentFrame = false; 586 m_renderingTaskCompletedForCurrentFrame = false;
520 } 587 }
521 588
522 void Canvas2DLayerBridge::didProcessTask() 589 void Canvas2DLayerBridge::didProcessTask()
(...skipping 21 matching lines...) Expand all
544 611
545 m_renderingTaskCompletedForCurrentFrame = true; 612 m_renderingTaskCompletedForCurrentFrame = true;
546 unregisterTaskObserver(); 613 unregisterTaskObserver();
547 } 614 }
548 615
549 void Canvas2DLayerBridge::willProcessTask() 616 void Canvas2DLayerBridge::willProcessTask()
550 { 617 {
551 ASSERT_NOT_REACHED(); 618 ASSERT_NOT_REACHED();
552 } 619 }
553 620
554 PassRefPtr<SkImage> Canvas2DLayerBridge::newImageSnapshot() 621 PassRefPtr<SkImage> Canvas2DLayerBridge::newImageSnapshot(AccelerationHint hint)
555 { 622 {
556 if (!checkSurfaceValid()) 623 if (!checkSurfaceValid())
557 return nullptr; 624 return nullptr;
625 getOrCreateSurface(hint);
558 flush(); 626 flush();
559 // A readback operation may alter the texture parameters, which may affect 627 // A readback operation may alter the texture parameters, which may affect
560 // the compositor's behavior. Therefore, we must trigger copy-on-write 628 // the compositor's behavior. Therefore, we must trigger copy-on-write
561 // even though we are not technically writing to the texture, only to its 629 // even though we are not technically writing to the texture, only to its
562 // parameters. 630 // parameters.
563 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode); 631 getOrCreateSurface()->notifyContentWillChange(SkSurface::kRetain_ContentChan geMode);
564 return adoptRef(m_surface->newImageSnapshot()); 632 return adoptRef(m_surface->newImageSnapshot());
565 } 633 }
566 634
567 void Canvas2DLayerBridge::willOverwriteCanvas() 635 void Canvas2DLayerBridge::willOverwriteCanvas()
568 { 636 {
569 skipQueuedDrawCommands(); 637 skipQueuedDrawCommands();
570 } 638 }
571 639
572 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { 640 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
573 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 641 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
574 m_image = other.m_image; 642 m_image = other.m_image;
575 m_parentLayerBridge = other.m_parentLayerBridge; 643 m_parentLayerBridge = other.m_parentLayerBridge;
576 } 644 }
577 645
578 } // namespace blink 646 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698