diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp | 781 |
1 files changed, 781 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp new file mode 100644 index 000000000..32c7dace4 --- /dev/null +++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp @@ -0,0 +1,781 @@ +/* + Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2012 Company 100, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if USE(COORDINATED_GRAPHICS) + +#include "CoordinatedGraphicsScene.h" + +#include "CoordinatedBackingStore.h" +#include "TextureMapper.h" +#include "TextureMapperBackingStore.h" +#include "TextureMapperGL.h" +#include "TextureMapperLayer.h" +#include <OpenGLShims.h> +#include <wtf/Atomics.h> +#include <wtf/MainThread.h> + +#if ENABLE(CSS_SHADERS) +#include "CoordinatedCustomFilterOperation.h" +#include "CoordinatedCustomFilterProgram.h" +#include "CustomFilterProgram.h" +#include "CustomFilterProgramInfo.h" +#endif + +namespace WebCore { + +void CoordinatedGraphicsScene::dispatchOnMainThread(const Function<void()>& function) +{ + if (isMainThread()) + function(); + else + callOnMainThread(function); +} + +static bool layerShouldHaveBackingStore(TextureMapperLayer* layer) +{ + return layer->drawsContent() && layer->contentsAreVisible() && !layer->size().isEmpty(); +} + +CoordinatedGraphicsScene::CoordinatedGraphicsScene(CoordinatedGraphicsSceneClient* client) + : m_client(client) + , m_isActive(false) + , m_rootLayerID(InvalidCoordinatedLayerID) + , m_backgroundColor(Color::white) + , m_setDrawsBackground(false) +{ + ASSERT(isMainThread()); +} + +CoordinatedGraphicsScene::~CoordinatedGraphicsScene() +{ +} + +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(); + TextureMapperLayer* currentRootLayer = rootLayer(); + if (!currentRootLayer) + return; + + TextureMapperLayer* layer = currentRootLayer; + + if (!layer) + return; + + layer->setTextureMapper(m_textureMapper.get()); + 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); + } + + 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)); +} + +void CoordinatedGraphicsScene::paintToGraphicsContext(PlatformGraphicsContext* platformContext) +{ + 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 (m_setDrawsBackground) + m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), m_backgroundColor); + + layer->paint(); + m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location()); + m_textureMapper->endPainting(); + m_textureMapper->setGraphicsContext(0); +} + +void CoordinatedGraphicsScene::setScrollPosition(const FloatPoint& scrollPosition) +{ + m_scrollPosition = scrollPosition; +} + +void CoordinatedGraphicsScene::updateViewport() +{ + ASSERT(isMainThread()); + if (m_client) + m_client->updateViewport(); +} + +void CoordinatedGraphicsScene::adjustPositionForFixedLayers() +{ + if (m_fixedLayers.isEmpty()) + return; + + // Fixed layer positions are updated by the web process when we update the visible contents rect / scroll position. + // If we want those layers to follow accurately the viewport when we move between the web process updates, we have to offset + // them by the delta between the current position and the position of the viewport used for the last layout. + FloatSize delta = m_scrollPosition - m_renderedContentsScrollPosition; + + LayerRawPtrMap::iterator end = m_fixedLayers.end(); + for (LayerRawPtrMap::iterator it = m_fixedLayers.begin(); it != end; ++it) + it->value->setScrollPositionDeltaIfNeeded(delta); +} + +#if USE(GRAPHICS_SURFACE) +void CoordinatedGraphicsScene::createCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (!state.canvasToken.isValid()) + return; + + RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore(TextureMapperSurfaceBackingStore::create()); + m_surfaceBackingStores.set(layer, canvasBackingStore); + canvasBackingStore->setGraphicsSurface(GraphicsSurface::create(state.canvasSize, state.canvasSurfaceFlags, state.canvasToken)); + layer->setContentsLayer(canvasBackingStore.get()); +} + +void CoordinatedGraphicsScene::syncCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + ASSERT(m_textureMapper); + + if (state.canvasChanged) { + destroyCanvasIfNeeded(layer, state); + createCanvasIfNeeded(layer, state); + } + + if (state.canvasShouldSwapBuffers) { + ASSERT(m_surfaceBackingStores.contains(layer)); + SurfaceBackingStoreMap::iterator it = m_surfaceBackingStores.find(layer); + RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore = it->value; + canvasBackingStore->swapBuffersIfNeeded(state.canvasFrontBuffer); + } +} + +void CoordinatedGraphicsScene::destroyCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (state.canvasToken.isValid()) + return; + + m_surfaceBackingStores.remove(layer); + layer->setContentsLayer(0); +} +#endif + +void CoordinatedGraphicsScene::setLayerRepaintCountIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (!layer->isShowingRepaintCounter() || !state.repaintCountChanged) + return; + + layer->setRepaintCount(state.repaintCount); +} + +void CoordinatedGraphicsScene::setLayerChildrenIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (!state.childrenChanged) + return; + + Vector<TextureMapperLayer*> children; + + for (size_t i = 0; i < state.children.size(); ++i) { + CoordinatedLayerID childID = state.children[i]; + TextureMapperLayer* child = layerByID(childID); + children.append(child); + } + layer->setChildren(children); +} + +#if ENABLE(CSS_FILTERS) +void CoordinatedGraphicsScene::setLayerFiltersIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (!state.filtersChanged) + return; + +#if ENABLE(CSS_SHADERS) + injectCachedCustomFilterPrograms(state.filters); +#endif + layer->setFilters(state.filters); +} +#endif + +#if ENABLE(CSS_SHADERS) +void CoordinatedGraphicsScene::syncCustomFilterPrograms(const CoordinatedGraphicsState& state) +{ + for (size_t i = 0; i < state.customFiltersToCreate.size(); ++i) + createCustomFilterProgram(state.customFiltersToCreate[i].first, state.customFiltersToCreate[i].second); + + for (size_t i = 0; i < state.customFiltersToRemove.size(); ++i) + removeCustomFilterProgram(state.customFiltersToRemove[i]); +} + +void CoordinatedGraphicsScene::injectCachedCustomFilterPrograms(const FilterOperations& filters) const +{ + for (size_t i = 0; i < filters.size(); ++i) { + FilterOperation* operation = filters.operations().at(i).get(); + if (operation->getOperationType() != FilterOperation::CUSTOM) + continue; + + CoordinatedCustomFilterOperation* customOperation = static_cast<CoordinatedCustomFilterOperation*>(operation); + ASSERT(!customOperation->program()); + CustomFilterProgramMap::const_iterator iter = m_customFilterPrograms.find(customOperation->programID()); + ASSERT(iter != m_customFilterPrograms.end()); + customOperation->setProgram(iter->value.get()); + } +} + +void CoordinatedGraphicsScene::createCustomFilterProgram(int id, const CustomFilterProgramInfo& programInfo) +{ + ASSERT(!m_customFilterPrograms.contains(id)); + m_customFilterPrograms.set(id, CoordinatedCustomFilterProgram::create(programInfo.vertexShaderString(), programInfo.fragmentShaderString(), programInfo.programType(), programInfo.mixSettings(), programInfo.meshType())); +} + +void CoordinatedGraphicsScene::removeCustomFilterProgram(int id) +{ + CustomFilterProgramMap::iterator iter = m_customFilterPrograms.find(id); + ASSERT(iter != m_customFilterPrograms.end()); + if (m_textureMapper) + m_textureMapper->removeCachedCustomFilterProgram(iter->value.get()); + m_customFilterPrograms.remove(iter); +} +#endif // ENABLE(CSS_SHADERS) + +void CoordinatedGraphicsScene::setLayerState(CoordinatedLayerID id, const CoordinatedGraphicsLayerState& layerState) +{ + ASSERT(m_rootLayerID != InvalidCoordinatedLayerID); + TextureMapperLayer* layer = layerByID(id); + + if (layerState.positionChanged) + layer->setPosition(layerState.pos); + + if (layerState.anchorPointChanged) + layer->setAnchorPoint(layerState.anchorPoint); + + if (layerState.sizeChanged) + layer->setSize(layerState.size); + + if (layerState.transformChanged) + layer->setTransform(layerState.transform); + + if (layerState.childrenTransformChanged) + layer->setChildrenTransform(layerState.childrenTransform); + + if (layerState.contentsRectChanged) + layer->setContentsRect(layerState.contentsRect); + + if (layerState.contentsTilingChanged) { + layer->setContentsTilePhase(layerState.contentsTilePhase); + layer->setContentsTileSize(layerState.contentsTileSize); + } + + if (layerState.opacityChanged) + layer->setOpacity(layerState.opacity); + + if (layerState.solidColorChanged) + layer->setSolidColor(layerState.solidColor); + + if (layerState.debugBorderColorChanged || layerState.debugBorderWidthChanged) + layer->setDebugVisuals(layerState.showDebugBorders, layerState.debugBorderColor, layerState.debugBorderWidth, layerState.showRepaintCounter); + + if (layerState.replicaChanged) + layer->setReplicaLayer(getLayerByIDIfExists(layerState.replica)); + + if (layerState.maskChanged) + layer->setMaskLayer(getLayerByIDIfExists(layerState.mask)); + + if (layerState.imageChanged) + assignImageBackingToLayer(layer, layerState.imageID); + + if (layerState.flagsChanged) { + layer->setContentsOpaque(layerState.contentsOpaque); + layer->setDrawsContent(layerState.drawsContent); + layer->setContentsVisible(layerState.contentsVisible); + layer->setBackfaceVisibility(layerState.backfaceVisible); + + // Never clip the root layer. + layer->setMasksToBounds(id == m_rootLayerID ? false : layerState.masksToBounds); + layer->setPreserves3D(layerState.preserves3D); + + bool fixedToViewportChanged = layer->fixedToViewport() != layerState.fixedToViewport; + layer->setFixedToViewport(layerState.fixedToViewport); + if (fixedToViewportChanged) { + if (layerState.fixedToViewport) + m_fixedLayers.add(id, layer); + else + m_fixedLayers.remove(id); + } + + layer->setIsScrollable(layerState.isScrollable); + } + + if (layerState.committedScrollOffsetChanged) + layer->didCommitScrollOffset(layerState.committedScrollOffset); + + prepareContentBackingStore(layer); + + // Apply Operations. + setLayerChildrenIfNeeded(layer, layerState); + createTilesIfNeeded(layer, layerState); + removeTilesIfNeeded(layer, layerState); + updateTilesIfNeeded(layer, layerState); +#if ENABLE(CSS_FILTERS) + setLayerFiltersIfNeeded(layer, layerState); +#endif + setLayerAnimationsIfNeeded(layer, layerState); +#if USE(GRAPHICS_SURFACE) + syncCanvasIfNeeded(layer, layerState); +#endif + setLayerRepaintCountIfNeeded(layer, layerState); +} + +TextureMapperLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id) +{ + return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0; +} + +void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& ids) +{ + for (size_t index = 0; index < ids.size(); ++index) + createLayer(ids[index]); +} + +void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id) +{ + OwnPtr<TextureMapperLayer> newLayer = adoptPtr(new TextureMapperLayer); + newLayer->setID(id); + newLayer->setScrollClient(this); + m_layers.add(id, newLayer.release()); +} + +void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs) +{ + for (size_t index = 0; index < layerIDs.size(); ++index) + deleteLayer(layerIDs[index]); +} + +void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID) +{ + OwnPtr<TextureMapperLayer> layer = m_layers.take(layerID); + ASSERT(layer); + + m_backingStores.remove(layer.get()); + m_fixedLayers.remove(layerID); +#if USE(GRAPHICS_SURFACE) + m_surfaceBackingStores.remove(layer.get()); +#endif +} + +void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID) +{ + ASSERT(layerID != InvalidCoordinatedLayerID); + ASSERT(m_rootLayerID == InvalidCoordinatedLayerID); + + m_rootLayerID = layerID; + + TextureMapperLayer* layer = layerByID(layerID); + ASSERT(m_rootLayer->children().isEmpty()); + m_rootLayer->addChild(layer); +} + +void CoordinatedGraphicsScene::prepareContentBackingStore(TextureMapperLayer* layer) +{ + if (!layerShouldHaveBackingStore(layer)) { + removeBackingStoreIfNeeded(layer); + return; + } + + createBackingStoreIfNeeded(layer); + resetBackingStoreSizeToLayerSize(layer); +} + +void CoordinatedGraphicsScene::createBackingStoreIfNeeded(TextureMapperLayer* layer) +{ + if (m_backingStores.contains(layer)) + return; + + RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create()); + m_backingStores.add(layer, backingStore); + layer->setBackingStore(backingStore); +} + +void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(TextureMapperLayer* layer) +{ + RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(layer); + if (!backingStore) + return; + + layer->setBackingStore(0); +} + +void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(TextureMapperLayer* layer) +{ + RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer); + ASSERT(backingStore); + backingStore->setSize(layer->size()); + m_backingStoresWithPendingBuffers.add(backingStore); +} + +void CoordinatedGraphicsScene::createTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (state.tilesToCreate.isEmpty()) + return; + + RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer); + ASSERT(backingStore); + + for (size_t i = 0; i < state.tilesToCreate.size(); ++i) + backingStore->createTile(state.tilesToCreate[i].tileID, state.tilesToCreate[i].scale); +} + +void CoordinatedGraphicsScene::removeTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (state.tilesToRemove.isEmpty()) + return; + + RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer); + if (!backingStore) + return; + + for (size_t i = 0; i < state.tilesToRemove.size(); ++i) + backingStore->removeTile(state.tilesToRemove[i]); + + m_backingStoresWithPendingBuffers.add(backingStore); +} + +void CoordinatedGraphicsScene::updateTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (state.tilesToUpdate.isEmpty()) + return; + + RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer); + ASSERT(backingStore); + + for (size_t i = 0; i < state.tilesToUpdate.size(); ++i) { + const TileUpdateInfo& tileInfo = state.tilesToUpdate[i]; + const SurfaceUpdateInfo& surfaceUpdateInfo = tileInfo.updateInfo; + + SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID); + ASSERT(surfaceIt != m_surfaces.end()); + + backingStore->updateTile(tileInfo.tileID, surfaceUpdateInfo.updateRect, tileInfo.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset); + m_backingStoresWithPendingBuffers.add(backingStore); + } +} + +void CoordinatedGraphicsScene::syncUpdateAtlases(const CoordinatedGraphicsState& state) +{ + for (size_t i = 0; i < state.updateAtlasesToCreate.size(); ++i) + createUpdateAtlas(state.updateAtlasesToCreate[i].first, state.updateAtlasesToCreate[i].second); + + for (size_t i = 0; i < state.updateAtlasesToRemove.size(); ++i) + removeUpdateAtlas(state.updateAtlasesToRemove[i]); +} + +void CoordinatedGraphicsScene::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> surface) +{ + ASSERT(!m_surfaces.contains(atlasID)); + m_surfaces.add(atlasID, surface); +} + +void CoordinatedGraphicsScene::removeUpdateAtlas(uint32_t atlasID) +{ + ASSERT(m_surfaces.contains(atlasID)); + m_surfaces.remove(atlasID); +} + +void CoordinatedGraphicsScene::syncImageBackings(const CoordinatedGraphicsState& state) +{ + for (size_t i = 0; i < state.imagesToRemove.size(); ++i) + removeImageBacking(state.imagesToRemove[i]); + + for (size_t i = 0; i < state.imagesToCreate.size(); ++i) + createImageBacking(state.imagesToCreate[i]); + + for (size_t i = 0; i < state.imagesToUpdate.size(); ++i) + updateImageBacking(state.imagesToUpdate[i].first, state.imagesToUpdate[i].second); + + for (size_t i = 0; i < state.imagesToClear.size(); ++i) + clearImageBackingContents(state.imagesToClear[i]); +} + +void CoordinatedGraphicsScene::createImageBacking(CoordinatedImageBackingID imageID) +{ + ASSERT(!m_imageBackings.contains(imageID)); + RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create()); + m_imageBackings.add(imageID, backingStore.release()); +} + +void CoordinatedGraphicsScene::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> surface) +{ + ASSERT(m_imageBackings.contains(imageID)); + ImageBackingMap::iterator it = m_imageBackings.find(imageID); + RefPtr<CoordinatedBackingStore> backingStore = it->value; + + // CoordinatedImageBacking is realized to CoordinatedBackingStore with only one tile in UI Process. + backingStore->createTile(1 /* id */, 1 /* scale */); + IntRect rect(IntPoint::zero(), surface->size()); + // See CoordinatedGraphicsLayer::shouldDirectlyCompositeImage() + ASSERT(2000 >= std::max(rect.width(), rect.height())); + backingStore->setSize(rect.size()); + backingStore->updateTile(1 /* id */, rect, rect, surface, rect.location()); + + m_backingStoresWithPendingBuffers.add(backingStore); +} + +void CoordinatedGraphicsScene::clearImageBackingContents(CoordinatedImageBackingID imageID) +{ + ASSERT(m_imageBackings.contains(imageID)); + ImageBackingMap::iterator it = m_imageBackings.find(imageID); + RefPtr<CoordinatedBackingStore> backingStore = it->value; + backingStore->removeAllTiles(); + m_backingStoresWithPendingBuffers.add(backingStore); +} + +void CoordinatedGraphicsScene::removeImageBacking(CoordinatedImageBackingID imageID) +{ + ASSERT(m_imageBackings.contains(imageID)); + + // We don't want TextureMapperLayer refers a dangling pointer. + m_releasedImageBackings.append(m_imageBackings.take(imageID)); +} + +void CoordinatedGraphicsScene::assignImageBackingToLayer(TextureMapperLayer* layer, CoordinatedImageBackingID imageID) +{ +#if USE(GRAPHICS_SURFACE) + if (m_surfaceBackingStores.contains(layer)) + return; +#endif + + if (imageID == InvalidCoordinatedImageBackingID) { + layer->setContentsLayer(0); + return; + } + + ImageBackingMap::iterator it = m_imageBackings.find(imageID); + ASSERT(it != m_imageBackings.end()); + layer->setContentsLayer(it->value.get()); +} + +void CoordinatedGraphicsScene::removeReleasedImageBackingsIfNeeded() +{ + m_releasedImageBackings.clear(); +} + +void CoordinatedGraphicsScene::commitPendingBackingStoreOperations() +{ + HashSet<RefPtr<CoordinatedBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end(); + for (HashSet<RefPtr<CoordinatedBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it) + (*it)->commitTileOperations(m_textureMapper.get()); + + m_backingStoresWithPendingBuffers.clear(); +} + +void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state) +{ + m_renderedContentsScrollPosition = state.scrollPosition; + + createLayers(state.layersToCreate); + deleteLayers(state.layersToRemove); + + if (state.rootCompositingLayer != m_rootLayerID) + setRootLayerID(state.rootCompositingLayer); + + syncImageBackings(state); + syncUpdateAtlases(state); +#if ENABLE(CSS_SHADERS) + syncCustomFilterPrograms(state); +#endif + + for (size_t i = 0; i < state.layersToUpdate.size(); ++i) + setLayerState(state.layersToUpdate[i].first, state.layersToUpdate[i].second); + + commitPendingBackingStoreOperations(); + removeReleasedImageBackingsIfNeeded(); + + // The pending tiles state is on its way for the screen, tell the web process to render the next one. + dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this)); +} + +void CoordinatedGraphicsScene::renderNextFrame() +{ + if (m_client) + m_client->renderNextFrame(); +} + +void CoordinatedGraphicsScene::ensureRootLayer() +{ + if (m_rootLayer) + return; + + m_rootLayer = adoptPtr(new TextureMapperLayer); + m_rootLayer->setMasksToBounds(false); + m_rootLayer->setDrawsContent(false); + m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0)); + + // The root layer should not have zero size, or it would be optimized out. + m_rootLayer->setSize(FloatSize(1.0, 1.0)); + + ASSERT(m_textureMapper); + m_rootLayer->setTextureMapper(m_textureMapper.get()); +} + +void CoordinatedGraphicsScene::syncRemoteContent() +{ + // We enqueue messages and execute them during paint, as they require an active GL context. + ensureRootLayer(); + + Vector<Function<void()> > renderQueue; + bool calledOnMainThread = WTF::isMainThread(); + if (!calledOnMainThread) + m_renderQueueMutex.lock(); + renderQueue.swap(m_renderQueue); + if (!calledOnMainThread) + m_renderQueueMutex.unlock(); + + for (size_t i = 0; i < renderQueue.size(); ++i) + renderQueue[i](); +} + +void CoordinatedGraphicsScene::purgeGLResources() +{ + m_imageBackings.clear(); + m_releasedImageBackings.clear(); +#if USE(GRAPHICS_SURFACE) + m_surfaceBackingStores.clear(); +#endif + m_surfaces.clear(); + + m_rootLayer.clear(); + m_rootLayerID = InvalidCoordinatedLayerID; + m_layers.clear(); + m_fixedLayers.clear(); + m_textureMapper.clear(); + m_backingStores.clear(); + m_backingStoresWithPendingBuffers.clear(); + + setActive(false); + dispatchOnMainThread(bind(&CoordinatedGraphicsScene::purgeBackingStores, this)); +} + +void CoordinatedGraphicsScene::dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset) +{ + m_client->commitScrollOffset(layerID, offset); +} + +void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset) +{ + dispatchOnMainThread(bind(&CoordinatedGraphicsScene::dispatchCommitScrollOffset, this, layerID, offset)); +} + +void CoordinatedGraphicsScene::purgeBackingStores() +{ + if (m_client) + m_client->purgeBackingStores(); +} + +void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state) +{ + if (!state.animationsChanged) + return; + +#if ENABLE(CSS_SHADERS) + for (size_t i = 0; i < state.animations.animations().size(); ++i) { + const KeyframeValueList& keyframes = state.animations.animations().at(i).keyframes(); + if (keyframes.property() != AnimatedPropertyWebkitFilter) + continue; + for (size_t j = 0; j < keyframes.size(); ++j) { + const FilterAnimationValue& filterValue = static_cast<const FilterAnimationValue&>(keyframes.at(j)); + injectCachedCustomFilterPrograms(filterValue.value()); + } + } +#endif + layer->setAnimations(state.animations); +} + +void CoordinatedGraphicsScene::detach() +{ + ASSERT(isMainThread()); + m_renderQueue.clear(); + m_client = 0; +} + +void CoordinatedGraphicsScene::appendUpdate(const Function<void()>& function) +{ + if (!m_isActive) + return; + + ASSERT(isMainThread()); + MutexLocker locker(m_renderQueueMutex); + m_renderQueue.append(function); +} + +void CoordinatedGraphicsScene::setActive(bool active) +{ + if (m_isActive == active) + return; + + // Have to clear render queue in both cases. + // If there are some updates in queue during activation then those updates are from previous instance of paint node + // and cannot be applied to the newly created instance. + m_renderQueue.clear(); + m_isActive = active; + if (m_isActive) + dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this)); +} + +void CoordinatedGraphicsScene::setBackgroundColor(const Color& color) +{ + m_backgroundColor = color; +} + +TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point) +{ + return rootLayer() ? rootLayer()->findScrollableContentsLayerAt(point) : 0; +} + +} // namespace WebCore + +#endif // USE(COORDINATED_GRAPHICS) |