#include "BaseLayerAndroid.h"
#include "ClassTracker.h"
#include "GLUtils.h"
+#include "ImagesManager.h"
#include "LayerAndroid.h"
+#include "ScrollableLayerAndroid.h"
#include "SkPath.h"
#include "TilesManager.h"
#include "TilesTracker.h"
+#include "TreeManager.h"
#include <wtf/CurrentTime.h>
+#include <pthread.h>
+
#include <cutils/log.h>
#include <wtf/text/CString.h>
using namespace android;
-GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
+GLWebViewState::GLWebViewState()
: m_zoomManager(this)
- , m_baseLayer(0)
- , m_currentBaseLayer(0)
- , m_previouslyUsedRoot(0)
, m_currentPictureCounter(0)
, m_usePageA(true)
, m_frameworkInval(0, 0, 0, 0)
, m_frameworkLayersInval(0, 0, 0, 0)
- , m_globalButtonMutex(buttonMutex)
- , m_baseLayerUpdate(true)
- , m_backgroundColor(SK_ColorWHITE)
, m_isScrolling(false)
, m_goingDown(true)
, m_goingLeft(false)
, m_expandedTileBoundsX(0)
, m_expandedTileBoundsY(0)
+ , m_scale(1)
+ , m_layersRenderingMode(kAllTextures)
{
m_viewport.setEmpty();
m_futureViewportTileBounds.setEmpty();
GLWebViewState::~GLWebViewState()
{
- // Unref the existing tree/PaintedSurfaces
- if (m_previouslyUsedRoot)
- TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, 0);
-
// Take care of the transfer queue such that Tex Gen thread will not stuck
TilesManager::instance()->unregisterGLWebViewState(this);
// We have to destroy the two tiled pages first as their destructor
// may depend on the existence of this GLWebViewState and some of its
// instance variables in order to complete.
- // Explicitely, currently we need to have the m_currentBaseLayer around
+ // Explicitely, currently we need to have the m_paintingBaseLayer around
// in order to complete any pending paint operations (the tiled pages
// will remove any pending operations, and wait if one is underway).
delete m_tiledPageA;
delete m_tiledPageB;
- SkSafeUnref(m_previouslyUsedRoot);
- SkSafeUnref(m_currentBaseLayer);
- SkSafeUnref(m_baseLayer);
- m_previouslyUsedRoot = 0;
- m_baseLayer = 0;
- m_currentBaseLayer = 0;
#ifdef DEBUG_COUNT
ClassTracker::instance()->decrement("GLWebViewState");
#endif
void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval,
bool showVisualIndicator, bool isPictureAfterFirstLayout)
{
- android::Mutex::Autolock lock(m_baseLayerLock);
if (!layer || isPictureAfterFirstLayout) {
+ // TODO: move this into TreeManager
m_tiledPageA->discardTextures();
m_tiledPageB->discardTextures();
}
- if (isPictureAfterFirstLayout) {
- m_baseLayerUpdate = true;
- m_invalidateRegion.setEmpty();
- }
- if (m_baseLayer && layer)
- m_baseLayer->swapExtra(layer);
-
- SkSafeRef(layer);
- SkSafeUnref(m_baseLayer);
- m_baseLayer = layer;
- if (m_baseLayer)
- m_baseLayer->setGLWebViewState(this);
-
- // We only update the layers if we are not currently
- // waiting for a tiledPage to be painted
- if (m_baseLayerUpdate) {
- SkSafeRef(layer);
- SkSafeUnref(m_currentBaseLayer);
- m_currentBaseLayer = layer;
+ if (layer) {
+ XLOG("new base layer %p, (inval region empty %d) with child %p", layer, inval.isEmpty(), layer->getChild(0));
+ layer->setState(this);
+ layer->markAsDirty(inval); // TODO: set in webview.cpp
}
+ m_treeManager.updateWithTree(layer, isPictureAfterFirstLayout);
m_glExtras.setDrawExtra(0);
- invalRegion(inval);
#ifdef MEASURES_PERF
if (m_measurePerfs && !showVisualIndicator)
TilesManager::instance()->setShowVisualIndicator(showVisualIndicator);
}
+void GLWebViewState::scrolledLayer(ScrollableLayerAndroid*)
+{
+ // TODO: only inval the area of the scrolled layer instead of
+ // doing a fullInval()
+ if (m_layersRenderingMode == kSingleSurfaceRendering)
+ fullInval();
+}
+
void GLWebViewState::invalRegion(const SkRegion& region)
{
+ if (m_layersRenderingMode == kSingleSurfaceRendering) {
+ // TODO: do the union of both layers tree to compute
+ //the minimum inval instead of doing a fullInval()
+ fullInval();
+ return;
+ }
SkRegion::Iterator iterator(region);
while (!iterator.done()) {
SkIRect r = iterator.rect();
}
}
-void GLWebViewState::unlockBaseLayerUpdate() {
- if (m_baseLayerUpdate)
- return;
-
- m_baseLayerUpdate = true;
- android::Mutex::Autolock lock(m_baseLayerLock);
- SkSafeRef(m_baseLayer);
- SkSafeUnref(m_currentBaseLayer);
- m_currentBaseLayer = m_baseLayer;
-
- invalRegion(m_invalidateRegion);
- m_invalidateRegion.setEmpty();
-}
-
void GLWebViewState::inval(const IntRect& rect)
{
- if (m_baseLayerUpdate) {
- // base layer isn't locked, so go ahead and issue the inval to both tiled pages
- m_currentPictureCounter++;
- if (!rect.isEmpty()) {
- // find which tiles fall within the invalRect and mark them as dirty
- m_tiledPageA->invalidateRect(rect, m_currentPictureCounter);
- m_tiledPageB->invalidateRect(rect, m_currentPictureCounter);
- if (m_frameworkInval.isEmpty())
- m_frameworkInval = rect;
- else
- m_frameworkInval.unite(rect);
- XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
- m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
- rect.x(), rect.y(), rect.width(), rect.height());
- }
- } else {
- // base layer is locked, so defer invalidation until unlockBaseLayerUpdate()
- m_invalidateRegion.op(rect.x(), rect.y(), rect.maxX(), rect.maxY(), SkRegion::kUnion_Op);
+ m_currentPictureCounter++;
+ if (!rect.isEmpty()) {
+ // find which tiles fall within the invalRect and mark them as dirty
+ m_tiledPageA->invalidateRect(rect, m_currentPictureCounter);
+ m_tiledPageB->invalidateRect(rect, m_currentPictureCounter);
+ if (m_frameworkInval.isEmpty())
+ m_frameworkInval = rect;
+ else
+ m_frameworkInval.unite(rect);
+ XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
+ m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
+ rect.x(), rect.y(), rect.width(), rect.height());
}
TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale());
}
unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
{
- android::Mutex::Autolock lock(m_baseLayerLock);
- if (m_currentBaseLayer) {
- m_globalButtonMutex->lock();
- m_currentBaseLayer->drawCanvas(canvas);
- m_globalButtonMutex->unlock();
- }
+ m_treeManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering);
return m_currentPictureCounter;
}
int GLWebViewState::baseContentWidth()
{
- return m_currentBaseLayer ? m_currentBaseLayer->content()->width() : 0;
+ return m_treeManager.baseContentWidth();
}
int GLWebViewState::baseContentHeight()
{
- return m_currentBaseLayer ? m_currentBaseLayer->content()->height() : 0;
+ return m_treeManager.baseContentHeight();
}
void GLWebViewState::setViewport(SkRect& viewport, float scale)
// allocate max possible number of tiles visible with this viewport
int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1;
int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1;
- int maxTextureCount = (viewMaxTileX + TILE_PREFETCH_DISTANCE * 2) *
- (viewMaxTileY + TILE_PREFETCH_DISTANCE * 2) * 2;
+
+ int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) *
+ (viewMaxTileY + m_expandedTileBoundsY * 2) * 2;
+
TilesManager::instance()->setMaxTextureCount(maxTextureCount);
m_tiledPageA->updateBaseTileSize();
m_tiledPageB->updateBaseTileSize();
m_frameworkLayersInval.setHeight(0);
}
-double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
- IntRect& webViewRect, int titleBarHeight,
- IntRect& screenClip, float scale)
+void GLWebViewState::drawBackground(Color& backgroundColor)
{
- int left = viewRect.x();
- int top = viewRect.y();
- int width = viewRect.width();
- int height = viewRect.height();
-
if (TilesManager::instance()->invertedScreen()) {
- float color = 1.0 - ((((float) m_backgroundColor.red() / 255.0) +
- ((float) m_backgroundColor.green() / 255.0) +
- ((float) m_backgroundColor.blue() / 255.0)) / 3.0);
+ float color = 1.0 - ((((float) backgroundColor.red() / 255.0) +
+ ((float) backgroundColor.green() / 255.0) +
+ ((float) backgroundColor.blue() / 255.0)) / 3.0);
glClearColor(color, color, color, 1);
} else {
- glClearColor((float)m_backgroundColor.red() / 255.0,
- (float)m_backgroundColor.green() / 255.0,
- (float)m_backgroundColor.blue() / 255.0, 1);
+ glClearColor((float)backgroundColor.red() / 255.0,
+ (float)backgroundColor.green() / 255.0,
+ (float)backgroundColor.blue() / 255.0, 1);
}
glClear(GL_COLOR_BUFFER_BIT);
+}
+double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
+ IntRect& webViewRect, int titleBarHeight,
+ IntRect& screenClip, float scale)
+{
+ int left = viewRect.x();
+ int top = viewRect.y();
+ int width = viewRect.width();
+ int height = viewRect.height();
glViewport(left, top, width, height);
ShaderProgram* shader = TilesManager::instance()->shader();
return currentTime;
}
+bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded)
+{
+ bool invalBase = false;
+ int maxTextures = TilesManager::instance()->maxTextureCount();
+ LayersRenderingMode layersRenderingMode = m_layersRenderingMode;
+
+ m_layersRenderingMode = kSingleSurfaceRendering;
+ if (nbTexturesNeeded.fixed < maxTextures)
+ m_layersRenderingMode = kFixedLayers;
+ if (nbTexturesNeeded.scrollable < maxTextures)
+ m_layersRenderingMode = kScrollableAndFixedLayers;
+ if (nbTexturesNeeded.clipped < maxTextures)
+ m_layersRenderingMode = kClippedTextures;
+ if (nbTexturesNeeded.full < maxTextures)
+ m_layersRenderingMode = kAllTextures;
+
+ if (m_layersRenderingMode < layersRenderingMode
+ && m_layersRenderingMode != kAllTextures)
+ invalBase = true;
+
+ if (m_layersRenderingMode > layersRenderingMode
+ && m_layersRenderingMode != kClippedTextures)
+ invalBase = true;
+
+#ifdef DEBUG
+ if (m_layersRenderingMode != layersRenderingMode) {
+ char* mode[] = { "kAllTextures", "kClippedTextures",
+ "kScrollableAndFixedLayers", "kFixedLayers", "kSingleSurfaceRendering" };
+ XLOGC("Change from mode %s to %s -- We need textures: fixed: %d,"
+ " scrollable: %d, clipped: %d, full: %d, max textures: %d",
+ static_cast<char*>(mode[layersRenderingMode]),
+ static_cast<char*>(mode[m_layersRenderingMode]),
+ nbTexturesNeeded.fixed,
+ nbTexturesNeeded.scrollable,
+ nbTexturesNeeded.clipped,
+ nbTexturesNeeded.full, maxTextures);
+ }
+#endif
+
+ // For now, anything below kClippedTextures is equivalent
+ // to kSingleSurfaceRendering
+ // TODO: implement the other rendering modes
+ if (m_layersRenderingMode > kClippedTextures)
+ m_layersRenderingMode = kSingleSurfaceRendering;
+
+ // update the base surface if needed
+ if (m_layersRenderingMode != layersRenderingMode
+ && invalBase) {
+ m_tiledPageA->discardTextures();
+ m_tiledPageB->discardTextures();
+ fullInval();
+ return true;
+ }
+ return false;
+}
+
+void GLWebViewState::fullInval()
+{
+ // TODO -- use base layer's size.
+ IntRect ir(0, 0, 1E6, 1E6);
+ inval(ir);
+}
+
bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
IntRect& clip, float scale, bool* buffersSwappedPtr)
{
+ m_scale = scale;
TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
viewport.fTop,
viewport.fRight,
TilesManager::instance()->getTilesTracker()->clear();
#endif
- m_baseLayerLock.lock();
- BaseLayerAndroid* baseLayer = m_currentBaseLayer;
- SkSafeRef(baseLayer);
- BaseLayerAndroid* baseForComposited = m_baseLayer;
- SkSafeRef(baseForComposited);
- m_baseLayerLock.unlock();
- if (!baseLayer) {
- SkSafeUnref(baseForComposited);
- return false;
- }
-
float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO;
float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO;
- bool useHorzPrefetch = viewWidth < baseContentWidth();
- bool useVertPrefetch = viewHeight < baseContentHeight();
+ bool useMinimalMemory = TilesManager::instance()->useMinimalMemory();
+ bool useHorzPrefetch = useMinimalMemory ? 0 : viewWidth < baseContentWidth();
+ bool useVertPrefetch = useMinimalMemory ? 0 : viewHeight < baseContentHeight();
m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
resetLayersDirtyArea();
- if (!baseForComposited ||
- (baseForComposited && !baseForComposited->countChildren())) {
- SkSafeRef(baseLayer);
- SkSafeUnref(baseForComposited);
- baseForComposited = baseLayer;
- }
-
- LayerAndroid* compositedRoot = 0;
- if (baseForComposited && baseForComposited->countChildren() >= 1)
- compositedRoot = static_cast<LayerAndroid*>(baseForComposited->getChild(0));
+ // when adding or removing layers, use the the paintingBaseLayer's tree so
+ // that content that moves to the base layer from a layer is synchronized
if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
XLOGC("WARNING, scale seems corrupted before update: %e", scale);
// the BaseTiles' texture.
TilesManager::instance()->transferQueue()->updateDirtyBaseTiles();
+ // Upload any pending ImageTexture
+ // Return true if we still have some images to upload.
+ // TODO: upload as many textures as possible within a certain time limit
+ bool ret = ImagesManager::instance()->uploadTextures();
+
if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
XLOGC("WARNING, scale seems corrupted after update: %e", scale);
// gather the textures we can use
TilesManager::instance()->gatherLayerTextures();
- if (compositedRoot != m_previouslyUsedRoot)
- TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, compositedRoot);
-
- // set up zoom manager, shaders, etc.
- m_backgroundColor = baseLayer->getBackgroundColor();
double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
- bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect,
- viewport, scale, buffersSwappedPtr);
+
+
+ TexturesResult nbTexturesNeeded;
+ bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering;
+ ret |= m_treeManager.drawGL(currentTime, rect, viewport,
+ scale, fastSwap,
+ buffersSwappedPtr, &nbTexturesNeeded);
+ if (!ret)
+ resetFrameworkInval();
+
+ ret |= setLayersRenderingMode(nbTexturesNeeded);
+
+ FloatRect extrasclip(0, 0, rect.width(), rect.height());
+ TilesManager::instance()->shader()->clip(extrasclip);
+
m_glExtras.drawGL(webViewRect, viewport, titleBarHeight);
glBindBuffer(GL_ARRAY_BUFFER, 0);
- SkSafeRef(compositedRoot);
- SkSafeUnref(m_previouslyUsedRoot);
- m_previouslyUsedRoot = compositedRoot;
-
+ // Clean up GL textures for video layer.
+ TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
ret |= TilesManager::instance()->invertedScreenSwitch();
if (ret) {
}
#endif
- SkSafeUnref(baseForComposited);
- SkSafeUnref(baseLayer);
#ifdef DEBUG
TilesManager::instance()->getTilesTracker()->showTrackTextures();
ImagesManager::instance()->showImages();
#endif
+
return ret;
}