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

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

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

Powered by Google App Engine
This is Rietveld 408576698