summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics
diff options
context:
space:
mode:
authorNicolas Roard <nicolasroard@google.com>2011-11-04 13:56:14 -0700
committerNicolas Roard <nicolasroard@google.com>2011-11-10 18:27:56 -0800
commit5997528e55d0dc6734718bde61faa8513b1dd54f (patch)
tree62b22677aeffd0f36ee9aa5c283e7eaab9cf9b1d /Source/WebCore/platform/graphics
parentc97291b2e7a966abf8dbad5cf2e0e8b033c3cd90 (diff)
downloadexternal_webkit-5997528e55d0dc6734718bde61faa8513b1dd54f.zip
external_webkit-5997528e55d0dc6734718bde61faa8513b1dd54f.tar.gz
external_webkit-5997528e55d0dc6734718bde61faa8513b1dd54f.tar.bz2
Fallback mode when running out of textures for layers
- Implements a degraded rendering mode when running out of textures - Speed up rendering by reusing the same SkBitmap in RasterRenderer - Some refactoring bug:5279231 Change-Id: I52943a87bed56c49b01b47fea4fa1a5c49e09e93
Diffstat (limited to 'Source/WebCore/platform/graphics')
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp27
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.h2
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp125
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.h19
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp3
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.h1
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp255
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h35
-rw-r--r--Source/WebCore/platform/graphics/android/PaintedSurface.cpp76
-rw-r--r--Source/WebCore/platform/graphics/android/PaintedSurface.h7
-rw-r--r--Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp23
-rw-r--r--Source/WebCore/platform/graphics/android/PerformanceMonitor.h1
-rw-r--r--Source/WebCore/platform/graphics/android/RasterRenderer.cpp19
-rw-r--r--Source/WebCore/platform/graphics/android/RasterRenderer.h4
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.cpp7
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.h4
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.cpp60
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.h13
19 files changed, 588 insertions, 99 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index 2a1b1de..0e6f64f 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -101,13 +101,14 @@ void BaseLayerAndroid::setContent(const PictureSet& src)
// setSize(src.width(), src.height());
}
-void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
+bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
{
#if USE(ACCELERATED_COMPOSITING)
android::Mutex::Autolock lock(m_drawLock);
#endif
if (!m_content.isEmpty())
m_content.draw(canvas);
+ return true;
}
#if USE(ACCELERATED_COMPOSITING)
@@ -307,16 +308,6 @@ bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
m_glWebViewState->resetFrameworkInval();
if (compositedRoot) {
- TransformationMatrix ident;
-
- bool animsRunning = compositedRoot->evaluateAnimations();
- if (animsRunning)
- needsRedraw = true;
-
- compositedRoot->updateFixedLayersPositions(visibleRect);
- FloatRect clip(0, 0, viewRect.width(), viewRect.height());
- compositedRoot->updateGLPositionsAndScale(
- ident, clip, 1, m_glWebViewState->zoomManager()->layersScale());
SkMatrix matrix;
matrix.setTranslate(viewRect.x(), viewRect.y());
@@ -326,20 +317,16 @@ bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
compositedRoot->nbLayers(),
compositedRoot->nbTexturedLayers());
#endif
-
- // Clean up GL textures for video layer.
- TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
-
- compositedRoot->prepare(m_glWebViewState);
- if (compositedRoot->drawGL(m_glWebViewState, matrix)) {
+ // For now, we render layers only if the rendering mode
+ // is kAllTextures or kClippedTextures
+ if (m_glWebViewState->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers
+ && compositedRoot->drawGL(m_glWebViewState, matrix)) {
if (TilesManager::instance()->layerTexturesRemain()) {
// only try redrawing for layers if layer textures remain,
// otherwise we'll repaint without getting anything done
needsRedraw = true;
}
- } else if (!animsRunning)
- m_glWebViewState->resetLayersDirtyArea();
-
+ }
}
m_previousVisible = visibleRect;
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
index ad77013..20942ec 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
@@ -58,7 +58,7 @@ public:
// the passed canvas. We used it to paint the GL tiles as well as
// WebView::copyBaseContentToPicture(), so a lock is necessary as
// we are running in different threads.
- void drawCanvas(SkCanvas* canvas);
+ virtual bool drawCanvas(SkCanvas* canvas);
bool drawGL(double currentTime, LayerAndroid* compositedRoot, IntRect& rect,
SkRect& viewport, float scale, bool* buffersSwappedPtr);
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 09e8cc4..e997b57 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -33,11 +33,14 @@
#include "GLUtils.h"
#include "ImagesManager.h"
#include "LayerAndroid.h"
+#include "ScrollableLayerAndroid.h"
#include "SkPath.h"
#include "TilesManager.h"
#include "TilesTracker.h"
#include <wtf/CurrentTime.h>
+#include <pthread.h>
+
#include <cutils/log.h>
#include <wtf/text/CString.h>
@@ -86,6 +89,7 @@ GLWebViewState::GLWebViewState()
, m_expandedTileBoundsX(0)
, m_expandedTileBoundsY(0)
, m_scale(1)
+ , m_layersRenderingMode(kAllTextures)
{
m_viewport.setEmpty();
m_futureViewportTileBounds.setEmpty();
@@ -151,7 +155,6 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval
SkSafeUnref(m_currentBaseLayer);
m_currentBaseLayer = layer;
-
// copy content from old composited root to new
LayerAndroid* oldRoot = m_currentBaseLayerRoot;
if (layer) {
@@ -173,7 +176,13 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval
m_paintingBaseLayer = layer;
}
m_glExtras.setDrawExtra(0);
- invalRegion(inval);
+
+ // TODO: do the union of both layers tree to compute
+ // the minimum inval instead of doing a fullInval()
+ if (m_layersRenderingMode == kSingleSurfaceRendering)
+ fullInval();
+ else
+ invalRegion(inval);
#ifdef MEASURES_PERF
if (m_measurePerfs && !showVisualIndicator)
@@ -184,6 +193,14 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval
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)
{
SkRegion::Iterator iterator(region);
@@ -241,6 +258,11 @@ unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
m_baseLayerLock.unlock();
if (base) {
base->drawCanvas(canvas);
+ if (m_layersRenderingMode == kSingleSurfaceRendering) {
+ LayerAndroid* rootLayer = static_cast<LayerAndroid*>(base->getChild(0));
+ if (rootLayer)
+ rootLayer->drawCanvas(canvas);
+ }
}
SkSafeUnref(base);
return m_currentPictureCounter;
@@ -402,6 +424,69 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
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)
@@ -475,10 +560,45 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
// set up zoom manager, shaders, etc.
m_backgroundColor = baseLayer->getBackgroundColor();
double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
+
+ if (compositedRoot)
+ compositedRoot->setState(this);
+
+ bool animsRunning = false;
+ TexturesResult nbTexturesNeeded;
+ if (compositedRoot) {
+ TransformationMatrix ident;
+ animsRunning = compositedRoot->evaluateAnimations();
+ bool hasFixedElements = compositedRoot->updateFixedLayersPositions(viewport);
+ if (m_layersRenderingMode == kSingleSurfaceRendering) {
+ // If we are in single surface rendering, we may have to fully
+ // invalidate if we have fixed elements or if we have CSS
+ // animations.
+ // TODO: compute the minimum invals
+ if (animsRunning || hasFixedElements)
+ fullInval();
+ }
+
+ // TODO: get the base document area for the original clip
+ FloatRect clip(0, 0, 1E6, 1E6);
+ compositedRoot->updateGLPositionsAndScale(ident, clip, 1, zoomManager()->layersScale());
+ compositedRoot->prepare(this);
+
+ ret |= animsRunning;
+
+ compositedRoot->computeTexturesAmount(&nbTexturesNeeded);
+ }
+ ret |= setLayersRenderingMode(nbTexturesNeeded);
+
+ // Clean up GL textures for video layer.
+ TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
+
ret |= baseLayer->drawGL(currentTime, compositedRoot, rect,
viewport, scale, buffersSwappedPtr);
+
FloatRect extrasclip(0, 0, rect.width(), rect.height());
TilesManager::instance()->shader()->clip(extrasclip);
+
m_glExtras.drawGL(webViewRect, viewport, titleBarHeight);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -543,6 +663,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
TilesManager::instance()->getTilesTracker()->showTrackTextures();
ImagesManager::instance()->showImages();
#endif
+
return ret;
}
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h
index 5f7ca71..a1adaf1 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h
@@ -57,6 +57,8 @@ namespace WebCore {
class BaseLayerAndroid;
class LayerAndroid;
+class ScrollableLayerAndroid;
+class TexturesResult;
/////////////////////////////////////////////////////////////////////////////////
// GL Architecture
@@ -208,6 +210,9 @@ public:
int titleBarHeight, IntRect& screenClip,
float scale);
+ bool setLayersRenderingMode(TexturesResult&);
+ void fullInval();
+
bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
IntRect& clip, float scale, bool* buffersSwappedPtr);
@@ -232,6 +237,18 @@ public:
float scale() { return m_scale; }
+ 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; }
+ void scrolledLayer(ScrollableLayerAndroid*);
+
private:
void inval(const IntRect& rect); // caller must hold m_baseLayerLock
void invalRegion(const SkRegion& region);
@@ -276,6 +293,8 @@ private:
int m_expandedTileBoundsY;
float m_scale;
+
+ LayersRenderingMode m_layersRenderingMode;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 05a0fdc..3e062f8 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -564,6 +564,7 @@ bool GraphicsLayerAndroid::repaint()
phase.set(GraphicsLayerPaintBackground);
if (!paintContext(m_contentLayer->recordContext(), layerBounds))
return false;
+ m_contentLayer->checkTextPresence();
// Construct the foreground layer and draw.
RenderBox* box = layer->renderBox();
@@ -582,6 +583,7 @@ bool GraphicsLayerAndroid::repaint()
layer->scrollToOffset(0, 0);
// At this point, it doesn't matter if painting failed.
(void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
+ m_foregroundLayer->checkTextPresence();
layer->scrollToOffset(scroll.width(), scroll.height());
// Construct the clip layer for masking the contents.
@@ -607,6 +609,7 @@ bool GraphicsLayerAndroid::repaint()
// picture.
if (!paintContext(m_contentLayer->recordContext(), layerBounds))
return false;
+ m_contentLayer->checkTextPresence();
// Check for a scrollable iframe and report the scrolling
// limits based on the view size.
if (m_contentLayer->contentIsScrollable()) {
diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h
index c8bb81d..89e101c 100644
--- a/Source/WebCore/platform/graphics/android/Layer.h
+++ b/Source/WebCore/platform/graphics/android/Layer.h
@@ -122,6 +122,7 @@ public:
// paint method
+ virtual bool drawCanvas(SkCanvas*) { return false; }
void draw(SkCanvas*, SkScalar opacity);
void draw(SkCanvas* canvas) {
this->draw(canvas, SK_Scalar1);
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index e0898e6..12a11bf 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -55,6 +55,87 @@ private:
int m_opacity;
};
+class HasTextBounder : public SkBounder {
+ virtual bool onIRect(const SkIRect& rect)
+ {
+ return false;
+ }
+};
+
+class HasTextCanvas : public SkCanvas {
+public:
+ HasTextCanvas(SkBounder* bounder, SkPicture* picture)
+ : m_picture(picture)
+ , m_hasText(false)
+ {
+ setBounder(bounder);
+ }
+
+ void setHasText()
+ {
+ m_hasText = true;
+ m_picture->abortPlayback();
+ }
+
+ bool hasText()
+ {
+ return m_hasText;
+ }
+
+ virtual bool clipPath(const SkPath&, SkRegion::Op) {
+ return true;
+ }
+
+ virtual void commonDrawBitmap(const SkBitmap& bitmap,
+ const SkIRect* rect,
+ const SkMatrix&,
+ const SkPaint&) {}
+
+ virtual void drawPaint(const SkPaint& paint) {}
+ virtual void drawPath(const SkPath&, const SkPaint& paint) {}
+ virtual void drawPoints(PointMode, size_t,
+ const SkPoint [], const SkPaint& paint) {}
+
+ virtual void drawRect(const SkRect& , const SkPaint& paint) {}
+ virtual void drawSprite(const SkBitmap& , int , int ,
+ const SkPaint* paint = NULL) {}
+
+ virtual void drawText(const void*, size_t byteLength, SkScalar,
+ SkScalar, const SkPaint& paint)
+ {
+ setHasText();
+ }
+
+ virtual void drawPosText(const void* , size_t byteLength,
+ const SkPoint [], const SkPaint& paint)
+ {
+ setHasText();
+ }
+
+ virtual void drawPosTextH(const void*, size_t byteLength,
+ const SkScalar [], SkScalar,
+ const SkPaint& paint)
+ {
+ setHasText();
+ }
+
+ virtual void drawTextOnPath(const void*, size_t byteLength,
+ const SkPath&, const SkMatrix*,
+ const SkPaint& paint)
+ {
+ setHasText();
+ }
+
+ virtual void drawPicture(SkPicture& picture) {
+ SkCanvas::drawPicture(picture);
+ }
+
+private:
+
+ SkPicture* m_picture;
+ bool m_hasText;
+};
+
///////////////////////////////////////////////////////////////////////////////
LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
@@ -75,7 +156,9 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
m_scale(1),
m_lastComputeTextureSize(0),
m_owningLayer(owner),
- m_type(LayerAndroid::WebCoreLayer)
+ m_type(LayerAndroid::WebCoreLayer),
+ m_state(0),
+ m_hasText(true)
{
m_backgroundColor = 0;
@@ -97,7 +180,9 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_imageTexture(0),
m_requestSent(false),
m_owningLayer(layer.m_owningLayer),
- m_type(LayerAndroid::UILayer)
+ m_type(LayerAndroid::UILayer),
+ m_state(0),
+ m_hasText(true)
{
m_isFixed = layer.m_isFixed;
m_imageRef = layer.m_imageRef;
@@ -141,12 +226,31 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_animations.add(key, (it->second)->copy());
}
+ m_hasText = layer.m_hasText;
+
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("LayerAndroid - recopy (UI?)");
ClassTracker::instance()->add(this);
#endif
}
+void LayerAndroid::checkTextPresence()
+{
+ if (m_recordingPicture) {
+ // Let's check if we have text or not. If we don't, we can limit
+ // ourselves to scale 1!
+ HasTextBounder hasTextBounder;
+ HasTextCanvas checker(&hasTextBounder, m_recordingPicture);
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ m_recordingPicture->width(),
+ m_recordingPicture->height());
+ checker.setBitmapDevice(bitmap);
+ checker.drawPicture(*m_recordingPicture);
+ m_hasText = checker.hasText();
+ }
+}
+
LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_haveClip(false),
m_isFixed(false),
@@ -160,7 +264,9 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_scale(1),
m_lastComputeTextureSize(0),
m_owningLayer(0),
- m_type(LayerAndroid::NavCacheLayer)
+ m_type(LayerAndroid::NavCacheLayer),
+ m_state(0),
+ m_hasText(true)
{
m_backgroundColor = 0;
m_dirty = false;
@@ -234,7 +340,8 @@ void LayerAndroid::addDirtyArea(GLWebViewState* glWebViewState)
IntSize layerSize(getSize().width(), getSize().height());
FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize);
- FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(m_clippingRect);
+ FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
+ FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect);
area.intersect(clip);
IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
@@ -489,8 +596,9 @@ const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) co
///////////////////////////////////////////////////////////////////////////////
-void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
+bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
{
+ bool hasFixedElements = false;
XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
viewport.fLeft, viewport.fTop,
viewport.width(), viewport.height());
@@ -509,6 +617,7 @@ void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* par
}
if (m_isFixed) {
+ hasFixedElements = true;
// So if this is a fixed layer inside a iframe, use the iframe offset
// and the iframe's size as the viewport and pass to the children
if (parentIframeLayer) {
@@ -546,7 +655,9 @@ void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* par
int count = this->countChildren();
for (int i = 0; i < count; i++)
- this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
+ hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
+
+ return hasFixedElements;
}
void LayerAndroid::updatePositions()
@@ -614,9 +725,9 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM
setDrawOpacity(opacity);
if (m_haveClip) {
- // The clipping rect calculation and intersetion will be done in Screen Coord now.
- FloatRect clip =
- TilesManager::instance()->shader()->rectInScreenCoord(m_drawTransform, layerSize);
+ // The clipping rect calculation and intersetion will be done in documents coordinates.
+ FloatRect rect(0, 0, layerSize.width(), layerSize.height());
+ FloatRect clip = m_drawTransform.mapRect(rect);
clip.intersect(clipping);
setDrawClip(clip);
} else {
@@ -707,6 +818,15 @@ int LayerAndroid::nbTexturedLayers()
return nb;
}
+void LayerAndroid::computeTexturesAmount(TexturesResult* result)
+{
+ int count = this->countChildren();
+ for (int i = 0; i < count; i++)
+ this->getChild(i)->computeTexturesAmount(result);
+ if (m_texture && m_visible)
+ m_texture->computeTexturesAmount(result);
+}
+
void LayerAndroid::showLayer(int indent)
{
char spaces[256];
@@ -714,15 +834,26 @@ void LayerAndroid::showLayer(int indent)
for (int i = 0; i < indent; i++)
spaces[i] = ' ';
- if (!indent)
+ if (!indent) {
XLOGC("\n\n--- LAYERS TREE ---");
+ IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
+ XLOGC("documentViewport(%d, %d, %d, %d)",
+ documentViewport.x(), documentViewport.y(),
+ documentViewport.width(), documentViewport.height());
+ }
IntRect r(0, 0, getWidth(), getHeight());
IntRect tr = m_drawTransform.mapRect(r);
- XLOGC("%s [%d:0x%x] - %s - (%d, %d, %d, %d) %s prepareContext(%d), pic w: %d h: %d",
+ IntRect visible = visibleArea();
+ IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
+ m_clippingRect.width(), m_clippingRect.height());
+ XLOGC("%s [%d:0x%x] - %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
+ "clip (%d, %d, %d, %d) %s prepareContext(%d), pic w: %d h: %d",
spaces, uniqueId(), m_owningLayer,
needsTexture() ? "needs a texture" : "no texture",
tr.x(), tr.y(), tr.width(), tr.height(),
+ visible.x(), visible.y(), visible.width(), visible.height(),
+ clip.x(), clip.y(), clip.width(), clip.height(),
contentIsScrollable() ? "SCROLLABLE" : "",
prepareContext(),
m_recordingPicture ? m_recordingPicture->width() : -1,
@@ -855,6 +986,15 @@ void LayerAndroid::clearDirtyRegion()
m_dirtyRegion.setEmpty();
}
+void LayerAndroid::setState(GLWebViewState* state)
+{
+ int count = this->countChildren();
+ for (int i = 0; i < count; i++)
+ this->getChild(i)->setState(state);
+
+ m_state = state;
+}
+
void LayerAndroid::prepare(GLWebViewState* glWebViewState)
{
m_state = glWebViewState;
@@ -880,9 +1020,80 @@ void LayerAndroid::prepare(GLWebViewState* glWebViewState)
m_imageTexture->prepareGL();
}
+IntRect LayerAndroid::unclippedArea()
+{
+ IntRect area;
+ area.setX(0);
+ area.setY(0);
+ area.setWidth(getSize().width());
+ area.setHeight(getSize().height());
+ return area;
+}
+
+IntRect LayerAndroid::visibleArea()
+{
+ IntRect area = unclippedArea();
+ // First, we get the transformed area of the layer,
+ // in document coordinates
+ IntRect rect = m_drawTransform.mapRect(area);
+ int dx = rect.x();
+ int dy = rect.y();
+
+ // Then we apply the clipping
+ IntRect clip(m_clippingRect);
+ rect.intersect(clip);
+
+ // Now clip with the viewport in documents coordinate
+ IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
+ rect.intersect(documentViewport);
+
+ // Finally, let's return the visible area, in layers coordinate
+ rect.move(-dx, -dy);
+ return rect;
+}
+
+bool LayerAndroid::drawCanvas(SkCanvas* canvas)
+{
+ if (!m_visible)
+ return false;
+
+ bool askScreenUpdate = false;
+
+ {
+ SkAutoCanvasRestore acr(canvas, true);
+ SkRect r;
+ r.set(m_clippingRect.x(), m_clippingRect.y(),
+ m_clippingRect.x() + m_clippingRect.width(),
+ m_clippingRect.y() + m_clippingRect.height());
+ canvas->clipRect(r);
+ SkMatrix matrix;
+ GLUtils::toSkMatrix(matrix, m_drawTransform);
+ SkMatrix canvasMatrix = canvas->getTotalMatrix();
+ matrix.postConcat(canvasMatrix);
+ canvas->setMatrix(matrix);
+ SkRect layerRect;
+ layerRect.fLeft = 0;
+ layerRect.fTop = 0;
+ layerRect.fRight = getWidth();
+ layerRect.fBottom = getHeight();
+ onDraw(canvas, m_drawOpacity);
+ }
+
+ // When the layer is dirty, the UI thread should be notified to redraw.
+ askScreenUpdate |= drawChildrenCanvas(canvas);
+ m_atomicSync.lock();
+ askScreenUpdate |= m_dirty;
+ if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
+ addDirtyArea(m_state);
+
+ m_atomicSync.unlock();
+ return askScreenUpdate;
+}
+
bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
{
- TilesManager::instance()->shader()->clip(m_clippingRect);
+ FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
+ TilesManager::instance()->shader()->clip(clippingRect);
if (!m_visible)
return false;
@@ -905,6 +1116,26 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
return askScreenUpdate;
}
+bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
+{
+ bool askScreenUpdate = false;
+ int count = this->countChildren();
+ if (count > 0) {
+ Vector <LayerAndroid*> sublayers;
+ for (int i = 0; i < count; i++)
+ sublayers.append(this->getChild(i));
+
+ // now we sort for the transparency
+ std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
+ for (int i = 0; i < count; i++) {
+ LayerAndroid* layer = sublayers[i];
+ askScreenUpdate |= layer->drawCanvas(canvas);
+ }
+ }
+
+ return askScreenUpdate;
+}
+
bool LayerAndroid::drawChildrenGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
{
bool askScreenUpdate = false;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 15a581e..b536b22 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -99,9 +99,25 @@ class RenderLayer;
class TiledPage;
class PaintedSurface;
+class TexturesResult {
+public:
+ TexturesResult()
+ : fixed(0)
+ , scrollable(0)
+ , clipped(0)
+ , full(0)
+ {}
+
+ int fixed;
+ int scrollable;
+ int clipped;
+ int full;
+};
+
class LayerAndroid : public Layer {
public:
enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer };
+
LayerAndroid(RenderLayer* owner);
LayerAndroid(const LayerAndroid& layer);
LayerAndroid(SkPicture*);
@@ -121,6 +137,9 @@ public:
IntRect clippedRect() const;
bool outsideViewport();
+ IntRect unclippedArea();
+ IntRect visibleArea();
+
virtual bool needsTexture();
void removeTexture(PaintedSurface*);
@@ -129,11 +148,17 @@ public:
int nbTexturedLayers();
void showLayer(int indent);
+ void computeTexturesAmount(TexturesResult*);
+
float getScale() { return m_scale; }
+ void setState(GLWebViewState*);
+
// draw layer and its children via Z, pre-order traversal
virtual bool drawGL(GLWebViewState*, SkMatrix&);
bool drawChildrenGL(GLWebViewState*, SkMatrix&);
+ virtual bool drawCanvas(SkCanvas*);
+ bool drawChildrenCanvas(SkCanvas*);
// prepare layer and its children via reverse-Z, post-order traversal
void prepare(GLWebViewState*);
@@ -212,7 +237,7 @@ public:
This call is recursive, so it should be called on the root of the
hierarchy.
*/
- void updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0);
+ bool updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0);
/** Call this to update the position attribute, so that later calls
like bounds() will report the corrected position.
@@ -284,6 +309,9 @@ public:
ImageTexture* imageTexture() { return m_imageTexture; }
int type() { return m_type; }
+ bool hasText() { return m_hasText; }
+ void checkTextPresence();
+
protected:
virtual void onDraw(SkCanvas*, SkScalar opacity);
@@ -387,8 +415,11 @@ private:
RenderLayer* m_owningLayer;
- GLWebViewState* m_state;
int m_type;
+ GLWebViewState* m_state;
+
+ bool m_hasText;
+
typedef Layer INHERITED;
};
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
index c0597a9..939d106 100644
--- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
@@ -142,24 +142,17 @@ void PaintedSurface::prepare(GLWebViewState* state)
m_layer->uniqueId(), m_layer,
m_layer->getScale());
- int w = m_layer->getSize().width();
- int h = m_layer->getSize().height();
-
- if (w != m_area.width())
- m_area.setWidth(w);
-
- if (h != m_area.height())
- m_area.setHeight(h);
-
- computeVisibleArea();
+ IntRect visibleArea = computeVisibleArea(m_layer);
m_scale = state->scale();
- XLOG("%x layer %d %x prepared at size (%d, %d) @ scale %.2f", this, m_layer->uniqueId(),
- m_layer, w, h, m_scale);
+ // If we do not have text, we may as well limit ourselves to
+ // a scale factor of one... this saves up textures.
+ if (m_scale > 1 && !m_layer->hasText())
+ m_scale = 1;
m_tiledTexture->prepare(state, m_scale, m_pictureUsed != m_layer->pictureUsed(),
- startFastSwap, m_visibleArea);
+ startFastSwap, visibleArea);
}
bool PaintedSurface::draw()
@@ -192,20 +185,53 @@ const TransformationMatrix* PaintedSurface::transform() {
return m_layer->drawTransform();
}
-void PaintedSurface::computeVisibleArea() {
+void PaintedSurface::computeTexturesAmount(TexturesResult* result)
+{
+ if (!m_tiledTexture)
+ return;
+
if (!m_layer)
return;
- IntRect layerRect = (*m_layer->drawTransform()).mapRect(m_area);
- IntRect clippedRect = TilesManager::instance()->shader()->clippedRectWithViewport(layerRect);
- m_visibleArea = (*m_layer->drawTransform()).inverse().mapRect(clippedRect);
- if (!m_visibleArea.isEmpty()) {
- float tileWidth = TilesManager::instance()->layerTileWidth();
- float tileHeight = TilesManager::instance()->layerTileHeight();
- int w = ceilf(m_area.width() * m_scale / tileWidth);
- int h = ceilf(m_area.height() * m_scale / tileHeight);
- if (w * h < MAX_UNCLIPPED_AREA)
- m_visibleArea = m_area;
- }
+
+ IntRect unclippedArea = m_layer->unclippedArea();
+ IntRect clippedVisibleArea = m_layer->visibleArea();
+ // get two numbers here:
+ // - textures needed for a clipped area
+ // - textures needed for an un-clipped area
+ int nbTexturesUnclipped = m_tiledTexture->nbTextures(unclippedArea, m_scale);
+ int nbTexturesClipped = m_tiledTexture->nbTextures(clippedVisibleArea, m_scale);
+
+ // Set kFixedLayers level
+ if (m_layer->isFixed())
+ result->fixed += nbTexturesClipped;
+
+ // Set kScrollableAndFixedLayers level
+ if (m_layer->contentIsScrollable()
+ || m_layer->isFixed())
+ result->scrollable += nbTexturesClipped;
+
+ // Set kClippedTextures level
+ result->clipped += nbTexturesClipped;
+
+ // Set kAllTextures level
+ if (m_layer->contentIsScrollable())
+ result->full += nbTexturesClipped;
+ else
+ result->full += nbTexturesUnclipped;
+}
+
+IntRect PaintedSurface::computeVisibleArea(LayerAndroid* layer) {
+ IntRect area;
+ if (!layer)
+ return area;
+
+ if (!layer->contentIsScrollable()
+ && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures)
+ area = layer->unclippedArea();
+ else
+ area = layer->visibleArea();
+
+ return area;
}
bool PaintedSurface::owns(BaseTileTexture* texture)
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h
index 2e01b80..83b2c9b 100644
--- a/Source/WebCore/platform/graphics/android/PaintedSurface.h
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h
@@ -63,14 +63,13 @@ public:
bool owns(BaseTileTexture* texture);
- void computeVisibleArea();
+ void computeTexturesAmount(TexturesResult*);
+ IntRect computeVisibleArea(LayerAndroid*);
// TilePainter methods for TiledTexture
virtual const TransformationMatrix* transform();
// used by TiledTexture
- const IntRect& area() { return m_area; }
- const IntRect& visibleArea() { return m_visibleArea; }
float scale() { return m_scale; }
float opacity();
unsigned int pictureUsed() { return m_pictureUsed; }
@@ -81,8 +80,6 @@ private:
LayerAndroid* m_layer;
DualTiledTexture* m_tiledTexture;
- IntRect m_area;
- IntRect m_visibleArea;
float m_scale;
unsigned int m_pictureUsed;
diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp
index 20d1299..241cbef 100644
--- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp
+++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp
@@ -27,6 +27,11 @@
#include <wtf/text/CString.h>
+#include <wtf/CurrentTime.h>
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PerformanceMonitor", __VA_ARGS__)
+
namespace WebCore {
PerformanceMonitor::PerformanceMonitor()
@@ -78,4 +83,22 @@ float PerformanceMonitor::getAverageDuration(const String &tag)
return m_tags.get(tag)->average_ms;
}
+void PerformanceMonitor::display(int limit)
+{
+ bool shown = false;
+ HashMap<String, PerfItem*, StringHash>::iterator end = m_tags.end();
+ for (HashMap<String, PerfItem*, StringHash>::iterator it = m_tags.begin(); it != end; ++it) {
+ PerfItem* item = it->second;
+ if (item->average_ms > limit) {
+ if (!shown) {
+ XLOGC("=== DISPLAY MONITOR ====");
+ shown = true;
+ }
+ XLOGC("item %s took longer than %d ms: %.2f", it->first.latin1().data(), limit, item->average_ms);
+ }
+ }
+ if (shown)
+ XLOGC("=== END DISPLAY MONITOR ====");
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h
index f4aaa92..4ebbf6a 100644
--- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h
+++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h
@@ -48,6 +48,7 @@ public:
void start(const String &tag);
void stop(const String &tag);
float getAverageDuration(const String &tag);
+ void display(int limit);
private:
HashMap<String, PerfItem*, StringHash> m_tags;
diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp
index f66c7c1..8bf6fcc 100644
--- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp
@@ -70,6 +70,10 @@ RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster)
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("RasterRenderer");
#endif
+ m_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ TilesManager::instance()->tileWidth(),
+ TilesManager::instance()->tileHeight());
+ m_bitmap.allocPixels();
}
RasterRenderer::~RasterRenderer()
@@ -84,20 +88,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can
if (renderInfo.measurePerf)
m_perfMon.start(TAG_CREATE_BITMAP);
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- renderInfo.invalRect->width(), renderInfo.invalRect->height());
- bitmap.allocPixels();
if (renderInfo.baseTile->isLayerTile()) {
- bitmap.setIsOpaque(false);
- bitmap.eraseARGB(0, 0, 0, 0);
+ m_bitmap.setIsOpaque(false);
+ m_bitmap.eraseARGB(0, 0, 0, 0);
} else {
- bitmap.setIsOpaque(true);
- bitmap.eraseARGB(255, 255, 255, 255);
+ m_bitmap.setIsOpaque(true);
+ m_bitmap.eraseARGB(255, 255, 255, 255);
}
- SkDevice* device = new SkDevice(NULL, bitmap, false);
+ SkDevice* device = new SkDevice(NULL, m_bitmap, false);
if (renderInfo.measurePerf) {
m_perfMon.stop(TAG_CREATE_BITMAP);
diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/RasterRenderer.h
index 4308452..69dfaf8 100644
--- a/Source/WebCore/platform/graphics/android/RasterRenderer.h
+++ b/Source/WebCore/platform/graphics/android/RasterRenderer.h
@@ -29,6 +29,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "BaseRenderer.h"
+#include "SkBitmap.h"
#include "SkRect.h"
class SkCanvas;
@@ -50,6 +51,9 @@ protected:
virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas);
virtual const String* getPerformanceTags(int& tagCount);
+private:
+ SkBitmap m_bitmap;
+
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
index bca2fd4..2643d2c 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
@@ -1,6 +1,8 @@
#include "config.h"
#include "ScrollableLayerAndroid.h"
+#include "GLWebViewState.h"
+
#if USE(ACCELERATED_COMPOSITING)
namespace WebCore {
@@ -19,6 +21,10 @@ bool ScrollableLayerAndroid::scrollTo(int x, int y)
return false;
setPosition(m_scrollLimits.fLeft - newX, m_scrollLimits.fTop - newY);
+
+ if (state())
+ state()->scrolledLayer(this);
+
return true;
}
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
index 0aad081..30b5c86 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
@@ -408,6 +408,8 @@ void ShaderProgram::setViewRect(const IntRect& viewRect)
translate.scale3d(1, -1, 1);
m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
+
+ m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(viewRect);
}
// This function transform a clip rect extracted from the current layer
@@ -437,6 +439,11 @@ FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect)
return m_documentToScreenMatrix.mapRect(rect);
}
+FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect)
+{
+ return m_documentToScreenMatrix.inverse().mapRect(rect);
+}
+
FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
{
FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h
index dbacd57..b309872 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h
@@ -67,6 +67,7 @@ public:
FloatRect rectInInvScreenCoord(const FloatRect& rect);
FloatRect rectInScreenCoord(const FloatRect& rect);
+ FloatRect convertScreenCoordToDocumentCoord(const FloatRect& rect);
FloatRect convertInvScreenCoordToScreenCoord(const FloatRect& rect);
FloatRect convertScreenCoordToInvScreenCoord(const FloatRect& rect);
@@ -75,6 +76,7 @@ public:
void setScreenClip(const IntRect& clip);
void clip(const FloatRect& rect);
IntRect clippedRectWithViewport(const IntRect& rect, int margin = 0);
+ FloatRect documentViewport() { return m_documentViewport; }
void resetBlending();
float contrast() { return m_contrast; }
@@ -125,6 +127,8 @@ private:
int m_titleBarHeight;
IntRect m_webViewRect;
+ FloatRect m_documentViewport;
+
// uniforms
GLint m_hProjectionMatrix;
GLint m_hAlpha;
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
index b252303..e1e5ec9 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
@@ -59,12 +59,13 @@ bool TiledTexture::ready() {
bool tilesVisible = false;
for (unsigned int i = 0; i < m_tiles.size(); i++) {
BaseTile* tile = m_tiles[i];
- if (tile->isTileVisible(m_area) && !tile->isTileReady()) {
- tilesAllReady = false;
- break;
- }
- if (tile->isTileVisible(m_area))
+ if (tile->isTileVisible(m_area)) {
tilesVisible = true;
+ if (!tile->isTileReady()) {
+ tilesAllReady = false;
+ break;
+ }
+ }
}
// For now, if no textures are available, consider ourselves as ready
// in order to unblock the zooming process.
@@ -74,38 +75,47 @@ bool TiledTexture::ready() {
|| !tilesVisible || tilesAllReady;
}
-void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint,
- bool startFastSwap, IntRect& visibleArea)
+IntRect TiledTexture::computeTilesArea(IntRect& visibleArea, float scale)
{
- if (!m_surface)
- return;
-
- if (!m_surface->layer())
- return;
-
- // first, how many tiles do we need
+ IntRect computedArea;
IntRect area(visibleArea.x() * scale,
visibleArea.y() * scale,
ceilf(visibleArea.width() * scale),
ceilf(visibleArea.height() * scale));
if (area.width() == 0 && area.height() == 0) {
- m_area.setWidth(0);
- m_area.setHeight(0);
- return;
+ computedArea.setWidth(0);
+ computedArea.setHeight(0);
+ return computedArea;
}
int tileWidth = TilesManager::instance()->layerTileWidth();
int tileHeight = TilesManager::instance()->layerTileHeight();
- m_area.setX(area.x() / tileWidth);
- m_area.setY(area.y() / tileHeight);
+ computedArea.setX(area.x() / tileWidth);
+ computedArea.setY(area.y() / tileHeight);
float right = (area.x() + area.width()) / (float) tileWidth;
float bottom = (area.y() + area.height()) / (float) tileHeight;
- m_area.setWidth(ceilf(right) - m_area.x());
- m_area.setHeight(ceilf(bottom) - m_area.y());
+ computedArea.setWidth(ceilf(right) - computedArea.x());
+ computedArea.setHeight(ceilf(bottom) - computedArea.y());
+ return computedArea;
+}
- XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
+void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint,
+ bool startFastSwap, IntRect& area)
+{
+ if (!m_surface)
+ return;
+
+ if (!m_surface->layer())
+ return;
+
+ m_area = computeTilesArea(area, scale);
+ if (m_area.isEmpty())
+ return;
+
+ XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of "
+ " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
this, scale,
visibleArea.x(), visibleArea.y(),
visibleArea.width(), visibleArea.height(),
@@ -210,6 +220,12 @@ BaseTile* TiledTexture::getTile(int x, int y)
return 0;
}
+int TiledTexture::nbTextures(IntRect& area, float scale)
+{
+ IntRect computedTilesArea = computeTilesArea(area, scale);
+ return computedTilesArea.width() * computedTilesArea.height();
+}
+
bool TiledTexture::draw()
{
#ifdef DEBUG
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h
index c6e9e09..5a47cd9 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.h
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.h
@@ -65,6 +65,8 @@ public:
removeTiles();
};
+ IntRect computeTilesArea(IntRect& visibleArea, float scale);
+
void prepare(GLWebViewState* state, float scale, bool repaint,
bool startFastSwap, IntRect& visibleArea);
bool draw();
@@ -87,6 +89,8 @@ public:
PaintedSurface* surface() { return m_surface; }
+ int nbTextures(IntRect& area, float scale);
+
private:
bool tileIsVisible(BaseTile* tile);
@@ -117,6 +121,15 @@ public:
bool draw();
void update(const SkRegion& dirtyArea, SkPicture* picture);
bool owns(BaseTileTexture* texture);
+
+ int nbTextures(IntRect& area, float scale)
+ {
+ // TODO: consider the zooming case for the backTexture
+ if (!m_frontTexture)
+ return 0;
+ return m_frontTexture->nbTextures(area, scale);
+ }
+
private:
// Delay before we schedule a new tile at the new scale factor
static const double s_zoomUpdateDelay = 0.2; // 200 ms