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

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

Powered by Google App Engine
This is Rietveld 408576698