blob: e325590e2f9f6ee6bd1b4643aa9aa3d2a7929527 [file] [log] [blame]
/*
* Copyright 2010, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GLWebViewState_h
#define GLWebViewState_h
#if USE(ACCELERATED_COMPOSITING)
#include "Color.h"
#include "DrawExtra.h"
#include "GLExtras.h"
#include "IntRect.h"
#include "SkCanvas.h"
#include "SkRect.h"
#include "SkRegion.h"
#include "SurfaceCollectionManager.h"
#include <utils/threads.h>
// Performance measurements probe
// To use it, enable the visual indicators in debug mode.
// turning off the visual indicators will flush the measures.
// #define MEASURES_PERF
#define MAX_MEASURES_PERF 2000
// Prefetch and render 1 tiles ahead of the scroll
// TODO: We should either dynamically change the outer bound by detecting the
// HW limit or save further in the GPU memory consumption.
#define TILE_PREFETCH_DISTANCE 1
namespace WebCore {
class BaseLayerAndroid;
class LayerAndroid;
class ScrollableLayerAndroid;
class TexturesResult;
/////////////////////////////////////////////////////////////////////////////////
// GL Architecture
/////////////////////////////////////////////////////////////////////////////////
//
// To draw things, WebView use a tree of layers. The root of that tree is a
// BaseLayerAndroid, which may have numerous LayerAndroid over it. The content
// of those layers are SkPicture, the content of the BaseLayer is an PictureSet.
//
// When drawing, we therefore have one large "surface" that is the BaseLayer,
// and (possibly) additional surfaces (usually smaller), which are the
// LayerAndroids. The BaseLayer usually corresponds to the normal web page
// content, the Layers are used for some parts such as specific divs (e.g. fixed
// position divs, or elements using CSS3D transforms, or containing video,
// plugins, etc.).
//
// *** NOTE: The GL drawing architecture only paints the BaseLayer for now.
//
// The rendering model is to use tiles to display the BaseLayer (as obviously a
// BaseLayer's area can be arbitrarly large). The idea is to compute a set of
// tiles covering the visibleContentRect's area, paint those tiles using the webview's
// content (i.e. the BaseLayer's PictureSet), then display those tiles.
// We check which tile we should use at every frame.
//
// Overview
// ---------
//
// The tiles are grouped into a TiledPage -- basically a map of tiles covering
// the BaseLayer's surface. When drawing, we ask the TiledPage to prepare()
// itself then draw itself on screen. The prepare() function is the one
// that schedules tiles to be painted -- i.e. the subset of tiles that intersect
// with the current visibleContentRect. When they are ready, we can display
// the TiledPage.
//
// Note that BaseLayerAndroid::drawGL() will return true to the java side if
// there is a need to be called again (i.e. if we do not have up to date
// textures or a transition is going on).
//
// Tiles are implemented as a Tile. It knows how to paint itself with the
// PictureSet, and to display itself. A GL texture is usually associated to it.
//
// We also works with two TiledPages -- one to display the page at the
// current scale factor, and another we use to paint the page at a different
// scale factor. I.e. when we zoom, we use TiledPage A, with its tiles scaled
// accordingly (and therefore possible loss of quality): this is fast as it's
// purely a hardware operation. When the user is done zooming, we ask for
// TiledPage B to be painted at the new scale factor, covering the
// visibleContentRect's area. When B is ready, we swap it with A.
//
// Texture allocation
// ------------------
//
// Obviously we cannot have every Tile having a GL texture -- we need to
// get the GL textures from an existing pool, and reuse them.
//
// The way we do it is that when we call TiledPage::prepare(), we group the
// tiles we need (i.e. in the visibleContentRect and dirty) into a TilesSet and call
// Tile::reserveTexture() for each tile (which ensures there is a specific
// GL textures backing the Tiles).
//
// reserveTexture() will ask the TilesManager for a texture. The allocation
// mechanism goal is to (in order):
// - prefers to allocate the same texture as the previous time
// - prefers to allocate textures that are as far from the visibleContentRect as possible
// - prefers to allocate textures that are used by different TiledPages
//
// Note that to compute the distance of each tile from the visibleContentRect, each time
// we prepare() a TiledPage. Also during each prepare() we compute which tiles
// are dirty based on the info we have received from webkit.
//
// Tile Invalidation
// ------------------
//
// We do not want to redraw a tile if the tile is up-to-date. A tile is
// considered to be dirty an in need of redrawing in the following cases
// - the tile has acquires a new texture
// - webkit invalidates all or part of the tiles contents
//
// To handle the case of webkit invalidation we store two ids (counters) of the
// pictureSets in the tile. The first id (A) represents the pictureSet used to
// paint the tile and the second id (B) represents the pictureSet in which the
// tile was invalidated by webkit. Thus, if A < B then tile is dirty.
//
// Since invalidates can occur faster than a full tiled page update, the tiled
// page is protected by a 'lock' (m_baseLayerUpdate) that is set to true to
// defer updates to the background layer, giving the foreground time to render
// content instead of constantly flushing with invalidates. See
// lockBaseLayerUpdate() & unlockBaseLayerUpdate().
//
// Painting scheduling
// -------------------
//
// The next operation is to schedule this TilesSet to be painted
// (TilesManager::schedulePaintForTilesSet()). TexturesGenerator
// will get the TilesSet and ask the Tiles in it to be painted.
//
// Tile::paintBitmap() will paint the texture using the BaseLayer's
// PictureSet (calling TiledPage::paintBaseLayerContent() which in turns
// calls GLWebViewState::paintBaseLayerContent()).
//
// Note that TexturesGenerator is running in a separate thread, the textures
// are shared using EGLImages (this is necessary to not slow down the rendering
// speed -- updating GL textures in the main GL thread would slow things down).
//
/////////////////////////////////////////////////////////////////////////////////
class GLWebViewState {
public:
GLWebViewState();
~GLWebViewState();
bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator,
bool isPictureAfterFirstLayout);
void paintExtras();
GLExtras* glExtras() { return &m_glExtras; }
void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; }
bool isScrolling() { return m_isScrolling || m_isVisibleContentRectScrolling; }
bool setLayersRenderingMode(TexturesResult&);
int drawGL(IntRect& rect, SkRect& visibleContentRect, IntRect* invalRect,
IntRect& screenRect, int titleBarHeight,
IntRect& clip, float scale,
bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
bool shouldDraw);
#ifdef MEASURES_PERF
void dumpMeasures();
#endif
void addDirtyArea(const IntRect& rect);
void resetLayersDirtyArea();
void doFrameworkFullInval();
bool inUnclippedDraw() { return m_inUnclippedDraw; }
bool goingDown() { return m_goingDown; }
bool goingLeft() { return m_goingLeft; }
float scale() { return m_scale; }
// Currently, we only use 3 modes : kAllTextures, kClippedTextures and
// kSingleSurfaceRendering ( for every mode > kClippedTextures ) .
enum LayersRenderingMode {
kAllTextures = 0, // all layers are drawn with textures fully covering them
kClippedTextures = 1, // all layers are drawn, but their textures will be clipped
kScrollableAndFixedLayers = 2, // only scrollable and fixed layers will be drawn
kFixedLayers = 3, // only fixed layers will be drawn
kSingleSurfaceRendering = 4 // no layers will be drawn on separate textures
// -- everything is drawn on the base surface.
};
LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; }
bool isSingleSurfaceRenderingMode() { return m_layersRenderingMode == kSingleSurfaceRendering; }
void scrollLayer(int layerId, int x, int y);
private:
void setVisibleContentRect(const SkRect& visibleContentRect, float scale);
double setupDrawing(const IntRect& invScreenRect, const SkRect& visibleContentRect,
const IntRect& screenRect, int titleBarHeight,
const IntRect& screenClip, float scale);
void showFrameInfo(const IntRect& rect, bool collectionsSwapped);
void clearRectWithColor(const IntRect& rect, float r, float g,
float b, float a);
double m_prevDrawTime;
SkRect m_visibleContentRect;
IntRect m_frameworkLayersInval;
bool m_doFrameworkFullInval;
bool m_inUnclippedDraw;
#ifdef MEASURES_PERF
unsigned int m_totalTimeCounter;
int m_timeCounter;
double m_delayTimes[MAX_MEASURES_PERF];
bool m_measurePerfs;
#endif
GLExtras m_glExtras;
bool m_isScrolling;
bool m_isVisibleContentRectScrolling;
bool m_goingDown;
bool m_goingLeft;
float m_scale;
LayersRenderingMode m_layersRenderingMode;
SurfaceCollectionManager m_surfaceCollectionManager;
};
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
#endif // GLWebViewState_h