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

Side by Side Diff: cc/CCThreadProxy.cpp

Issue 10916292: Adaptively throttle texture uploads (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Add tests. Created 8 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
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 6
7 #include "CCThreadProxy.h" 7 #include "CCThreadProxy.h"
8 8
9 #include "CCDelayBasedTimeSource.h" 9 #include "CCDelayBasedTimeSource.h"
10 #include "CCDrawQuad.h" 10 #include "CCDrawQuad.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 , m_started(false) 54 , m_started(false)
55 , m_texturesAcquired(true) 55 , m_texturesAcquired(true)
56 , m_inCompositeAndReadback(false) 56 , m_inCompositeAndReadback(false)
57 , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread())) 57 , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread()))
58 , m_beginFrameCompletionEventOnImplThread(0) 58 , m_beginFrameCompletionEventOnImplThread(0)
59 , m_readbackRequestOnImplThread(0) 59 , m_readbackRequestOnImplThread(0)
60 , m_commitCompletionEventOnImplThread(0) 60 , m_commitCompletionEventOnImplThread(0)
61 , m_textureAcquisitionCompletionEventOnImplThread(0) 61 , m_textureAcquisitionCompletionEventOnImplThread(0)
62 , m_resetContentsTexturesPurgedAfterCommitOnImplThread(false) 62 , m_resetContentsTexturesPurgedAfterCommitOnImplThread(false)
63 , m_nextFrameIsNewlyCommittedFrameOnImplThread(false) 63 , m_nextFrameIsNewlyCommittedFrameOnImplThread(false)
64 , m_mostRecentMaxTextureUpdatesOnMainThread(CCTextureUpdateController::maxTe xtureUpdatesDefault())
64 , m_renderVSyncEnabled(layerTreeHost->settings().renderVSyncEnabled) 65 , m_renderVSyncEnabled(layerTreeHost->settings().renderVSyncEnabled)
66 , m_totalCommitTime(0)
67 , m_totalCommitCount(0)
65 { 68 {
66 TRACE_EVENT0("cc", "CCThreadProxy::CCThreadProxy"); 69 TRACE_EVENT0("cc", "CCThreadProxy::CCThreadProxy");
67 ASSERT(isMainThread()); 70 ASSERT(isMainThread());
68 } 71 }
69 72
70 CCThreadProxy::~CCThreadProxy() 73 CCThreadProxy::~CCThreadProxy()
71 { 74 {
72 TRACE_EVENT0("cc", "CCThreadProxy::~CCThreadProxy"); 75 TRACE_EVENT0("cc", "CCThreadProxy::~CCThreadProxy");
73 ASSERT(isMainThread()); 76 ASSERT(isMainThread());
74 ASSERT(!m_started); 77 ASSERT(!m_started);
75 } 78 }
76 79
77 bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) 80 bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
78 { 81 {
79 TRACE_EVENT0("cc", "CCThreadPRoxy::compositeAndReadback"); 82 TRACE_EVENT0("cc", "CCThreadPRoxy::compositeAndReadback");
80 ASSERT(isMainThread()); 83 ASSERT(isMainThread());
81 ASSERT(m_layerTreeHost); 84 ASSERT(m_layerTreeHost);
82 85
83 if (!m_layerTreeHost->initializeRendererIfNeeded()) { 86 if (!m_layerTreeHost->initializeRendererIfNeeded()) {
84 TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized"); 87 TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized");
85 return false; 88 return false;
86 } 89 }
87 90
88
89 // Perform a synchronous commit. 91 // Perform a synchronous commit.
90 { 92 {
91 DebugScopedSetMainThreadBlocked mainThreadBlocked; 93 DebugScopedSetMainThreadBlocked mainThreadBlocked;
92 CCCompletionEvent beginFrameCompletion; 94 CCCompletionEvent beginFrameCompletion;
93 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy: :forceBeginFrameOnImplThread, &beginFrameCompletion)); 95 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy: :forceBeginFrameOnImplThread, &beginFrameCompletion));
94 beginFrameCompletion.wait(); 96 beginFrameCompletion.wait();
95 } 97 }
96 m_inCompositeAndReadback = true; 98 m_inCompositeAndReadback = true;
97 beginFrame(); 99 beginFrame(m_mostRecentMaxTextureUpdatesOnMainThread);
98 m_inCompositeAndReadback = false; 100 m_inCompositeAndReadback = false;
99 101
100 // Perform a synchronous readback. 102 // Perform a synchronous readback.
101 ReadbackRequest request; 103 ReadbackRequest request;
102 request.rect = rect; 104 request.rect = rect;
103 request.pixels = pixels; 105 request.pixels = pixels;
104 { 106 {
105 DebugScopedSetMainThreadBlocked mainThreadBlocked; 107 DebugScopedSetMainThreadBlocked mainThreadBlocked;
106 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy: :requestReadbackOnImplThread, &request)); 108 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy: :requestReadbackOnImplThread, &request));
107 request.completion.wait(); 109 request.completion.wait();
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 context.leakPtr(), 244 context.leakPtr(),
243 &recreateSucceeded, 245 &recreateSucceeded,
244 &capabilities)); 246 &capabilities));
245 completion.wait(); 247 completion.wait();
246 248
247 if (recreateSucceeded) 249 if (recreateSucceeded)
248 m_RendererCapabilitiesMainThreadCopy = capabilities; 250 m_RendererCapabilitiesMainThreadCopy = capabilities;
249 return recreateSucceeded; 251 return recreateSucceeded;
250 } 252 }
251 253
252 void CCThreadProxy::implSideRenderingStats(CCRenderingStats& stats) 254 void CCThreadProxy::renderingStats(CCRenderingStats& stats)
253 { 255 {
254 ASSERT(isMainThread()); 256 ASSERT(isMainThread());
255 257
256 DebugScopedSetMainThreadBlocked mainThreadBlocked; 258 DebugScopedSetMainThreadBlocked mainThreadBlocked;
257 CCCompletionEvent completion; 259 CCCompletionEvent completion;
258 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::imp lSideRenderingStatsOnImplThread, 260 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::ren deringStatsOnImplThread,
259 &completion, 261 &completion,
260 &stats)); 262 &stats));
263 stats.totalCommitTimeInSeconds = m_totalCommitTime;
264 stats.totalCommitCount = m_totalCommitCount;
265
261 completion.wait(); 266 completion.wait();
262 } 267 }
263 268
264 const RendererCapabilities& CCThreadProxy::rendererCapabilities() const 269 const RendererCapabilities& CCThreadProxy::rendererCapabilities() const
265 { 270 {
266 ASSERT(m_rendererInitialized); 271 ASSERT(m_rendererInitialized);
267 return m_RendererCapabilitiesMainThreadCopy; 272 return m_RendererCapabilitiesMainThreadCopy;
268 } 273 }
269 274
270 void CCThreadProxy::loseContext() 275 void CCThreadProxy::loseContext()
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 void CCThreadProxy::scheduledActionBeginFrame() 456 void CCThreadProxy::scheduledActionBeginFrame()
452 { 457 {
453 TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame"); 458 TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame");
454 ASSERT(!m_pendingBeginFrameRequest); 459 ASSERT(!m_pendingBeginFrameRequest);
455 m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState()); 460 m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState());
456 m_pendingBeginFrameRequest->monotonicFrameBeginTime = monotonicallyIncreasin gTime(); 461 m_pendingBeginFrameRequest->monotonicFrameBeginTime = monotonicallyIncreasin gTime();
457 m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollD eltas(); 462 m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollD eltas();
458 m_pendingBeginFrameRequest->contentsTexturesWereDeleted = m_layerTreeHostImp l->contentsTexturesPurged(); 463 m_pendingBeginFrameRequest->contentsTexturesWereDeleted = m_layerTreeHostImp l->contentsTexturesPurged();
459 m_pendingBeginFrameRequest->memoryAllocationLimitBytes = m_layerTreeHostImpl ->memoryAllocationLimitBytes(); 464 m_pendingBeginFrameRequest->memoryAllocationLimitBytes = m_layerTreeHostImpl ->memoryAllocationLimitBytes();
460 465
461 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFr ame)); 466 size_t maxTextureUpdates = CCTextureUpdateController::maxTextureUpdatesDefau lt();
467 if (m_layerTreeHostImpl && m_layerTreeHostImpl->renderer() && m_layerTreeHos tImpl->renderer()->textureUploader())
468 maxTextureUpdates = CCTextureUpdateController::maxTextureUpdates(m_layer TreeHostImpl->renderer()->textureUploader());
469
470 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFr ame, maxTextureUpdates));
462 471
463 if (m_beginFrameCompletionEventOnImplThread) { 472 if (m_beginFrameCompletionEventOnImplThread) {
464 m_beginFrameCompletionEventOnImplThread->signal(); 473 m_beginFrameCompletionEventOnImplThread->signal();
465 m_beginFrameCompletionEventOnImplThread = 0; 474 m_beginFrameCompletionEventOnImplThread = 0;
466 } 475 }
467 } 476 }
468 477
469 void CCThreadProxy::beginFrame() 478 void CCThreadProxy::beginFrame(size_t maxTextureUpdates)
470 { 479 {
471 TRACE_EVENT0("cc", "CCThreadProxy::beginFrame"); 480 TRACE_EVENT0("cc", "CCThreadProxy::beginFrame");
472 ASSERT(isMainThread()); 481 ASSERT(isMainThread());
482
483 m_mostRecentMaxTextureUpdatesOnMainThread = maxTextureUpdates;
484
473 if (!m_layerTreeHost) 485 if (!m_layerTreeHost)
474 return; 486 return;
475 487
476 if (!m_pendingBeginFrameRequest) { 488 if (!m_pendingBeginFrameRequest) {
477 TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage"); 489 TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage");
478 return; 490 return;
479 } 491 }
480 492
481 if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::ha veCompositorThreadContext()) 493 if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::ha veCompositorThreadContext())
482 WebSharedGraphicsContext3D::createCompositorThreadContext(); 494 WebSharedGraphicsContext3D::createCompositorThreadContext();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 536
525 if (!m_layerTreeHost->initializeRendererIfNeeded()) { 537 if (!m_layerTreeHost->initializeRendererIfNeeded()) {
526 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed"); 538 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed");
527 return; 539 return;
528 } 540 }
529 541
530 if (request->contentsTexturesWereDeleted) 542 if (request->contentsTexturesWereDeleted)
531 m_layerTreeHost->unlinkAllContentTextures(); 543 m_layerTreeHost->unlinkAllContentTextures();
532 544
533 OwnPtr<CCTextureUpdateQueue> queue = adoptPtr(new CCTextureUpdateQueue); 545 OwnPtr<CCTextureUpdateQueue> queue = adoptPtr(new CCTextureUpdateQueue);
534 m_layerTreeHost->updateLayers(*(queue.get()), request->memoryAllocationLimit Bytes); 546 m_layerTreeHost->updateLayers(*(queue.get()), request->memoryAllocationLimit Bytes, maxTextureUpdates);
535 547
536 // Once single buffered layers are committed, they cannot be modified until 548 // Once single buffered layers are committed, they cannot be modified until
537 // they are drawn by the impl thread. 549 // they are drawn by the impl thread.
538 m_texturesAcquired = false; 550 m_texturesAcquired = false;
539 551
540 m_layerTreeHost->willCommit(); 552 m_layerTreeHost->willCommit();
541 // Before applying scrolls and calling animate, we set m_animateRequested to 553 // Before applying scrolls and calling animate, we set m_animateRequested to
542 // false. If it is true now, it means setNeedAnimate was called again, but 554 // false. If it is true now, it means setNeedAnimate was called again, but
543 // during a state when m_commitRequestSentToImplThread = true. We need to 555 // during a state when m_commitRequestSentToImplThread = true. We need to
544 // force that call to happen again now so that the commit request is sent to 556 // force that call to happen again now so that the commit request is sent to
545 // the impl thread. 557 // the impl thread.
546 if (m_animateRequested) { 558 if (m_animateRequested) {
547 // Forces setNeedsAnimate to consider posting a commit task. 559 // Forces setNeedsAnimate to consider posting a commit task.
548 m_animateRequested = false; 560 m_animateRequested = false;
549 setNeedsAnimate(); 561 setNeedsAnimate();
550 } 562 }
551 563
552 // Notify the impl thread that the beginFrame has completed. This will 564 // Notify the impl thread that the beginFrame has completed. This will
553 // begin the commit process, which is blocking from the main thread's 565 // begin the commit process, which is blocking from the main thread's
554 // point of view, but asynchronously performed on the impl thread, 566 // point of view, but asynchronously performed on the impl thread,
555 // coordinated by the CCScheduler. 567 // coordinated by the CCScheduler.
556 { 568 {
557 TRACE_EVENT0("cc", "commit"); 569 TRACE_EVENT0("cc", "commit");
570
558 DebugScopedSetMainThreadBlocked mainThreadBlocked; 571 DebugScopedSetMainThreadBlocked mainThreadBlocked;
559 572
573 double startTime = WTF::monotonicallyIncreasingTime();
560 CCCompletionEvent completion; 574 CCCompletionEvent completion;
561 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy: :beginFrameCompleteOnImplThread, &completion, queue.release(), request->contents TexturesWereDeleted)); 575 CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy: :beginFrameCompleteOnImplThread, &completion, queue.release(), request->contents TexturesWereDeleted, maxTextureUpdates));
562 completion.wait(); 576 completion.wait();
577 double endTime = WTF::monotonicallyIncreasingTime();
578
579 double commitTime = endTime - startTime;
580 m_totalCommitTime += commitTime;
581 m_totalCommitCount++;
563 } 582 }
564 583
565 m_layerTreeHost->commitComplete(); 584 m_layerTreeHost->commitComplete();
566 m_layerTreeHost->didBeginFrame(); 585 m_layerTreeHost->didBeginFrame();
567 } 586 }
568 587
569 void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion , PassOwnPtr<CCTextureUpdateQueue> queue, bool contentsTexturesWereDeleted) 588 void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion , PassOwnPtr<CCTextureUpdateQueue> queue, bool contentsTexturesWereDeleted, size _t maxTextureUpdates)
570 { 589 {
571 TRACE_EVENT0("cc", "CCThreadProxy::beginFrameCompleteOnImplThread"); 590 TRACE_EVENT0("cc", "CCThreadProxy::beginFrameCompleteOnImplThread");
572 ASSERT(!m_commitCompletionEventOnImplThread); 591 ASSERT(!m_commitCompletionEventOnImplThread);
573 ASSERT(isImplThread() && isMainThreadBlocked()); 592 ASSERT(isImplThread() && isMainThreadBlocked());
574 ASSERT(m_schedulerOnImplThread); 593 ASSERT(m_schedulerOnImplThread);
575 ASSERT(m_schedulerOnImplThread->commitPending()); 594 ASSERT(m_schedulerOnImplThread->commitPending());
576 595
577 if (!m_layerTreeHostImpl) { 596 if (!m_layerTreeHostImpl) {
578 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree"); 597 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
579 completion->signal(); 598 completion->signal();
580 return; 599 return;
581 } 600 }
582 601
583 if (contentsTexturesWereDeleted) { 602 if (contentsTexturesWereDeleted) {
584 ASSERT(m_layerTreeHostImpl->contentsTexturesPurged()); 603 ASSERT(m_layerTreeHostImpl->contentsTexturesPurged());
585 // We unlinked all textures on the main thread, delete them now. 604 // We unlinked all textures on the main thread, delete them now.
586 m_layerTreeHost->deleteUnlinkedTextures(); 605 m_layerTreeHost->deleteUnlinkedTextures();
587 // Mark that we can start drawing again when this commit is complete. 606 // Mark that we can start drawing again when this commit is complete.
588 m_resetContentsTexturesPurgedAfterCommitOnImplThread = true; 607 m_resetContentsTexturesPurgedAfterCommitOnImplThread = true;
589 } else if (m_layerTreeHostImpl->contentsTexturesPurged()) { 608 } else if (m_layerTreeHostImpl->contentsTexturesPurged()) {
590 // We purged the content textures on the impl thread between the time we 609 // We purged the content textures on the impl thread between the time we
591 // posted the beginFrame task and now, meaning we have a bunch of 610 // posted the beginFrame task and now, meaning we have a bunch of
592 // uploads that are now invalid. Clear the uploads (they all go to 611 // uploads that are now invalid. Clear the uploads (they all go to
593 // content textures), and kick another commit to fill them again. 612 // content textures), and kick another commit to fill them again.
594 queue->clearUploads(); 613 queue->clearUploads();
595 setNeedsCommitOnImplThread(); 614 setNeedsCommitOnImplThread();
596 } 615 }
597 616
598 m_currentTextureUpdateControllerOnImplThread = CCTextureUpdateController::cr eate(CCProxy::implThread(), queue, m_layerTreeHostImpl->resourceProvider(), m_la yerTreeHostImpl->renderer()->textureCopier(), m_layerTreeHostImpl->renderer()->t extureUploader()); 617 m_currentTextureUpdateControllerOnImplThread = CCTextureUpdateController::cr eate(CCProxy::implThread(), queue, m_layerTreeHostImpl->resourceProvider(), m_la yerTreeHostImpl->renderer()->textureCopier(), m_layerTreeHostImpl->renderer()->t extureUploader(), maxTextureUpdates);
599 m_commitCompletionEventOnImplThread = completion; 618 m_commitCompletionEventOnImplThread = completion;
600 619
601 m_schedulerOnImplThread->beginFrameComplete(); 620 m_schedulerOnImplThread->beginFrameComplete();
602 } 621 }
603 622
604 void CCThreadProxy::beginFrameAbortedOnImplThread() 623 void CCThreadProxy::beginFrameAbortedOnImplThread()
605 { 624 {
606 TRACE_EVENT0("cc", "CCThreadProxy::beginFrameAbortedOnImplThread"); 625 TRACE_EVENT0("cc", "CCThreadProxy::beginFrameAbortedOnImplThread");
607 ASSERT(isImplThread()); 626 ASSERT(isImplThread());
608 ASSERT(m_schedulerOnImplThread); 627 ASSERT(m_schedulerOnImplThread);
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 m_schedulerOnImplThread.clear(); 907 m_schedulerOnImplThread.clear();
889 completion->signal(); 908 completion->signal();
890 } 909 }
891 910
892 void CCThreadProxy::setFullRootLayerDamageOnImplThread() 911 void CCThreadProxy::setFullRootLayerDamageOnImplThread()
893 { 912 {
894 ASSERT(isImplThread()); 913 ASSERT(isImplThread());
895 m_layerTreeHostImpl->setFullRootLayerDamage(); 914 m_layerTreeHostImpl->setFullRootLayerDamage();
896 } 915 }
897 916
898 size_t CCThreadProxy::maxPartialTextureUpdates() const
899 {
900 return CCTextureUpdateController::maxPartialTextureUpdates();
901 }
902
903 void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, C CGraphicsContext* contextPtr, bool* recreateSucceeded, RendererCapabilities* cap abilities) 917 void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, C CGraphicsContext* contextPtr, bool* recreateSucceeded, RendererCapabilities* cap abilities)
904 { 918 {
905 TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread"); 919 TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread");
906 ASSERT(isImplThread()); 920 ASSERT(isImplThread());
907 if (!m_layerTreeHostImpl->contentsTexturesPurged()) 921 if (!m_layerTreeHostImpl->contentsTexturesPurged())
908 m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl- >resourceProvider()); 922 m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl- >resourceProvider());
909 *recreateSucceeded = m_layerTreeHostImpl->initializeRenderer(adoptPtr(contex tPtr), textureUploader); 923 *recreateSucceeded = m_layerTreeHostImpl->initializeRenderer(adoptPtr(contex tPtr), textureUploader);
910 if (*recreateSucceeded) { 924 if (*recreateSucceeded) {
911 *capabilities = m_layerTreeHostImpl->rendererCapabilities(); 925 *capabilities = m_layerTreeHostImpl->rendererCapabilities();
912 m_schedulerOnImplThread->didRecreateContext(); 926 m_schedulerOnImplThread->didRecreateContext();
913 } 927 }
914 completion->signal(); 928 completion->signal();
915 } 929 }
916 930
917 void CCThreadProxy::implSideRenderingStatsOnImplThread(CCCompletionEvent* comple tion, CCRenderingStats* stats) 931 void CCThreadProxy::renderingStatsOnImplThread(CCCompletionEvent* completion, CC RenderingStats* stats)
918 { 932 {
919 ASSERT(isImplThread()); 933 ASSERT(isImplThread());
920 m_layerTreeHostImpl->renderingStats(*stats); 934 m_layerTreeHostImpl->renderingStats(*stats);
921 completion->signal(); 935 completion->signal();
922 } 936 }
923 937
924 } // namespace WebCore 938 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698