void CCThreadProxy::setNeedsRedraw() { ASSERT(isMainThread()); TRACE_EVENT("CCThreadProxy::setNeedsRedraw", this, 0); CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFullRootLayerDamageOnImplThread)); CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread)); }
bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) { TRACE_EVENT("CCThreadPRoxy::compositeAndReadback", this, 0); ASSERT(isMainThread()); ASSERT(m_layerTreeHost); if (!m_layerRendererInitialized) { TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0); return false; } // Perform a synchronous commit. CCCompletionEvent beginFrameCompletion; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, AllowCrossThreadAccess(&beginFrameCompletion))); beginFrameCompletion.wait(); beginFrame(); // Perform a synchronous readback. ReadbackRequest request; request.rect = rect; request.pixels = pixels; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestReadbackOnImplThread, AllowCrossThreadAccess(&request))); request.completion.wait(); return request.success; }
bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) { TRACE_EVENT("CCThreadPRoxy::compositeAndReadback", this, 0); ASSERT(isMainThread()); ASSERT(m_layerTreeHost); // If a commit is pending, perform the commit first. if (m_commitRequested) { // This bit of code is uglier than it should be because returning // pointers via the CCThread task model is really messy. Effectively, we // are making a blocking call to createBeginFrameAndCommitTaskOnImplThread, // and trying to get the CCMainThread::Task it returns so we can run it. OwnPtr<CCMainThread::Task> beginFrameAndCommitTask; { CCMainThread::Task* taskPtr = 0; CCCompletionEvent completion; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread, AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(&taskPtr))); completion.wait(); beginFrameAndCommitTask = adoptPtr(taskPtr); } beginFrameAndCommitTask->performTask(); } // Draw using the new tree and read back the results. bool success = false; CCCompletionEvent completion; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::drawLayersAndReadbackOnImplThread, AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(&success), AllowCrossThreadAccess(pixels), rect)); completion.wait(); return success; }
void CCThreadProxy::onSwapBuffersCompleteOnImplThread() { ASSERT(isImplThread()); TRACE_EVENT("CCThreadProxy::onSwapBuffersCompleteOnImplThread", this, 0); m_schedulerOnImplThread->didSwapBuffersComplete(); m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCompleteSwapBuffers)); }
bool CCThreadProxy::recreateContext() { TRACE_EVENT0("cc", "CCThreadProxy::recreateContext"); ASSERT(isMainThread()); // Try to create the context. RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext(); if (!context) return false; ASSERT(context->hasOneRef()); // Leak the context pointer so we can transfer ownership of it to the other side... GraphicsContext3D* contextPtr = context.release().leakRef(); ASSERT(contextPtr->hasOneRef()); // Make a blocking call to recreateContextOnImplThread. The results of that // call are pushed into the recreateSucceeded and capabilities local // variables. CCCompletionEvent completion; bool recreateSucceeded = false; LayerRendererCapabilities capabilities; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::recreateContextOnImplThread, AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(contextPtr), AllowCrossThreadAccess(&recreateSucceeded), AllowCrossThreadAccess(&capabilities))); completion.wait(); if (recreateSucceeded) m_layerRendererCapabilitiesMainThreadCopy = capabilities; return recreateSucceeded; }
bool CCThreadProxy::initializeLayerRenderer() { TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0); RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D(); if (!context) return false; ASSERT(context->hasOneRef()); // Leak the context pointer so we can transfer ownership of it to the other side... GraphicsContext3D* contextPtr = context.release().leakRef(); ASSERT(contextPtr->hasOneRef()); // Make a blocking call to initializeLayerRendererOnImplThread. The results of that call // are pushed into the initializeSucceeded and capabilities local variables. CCCompletionEvent completion; bool initializeSucceeded = false; LayerRendererCapabilities capabilities; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::initializeLayerRendererOnImplThread, AllowCrossThreadAccess(contextPtr), AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(&initializeSucceeded), AllowCrossThreadAccess(&capabilities), AllowCrossThreadAccess(&m_compositorIdentifier))); completion.wait(); if (initializeSucceeded) m_layerRendererCapabilitiesMainThreadCopy = capabilities; return initializeSucceeded; }
void CCThreadProxy::start() { // Create LayerTreeHostImpl. CCCompletionEvent completion; ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::initializeImplOnCCThread, AllowCrossThreadAccess(&completion))); completion.wait(); }
void CCThreadProxy::setVisible(bool visible) { ASSERT(isMainThread()); CCCompletionEvent completion; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setVisibleOnImplThread, AllowCrossThreadAccess(&completion), visible)); completion.wait(); }
void CCThreadProxy::finishAllRendering() { ASSERT(CCProxy::isMainThread()); // Make sure all GL drawing is finished on the impl thread. CCCompletionEvent completion; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::finishAllRenderingOnImplThread, AllowCrossThreadAccess(&completion))); completion.wait(); }
void CCThreadProxy::setNeedsCommitAndRedraw() { ASSERT(isMainThread()); if (m_commitPending) return; TRACE_EVENT("CCThreadProxy::setNeedsCommitAndRedraw", this, 0); m_commitPending = true; ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitAndRedrawOnCCThread)); }
void CCThreadProxy::setNeedsCommit() { ASSERT(isMainThread()); if (m_commitRequested) return; TRACE_EVENT("CCThreadProxy::setNeedsCommit", this, 0); m_commitRequested = true; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); }
void CCThreadProxy::start() { ASSERT(isMainThread()); ASSERT(s_ccThread); // Create LayerTreeHostImpl. CCCompletionEvent completion; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::initializeImplOnImplThread, AllowCrossThreadAccess(&completion))); completion.wait(); m_started = true; }
void CCThreadProxy::stop() { TRACE_EVENT("CCThreadProxy::stop", this, 0); ASSERT(isMainThread()); // Synchronously deletes the impl. CCCompletionEvent completion; ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::layerTreeHostClosedOnCCThread, AllowCrossThreadAccess(&completion))); completion.wait(); ASSERT(!m_layerTreeHostImpl); // verify that the impl deleted. m_layerTreeHost = 0; }
CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapInternal(bool forcedDraw) { TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0); CCScheduledActionDrawAndSwapResult result; result.didDraw = false; result.didSwap = false; ASSERT(isImplThread()); ASSERT(m_layerTreeHostImpl); if (!m_layerTreeHostImpl) return result; // FIXME: compute the frame display time more intelligently double monotonicTime = monotonicallyIncreasingTime(); double wallClockTime = currentTime(); m_inputHandlerOnImplThread->animate(monotonicTime); m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); CCLayerTreeHostImpl::FrameData frame; bool drawFrame = m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw; if (drawFrame) { m_layerTreeHostImpl->drawLayers(frame); result.didDraw = true; } // Check for a pending compositeAndReadback. if (m_readbackRequestOnImplThread) { ASSERT(drawFrame); // This should be a forcedDraw m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect); m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost(); m_readbackRequestOnImplThread->completion.signal(); m_readbackRequestOnImplThread = 0; } if (drawFrame) result.didSwap = m_layerTreeHostImpl->swapBuffers(); // Process any finish request if (m_finishAllRenderingCompletionEventOnImplThread) { ASSERT(drawFrame); // This should be a forcedDraw m_layerTreeHostImpl->finishAllRendering(); m_finishAllRenderingCompletionEventOnImplThread->signal(); m_finishAllRenderingCompletionEventOnImplThread = 0; } // Tell the main thread that the the newly-commited frame was drawn. if (m_nextFrameIsNewlyCommittedFrameOnImplThread) { m_nextFrameIsNewlyCommittedFrameOnImplThread = false; m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame)); } ASSERT(drawFrame || (!drawFrame && !forcedDraw)); return result; }
void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollUpdateSet> scrollInfo) { TRACE_EVENT("CCThreadProxy::beginFrameAndCommit", this, 0); ASSERT(isMainThread()); if (!m_layerTreeHost) return; // Scroll deltas need to be applied even if the commit will be dropped. m_layerTreeHost->applyScrollDeltas(*scrollInfo.get()); // Drop beginFrameAndCommit calls that occur out of sequence. See createBeginFrameAndCommitTaskOnImplThread for // an explanation of how out-of-sequence beginFrameAndCommit tasks can occur. if (sequenceNumber < m_lastExecutedBeginFrameAndCommitSequenceNumber) { TRACE_EVENT("EarlyOut_StaleBeginFrameAndCommit", this, 0); return; } m_lastExecutedBeginFrameAndCommitSequenceNumber = sequenceNumber; // FIXME: recreate the context if it was requested by the impl thread { TRACE_EVENT("CCLayerTreeHost::animateAndLayout", this, 0); m_layerTreeHost->animateAndLayout(frameBeginTime); } ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber); // Clear the commit flag after animateAndLayout here --- objects that only // layout when painted will trigger another setNeedsCommit inside // updateLayers. m_commitRequested = false; m_layerTreeHost->updateLayers(); { // Blocking call to CCThreadProxy::commitOnImplThread TRACE_EVENT("commit", this, 0); CCCompletionEvent completion; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::commitOnImplThread, AllowCrossThreadAccess(&completion))); completion.wait(); } m_layerTreeHost->commitComplete(); if (m_redrawAfterCommit) setNeedsRedraw(); m_redrawAfterCommit = false; ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber); }
void CCThreadProxy::scheduledActionBeginFrame() { TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame"); ASSERT(!m_pendingBeginFrameRequest); m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState()); m_pendingBeginFrameRequest->frameBeginTime = 0; m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas(); m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame)); if (m_beginFrameCompletionEventOnImplThread) { m_beginFrameCompletionEventOnImplThread->signal(); m_beginFrameCompletionEventOnImplThread = 0; } }
bool CCThreadProxy::initializeContext() { TRACE_EVENT("CCThreadProxy::initializeContext", this, 0); RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext(); if (!context) return false; ASSERT(context->hasOneRef()); // Leak the context pointer so we can transfer ownership of it to the other side... GraphicsContext3D* contextPtr = context.release().leakRef(); ASSERT(contextPtr->hasOneRef()); CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeContextOnImplThread, AllowCrossThreadAccess(contextPtr))); return true; }
void CCThreadProxy::stop() { TRACE_EVENT("CCThreadProxy::stop", this, 0); ASSERT(isMainThread()); ASSERT(m_started); // Synchronously deletes the impl. CCCompletionEvent completion; s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::layerTreeHostClosedOnImplThread, AllowCrossThreadAccess(&completion))); completion.wait(); m_mainThreadProxy->shutdown(); // Stop running tasks posted to us. ASSERT(!m_layerTreeHostImpl); // verify that the impl deleted. m_layerTreeHost = 0; m_started = false; }
void CCThreadProxy::beginFrameAndCommit(double frameBeginTime) { ASSERT(isMainThread()); if (!m_layerTreeHost) return; TRACE_EVENT("CCThreadProxy::requestFrameAndCommit", this, 0); { TRACE_EVENT("CCLayerTreeHost::animateAndLayout", this, 0); m_layerTreeHost->animateAndLayout(frameBeginTime); } m_commitPending = false; // Blocking call to CCThreadProxy::performCommit CCCompletionEvent completion; ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::commitOnCCThread, AllowCrossThreadAccess(&completion))); completion.wait(); }
bool CCThreadProxy::initializeLayerRenderer() { TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0); // Make a blocking call to initializeLayerRendererOnImplThread. The results of that call // are pushed into the initializeSucceeded and capabilities local variables. CCCompletionEvent completion; bool initializeSucceeded = false; LayerRendererCapabilities capabilities; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeLayerRendererOnImplThread, AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(&initializeSucceeded), AllowCrossThreadAccess(&capabilities))); completion.wait(); if (initializeSucceeded) { m_layerRendererInitialized = true; m_layerRendererCapabilitiesMainThreadCopy = capabilities; } return initializeSucceeded; }
void CCThreadProxy::scheduledActionDrawAndSwap() { TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0); ASSERT(isImplThread()); if (!m_layerTreeHostImpl) return; // FIXME: compute the frame display time more intelligently double monotonicTime = monotonicallyIncreasingTime(); double wallClockTime = currentTime(); m_inputHandlerOnImplThread->willDraw(monotonicTime); m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); m_layerTreeHostImpl->drawLayers(); // Check for a pending compositeAndReadback. if (m_readbackRequestOnImplThread) { m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect); m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost(); m_readbackRequestOnImplThread->completion.signal(); m_readbackRequestOnImplThread = 0; } m_layerTreeHostImpl->swapBuffers(); // Process any finish request if (m_finishAllRenderingCompletionEventOnImplThread) { m_layerTreeHostImpl->finishAllRendering(); m_finishAllRenderingCompletionEventOnImplThread->signal(); m_finishAllRenderingCompletionEventOnImplThread = 0; } // Tell the main thread that the the newly-commited frame was drawn. if (m_nextFrameIsNewlyCommittedFrameOnImplThread) { m_nextFrameIsNewlyCommittedFrameOnImplThread = false; m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame)); } }
void CCThreadProxy::setNeedsRedraw() { ASSERT(isMainThread()); ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnCCThread)); }
void CCThreadProxy::setNeedsRedraw() { ASSERT(isMainThread()); TRACE_EVENT("CCThreadProxy::setNeedsRedraw", this, 0); s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread)); }
void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) { ASSERT(CCProxy::isMainThread()); CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, duration)); }
void CCThreadProxy::loseContext() { CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::didLoseContextOnImplThread)); }
void CCThreadProxy::scheduledActionBeginContextRecreation() { ASSERT(isImplThread()); m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation)); }
void CCThreadProxy::beginFrame() { TRACE_EVENT0("cc", "CCThreadProxy::beginFrame"); ASSERT(isMainThread()); if (!m_layerTreeHost) return; if (!m_pendingBeginFrameRequest) { TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage"); return; } OwnPtr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.release()); // Do not notify the impl thread of commit requests that occur during // the apply/animate/layout part of the beginFrameAndCommit process since // those commit requests will get painted immediately. Once we have done // the paint, m_commitRequested will be set to false to allow new commit // requests to be scheduled. m_commitRequested = true; // On the other hand, the animationRequested flag needs to be cleared // here so that any animation requests generated by the apply or animate // callbacks will trigger another frame. m_animateRequested = false; // FIXME: technically, scroll deltas need to be applied for dropped commits as well. // Re-do the commit flow so that we don't send the scrollInfo on the BFAC message. m_layerTreeHost->applyScrollAndScale(*request->scrollInfo); // FIXME: recreate the context if it was requested by the impl thread. m_layerTreeHost->updateAnimations(request->frameBeginTime); m_layerTreeHost->layout(); // Clear the commit flag after updating animations and layout here --- objects that only // layout when painted will trigger another setNeedsCommit inside // updateLayers. m_commitRequested = false; if (!m_layerTreeHost->updateLayers()) return; // Before applying scrolls and calling animate, we set m_animateRequested to false. // If it is true now, it means setNeedAnimate was called again. Call setNeedsCommit // now so that we get begin frame when this one is done. if (m_animateRequested) setNeedsCommit(); // Notify the impl thread that the beginFrame has completed. This will // begin the commit process, which is blocking from the main thread's // point of view, but asynchronously performed on the impl thread, // coordinated by the CCScheduler. { TRACE_EVENT("commit", this, 0); CCCompletionEvent completion; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameCompleteOnImplThread, AllowCrossThreadAccess(&completion))); completion.wait(); } m_layerTreeHost->commitComplete(); }
void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime) { ASSERT(isImplThread()); TRACE_EVENT("CCThreadProxy::postAnimationEventsToMainThreadOnImplThread", this, 0); m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events, wallClockTime)); }