blob: c05c30d2ed60cc44e2dd758038a48b73609383ac [file] [log] [blame]
// Copyright 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_LAYER_TREE_HOST_IMPL_H_
#define CC_LAYER_TREE_HOST_IMPL_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "cc/animation_events.h"
#include "cc/cc_export.h"
#include "cc/input_handler.h"
#include "cc/layer_sorter.h"
#include "cc/render_pass.h"
#include "cc/render_pass_sink.h"
#include "cc/renderer.h"
#include "cc/tile_manager.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/rect.h"
#include <public/WebCompositorOutputSurfaceClient.h>
namespace cc {
class CompletionEvent;
class DebugRectHistory;
class FrameRateCounter;
class HeadsUpDisplayLayerImpl;
class LayerImpl;
class LayerTreeHostImplTimeSourceAdapter;
class PageScaleAnimation;
class RenderPassDrawQuad;
class ResourceProvider;
struct RendererCapabilities;
struct RenderingStats;
// LayerTreeHost->Proxy callback interface.
class LayerTreeHostImplClient {
public:
virtual void didLoseContextOnImplThread() = 0;
virtual void onSwapBuffersCompleteOnImplThread() = 0;
virtual void onVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) = 0;
virtual void onCanDrawStateChanged(bool canDraw) = 0;
virtual void setNeedsRedrawOnImplThread() = 0;
virtual void setNeedsCommitOnImplThread() = 0;
virtual void setNeedsManageTilesOnImplThread() = 0;
virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, base::Time wallClockTime) = 0;
// Returns true if resources were deleted by this call.
virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) = 0;
virtual void sendManagedMemoryStats() = 0;
};
// PinchZoomViewport models the bounds and offset of the viewport that is used during a pinch-zoom operation.
// It tracks the layout-space dimensions of the viewport before any applied scale, and then tracks the layout-space
// coordinates of the viewport respecting the pinch settings.
class PinchZoomViewport {
public:
PinchZoomViewport();
float totalPageScaleFactor() const;
void setPageScaleFactor(float factor) { m_pageScaleFactor = factor; }
float pageScaleFactor() const { return m_pageScaleFactor; }
void setPageScaleDelta(float delta);
float pageScaleDelta() const { return m_pageScaleDelta; }
float minPageScaleFactor() const { return m_minPageScaleFactor; }
float maxPageScaleFactor() const { return m_maxPageScaleFactor; }
void setSentPageScaleDelta(float delta) { m_sentPageScaleDelta = delta; }
float sentPageScaleDelta() const { return m_sentPageScaleDelta; }
void setDeviceScaleFactor(float factor) { m_deviceScaleFactor = factor; }
float deviceScaleFactor() const { return m_deviceScaleFactor; }
// Returns true if the passed parameters were different from those previously
// cached.
bool setPageScaleFactorAndLimits(float pageScaleFactor,
float minPageScaleFactor,
float maxPageScaleFactor);
// Returns the bounds and offset of the scaled and translated viewport to use for pinch-zoom.
gfx::RectF bounds() const;
const gfx::Vector2dF& zoomedViewportOffset() const { return m_zoomedViewportOffset; }
void setLayoutViewportSize(const gfx::SizeF& size) { m_layoutViewportSize = size; }
// Apply the scroll offset in layout space to the offset of the pinch-zoom viewport. The viewport cannot be
// scrolled outside of the layout viewport bounds. Returns the component of the scroll that is un-applied due to
// this constraint.
gfx::Vector2dF applyScroll(const gfx::Vector2dF&);
// The implTransform goes from the origin of the unzoomedDeviceViewport to the
// origin of the zoomedDeviceViewport.
//
// implTransform = S[pageScale] * Tr[-zoomedDeviceViewportOffset]
gfx::Transform implTransform(bool pageScalePinchZoomEnabled) const;
private:
float m_pageScaleFactor;
float m_pageScaleDelta;
float m_sentPageScaleDelta;
float m_maxPageScaleFactor;
float m_minPageScaleFactor;
float m_deviceScaleFactor;
gfx::Vector2dF m_zoomedViewportOffset;
gfx::SizeF m_layoutViewportSize;
};
// LayerTreeHostImpl owns the LayerImpl tree as well as associated rendering state
class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
public RendererClient,
public TileManagerClient,
public NON_EXPORTED_BASE(WebKit::WebCompositorOutputSurfaceClient) {
typedef std::vector<LayerImpl*> LayerList;
public:
static scoped_ptr<LayerTreeHostImpl> create(const LayerTreeSettings&, LayerTreeHostImplClient*, Proxy*);
virtual ~LayerTreeHostImpl();
// InputHandlerClient implementation
virtual InputHandlerClient::ScrollStatus scrollBegin(gfx::Point, InputHandlerClient::ScrollInputType) OVERRIDE;
virtual bool scrollBy(const gfx::Point&, const gfx::Vector2d&) OVERRIDE;
virtual void scrollEnd() OVERRIDE;
virtual void pinchGestureBegin() OVERRIDE;
virtual void pinchGestureUpdate(float, gfx::Point) OVERRIDE;
virtual void pinchGestureEnd() OVERRIDE;
virtual void startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta duration) OVERRIDE;
virtual void scheduleAnimation() OVERRIDE;
virtual bool haveTouchEventHandlersAt(const gfx::Point&) OVERRIDE;
struct CC_EXPORT FrameData : public RenderPassSink {
FrameData();
~FrameData();
std::vector<gfx::Rect> occludingScreenSpaceRects;
std::vector<gfx::Rect> nonOccludingScreenSpaceRects;
RenderPassList renderPasses;
RenderPassIdHashMap renderPassesById;
LayerList* renderSurfaceLayerList;
LayerList willDrawLayers;
// RenderPassSink implementation.
virtual void appendRenderPass(scoped_ptr<RenderPass>) OVERRIDE;
};
// Virtual for testing.
virtual void beginCommit();
virtual void commitComplete();
virtual void animate(base::TimeTicks monotonicTime, base::Time wallClockTime);
void manageTiles();
// Returns false if problems occured preparing the frame, and we should try
// to avoid displaying the frame. If prepareToDraw is called,
// didDrawAllLayers must also be called, regardless of whether drawLayers is
// called between the two.
virtual bool prepareToDraw(FrameData&);
virtual void drawLayers(const FrameData&);
// Must be called if and only if prepareToDraw was called.
void didDrawAllLayers(const FrameData&);
// RendererClient implementation
virtual const gfx::Size& deviceViewportSize() const OVERRIDE;
virtual const LayerTreeSettings& settings() const OVERRIDE;
virtual void didLoseContext() OVERRIDE;
virtual void onSwapBuffersComplete() OVERRIDE;
virtual void setFullRootLayerDamage() OVERRIDE;
virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
virtual bool hasImplThread() const OVERRIDE;
// TileManagerClient implementation.
virtual void ScheduleManageTiles() OVERRIDE;
virtual void ScheduleRedraw() OVERRIDE;
// WebCompositorOutputSurfaceClient implementation.
virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE;
// Implementation
bool canDraw();
GraphicsContext* context() const;
std::string layerTreeAsText() const;
void finishAllRendering();
int sourceAnimationFrameNumber() const;
bool initializeRenderer(scoped_ptr<GraphicsContext>);
bool isContextLost();
TileManager* tileManager() { return m_tileManager.get(); }
Renderer* renderer() { return m_renderer.get(); }
const RendererCapabilities& rendererCapabilities() const;
bool swapBuffers();
void readback(void* pixels, const gfx::Rect&);
void setRootLayer(scoped_ptr<LayerImpl>);
LayerImpl* rootLayer() { return m_rootLayerImpl.get(); }
void setHudLayer(HeadsUpDisplayLayerImpl* layerImpl) { m_hudLayerImpl = layerImpl; }
HeadsUpDisplayLayerImpl* hudLayer() { return m_hudLayerImpl; }
// Release ownership of the current layer tree and replace it with an empty
// tree. Returns the root layer of the detached tree.
scoped_ptr<LayerImpl> detachLayerTree();
LayerImpl* rootScrollLayer() const { return m_rootScrollLayerImpl; }
bool visible() const { return m_visible; }
void setVisible(bool);
int sourceFrameNumber() const { return m_sourceFrameNumber; }
void setSourceFrameNumber(int frameNumber) { m_sourceFrameNumber = frameNumber; }
bool contentsTexturesPurged() const { return m_contentsTexturesPurged; }
void setContentsTexturesPurged();
void resetContentsTexturesPurged();
size_t memoryAllocationLimitBytes() const { return m_managedMemoryPolicy.bytesLimitWhenVisible; }
void setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize);
const gfx::Size& layoutViewportSize() const { return m_layoutViewportSize; }
float deviceScaleFactor() const { return m_deviceScaleFactor; }
void setDeviceScaleFactor(float);
float pageScaleFactor() const;
void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor);
scoped_ptr<ScrollAndScaleSet> processScrollDeltas();
gfx::Transform implTransform() const;
void startPageScaleAnimation(gfx::Vector2d targetOffset, bool useAnchor, float scale, base::TimeDelta duration);
SkColor backgroundColor() const { return m_backgroundColor; }
void setBackgroundColor(SkColor color) { m_backgroundColor = color; }
bool hasTransparentBackground() const { return m_hasTransparentBackground; }
void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; }
bool needsAnimateLayers() const { return m_needsAnimateLayers; }
void setNeedsAnimateLayers() { m_needsAnimateLayers = true; }
void setNeedsRedraw();
void renderingStats(RenderingStats*) const;
void updateRootScrollLayerImplTransform();
FrameRateCounter* fpsCounter() const { return m_fpsCounter.get(); }
DebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); }
ResourceProvider* resourceProvider() const { return m_resourceProvider.get(); }
Proxy* proxy() const { return m_proxy; }
class CC_EXPORT CullRenderPassesWithCachedTextures {
public:
bool shouldRemoveRenderPass(const RenderPassDrawQuad&, const FrameData&) const;
// Iterates from the root first, in order to remove the surfaces closest
// to the root with cached textures, and all surfaces that draw into
// them.
size_t renderPassListBegin(const RenderPassList& list) const { return list.size() - 1; }
size_t renderPassListEnd(const RenderPassList&) const { return 0 - 1; }
size_t renderPassListNext(size_t it) const { return it - 1; }
CullRenderPassesWithCachedTextures(Renderer& renderer) : m_renderer(renderer) { }
private:
Renderer& m_renderer;
};
class CC_EXPORT CullRenderPassesWithNoQuads {
public:
bool shouldRemoveRenderPass(const RenderPassDrawQuad&, const FrameData&) const;
// Iterates in draw order, so that when a surface is removed, and its
// target becomes empty, then its target can be removed also.
size_t renderPassListBegin(const RenderPassList&) const { return 0; }
size_t renderPassListEnd(const RenderPassList& list) const { return list.size(); }
size_t renderPassListNext(size_t it) const { return it + 1; }
};
template<typename RenderPassCuller>
static void removeRenderPasses(RenderPassCuller, FrameData&);
protected:
LayerTreeHostImpl(const LayerTreeSettings&, LayerTreeHostImplClient*, Proxy*);
void animatePageScale(base::TimeTicks monotonicTime);
void animateScrollbars(base::TimeTicks monotonicTime);
// Exposed for testing.
void calculateRenderSurfaceLayerList(LayerList&);
// Virtual for testing.
virtual void animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime);
// Virtual for testing.
virtual base::TimeDelta lowFrequencyAnimationInterval() const;
LayerTreeHostImplClient* m_client;
Proxy* m_proxy;
int m_sourceFrameNumber;
private:
void computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo);
void computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo);
void makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, gfx::Vector2d scrollOffset, float pageScale);
void setPageScaleDelta(float);
void updateMaxScrollOffset();
void trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList);
// Returns false if the frame should not be displayed. This function should
// only be called from prepareToDraw, as didDrawAllLayers must be called
// if this helper function is called.
bool calculateRenderPasses(FrameData&);
void animateLayersRecursive(LayerImpl*, base::TimeTicks monotonicTime, base::Time wallClockTime, AnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers);
void setBackgroundTickingEnabled(bool);
gfx::Size contentSize() const;
void sendDidLoseContextRecursive(LayerImpl*);
void clearRenderSurfaces();
bool ensureRenderSurfaceLayerList();
void clearCurrentlyScrollingLayer();
void animateScrollbarsRecursive(LayerImpl*, base::TimeTicks monotonicTime);
void dumpRenderSurfaces(std::string*, int indent, const LayerImpl*) const;
scoped_ptr<GraphicsContext> m_context;
scoped_ptr<ResourceProvider> m_resourceProvider;
scoped_ptr<Renderer> m_renderer;
scoped_ptr<TileManager> m_tileManager;
scoped_ptr<LayerImpl> m_rootLayerImpl;
LayerImpl* m_rootScrollLayerImpl;
LayerImpl* m_currentlyScrollingLayerImpl;
HeadsUpDisplayLayerImpl* m_hudLayerImpl;
int m_scrollingLayerIdFromPreviousTree;
bool m_scrollDeltaIsInViewportSpace;
LayerTreeSettings m_settings;
gfx::Size m_layoutViewportSize;
gfx::Size m_deviceViewportSize;
float m_deviceScaleFactor;
bool m_visible;
bool m_contentsTexturesPurged;
ManagedMemoryPolicy m_managedMemoryPolicy;
SkColor m_backgroundColor;
bool m_hasTransparentBackground;
// If this is true, it is necessary to traverse the layer tree ticking the animators.
bool m_needsAnimateLayers;
bool m_pinchGestureActive;
gfx::Point m_previousPinchAnchor;
scoped_ptr<PageScaleAnimation> m_pageScaleAnimation;
// This is used for ticking animations slowly when hidden.
scoped_ptr<LayerTreeHostImplTimeSourceAdapter> m_timeSourceClientAdapter;
LayerSorter m_layerSorter;
// List of visible layers for the most recently prepared frame. Used for
// rendering and input event hit testing.
LayerList m_renderSurfaceLayerList;
PinchZoomViewport m_pinchZoomViewport;
scoped_ptr<FrameRateCounter> m_fpsCounter;
scoped_ptr<DebugRectHistory> m_debugRectHistory;
size_t m_numImplThreadScrolls;
size_t m_numMainThreadScrolls;
size_t m_cumulativeNumLayersInLayerTree;
DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
};
} // namespace cc
#endif // CC_LAYER_TREE_HOST_IMPL_H_