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

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

Powered by Google App Engine
This is Rietveld 408576698