void CCLayerTreeHostImpl::setFullRootLayerDamage() { if (rootLayer()) { CCRenderSurface* renderSurface = rootLayer()->renderSurface(); if (renderSurface) renderSurface->damageTracker()->forceFullDamageNextUpdate(); } }
String LayerRendererChromium::layerTreeAsText() const { TextStream ts; if (rootLayer()) { ts << rootLayer()->layerTreeAsText(); ts << "RenderSurfaces:\n"; dumpRenderSurfaces(ts, 1, rootLayer()); } return ts.release(); }
void PaintLayerCompositor::updateWithoutAcceleratedCompositing(CompositingUpdateType updateType) { ASSERT(!hasAcceleratedCompositing()); if (updateType >= CompositingUpdateAfterCompositingInputChange) CompositingInputsUpdater(rootLayer()).update(); #if ENABLE(ASSERT) CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(rootLayer()); #endif }
void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList) { renderSurfaceLayerList.append(rootLayer()); if (!rootLayer()->renderSurface()) rootLayer()->createRenderSurface(); rootLayer()->renderSurface()->clearLayerList(); rootLayer()->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize())); rootLayer()->setClipRect(IntRect(IntPoint(), viewportSize())); { TransformationMatrix identityMatrix; TRACE_EVENT("CCLayerTreeHostImpl::calcDrawEtc", this, 0); CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer(), rootLayer(), identityMatrix, identityMatrix, renderSurfaceLayerList, rootLayer()->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize); } if (layerRendererCapabilities().usingPartialSwap) trackDamageForAllSurfaces(rootLayer(), renderSurfaceLayerList); m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect(); for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface); FloatRect surfaceDamageRect; if (layerRendererCapabilities().usingPartialSwap) surfaceDamageRect = damageInSurfaceSpace(renderSurfaceLayer, m_rootDamageRect); pass->setSurfaceDamageRect(surfaceDamageRect); const CCLayerList& layerList = renderSurface->layerList(); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { CCLayerImpl* layer = layerList[layerIndex]; if (layer->visibleLayerRect().isEmpty()) continue; if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, renderSurfaceLayer->id())) { pass->appendQuadsForRenderSurfaceLayer(layer); continue; } layer->willDraw(m_layerRenderer.get()); pass->appendQuadsForLayer(layer); } passes.append(pass.release()); } }
void LegacyCACFLayerTreeHost::resize() { if (!m_d3dDevice) return; // Resetting the device might fail here. But that's OK, because if it does it we will attempt to // reset the device the next time we try to render. resetDevice(ChangedWindowSize); if (rootLayer()) { rootLayer()->setBounds(bounds()); flushContext(); } }
void CCLayerTreeHost::updateLayers(CCTextureUpdateQueue& queue, size_t memoryAllocationLimitBytes) { ASSERT(m_rendererInitialized); ASSERT(memoryAllocationLimitBytes); if (!rootLayer()) return; if (layoutViewportSize().isEmpty()) return; m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes); updateLayers(rootLayer(), queue); }
void CoordinatedGraphicsScene::paintToGraphicsContext(PlatformGraphicsContext* platformContext, const Color& backgroundColor, bool drawsBackground) { if (!m_textureMapper) m_textureMapper = TextureMapper::create(); ASSERT(m_textureMapper->accelerationMode() == TextureMapper::SoftwareMode); syncRemoteContent(); TextureMapperLayer* layer = rootLayer(); if (!layer) return; GraphicsContext graphicsContext(platformContext); m_textureMapper->setGraphicsContext(&graphicsContext); m_textureMapper->beginPainting(); IntRect clipRect = graphicsContext.clipBounds(); if (drawsBackground) m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), backgroundColor); else m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), m_viewBackgroundColor); layer->paint(); m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location()); m_textureMapper->endPainting(); m_textureMapper->setGraphicsContext(0); }
bool TestMouseManager::testSimple() { Handle<Layer> rootLayer(new Layer()); Handle<Renderable> target1(new Renderable()); rootLayer->addChild(target1); rootLayer->setInteractive(true); target1->setInteractive(true); target1->setSize(50, 50); target1->setPosition(50, 50); TestListener targetListener; target1->addEventListener(MOUSE_DOWN, &targetListener); TestListener layerListener; rootLayer->addEventListener(MOUSE_DOWN, &layerListener); MouseManager *manager = MouseManager::getManager(); manager->setRootLayer(rootLayer); manager->onMouseDown(LEFT_BUTTON, 0, 0); assert(NULL == targetListener.lastEvent.get()); assert(NULL == layerListener.lastEvent.get()); manager->onMouseDown(LEFT_BUTTON, 51, 52); assert(NULL != targetListener.lastEvent.get()); am_equals(1, targetListener.lastEvent->getLocalMouseX()); am_equals(2, targetListener.lastEvent->getLocalMouseY()); assert(NULL != layerListener.lastEvent.get()); assert(layerListener.lastEvent->getEventTarget() == target1); am_equals(1, layerListener.lastEvent->getLocalMouseX()); am_equals(2, layerListener.lastEvent->getLocalMouseY()); return true; }
void PaintLayerCompositor::fullyInvalidatePaint() { // We're walking all compositing layers and invalidating them, so there's // no need to have up-to-date compositing state. DisableCompositingQueryAsserts disabler; fullyInvalidatePaintRecursive(rootLayer()); }
void PaintLayerCompositor::updateIfNeededRecursive() { FrameView* view = m_layoutView.frameView(); if (view->shouldThrottleRendering()) return; for (Frame* child = m_layoutView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) { if (!child->isLocalFrame()) continue; LocalFrame* localFrame = toLocalFrame(child); // It's possible for trusted Pepper plugins to force hit testing in situations where // the frame tree is in an inconsistent state, such as in the middle of frame detach. // TODO(bbudge) Remove this check when trusted Pepper plugins are gone. if (localFrame->document()->isActive()) localFrame->contentLayoutObject()->compositor()->updateIfNeededRecursive(); } TRACE_EVENT0("blink", "PaintLayerCompositor::updateIfNeededRecursive"); ASSERT(!m_layoutView.needsLayout()); ScriptForbiddenScope forbidScript; // FIXME: enableCompositingModeIfNeeded can trigger a CompositingUpdateRebuildTree, // which asserts that it's not InCompositingUpdate. enableCompositingModeIfNeeded(); if (m_needsUpdateDescendantDependentFlags) { updateDescendantDependentFlagsForEntireSubtree(*rootLayer()); m_needsUpdateDescendantDependentFlags = false; } m_layoutView.commitPendingSelection(); lifecycle().advanceTo(DocumentLifecycle::InCompositingUpdate); updateIfNeeded(); lifecycle().advanceTo(DocumentLifecycle::CompositingClean); DocumentAnimations::updateCompositorAnimations(m_layoutView.document()); m_layoutView.frameView()->scrollableArea()->updateCompositorScrollAnimations(); if (const FrameView::ScrollableAreaSet* animatingScrollableAreas = m_layoutView.frameView()->animatingScrollableAreas()) { for (ScrollableArea* scrollableArea : *animatingScrollableAreas) scrollableArea->updateCompositorScrollAnimations(); } #if ENABLE(ASSERT) ASSERT(lifecycle().state() == DocumentLifecycle::CompositingClean); assertNoUnresolvedDirtyBits(); for (Frame* child = m_layoutView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) { if (!child->isLocalFrame()) continue; LocalFrame* localFrame = toLocalFrame(child); if (localFrame->shouldThrottleRendering()) continue; localFrame->contentLayoutObject()->compositor()->assertNoUnresolvedDirtyBits(); } #endif }
bool CCLayerTreeHostImpl::canDraw() { if (!rootLayer()) return false; if (viewportSize().isEmpty()) return false; return true; }
void WKCACFViewLayerTreeHost::updateViewIfNeeded() { if (!m_viewNeedsUpdate) return; m_viewNeedsUpdate = false; CGRect layerBounds = rootLayer()->bounds(); CGRect bounds = this->bounds(); WKCACFViewUpdate(m_view.get(), window(), &bounds); if (CGRectEqualToRect(layerBounds, rootLayer()->bounds())) return; // Flush the context so the layer's rendered bounds will match our bounds. flushContext(); }
void PaintLayerCompositor::updateAcceleratedCompositingSettings() { m_compositingReasonFinder.updateTriggers(); m_hasAcceleratedCompositing = m_layoutView.document().settings()->acceleratedCompositingEnabled(); m_rootShouldAlwaysCompositeDirty = true; if (m_rootLayerAttachment != RootLayerUnattached) rootLayer()->setNeedsCompositingInputsUpdate(); }
TextureMapperCache* TextureMapperNode::cache() { TextureMapperNode* root = rootLayer(); if (!root) return 0; if (!root->m_cache) root->m_cache = new TextureMapperCache; return root->m_cache; }
TextureMapperLayerClientQt::TextureMapperLayerClientQt(QWebFrame* frame, GraphicsLayer* layer) : m_frame(frame) , m_rootGraphicsLayer(GraphicsLayer::create(0)) { m_frame->d->rootTextureMapperLayer = rootLayer(); m_rootGraphicsLayer->addChild(layer); m_rootGraphicsLayer->setDrawsContent(false); m_rootGraphicsLayer->setMasksToBounds(false); m_rootGraphicsLayer->setSize(IntSize(1, 1)); }
// This function commits the CCLayerTreeHost to an impl tree. When modifying // this function, keep in mind that the function *runs* on the impl thread! Any // code that is logically a main thread operation, e.g. deletion of a LayerChromium, // should be delayed until the CCLayerTreeHost::commitComplete, which will run // after the commit, but on the main thread. void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) { ASSERT(CCProxy::isImplThread()); hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer())); // We may have added an animation during the tree sync. This will cause both layer tree hosts // to visit their controllers. if (rootLayer()) { hostImpl->setNeedsAnimateLayers(); m_needsAnimateLayers = true; } hostImpl->setSourceFrameNumber(frameNumber()); hostImpl->setViewportSize(viewportSize()); hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor); hostImpl->setBackgroundColor(m_backgroundColor); m_frameNumber++; }
void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, TextureMapper::PaintFlags PaintFlags) { if (!m_textureMapper) { m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode); static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true); } ASSERT(m_textureMapper->accelerationMode() == TextureMapper::OpenGLMode); syncRemoteContent(); adjustPositionForFixedLayers(); GraphicsLayer* currentRootLayer = rootLayer(); if (!currentRootLayer) return; TextureMapperLayer* layer = toTextureMapperLayer(currentRootLayer); if (!layer) return; layer->setTextureMapper(m_textureMapper.get()); if (!m_animationsLocked) layer->applyAnimationsRecursively(); m_textureMapper->beginPainting(PaintFlags); m_textureMapper->beginClip(TransformationMatrix(), clipRect); if (m_setDrawsBackground) { RGBA32 rgba = makeRGBA32FromFloats(m_backgroundColor.red(), m_backgroundColor.green(), m_backgroundColor.blue(), m_backgroundColor.alpha() * opacity); m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba)); } if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) { currentRootLayer->setOpacity(opacity); currentRootLayer->setTransform(matrix); currentRootLayer->flushCompositingStateForThisLayerOnly(); } layer->paint(); m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location(), matrix); m_textureMapper->endClip(); m_textureMapper->endPainting(); if (layer->descendantsOrSelfHaveRunningAnimations()) dispatchOnMainThread(bind(&CoordinatedGraphicsScene::updateViewport, this)); #if ENABLE(REQUEST_ANIMATION_FRAME) if (m_animationFrameRequested) { m_animationFrameRequested = false; dispatchOnMainThread(bind(&CoordinatedGraphicsScene::animationFrameReady, this)); } #endif }
void PaintLayerCompositor::didLayout() { // FIXME: Technically we only need to do this when the FrameView's // isScrollable method would return a different value. m_rootShouldAlwaysCompositeDirty = true; enableCompositingModeIfNeeded(); // FIXME: Rather than marking the entire LayoutView as dirty, we should // track which Layers moved during layout and only dirty those // specific Layers. rootLayer()->setNeedsCompositingInputsUpdate(); }
void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, const Color& backgroundColor, bool drawsBackground, const FloatPoint& contentPosition, TextureMapper::PaintFlags PaintFlags) { if (!m_textureMapper) { m_textureMapper = TextureMapper::create(); static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true); } syncRemoteContent(); adjustPositionForFixedLayers(contentPosition); TextureMapperLayer* currentRootLayer = rootLayer(); if (!currentRootLayer) return; #if USE(COORDINATED_GRAPHICS_THREADED) for (auto& proxy : m_platformLayerProxies.values()) proxy->swapBuffer(); #endif currentRootLayer->setTextureMapper(m_textureMapper.get()); currentRootLayer->applyAnimationsRecursively(); m_textureMapper->beginPainting(PaintFlags); m_textureMapper->beginClip(TransformationMatrix(), clipRect); if (drawsBackground) { RGBA32 rgba = makeRGBA32FromFloats(backgroundColor.red(), backgroundColor.green(), backgroundColor.blue(), backgroundColor.alpha() * opacity); m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba)); } else { GraphicsContext3D* context = static_cast<TextureMapperGL*>(m_textureMapper.get())->graphicsContext3D(); context->clearColor(m_viewBackgroundColor.red() / 255.0f, m_viewBackgroundColor.green() / 255.0f, m_viewBackgroundColor.blue() / 255.0f, m_viewBackgroundColor.alpha() / 255.0f); context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); } if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) { currentRootLayer->setOpacity(opacity); currentRootLayer->setTransform(matrix); } currentRootLayer->paint(); m_fpsCounter.updateFPSAndDisplay(*m_textureMapper, clipRect.location(), matrix); m_textureMapper->endClip(); m_textureMapper->endPainting(); if (currentRootLayer->descendantsOrSelfHaveRunningAnimations()) { RefPtr<CoordinatedGraphicsScene> protector(this); dispatchOnClientRunLoop([=] { protector->updateViewport(); }); } }
void CCLayerTreeHost::updateLayers(CCTextureUpdater& updater) { ASSERT(m_layerRendererInitialized); // The visible state and memory allocation are set independently and in // arbitrary order, so do not change the memory allocation used for the // current commit until both values match intentions. // FIXME: These two states should be combined into a single action so we // need a single commit to change visible state, and this can be removed. bool memoryAllocationStateMatchesVisibility = m_visible == m_memoryAllocationIsForDisplay; if (memoryAllocationStateMatchesVisibility) { m_contentsTextureManager->setMemoryAllocationLimitBytes(m_memoryAllocationBytes); m_frameIsForDisplay = m_memoryAllocationIsForDisplay; } if (!rootLayer()) return; if (viewportSize().isEmpty()) return; updateLayers(rootLayer(), updater); }
// This function commits the CCLayerTreeHost to an impl tree. When modifying // this function, keep in mind that the function *runs* on the impl thread! Any // code that is logically a main thread operation, e.g. deletion of a LayerChromium, // should be delayed until the CCLayerTreeHost::commitComplete, which will run // after the commit, but on the main thread. void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) { ASSERT(CCProxy::isImplThread()); hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->detachLayerTree(), hostImpl)); // We may have added an animation during the tree sync. This will cause both layer tree hosts // to visit their controllers. if (rootLayer() && m_needsAnimateLayers) hostImpl->setNeedsAnimateLayers(); hostImpl->setSourceFrameNumber(frameNumber()); hostImpl->setViewportSize(viewportSize()); hostImpl->setDeviceScaleFactor(deviceScaleFactor()); hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor); hostImpl->setBackgroundColor(m_backgroundColor); hostImpl->setHasTransparentBackground(m_hasTransparentBackground); hostImpl->setVisible(m_visible); hostImpl->setSourceFrameCanBeDrawn(m_frameIsForDisplay); m_frameNumber++; }
void workbench_physical_Diagram::init() { if (!_data) _data = new workbench_physical_Diagram::ImplData(this); model_Diagram::set_data(_data); if (_rootLayer.is_valid()) throw std::logic_error("rootLayer value is already initialized"); rootLayer(workbench_physical_LayerRef(grt::Initialized)); _rootLayer->owner(this); _rootLayer->width(width()); _rootLayer->height(height()); }
bool CCLayerTreeHost::updateLayers(CCTextureUpdater& updater) { if (!m_layerRendererInitialized) { initializeLayerRenderer(); // If we couldn't initialize, then bail since we're returning to software mode. if (!m_layerRendererInitialized) return false; } if (m_contextLost) { if (recreateContext() != RecreateSucceeded) return false; } if (!rootLayer()) return true; if (viewportSize().isEmpty()) return true; updateLayers(rootLayer(), updater); return true; }
PassOwnPtr<CCScrollUpdateSet> CCLayerTreeHostImpl::processScrollDeltas() { OwnPtr<CCScrollUpdateSet> scrollInfo = adoptPtr(new CCScrollUpdateSet()); // FIXME: track scrolls from layers other than the root if (rootLayer() && !rootLayer()->scrollDelta().isZero()) { CCLayerTreeHostCommon::ScrollUpdateInfo info; info.layerId = rootLayer()->id(); info.scrollDelta = rootLayer()->scrollDelta(); scrollInfo->append(info); rootLayer()->setScrollPosition(rootLayer()->scrollPosition() + rootLayer()->scrollDelta()); rootLayer()->setScrollDelta(IntSize()); } return scrollInfo.release(); }
// This function needs to be reentrant. void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity) { if (!m_textureMapper) m_textureMapper = TextureMapperGL::create(); syncRemoteContent(); GraphicsLayer* currentRootLayer = rootLayer(); if (!currentRootLayer) return; TextureMapperNode* node = toTextureMapperNode(currentRootLayer); if (!node) return; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); IntRect viewportRect(viewport[0], viewport[1], viewport[2], viewport[3]); m_textureMapper->setViewportSize(IntSize(viewport[2], viewport[3])); node->setTextureMapper(m_textureMapper.get()); m_textureMapper->beginPainting(); m_textureMapper->bindSurface(0); if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) { currentRootLayer->setOpacity(opacity); currentRootLayer->setTransform(matrix); currentRootLayer->syncCompositingStateForThisLayerOnly(); } TextureMapperNode::NodeRectMap nodeVisualContentsRectMap; if (node->collectVisibleContentsRects(nodeVisualContentsRectMap, viewportRect)) { TextureMapperNode::NodeRectMap::iterator endIterator = nodeVisualContentsRectMap.end(); for (TextureMapperNode::NodeRectMap::iterator it = nodeVisualContentsRectMap.begin(); it != endIterator; ++it) { WebLayerID layerID = it->first->id(); // avoid updating non-synced root layer if (!layerID) continue; IntRect visibleRect = IntRect(it->second); setVisibleContentsRectForLayer(layerID, visibleRect); } } node->paint(); m_textureMapper->endPainting(); if (node->descendantsOrSelfHaveRunningAnimations()) { node->syncAnimationsRecursively(); m_viewportUpdateTimer.startOneShot(0); } }
void WKCACFLayer::setNeedsCommit() { CACFContextRef context = CACFLayerGetContext(rootLayer()->layer()); // The context might now be set yet. This happens if a property gets set // before placing the layer in the tree. In this case we don't need to // worry about remembering the context because we will when the layer is // added to the tree. if (context) WKCACFContextFlusher::shared().addContext(context); // Call notifySyncRequired(), which in this implementation plumbs through to // call setRootLayerNeedsDisplay() on the WebView, which causes the CACFRenderer // to render a frame. if (m_owner) m_owner->notifySyncRequired(); }
void LayerTreeHostCAWin::platformInitialize() { m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow)); WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this)); WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer()); WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this); // Passing WS_DISABLED makes the window invisible to mouse events, which lets WKView's normal // event handling mechanism work even when this window is obscuring the entire WKView HWND. // Note that m_webPage->nativeWindow() is owned by the UI process, so this creates a cross- // process window hierarchy (and thus implicitly attaches the input queues of the UI and web // processes' main threads). m_window = adoptPtr(new WKCACFViewWindow(m_view.get(), m_webPage->nativeWindow(), WS_DISABLED)); CGRect bounds = m_webPage->bounds(); WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds); m_layerTreeContext.window = m_window->window(); }
void LayerRendererChromium::drawLayers() { // FIXME: use the frame begin time from the overall compositor scheduler. // This value is currently inaccessible because it is up in Chromium's // RenderWidget. m_headsUpDisplay->onFrameBegin(currentTime()); if (!rootLayer()) return; size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes(); m_renderSurfaceTextureManager->setMemoryLimitBytes(TextureManager::highLimitBytes() - contentsMemoryUseBytes); drawLayersInternal(); if (TextureManager::reclaimLimitBytes() > contentsMemoryUseBytes) m_renderSurfaceTextureManager->reduceMemoryToLimit(TextureManager::reclaimLimitBytes() - contentsMemoryUseBytes); else m_renderSurfaceTextureManager->reduceMemoryToLimit(0); m_renderSurfaceTextureManager->deleteEvictedTextures(m_renderSurfaceTextureAllocator.get()); if (settings().compositeOffscreen) copyOffscreenTextureToDisplay(); }
bool LegacyCACFLayerTreeHost::createRenderer() { if (m_d3dDevice || !m_mightBeAbleToCreateDeviceLater) return m_d3dDevice; m_mightBeAbleToCreateDeviceLater = false; D3DPRESENT_PARAMETERS parameters = initialPresentationParameters(); if (!d3d() || !::IsWindow(window())) return false; // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero // size eventually, and then the backbuffer size will get reset. RECT rect; GetClientRect(window(), &rect); if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) { parameters.BackBufferWidth = 1; parameters.BackBufferHeight = 1; } D3DCAPS9 d3dCaps; if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps))) return false; DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE; if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps) behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; else behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; COMPtr<IDirect3DDevice9> device; if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window(), behaviorFlags, ¶meters, &device))) { // In certain situations (e.g., shortly after waking from sleep), Direct3DCreate9() will // return an IDirect3D9 for which IDirect3D9::CreateDevice will always fail. In case we // have one of these bad IDirect3D9s, get rid of it so we'll fetch a new one the next time // we want to call CreateDevice. s_d3d->Release(); s_d3d = 0; // Even if we don't have a bad IDirect3D9, in certain situations (e.g., shortly after // waking from sleep), CreateDevice will fail, but will later succeed if called again. m_mightBeAbleToCreateDeviceLater = true; return false; } // Now that we've created the IDirect3DDevice9 based on the capabilities we // got from the IDirect3D9 global object, we requery the device for its // actual capabilities. The capabilities returned by the device can // sometimes be more complete, for example when using software vertex // processing. D3DCAPS9 deviceCaps; if (FAILED(device->GetDeviceCaps(&deviceCaps))) return false; if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps)) return false; m_d3dDevice = device; initD3DGeometry(); wkCACFContextSetD3DDevice(m_context, m_d3dDevice.get()); if (IsWindow(window())) { rootLayer()->setBounds(bounds()); flushContext(); } return true; }
void LegacyCACFLayerTreeHost::render(const Vector<CGRect>& windowDirtyRects) { ASSERT(m_d3dDevice); if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } CGRect bounds = this->bounds(); // Give the renderer some space to use. This needs to be valid until the // wkCACFContextFinishUpdate() call below. char space[4096]; if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), CACurrentMediaTime(), bounds, windowDirtyRects.data(), windowDirtyRects.size())) return; HRESULT err = S_OK; CFTimeInterval timeToNextRender = numeric_limits<CFTimeInterval>::infinity(); do { // FIXME: don't need to clear dirty region if layer tree is opaque. WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context); if (!e) break; Vector<D3DRECT, 64> rects; for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) { D3DRECT rect; rect.x1 = r->origin.x; rect.x2 = rect.x1 + r->size.width; rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height); rect.y2 = rect.y1 + r->size.height; rects.append(rect); } wkCACFUpdateRectEnumeratorRelease(e); timeToNextRender = wkCACFContextGetNextUpdateTime(m_context); if (rects.isEmpty()) break; m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0); m_d3dDevice->BeginScene(); wkCACFContextRenderUpdate(m_context); m_d3dDevice->EndScene(); err = m_d3dDevice->Present(0, 0, 0, 0); if (err == D3DERR_DEVICELOST) { wkCACFContextAddUpdateRect(m_context, bounds); if (!resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } } } while (err == D3DERR_DEVICELOST); wkCACFContextFinishUpdate(m_context); #ifndef NDEBUG if (m_printTree) rootLayer()->printTree(); #endif // If timeToNextRender is not infinity, it means animations are running, so queue up to render again if (timeToNextRender != numeric_limits<CFTimeInterval>::infinity()) renderSoon(); }