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

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

Issue 117703004: Free temporary GPU and memory resources held by inactive or hidden 2D canvases (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fixed upstream git branch Created 7 years 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 23 matching lines...) Expand all
34 #include "platform/graphics/Canvas2DLayerManager.h" 34 #include "platform/graphics/Canvas2DLayerManager.h"
35 #include "platform/graphics/GraphicsLayer.h" 35 #include "platform/graphics/GraphicsLayer.h"
36 #include "platform/graphics/gpu/SharedGraphicsContext3D.h" 36 #include "platform/graphics/gpu/SharedGraphicsContext3D.h"
37 #include "public/platform/Platform.h" 37 #include "public/platform/Platform.h"
38 #include "public/platform/WebCompositorSupport.h" 38 #include "public/platform/WebCompositorSupport.h"
39 #include "public/platform/WebGraphicsContext3D.h" 39 #include "public/platform/WebGraphicsContext3D.h"
40 40
41 using blink::WebExternalTextureLayer; 41 using blink::WebExternalTextureLayer;
42 using blink::WebGraphicsContext3D; 42 using blink::WebGraphicsContext3D;
43 43
44 namespace {
45 const size_t MaxSize = ~static_cast<size_t>(0);
eseidel 2013/12/19 02:56:32 std::limits?
46 }
47
44 namespace WebCore { 48 namespace WebCore {
45 49
46 static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const IntSize& size, int msaaSampleCount) 50 static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const IntSize& size, int msaaSampleCount)
47 { 51 {
48 ASSERT(!context3D->webContext()->isContextLost()); 52 ASSERT(!context3D->webContext()->isContextLost());
49 GrContext* gr = context3D->grContext(); 53 GrContext* gr = context3D->grContext();
50 if (!gr) 54 if (!gr)
51 return 0; 55 return 0;
52 gr->resetContext(); 56 gr->resetContext();
53 SkImageInfo info; 57 SkImageInfo info;
54 info.fWidth = size.width(); 58 info.fWidth = size.width();
55 info.fHeight = size.height(); 59 info.fHeight = size.height();
56 info.fColorType = kPMColor_SkColorType; 60 info.fColorType = kPMColor_SkColorType;
57 info.fAlphaType = kPremul_SkAlphaType; 61 info.fAlphaType = kPremul_SkAlphaType;
58 return adoptRef(SkSurface::NewRenderTarget(gr, info, msaaSampleCount)); 62 return adoptRef(SkSurface::NewRenderTarget(gr, info, msaaSampleCount));
59 } 63 }
60 64
61 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount) 65 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(Canvas2DLayerBridgeC lient* client, const IntSize& size, OpacityMode opacityMode, int msaaSampleCount )
62 { 66 {
63 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); 67 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
64 RefPtr<GraphicsContext3D> context = SharedGraphicsContext3D::get(); 68 RefPtr<GraphicsContext3D> context = SharedGraphicsContext3D::get();
65 RefPtr<SkSurface> surface(createSkSurface(context.get(), size, msaaSampleCou nt)); 69 RefPtr<SkSurface> surface(createSkSurface(context.get(), size, msaaSampleCou nt));
66 if (!surface) 70 if (!surface)
67 return 0; 71 return 0;
68 RefPtr<Canvas2DLayerBridge> layerBridge; 72 RefPtr<Canvas2DLayerBridge> layerBridge;
69 OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface. get())); 73 OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface. get()));
70 layerBridge = adoptRef(new Canvas2DLayerBridge(context, canvas.release(), ms aaSampleCount, opacityMode)); 74 layerBridge = adoptRef(new Canvas2DLayerBridge(client, context, canvas.relea se(), msaaSampleCount, opacityMode));
71 return layerBridge.release(); 75 return layerBridge.release();
72 } 76 }
73 77
74 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMod e) 78 Canvas2DLayerBridge::Canvas2DLayerBridge(Canvas2DLayerBridgeClient* client, Pass RefPtr<GraphicsContext3D> context, PassOwnPtr<SkDeferredCanvas> canvas, int msaa SampleCount, OpacityMode opacityMode)
75 : m_canvas(canvas) 79 : m_client(client)
80 , m_canvas(canvas)
76 , m_context(context) 81 , m_context(context)
77 , m_msaaSampleCount(msaaSampleCount) 82 , m_msaaSampleCount(msaaSampleCount)
78 , m_bytesAllocated(0) 83 , m_bytesAllocated(0)
79 , m_didRecordDrawCommand(false) 84 , m_didRecordDrawCommand(false)
80 , m_surfaceIsValid(true) 85 , m_surfaceIsValid(true)
81 , m_framesPending(0) 86 , m_framesPending(0)
87 , m_framesSinceMailboxRelease(0)
82 , m_destructionInProgress(false) 88 , m_destructionInProgress(false)
83 , m_rateLimitingEnabled(false) 89 , m_rateLimitingEnabled(false)
84 , m_next(0) 90 , m_next(0)
85 , m_prev(0) 91 , m_prev(0)
86 , m_lastImageId(0) 92 , m_lastImageId(0)
93 , m_releasedMailboxInfo(0)
87 { 94 {
88 ASSERT(m_canvas); 95 ASSERT(m_canvas);
96 ASSERT(m_client);
89 // Used by browser tests to detect the use of a Canvas2DLayerBridge. 97 // Used by browser tests to detect the use of a Canvas2DLayerBridge.
90 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); 98 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
91 m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createEx ternalTextureLayer(this)); 99 m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createEx ternalTextureLayer(this));
92 m_layer->setOpaque(opacityMode == Opaque); 100 m_layer->setOpaque(opacityMode == Opaque);
93 m_layer->setBlendBackgroundColor(opacityMode != Opaque); 101 m_layer->setBlendBackgroundColor(opacityMode != Opaque);
94 GraphicsLayer::registerContentsLayer(m_layer->layer()); 102 GraphicsLayer::registerContentsLayer(m_layer->layer());
95 m_layer->setRateLimitContext(m_rateLimitingEnabled); 103 m_layer->setRateLimitContext(m_rateLimitingEnabled);
96 m_canvas->setNotificationClient(this); 104 m_canvas->setNotificationClient(this);
97 } 105 }
98 106
99 Canvas2DLayerBridge::~Canvas2DLayerBridge() 107 Canvas2DLayerBridge::~Canvas2DLayerBridge()
100 { 108 {
101 ASSERT(m_destructionInProgress); 109 ASSERT(m_destructionInProgress);
102 m_layer.clear(); 110 m_layer.clear();
111 freeReleasedMailbox();
112 #if !ASSERT_DISABLED
103 Vector<MailboxInfo>::iterator mailboxInfo; 113 Vector<MailboxInfo>::iterator mailboxInfo;
104 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) { 114 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) {
105 ASSERT(mailboxInfo->m_status != MailboxInUse); 115 ASSERT(mailboxInfo->m_status != MailboxInUse);
106 if (mailboxInfo->m_status == MailboxReleased) { 116 ASSERT(mailboxInfo->m_status != MailboxReleased);
107 if (mailboxInfo->m_mailbox.syncPoint) {
108 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
109 mailboxInfo->m_mailbox.syncPoint = 0;
110 }
111 // Invalidate texture state in case the compositor altered it since the copy-on-write.
112 mailboxInfo->m_image->getTexture()->invalidateCachedState();
113 }
114 } 117 }
118 #endif
115 m_mailboxes.clear(); 119 m_mailboxes.clear();
116 } 120 }
117 121
118 void Canvas2DLayerBridge::beginDestruction() 122 void Canvas2DLayerBridge::beginDestruction()
119 { 123 {
120 ASSERT(!m_destructionInProgress); 124 ASSERT(!m_destructionInProgress);
121 m_destructionInProgress = true; 125 m_destructionInProgress = true;
122 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 126 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
123 m_canvas->setNotificationClient(0); 127 m_canvas->setNotificationClient(0);
124 m_layer->clearTexture(); 128 m_layer->clearTexture();
125 Canvas2DLayerManager::get().layerToBeDestroyed(this); 129 Canvas2DLayerManager::get().layerToBeDestroyed(this);
126 // Orphaning the layer is required to trigger the recration of a new layer 130 // Orphaning the layer is required to trigger the recration of a new layer
127 // in the case where destruction is caused by a canvas resize. Test: 131 // in the case where destruction is caused by a canvas resize. Test:
128 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html 132 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
129 m_layer->layer()->removeFromParent(); 133 m_layer->layer()->removeFromParent();
130 } 134 }
131 135
136 bool Canvas2DLayerBridge::hidden() const
137 {
138 return m_destructionInProgress || m_client->hidden();
139 }
140
141 void Canvas2DLayerBridge::freeTransientResources()
142 {
143 freeReleasedMailbox();
144 flush();
145 freeMemoryIfPossible(MaxSize);
146 }
147
148 bool Canvas2DLayerBridge::hasTransientResources() const
149 {
150 return hasReleasedMailbox() || bytesAllocated();
151 }
152
132 void Canvas2DLayerBridge::limitPendingFrames() 153 void Canvas2DLayerBridge::limitPendingFrames()
133 { 154 {
134 ASSERT(!m_destructionInProgress); 155 ASSERT(!m_destructionInProgress);
135 if (m_didRecordDrawCommand) { 156 if (m_didRecordDrawCommand) {
136 m_framesPending++; 157 m_framesPending++;
137 m_didRecordDrawCommand = false; 158 m_didRecordDrawCommand = false;
138 if (m_framesPending > 1) { 159 if (m_framesPending > 1) {
139 // Turn on the rate limiter if this layer tends to accumulate a 160 // Turn on the rate limiter if this layer tends to accumulate a
140 // non-discardable multi-frame backlog of draw commands. 161 // non-discardable multi-frame backlog of draw commands.
141 setRateLimitingEnabled(true); 162 setRateLimitingEnabled(true);
142 } 163 }
143 if (m_rateLimitingEnabled) { 164 if (m_rateLimitingEnabled) {
144 flush(); 165 flush();
145 } 166 }
146 } 167 }
168 if (m_releasedMailboxInfo && ++m_framesSinceMailboxRelease >= 2) {
169 freeReleasedMailbox();
170 }
147 } 171 }
148 172
149 void Canvas2DLayerBridge::prepareForDraw() 173 void Canvas2DLayerBridge::prepareForDraw()
150 { 174 {
151 ASSERT(!m_destructionInProgress); 175 ASSERT(!m_destructionInProgress);
152 ASSERT(m_layer); 176 ASSERT(m_layer);
153 if (!isValid()) { 177 if (!isValid()) {
154 if (m_canvas) { 178 if (m_canvas) {
155 // drop pending commands because there is no surface to draw to 179 // drop pending commands because there is no surface to draw to
156 m_canvas->silentFlush(); 180 m_canvas->silentFlush();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr _t)bytesFreed)); 231 Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr _t)bytesFreed));
208 m_bytesAllocated -= bytesFreed; 232 m_bytesAllocated -= bytesFreed;
209 return bytesFreed; 233 return bytesFreed;
210 } 234 }
211 235
212 void Canvas2DLayerBridge::flush() 236 void Canvas2DLayerBridge::flush()
213 { 237 {
214 ASSERT(!m_destructionInProgress); 238 ASSERT(!m_destructionInProgress);
215 if (m_canvas->hasPendingCommands()) { 239 if (m_canvas->hasPendingCommands()) {
216 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); 240 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
241 freeReleasedMailbox(); // To avoid unnecessary triple-buffering
217 m_canvas->flush(); 242 m_canvas->flush();
218 } 243 }
219 } 244 }
220 245
246 void Canvas2DLayerBridge::freeReleasedMailbox()
247 {
248 if (m_releasedMailboxInfo) {
249 ASSERT(m_releasedMailboxInfo->m_status == MailboxReleased);
250 if (m_releasedMailboxInfo->m_mailbox.syncPoint) {
251 context()->waitSyncPoint(m_releasedMailboxInfo->m_mailbox.syncPoint) ;
252 m_releasedMailboxInfo->m_mailbox.syncPoint = 0;
253 }
254 // Invalidate texture state in case the compositor altered it since the copy-on-write.
255 m_releasedMailboxInfo->m_image->getTexture()->invalidateCachedState();
256 m_releasedMailboxInfo->m_image.clear();
257 m_releasedMailboxInfo->m_status = MailboxAvailable;
258 m_releasedMailboxInfo = 0;
259 }
260 }
261
221 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() 262 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context()
222 { 263 {
223 // Check on m_layer is necessary because context() may be called during 264 // Check on m_layer is necessary because context() may be called during
224 // the destruction of m_layer 265 // the destruction of m_layer
225 if (m_layer) { 266 if (m_layer) {
226 isValid(); // To ensure rate limiter is disabled if context is lost. 267 isValid(); // To ensure rate limiter is disabled if context is lost.
227 } 268 }
228 return m_context->webContext(); 269 return m_context->webContext();
229 } 270 }
230 271
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 m_canvas->silentFlush(); 311 m_canvas->silentFlush();
271 return false; 312 return false;
272 } 313 }
273 if (!isValid()) 314 if (!isValid())
274 return false; 315 return false;
275 // Release to skia textures that were previouosly released by the 316 // Release to skia textures that were previouosly released by the
276 // compositor. We do this before acquiring the next snapshot in 317 // compositor. We do this before acquiring the next snapshot in
277 // order to cap maximum gpu memory consumption. 318 // order to cap maximum gpu memory consumption.
278 m_context->makeContextCurrent(); 319 m_context->makeContextCurrent();
279 flush(); 320 flush();
280 Vector<MailboxInfo>::iterator mailboxInfo; 321
281 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) { 322 RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot());
282 if (mailboxInfo->m_status == MailboxReleased) { 323
283 if (mailboxInfo->m_mailbox.syncPoint) {
284 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
285 mailboxInfo->m_mailbox.syncPoint = 0;
286 }
287 // Invalidate texture state in case the compositor altered it since the copy-on-write.
288 mailboxInfo->m_image->getTexture()->invalidateCachedState();
289 mailboxInfo->m_image.reset(0);
290 mailboxInfo->m_status = MailboxAvailable;
291 }
292 }
293 SkAutoTUnref<SkImage> image(m_canvas->newImageSnapshot());
294 // Early exit if canvas was not drawn to since last prepareMailbox 324 // Early exit if canvas was not drawn to since last prepareMailbox
295 if (image->uniqueID() == m_lastImageId) 325 if (image->uniqueID() == m_lastImageId)
296 return false; 326 return false;
297 m_lastImageId = image->uniqueID(); 327 m_lastImageId = image->uniqueID();
298 328
299 mailboxInfo = createMailboxInfo(); 329 MailboxInfo* mailboxInfo = createMailboxInfo();
300 mailboxInfo->m_status = MailboxInUse; 330 mailboxInfo->m_status = MailboxInUse;
301 mailboxInfo->m_image.swap(&image); 331 mailboxInfo->m_image = image;
332
302 // Because of texture sharing with the compositor, we must invalidate 333 // Because of texture sharing with the compositor, we must invalidate
303 // the state cached in skia so that the deferred copy on write 334 // the state cached in skia so that the deferred copy on write
304 // in SkSurface_Gpu does not make any false assumptions. 335 // in SkSurface_Gpu does not make any false assumptions.
305 mailboxInfo->m_image->getTexture()->invalidateCachedState(); 336 mailboxInfo->m_image->getTexture()->invalidateCachedState();
306 337
307 ASSERT(mailboxInfo->m_mailbox.syncPoint == 0); 338 ASSERT(mailboxInfo->m_mailbox.syncPoint == 0);
308 ASSERT(mailboxInfo->m_image.get()); 339 ASSERT(mailboxInfo->m_image.get());
309 ASSERT(mailboxInfo->m_image->getTexture()); 340 ASSERT(mailboxInfo->m_image->getTexture());
310 341
311 m_context->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->ge tTextureHandle()); 342 m_context->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->ge tTextureHandle());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 // kMaxSwapBuffersPending+1 (in render_widget.h). 379 // kMaxSwapBuffersPending+1 (in render_widget.h).
349 // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. 380 // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2.
350 // TODO(piman): fix this. 381 // TODO(piman): fix this.
351 ASSERT(m_mailboxes.size() <= 4); 382 ASSERT(m_mailboxes.size() <= 4);
352 ASSERT(mailboxInfo < m_mailboxes.end()); 383 ASSERT(mailboxInfo < m_mailboxes.end());
353 return mailboxInfo; 384 return mailboxInfo;
354 } 385 }
355 386
356 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox & mailbox) 387 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox & mailbox)
357 { 388 {
389 freeReleasedMailbox(); // Never have more than one mailbox in the released s tate.
358 Vector<MailboxInfo>::iterator mailboxInfo; 390 Vector<MailboxInfo>::iterator mailboxInfo;
359 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) { 391 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) {
360 if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.na me))) { 392 if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.na me))) {
361 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; 393 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
362 ASSERT(mailboxInfo->m_status == MailboxInUse); 394 ASSERT(mailboxInfo->m_status == MailboxInUse);
363 mailboxInfo->m_status = MailboxReleased; 395 mailboxInfo->m_status = MailboxReleased;
364 // Trigger Canvas2DLayerBridge self-destruction if this is the 396 // Trigger Canvas2DLayerBridge self-destruction if this is the
365 // last live mailbox and the layer bridge is not externally 397 // last live mailbox and the layer bridge is not externally
366 // referenced. 398 // referenced.
367 ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); 399 ASSERT(mailboxInfo->m_parentLayerBridge.get() == this);
368 mailboxInfo->m_parentLayerBridge.clear(); 400 mailboxInfo->m_parentLayerBridge.clear();
401 m_releasedMailboxInfo = mailboxInfo;
402 m_framesSinceMailboxRelease = 0;
403 if (hidden()) {
404 freeReleasedMailbox();
405 } else {
406 Canvas2DLayerManager::get().setLayerHasFreeableResources(this);
407 }
369 return; 408 return;
370 } 409 }
371 } 410 }
372 } 411 }
373 412
374 blink::WebLayer* Canvas2DLayerBridge::layer() const 413 blink::WebLayer* Canvas2DLayerBridge::layer() const
375 { 414 {
376 ASSERT(m_layer); 415 ASSERT(m_layer);
377 return m_layer->layer(); 416 return m_layer->layer();
378 } 417 }
(...skipping 15 matching lines...) Expand all
394 m_context->flush(); 433 m_context->flush();
395 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( ); 434 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( );
396 if (renderTarget) { 435 if (renderTarget) {
397 return renderTarget->asTexture()->getTextureHandle(); 436 return renderTarget->asTexture()->getTextureHandle();
398 } 437 }
399 return 0; 438 return 0;
400 } 439 }
401 440
402 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { 441 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
403 // This copy constructor should only be used for Vector reallocation 442 // This copy constructor should only be used for Vector reallocation
404 // Assuming 'other' is to be destroyed, we swap m_image ownership 443 // Assuming 'other' is to be destroyed, we transfer m_image ownership
405 // rather than do a refcount dance. 444 // rather than do a refcount dance.
406 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 445 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
407 m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image)); 446 m_image = const_cast<MailboxInfo*>(&other)->m_image.release();
408 m_status = other.m_status; 447 m_status = other.m_status;
409 } 448 }
410 449
411 } 450 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698