Merge "Revert "Put canvas on a layer"" into ics-mr1
diff --git a/Source/WebCore/loader/cache/CachedImage.cpp b/Source/WebCore/loader/cache/CachedImage.cpp
index ba30860..6867302 100644
--- a/Source/WebCore/loader/cache/CachedImage.cpp
+++ b/Source/WebCore/loader/cache/CachedImage.cpp
@@ -57,6 +57,7 @@
, m_image(0)
, m_decodedDataDeletionTimer(this, &CachedImage::decodedDataDeletionTimerFired)
, m_shouldPaintBrokenImage(true)
+ , m_autoLoadWasPreventedBySettings(false)
{
setStatus(Unknown);
}
@@ -66,6 +67,7 @@
, m_image(image)
, m_decodedDataDeletionTimer(this, &CachedImage::decodedDataDeletionTimerFired)
, m_shouldPaintBrokenImage(true)
+ , m_autoLoadWasPreventedBySettings(false)
{
setStatus(Cached);
setLoading(false);
diff --git a/Source/WebCore/loader/cache/CachedImage.h b/Source/WebCore/loader/cache/CachedImage.h
index 42c7814..79643d7 100644
--- a/Source/WebCore/loader/cache/CachedImage.h
+++ b/Source/WebCore/loader/cache/CachedImage.h
@@ -75,7 +75,7 @@
void clear();
- bool stillNeedsLoad() const { return !errorOccurred() && status() == Unknown && !isLoading(); }
+ bool stillNeedsLoad() const { return (!errorOccurred() && status() == Unknown && !isLoading()) || (m_autoLoadWasPreventedBySettings && !inCache()); }
void load();
// ImageObserver
@@ -86,6 +86,8 @@
virtual void animationAdvanced(const Image*);
virtual void changedInRect(const Image*, const IntRect&);
+ void setAutoLoadWasPreventedBySettings(bool prevented) { m_autoLoadWasPreventedBySettings = prevented; }
+
private:
void createImage();
size_t maximumDecodedImageSize();
@@ -98,6 +100,7 @@
RefPtr<Image> m_image;
Timer<CachedImage> m_decodedDataDeletionTimer;
bool m_shouldPaintBrokenImage;
+ bool m_autoLoadWasPreventedBySettings;
};
}
diff --git a/Source/WebCore/loader/cache/CachedResource.cpp b/Source/WebCore/loader/cache/CachedResource.cpp
index 95f5522..e599769 100644
--- a/Source/WebCore/loader/cache/CachedResource.cpp
+++ b/Source/WebCore/loader/cache/CachedResource.cpp
@@ -261,7 +261,7 @@
void CachedResource::didAddClient(CachedResourceClient* c)
{
- if (!isLoading())
+ if (!isLoading() && !stillNeedsLoad())
c->notifyFinished(this);
}
diff --git a/Source/WebCore/loader/cache/CachedResource.h b/Source/WebCore/loader/cache/CachedResource.h
index 72b00e5..2f33ac7 100644
--- a/Source/WebCore/loader/cache/CachedResource.h
+++ b/Source/WebCore/loader/cache/CachedResource.h
@@ -127,6 +127,7 @@
bool isLoading() const { return m_loading; }
void setLoading(bool b) { m_loading = b; }
+ virtual bool stillNeedsLoad() const { return false; }
virtual bool isImage() const { return false; }
bool isLinkResource() const
diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp
index 38fcee4..91c0629 100644
--- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp
+++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp
@@ -138,14 +138,21 @@
}
}
CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url, String()));
- if (autoLoadImages() && resource && resource->stillNeedsLoad()) {
+ if (resource) {
#ifdef ANDROID_BLOCK_NETWORK_IMAGE
- if (shouldBlockNetworkImage(url)) {
- return resource;
- }
+ resource->setAutoLoadWasPreventedBySettings(!autoLoadImages() || shouldBlockNetworkImage(url));
+#else
+ resource->setAutoLoadWasPreventedBySettings(!autoLoadImages());
#endif
- resource->setLoading(true);
- load(resource, true);
+ if (autoLoadImages() && resource->stillNeedsLoad()) {
+#ifdef ANDROID_BLOCK_NETWORK_IMAGE
+ if (shouldBlockNetworkImage(url)) {
+ return resource;
+ }
+#endif
+ resource->setLoading(true);
+ load(resource, true);
+ }
}
return resource;
}
@@ -520,9 +527,12 @@
if (shouldBlockNetworkImage(image->url()))
continue;
#endif
+ image->setAutoLoadWasPreventedBySettings(false);
- if (image->stillNeedsLoad())
+ if (image->stillNeedsLoad()) {
+ image->setLoading(true);
load(image, true);
+ }
}
}
}
@@ -536,7 +546,6 @@
KURL kurl = m_document->completeURL(url);
if (kurl.protocolIs("http") || kurl.protocolIs("https"))
return true;
-
return false;
}
@@ -555,8 +564,11 @@
CachedResource* resource = it->second.get();
if (resource->type() == CachedResource::ImageResource) {
CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource));
- if (image->stillNeedsLoad())
+ image->setAutoLoadWasPreventedBySettings(false);
+ if (image->stillNeedsLoad()) {
+ image->setLoading(true);
load(image, true);
+ }
}
}
}
diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp
index 5601269..6b22359 100644
--- a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp
+++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp
@@ -49,6 +49,8 @@
namespace WebCore {
+static int gUniqueId;
+
static long gDebugAndroidAnimationInstances;
long AndroidAnimation::instancesCount()
@@ -69,27 +71,11 @@
, m_timingFunction(animation->timingFunction())
, m_type(type)
, m_operations(operations)
+ , m_uniqueId(++gUniqueId)
+ , m_hasFinished(false)
{
ASSERT(m_timingFunction);
- if (!static_cast<int>(beginTime)) // time not set
- m_beginTime = WTF::currentTime();
-
- gDebugAndroidAnimationInstances++;
-}
-
-AndroidAnimation::AndroidAnimation(AndroidAnimation* anim)
- : m_beginTime(anim->m_beginTime)
- , m_duration(anim->m_duration)
- , m_fillsBackwards(anim->m_fillsBackwards)
- , m_fillsForwards(anim->m_fillsForwards)
- , m_iterationCount(anim->m_iterationCount)
- , m_direction(anim->m_direction)
- , m_timingFunction(anim->m_timingFunction)
- , m_name(anim->name())
- , m_type(anim->m_type)
- , m_operations(anim->m_operations)
-{
gDebugAndroidAnimationInstances++;
}
@@ -98,20 +84,23 @@
gDebugAndroidAnimationInstances--;
}
+void AndroidAnimation::suggestBeginTime(double time)
+{
+ if (m_beginTime <= 0.000001) // overflow or not yet set
+ m_beginTime = time;
+}
+
double AndroidAnimation::elapsedTime(double time)
{
- if (m_beginTime <= 0.000001) // overflow or not correctly set
- m_beginTime = time;
-
- m_elapsedTime = time - m_beginTime;
+ double elapsedTime = (m_beginTime < 0.000001) ? 0 : time - m_beginTime;
if (m_duration <= 0)
m_duration = 0.000001;
- if (m_elapsedTime < 0) // animation not yet started.
+ if (elapsedTime < 0) // animation not yet started.
return 0;
- return m_elapsedTime;
+ return elapsedTime;
}
bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress)
@@ -127,6 +116,13 @@
// If not infinite, return false if we are done
if (m_iterationCount > 0 && progress > dur) {
*finalProgress = 1.0;
+ if (!m_hasFinished) {
+ // first time past duration, continue with progress 1.0 so the
+ // element's final position lines up with it's last keyframe
+ m_hasFinished = true;
+ return true;
+ }
+
return false;
}
@@ -187,7 +183,7 @@
if (progress < 0) {
// The animation hasn't started yet
- if (m_fillsBackwards) {
+ if (m_fillsBackwards || m_beginTime <= 0.000001) {
// in this case we want to apply the initial keyframe to the layer
applyForProgress(layer, 0);
}
@@ -195,7 +191,7 @@
return true;
}
- if (progress >= 1) {
+ if (progress > 1) {
if (!m_fillsForwards)
return false;
progress = 1;
@@ -225,16 +221,6 @@
{
}
-AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim)
- : AndroidAnimation(anim)
-{
-}
-
-PassRefPtr<AndroidAnimation> AndroidOpacityAnimation::copy()
-{
- return adoptRef(new AndroidOpacityAnimation(this));
-}
-
void AndroidAnimation::pickValues(double progress, int* start, int* end)
{
float distance = -1;
@@ -298,16 +284,6 @@
{
}
-AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim)
- : AndroidAnimation(anim)
-{
-}
-
-PassRefPtr<AndroidAnimation> AndroidTransformAnimation::copy()
-{
- return adoptRef(new AndroidTransformAnimation(this));
-}
-
void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float progress)
{
// First, we need to get the from and to values
diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/AndroidAnimation.h
index 16a63e8..dca769f 100644
--- a/Source/WebCore/platform/graphics/android/AndroidAnimation.h
+++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.h
@@ -33,16 +33,15 @@
class TimingFunction;
-class AndroidAnimation : public RefCounted<AndroidAnimation> {
+class AndroidAnimation : public ThreadSafeRefCounted<AndroidAnimation> {
public:
AndroidAnimation(AnimatedPropertyID type,
const Animation* animation,
KeyframeValueList* operations,
double beginTime);
- AndroidAnimation(AndroidAnimation* anim);
virtual ~AndroidAnimation();
- virtual PassRefPtr<AndroidAnimation> copy() = 0;
+ void suggestBeginTime(double time);
double elapsedTime(double time);
void pickValues(double progress, int* start, int* end);
bool checkIterationsAndProgress(double time, float* finalProgress);
@@ -56,11 +55,10 @@
AnimatedPropertyID type() { return m_type; }
bool fillsBackwards() { return m_fillsBackwards; }
bool fillsForwards() { return m_fillsForwards; }
-
+ int uniqueId() { return m_uniqueId; }
protected:
double m_beginTime;
- double m_elapsedTime;
double m_duration;
bool m_fillsBackwards;
bool m_fillsForwards;
@@ -70,6 +68,8 @@
String m_name;
AnimatedPropertyID m_type;
KeyframeValueList* m_operations;
+ int m_uniqueId;
+ bool m_hasFinished;
};
class AndroidOpacityAnimation : public AndroidAnimation {
@@ -80,8 +80,6 @@
AndroidOpacityAnimation(const Animation* animation,
KeyframeValueList* operations,
double beginTime);
- AndroidOpacityAnimation(AndroidOpacityAnimation* anim);
- virtual PassRefPtr<AndroidAnimation> copy();
virtual void applyForProgress(LayerAndroid* layer, float progress);
};
@@ -96,9 +94,6 @@
KeyframeValueList* operations,
double beginTime);
- AndroidTransformAnimation(AndroidTransformAnimation* anim);
- virtual PassRefPtr<AndroidAnimation> copy();
-
virtual void applyForProgress(LayerAndroid* layer, float progress);
};
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index 8358b2a..9c7716c 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -264,6 +264,7 @@
// the two pages (current one and future one with the new scale factor)
if (zoomManager->didReceivedRequest()) {
float nextTiledPageTransparency = 1;
+ m_state->resetFrameworkInval();
zoomManager->processTransition(currentTime, scale, &doZoomPageSwap,
&nextTiledPageTransparency, &transparency);
nextTiledPage->prepareForDrawGL(nextTiledPageTransparency, viewportTileBounds);
@@ -370,8 +371,7 @@
updateLayerPositions(visibleRect);
// For now, we render layers only if the rendering mode
// is kAllTextures or kClippedTextures
- if (m_state->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers
- && compositedRoot->drawGL()) {
+ if (compositedRoot->drawGL()) {
if (TilesManager::instance()->layerTexturesRemain()) {
// only try redrawing for layers if layer textures remain,
// otherwise we'll repaint without getting anything done
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp
index a331dfc..27bd482 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp
@@ -204,6 +204,7 @@
}
cliperator.next();
}
+
if (!intersect)
return;
@@ -268,7 +269,7 @@
}
if (m_frontTexture->readyFor(this)) {
- if (isLayerTile())
+ if (isLayerTile() && m_painter && m_painter->transform())
TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(),
rect, m_frontTexture->m_ownTextureId,
transparency, true);
diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/ClassTracker.cpp
index 92d406c..eb810a8 100644
--- a/Source/WebCore/platform/graphics/android/ClassTracker.cpp
+++ b/Source/WebCore/platform/graphics/android/ClassTracker.cpp
@@ -27,6 +27,7 @@
#include "ClassTracker.h"
#include "LayerAndroid.h"
+#include "TilesManager.h"
#include <cutils/log.h>
#include <wtf/CurrentTime.h>
@@ -35,6 +36,9 @@
#undef XLOG
#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ClassTracker", __VA_ARGS__)
+#define DEBUG_LAYERS
+#undef DEBUG_LAYERS
+
namespace WebCore {
ClassTracker* ClassTracker::instance()
@@ -66,7 +70,6 @@
m_classes.set(name, value - 1);
}
-
void ClassTracker::add(LayerAndroid* layer)
{
android::Mutex::Autolock lock(m_lock);
@@ -88,6 +91,21 @@
iter->first.latin1().data(), iter->second);
}
XLOG("*** %d Layers ***", m_layers.size());
+ int nbTextures = 0;
+ int nbAllocatedTextures = 0;
+ int nbLayerTextures = 0;
+ int nbAllocatedLayerTextures = 0;
+ float textureSize = 256 * 256 * 4 / 1024.0 / 1024.0;
+ TilesManager::instance()->gatherTexturesNumbers(&nbTextures, &nbAllocatedTextures,
+ &nbLayerTextures, &nbAllocatedLayerTextures);
+ XLOG("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb",
+ nbAllocatedTextures, nbTextures,
+ nbAllocatedTextures * textureSize,
+ nbAllocatedLayerTextures, nbLayerTextures,
+ nbAllocatedLayerTextures * textureSize,
+ (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize);
+
+#ifdef DEBUG_LAYERS
for (unsigned int i = 0; i < m_layers.size(); i++) {
LayerAndroid* layer = m_layers[i];
XLOG("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x",
@@ -98,6 +116,7 @@
layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(),
(LayerAndroid*) layer->getParent());
}
+#endif
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp
index 81dbdae..0a8c0c1 100644
--- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp
@@ -98,6 +98,10 @@
SkLayerDrawLooper* looper = new SkLayerDrawLooper;
paint->setLooper(looper)->unref();
+ // The layerDrawLooper uses at the root paint to determine the text
+ // encoding so we need to make sure it is properly configured.
+ updateForFont(paint, font);
+
// Specify the behavior of the looper
SkLayerDrawLooper::LayerInfo info;
info.fPaintBits = SkLayerDrawLooper::kEntirePaint_Bits;
diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp
index d1fe51a..97a53fe 100644
--- a/Source/WebCore/platform/graphics/android/GLUtils.cpp
+++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp
@@ -562,6 +562,15 @@
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
}
+void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix)
+{
+ transformMatrix.setMatrix(
+ matrix[0], matrix[1], matrix[2], matrix[3],
+ matrix[4], matrix[5], matrix[6], matrix[7],
+ matrix[8], matrix[9], matrix[10], matrix[11],
+ matrix[12], matrix[13], matrix[14], matrix[15]);
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h
index b952513..68acbab 100644
--- a/Source/WebCore/platform/graphics/android/GLUtils.h
+++ b/Source/WebCore/platform/graphics/android/GLUtils.h
@@ -83,6 +83,7 @@
static void updateSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR);
#endif
static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap);
+ static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix);
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 5206b7a..273c478 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -84,9 +84,9 @@
, m_goingLeft(false)
, m_expandedTileBoundsX(0)
, m_expandedTileBoundsY(0)
+ , m_highEndGfx(false)
, m_scale(1)
, m_layersRenderingMode(kAllTextures)
- , m_highEndGfx(false)
{
m_viewport.setEmpty();
m_futureViewportTileBounds.setEmpty();
@@ -150,8 +150,10 @@
TilesManager::instance()->setShowVisualIndicator(showVisualIndicator);
}
-void GLWebViewState::scrolledLayer(ScrollableLayerAndroid*)
+void GLWebViewState::scrollLayer(int layerId, int x, int y)
{
+ m_treeManager.updateScrollableLayer(layerId, x, y);
+
// TODO: only inval the area of the scrolled layer instead of
// doing a fullInval()
if (m_layersRenderingMode == kSingleSurfaceRendering)
@@ -335,20 +337,25 @@
int top = viewRect.y();
int width = viewRect.width();
int height = viewRect.height();
- glViewport(left, top, width, height);
ShaderProgram* shader = TilesManager::instance()->shader();
if (shader->program() == -1) {
XLOG("Reinit shader");
shader->init();
}
+ shader->setViewport(visibleRect, scale);
shader->setViewRect(viewRect);
- shader->setViewport(visibleRect);
shader->setWebViewRect(webViewRect);
shader->setTitleBarHeight(titleBarHeight);
shader->setScreenClip(screenClip);
shader->resetBlending();
+ shader->calculateAnimationDelta();
+
+ glViewport(left + shader->getAnimationDeltaX(),
+ top - shader->getAnimationDeltaY(),
+ width, height);
+
double currentTime = WTF::currentTime();
setViewport(visibleRect, scale);
@@ -379,6 +386,9 @@
if (nbTexturesNeeded.full < maxTextures)
m_layersRenderingMode = kAllTextures;
+ if (!maxTextures && !nbTexturesNeeded.full)
+ m_layersRenderingMode = kAllTextures;
+
if (m_layersRenderingMode < layersRenderingMode
&& m_layersRenderingMode != kAllTextures)
invalBase = true;
@@ -428,7 +438,8 @@
bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
- IntRect& clip, float scale, bool* buffersSwappedPtr)
+ IntRect& clip, float scale,
+ bool* treesSwappedPtr, bool* newTreeHasAnimPtr)
{
m_scale = scale;
TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
@@ -470,7 +481,7 @@
// 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();
+ bool ret = ImagesManager::instance()->prepareTextures(this);
if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
XLOGC("WARNING, scale seems corrupted after update: %e", scale);
@@ -485,10 +496,18 @@
bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering;
ret |= m_treeManager.drawGL(currentTime, rect, viewport,
scale, fastSwap,
- buffersSwappedPtr, &nbTexturesNeeded);
+ treesSwappedPtr, newTreeHasAnimPtr,
+ &nbTexturesNeeded);
if (!ret)
resetFrameworkInval();
+ int nbTexturesForImages = ImagesManager::instance()->nbTextures();
+ XLOG("*** We have %d textures for images, %d full, %d clipped, total %d / %d",
+ nbTexturesForImages, nbTexturesNeeded.full, nbTexturesNeeded.clipped,
+ nbTexturesNeeded.full + nbTexturesForImages,
+ nbTexturesNeeded.clipped + nbTexturesForImages);
+ nbTexturesNeeded.full += nbTexturesForImages;
+ nbTexturesNeeded.clipped += nbTexturesForImages;
ret |= setLayersRenderingMode(nbTexturesNeeded);
FloatRect extrasclip(0, 0, rect.width(), rect.height());
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h
index 2a6c8df..8d89704 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h
@@ -214,7 +214,8 @@
bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
- IntRect& clip, float scale, bool* buffersSwappedPtr);
+ IntRect& clip, float scale,
+ bool* treesSwappedPtr, bool* newTreeHasAnimPtr);
#ifdef MEASURES_PERF
void dumpMeasures();
@@ -247,7 +248,7 @@
};
LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; }
- void scrolledLayer(ScrollableLayerAndroid*);
+ void scrollLayer(int layerId, int x, int y);
void invalRegion(const SkRegion& region);
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 3e062f8..6990503 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -119,8 +119,8 @@
m_needsRepaint(false),
m_needsNotifyClient(false),
m_haveContents(false),
- m_haveImage(false),
m_newImage(false),
+ m_image(0),
m_foregroundLayer(0),
m_foregroundClipLayer(0)
{
@@ -132,6 +132,9 @@
GraphicsLayerAndroid::~GraphicsLayerAndroid()
{
+ if (m_image)
+ m_image->deref();
+
m_contentLayer->unref();
SkSafeUnref(m_foregroundLayer);
SkSafeUnref(m_foregroundClipLayer);
@@ -331,6 +334,9 @@
void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
{
+ if (b == m_backfaceVisibility)
+ return;
+
GraphicsLayer::setBackfaceVisibility(b);
m_contentLayer->setBackfaceVisibility(b);
askForSync();
@@ -397,7 +403,7 @@
void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
{
- if (color == m_backgroundColor)
+ if (color == m_backgroundColor && m_backgroundColorSet)
return;
LOG("(%x) setBackgroundColor", this);
GraphicsLayer::setBackgroundColor(color);
@@ -409,6 +415,9 @@
void GraphicsLayerAndroid::clearBackgroundColor()
{
+ if (!m_backgroundColorSet)
+ return;
+
LOG("(%x) clearBackgroundColor", this);
GraphicsLayer::clearBackgroundColor();
askForSync();
@@ -551,7 +560,7 @@
LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
this, gPaused, m_needsRepaint, m_haveContents);
- if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) {
+ if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
// with SkPicture, we request the entire layer's content.
IntRect layerBounds(0, 0, m_size.width(), m_size.height());
@@ -602,7 +611,14 @@
m_foregroundLayer->setPosition(-x, -y);
// Set the scrollable bounds of the layer.
m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
- m_foregroundLayer->markAsDirty(m_dirtyRegion);
+
+ // Invalidate the entire layer for now, as webkit will only send the
+ // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
+ // offsetting the invals by the scroll position would not be enough.
+ // TODO: have webkit send us invals even for non visible area
+ SkRegion region;
+ region.setRect(0, 0, contentsRect.width(), contentsRect.height());
+ m_foregroundLayer->markAsDirty(region);
m_foregroundLayer->needsRepaint();
} else {
// If there is no contents clip, we can draw everything into one
@@ -633,7 +649,7 @@
return true;
}
- if (m_needsRepaint && m_haveImage && m_newImage) {
+ if (m_needsRepaint && m_image && m_newImage) {
// We need to tell the GL thread that we will need to repaint the
// texture. Only do so if we effectively have a new image!
m_contentLayer->markAsDirty(m_dirtyRegion);
@@ -666,7 +682,7 @@
{
// rect is in the render object coordinates
- if (!m_haveImage && !drawsContent()) {
+ if (!m_image && !drawsContent()) {
LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
this, rect.x(), rect.y(), rect.width(), rect.height());
return;
@@ -830,14 +846,23 @@
void GraphicsLayerAndroid::setContentsToImage(Image* image)
{
TLOG("(%x) setContentsToImage", this, image);
- if (image) {
+ if (image && image != m_image) {
+ image->ref();
+ if (m_image)
+ m_image->deref();
+ m_image = image;
+
+ SkBitmapRef* bitmap = image->nativeImageForCurrentFrame();
+ m_contentLayer->setContentsImage(bitmap);
+
m_haveContents = true;
- m_haveImage = true;
m_newImage = true;
- m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame());
}
- if (m_haveImage && !image)
+ if (!image && m_image) {
m_contentLayer->setContentsImage(0);
+ m_image->deref();
+ m_image = 0;
+ }
setNeedsDisplay();
askForSync();
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index af8d7ce..358f674 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -145,8 +145,8 @@
bool m_needsNotifyClient;
bool m_haveContents;
- bool m_haveImage;
bool m_newImage;
+ Image* m_image;
SkRegion m_dirtyRegion;
diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
index 96f7713..23e3899 100644
--- a/Source/WebCore/platform/graphics/android/ImageTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
@@ -27,8 +27,11 @@
#include "ImageTexture.h"
#include "ImagesManager.h"
+#include "LayerAndroid.h"
#include "SkDevice.h"
+#include "SkPicture.h"
#include "TilesManager.h"
+#include "TiledTexture.h"
#include <cutils/log.h>
#include <wtf/CurrentTime.h>
@@ -51,33 +54,57 @@
namespace WebCore {
-ImageTexture::ImageTexture(SkBitmapRef* img)
- : m_imageRef(img)
- , m_image(0)
- , m_textureId(0)
- , m_refCount(0)
+// CRC computation adapted from Tools/DumpRenderTree/CyclicRedundancyCheck.cpp
+static void makeCrcTable(unsigned crcTable[256])
+{
+ for (unsigned i = 0; i < 256; i++) {
+ unsigned c = i;
+ for (int k = 0; k < 8; k++) {
+ if (c & 1)
+ c = -306674912 ^ ((c >> 1) & 0x7fffffff);
+ else
+ c = c >> 1;
+ }
+ crcTable[i] = c;
+ }
+}
+
+unsigned computeCrc(uint8_t* buffer, size_t size)
+{
+ static unsigned crcTable[256];
+ static bool crcTableComputed = false;
+ if (!crcTableComputed) {
+ makeCrcTable(crcTable);
+ crcTableComputed = true;
+ }
+
+ unsigned crc = 0xffffffffL;
+ for (size_t i = 0; i < size; ++i)
+ crc = crcTable[(crc ^ buffer[i]) & 0xff] ^ ((crc >> 8) & 0x00ffffffL);
+ return crc ^ 0xffffffffL;
+}
+
+ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc)
+ : m_image(bmp)
+ , m_texture(0)
+ , m_layer(0)
+ , m_picture(0)
+ , m_crc(crc)
{
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("ImageTexture");
#endif
- if (!m_imageRef)
+ if (!m_image)
return;
- SkBitmap* bitmap = &m_imageRef->bitmap();
- m_image = new SkBitmap();
- int w = bitmap->width();
- int h = bitmap->height();
- m_image->setConfig(SkBitmap::kARGB_8888_Config, w, h);
- m_image->allocPixels();
- SkDevice* device = new SkDevice(NULL, *m_image, false);
- SkCanvas canvas;
- canvas.setDevice(device);
- device->unref();
- SkRect dest;
- dest.set(0, 0, w, h);
- m_image->setIsOpaque(false);
- m_image->eraseARGB(0, 0, 0, 0);
- canvas.drawBitmapRect(*bitmap, 0, dest);
+ // NOTE: This constructor is called on the webcore thread
+
+ // Create a picture containing the image (needed for TiledTexture)
+ m_picture = new SkPicture();
+ SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height());
+ pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0));
+ pcanvas->drawBitmap(*m_image, 0, 0);
+ m_picture->endRecording();
}
ImageTexture::~ImageTexture()
@@ -86,61 +113,142 @@
ClassTracker::instance()->decrement("ImageTexture");
#endif
delete m_image;
+ delete m_texture;
+ SkSafeUnref(m_picture);
}
-void ImageTexture::prepareGL()
+SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap)
{
- if (m_textureId)
- return;
+ SkBitmap* img = new SkBitmap();
+ int w = bitmap->width();
+ int h = bitmap->height();
- ImagesManager::instance()->scheduleTextureUpload(this);
+ // Create a copy of the image
+ img->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ img->allocPixels();
+ SkDevice* device = new SkDevice(NULL, *img, false);
+ SkCanvas canvas;
+ canvas.setDevice(device);
+ device->unref();
+ SkRect dest;
+ dest.set(0, 0, w, h);
+ img->setIsOpaque(false);
+ img->eraseARGB(0, 0, 0, 0);
+ canvas.drawBitmapRect(*bitmap, 0, dest);
+
+ return img;
}
-void ImageTexture::uploadGLTexture()
+unsigned ImageTexture::computeCRC(const SkBitmap* bitmap)
{
- if (m_textureId)
- return;
+ if (!bitmap)
+ return 0;
+ bitmap->lockPixels();
+ uint8_t* img = static_cast<uint8_t*>(bitmap->getPixels());
+ unsigned crc = computeCrc(img, bitmap->getSize());
+ bitmap->unlockPixels();
+ return crc;
+}
- glGenTextures(1, &m_textureId);
- GLUtils::createTextureWithBitmap(m_textureId, *m_image);
+bool ImageTexture::equalsCRC(unsigned crc)
+{
+ return m_crc == crc;
+}
+
+int ImageTexture::nbTextures()
+{
+ if (!hasContentToShow())
+ return 0;
+ if (!m_texture)
+ return 0;
+
+ // TODO: take in account the visible clip (need to maintain
+ // a list of the clients layer, etc.)
+ IntRect visibleArea(0, 0, m_image->width(), m_image->height());
+ int nbTextures = m_texture->nbTextures(visibleArea, 1.0);
+ XLOG("ImageTexture %p, %d x %d needs %d textures",
+ this, m_image->width(), m_image->height(),
+ nbTextures);
+ return nbTextures;
+}
+
+bool ImageTexture::hasContentToShow()
+{
+ // Don't display 1x1 image -- no need to allocate a full texture for this
+ if (!m_image)
+ return false;
+ if (m_image->width() == 1 && m_image->height() == 1)
+ return false;
+ return true;
+}
+
+bool ImageTexture::prepareGL(GLWebViewState* state)
+{
+ if (!hasContentToShow())
+ return false;
+
+ if (!m_texture && m_picture) {
+ m_texture = new TiledTexture(this);
+ SkRegion region;
+ region.setRect(0, 0, m_image->width(), m_image->height());
+ m_texture->update(region, m_picture);
+ }
+
+ if (!m_texture)
+ return false;
+
+ IntRect visibleArea(0, 0, m_image->width(), m_image->height());
+ m_texture->prepare(state, 1.0, true, true, visibleArea);
+ if (m_texture->ready()) {
+ m_texture->swapTiles();
+ return false;
+ }
+ return true;
+}
+
+const TransformationMatrix* ImageTexture::transform()
+{
+ if (!m_layer)
+ return 0;
+
+ FloatPoint p(0, 0);
+ p = m_layer->drawTransform()->mapPoint(p);
+ IntRect layerArea = m_layer->unclippedArea();
+ float scaleW = static_cast<float>(layerArea.width()) / static_cast<float>(m_image->width());
+ float scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(m_image->height());
+ TransformationMatrix d = *(m_layer->drawTransform());
+ TransformationMatrix m;
+ m.scaleNonUniform(scaleW, scaleH);
+ m_layerMatrix = d.multiply(m);
+ return &m_layerMatrix;
+}
+
+float ImageTexture::opacity()
+{
+ if (!m_layer)
+ return 1.0;
+ return m_layer->drawOpacity();
}
void ImageTexture::drawGL(LayerAndroid* layer)
{
if (!layer)
return;
- if (!m_textureId)
- return;
- if (!m_image)
+ if (!hasContentToShow())
return;
- SkRect rect;
- rect.fLeft = 0;
- rect.fTop = 0;
- rect.fRight = layer->getSize().width();
- rect.fBottom = layer->getSize().height();
- TilesManager::instance()->shader()->drawLayerQuad(*layer->drawTransform(),
- rect, m_textureId,
- layer->drawOpacity(), true);
+ // TiledTexture::draw() will call us back to know the
+ // transform and opacity, so we need to set m_layer
+ m_layer = layer;
+ if (m_texture)
+ m_texture->draw();
+ m_layer = 0;
}
void ImageTexture::drawCanvas(SkCanvas* canvas, SkRect& rect)
{
- canvas->drawBitmapRect(*m_image, 0, rect);
-}
-
-void ImageTexture::release()
-{
- if (m_refCount >= 1)
- m_refCount--;
- if (!m_refCount)
- deleteTexture();
-}
-
-void ImageTexture::deleteTexture()
-{
- if (m_textureId)
- glDeleteTextures(1, &m_textureId);
+ if (canvas && m_image)
+ canvas->drawBitmapRect(*m_image, 0, rect);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/ImageTexture.h
index cea79c3..6c6a075 100644
--- a/Source/WebCore/platform/graphics/android/ImageTexture.h
+++ b/Source/WebCore/platform/graphics/android/ImageTexture.h
@@ -29,57 +29,78 @@
#include "GLUtils.h"
#include "SkBitmap.h"
#include "SkBitmapRef.h"
+#include "SkPicture.h"
#include "SkRefCnt.h"
#include "LayerAndroid.h"
namespace WebCore {
class LayerAndroid;
+class TexturesResult;
+class TiledTexture;
/////////////////////////////////////////////////////////////////////////////////
// Image sharing codepath for layers
/////////////////////////////////////////////////////////////////////////////////
//
-// We receive an SkBitmapRef on the webcore thread; from this we create
-// an ImageTexture instance and keep it in TilesManager in a hashmap
-// (see TilesManager::addImage())
+// Layers containing only an image take a slightly different codepath;
+// GraphicsLayer::setContentsToImage() is called on the webcore thread,
+// passing an Image instance. We get the native image (an SkBitmap) and create
+// an ImageTexture instance with it (or increment the refcount of an existing
+// instance if the SkBitmap is similar to one already stored in ImagesManager,
+// i.e. if two GraphicsLayer share the same image).
//
-// The ImageTexture will recopy the pointed SkBitmap locally (so we can safely
-// use it on the texture generation thread), and just use the SkBitmapRef as a
-// key.
+// To detect if an image is similar, we compute and use a CRC. Each ImageTexture
+// is stored in ImagesManager using its CRC as a hash key.
+// Simply comparing the address is not enough -- different image could end up
+// at the same address (i.e. the image is deallocated then a new one is
+// reallocated at the old address)
//
-// Layers on the shared image path will ask TilesManager for the corresponding
-// ImageTexture, instead of using a PaintedSurface+TiledTexture.
-// When the ImageTexture is prepared for the first time, we directly upload
-// the bitmap to a texture.
+// Each ImageTexture's CRC being unique, LayerAndroid instances simply store that
+// and retain/release the corresponding ImageTexture (so that
+// queued painting request will work correctly and not crash...).
+// LayerAndroid running on the UI thread will get the corresponding
+// ImageTexture at draw time.
//
-// TODO: limit how many ImageTextures can be uploaded in one draw cycle
-// TODO: limit the size of ImageTextures (use a TiledTexture when needed)
+// ImageTexture recopy the original SkBitmap so that they can safely be used
+// on a different thread; it uses TiledTexture to allocate and paint the image,
+// so that we can share the same textures and limits as the rest of the layers.
//
/////////////////////////////////////////////////////////////////////////////////
-class ImageTexture {
+class ImageTexture : public SurfacePainter {
public:
- ImageTexture(SkBitmapRef* img);
+ ImageTexture(SkBitmap* bmp, unsigned crc);
virtual ~ImageTexture();
- void prepareGL();
- void uploadGLTexture();
+ bool prepareGL(GLWebViewState*);
void drawGL(LayerAndroid* painter);
void drawCanvas(SkCanvas*, SkRect&);
- void retain() { m_refCount++; }
- void release();
- unsigned int refCount() { return m_refCount; }
- SkBitmapRef* imageRef() { return m_imageRef; }
+ bool hasContentToShow();
SkBitmap* bitmap() { return m_image; }
+ unsigned imageCRC() { return m_crc; }
+
+ static SkBitmap* convertBitmap(SkBitmap* bitmap);
+
+ static unsigned computeCRC(const SkBitmap* bitmap);
+ bool equalsCRC(unsigned crc);
+
+ // methods used by TiledTexture
+ virtual const TransformationMatrix* transform();
+ virtual float opacity();
+
+ int nbTextures();
+
+ virtual SurfaceType type() { return SurfacePainter::ImageSurface; }
private:
- void deleteTexture();
-
SkBitmapRef* m_imageRef;
SkBitmap* m_image;
- GLuint m_textureId;
- unsigned int m_refCount;
+ TiledTexture* m_texture;
+ LayerAndroid* m_layer;
+ SkPicture* m_picture;
+ TransformationMatrix m_layerMatrix;
+ unsigned m_crc;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/ImagesManager.cpp
index 21f9fe9..65c41d1 100644
--- a/Source/WebCore/platform/graphics/android/ImagesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/ImagesManager.cpp
@@ -26,6 +26,9 @@
#include "config.h"
#include "ImagesManager.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkRefCnt.h"
#include "ImageTexture.h"
#include <cutils/log.h>
@@ -59,71 +62,88 @@
ImagesManager* ImagesManager::gInstance = 0;
-void ImagesManager::addImage(SkBitmapRef* imgRef)
+ImageTexture* ImagesManager::setImage(SkBitmapRef* imgRef)
{
if (!imgRef)
- return;
+ return 0;
- android::Mutex::Autolock lock(m_imagesLock);
- if (!m_images.contains(imgRef))
- m_images.set(imgRef, new ImageTexture(imgRef));
-}
+ SkBitmap* bitmap = &imgRef->bitmap();
+ ImageTexture* image = 0;
+ SkBitmap* img = 0;
+ unsigned crc = 0;
-void ImagesManager::removeImage(SkBitmapRef* imgRef)
-{
- android::Mutex::Autolock lock(m_imagesLock);
- if (!m_images.contains(imgRef))
- return;
+ img = ImageTexture::convertBitmap(bitmap);
+ crc = ImageTexture::computeCRC(img);
- ImageTexture* image = m_images.get(imgRef);
- image->release();
-
- if (!image->refCount()) {
- m_images.remove(imgRef);
- delete image;
+ {
+ android::Mutex::Autolock lock(m_imagesLock);
+ if (m_images.contains(crc)) {
+ image = m_images.get(crc);
+ SkSafeRef(image);
+ return image;
+ }
}
-}
-void ImagesManager::showImages()
-{
- XLOGC("We have %d images", m_images.size());
- HashMap<SkBitmapRef*, ImageTexture*>::iterator end = m_images.end();
- int i = 0;
- for (HashMap<SkBitmapRef*, ImageTexture*>::iterator it = m_images.begin(); it != end; ++it) {
- XLOGC("Image %x (%d/%d) has %d references", it->first, i,
- m_images.size(), it->second->refCount());
- i++;
- }
-}
+ // the image is not in the map, we add it
-ImageTexture* ImagesManager::getTextureForImage(SkBitmapRef* img, bool retain)
-{
+ image = new ImageTexture(img, crc);
+
android::Mutex::Autolock lock(m_imagesLock);
- ImageTexture* image = m_images.get(img);
- if (retain && image)
- image->retain();
+ m_images.set(crc, image);
+
return image;
}
-void ImagesManager::scheduleTextureUpload(ImageTexture* texture)
+ImageTexture* ImagesManager::retainImage(unsigned imgCRC)
{
- if (m_imagesToUpload.contains(texture))
- return;
+ if (!imgCRC)
+ return 0;
- texture->retain();
- m_imagesToUpload.append(texture);
+ android::Mutex::Autolock lock(m_imagesLock);
+ ImageTexture* image = 0;
+ if (m_images.contains(imgCRC)) {
+ image = m_images.get(imgCRC);
+ SkSafeRef(image);
+ }
+ return image;
}
-bool ImagesManager::uploadTextures()
+void ImagesManager::releaseImage(unsigned imgCRC)
{
- // scheduleUpload and uploadTextures are called on the same thread
- if (!m_imagesToUpload.size())
- return false;
- ImageTexture* texture = m_imagesToUpload.last();
- texture->uploadGLTexture();
- m_imagesToUpload.removeLast();
- removeImage(texture->imageRef());
- return m_imagesToUpload.size();
+ if (!imgCRC)
+ return;
+
+ android::Mutex::Autolock lock(m_imagesLock);
+ if (m_images.contains(imgCRC)) {
+ ImageTexture* image = m_images.get(imgCRC);
+ if (image->getRefCnt() == 1)
+ m_images.remove(imgCRC);
+ SkSafeUnref(image);
+ }
+}
+
+int ImagesManager::nbTextures()
+{
+ android::Mutex::Autolock lock(m_imagesLock);
+ HashMap<unsigned, ImageTexture*>::iterator end = m_images.end();
+ int i = 0;
+ int nb = 0;
+ for (HashMap<unsigned, ImageTexture*>::iterator it = m_images.begin(); it != end; ++it) {
+ nb += it->second->nbTextures();
+ i++;
+ }
+ return nb;
+}
+
+bool ImagesManager::prepareTextures(GLWebViewState* state)
+{
+ bool ret = false;
+ android::Mutex::Autolock lock(m_imagesLock);
+ HashMap<unsigned, ImageTexture*>::iterator end = m_images.end();
+ for (HashMap<unsigned, ImageTexture*>::iterator it = m_images.begin(); it != end; ++it) {
+ ret |= it->second->prepareGL(state);
+ }
+ return ret;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.h b/Source/WebCore/platform/graphics/android/ImagesManager.h
index 2fcb9fd..a3ea859 100644
--- a/Source/WebCore/platform/graphics/android/ImagesManager.h
+++ b/Source/WebCore/platform/graphics/android/ImagesManager.h
@@ -35,17 +35,18 @@
namespace WebCore {
class ImageTexture;
+class GLWebViewState;
class ImagesManager {
public:
static ImagesManager* instance();
- void addImage(SkBitmapRef* img);
- void removeImage(SkBitmapRef* img);
- ImageTexture* getTextureForImage(SkBitmapRef* img, bool retain = true);
- void showImages();
- void scheduleTextureUpload(ImageTexture* texture);
- bool uploadTextures();
+ ImageTexture* setImage(SkBitmapRef* imgRef);
+ ImageTexture* retainImage(unsigned imgCRC);
+ void releaseImage(unsigned imgCRC);
+
+ bool prepareTextures(GLWebViewState*);
+ int nbTextures();
private:
ImagesManager() {}
@@ -53,8 +54,7 @@
static ImagesManager* gInstance;
android::Mutex m_imagesLock;
- HashMap<SkBitmapRef*, ImageTexture*> m_images;
- Vector<ImageTexture*> m_imagesToUpload;
+ HashMap<unsigned, ImageTexture*> m_images;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index 9e7626a..962bcdf 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -149,8 +149,7 @@
m_recordingPicture(0),
m_uniqueId(++gUniqueId),
m_texture(0),
- m_imageRef(0),
- m_imageTexture(0),
+ m_imageCRC(0),
m_pictureUsed(0),
m_scale(1),
m_lastComputeTextureSize(0),
@@ -174,15 +173,15 @@
m_isIframe(layer.m_isIframe),
m_uniqueId(layer.m_uniqueId),
m_texture(0),
- m_imageTexture(0),
m_owningLayer(layer.m_owningLayer),
m_type(LayerAndroid::UILayer),
m_hasText(true)
{
m_isFixed = layer.m_isFixed;
- m_imageRef = layer.m_imageRef;
- if (m_imageRef)
- ImagesManager::instance()->addImage(m_imageRef);
+ m_imageCRC = layer.m_imageCRC;
+ if (m_imageCRC)
+ ImagesManager::instance()->retainImage(m_imageCRC);
+
m_renderLayerPos = layer.m_renderLayerPos;
m_transform = layer.m_transform;
m_backfaceVisibility = layer.m_backfaceVisibility;
@@ -216,14 +215,13 @@
KeyframesMap::const_iterator end = layer.m_animations.end();
for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
- pair<String, int> key((it->second)->name(), (it->second)->type());
- m_animations.add(key, (it->second)->copy());
+ m_animations.add(it->first, it->second);
}
m_hasText = layer.m_hasText;
#ifdef DEBUG_COUNT
- ClassTracker::instance()->increment("LayerAndroid - recopy (UI?)");
+ ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
ClassTracker::instance()->add(this);
#endif
}
@@ -252,8 +250,7 @@
m_recordingPicture(picture),
m_uniqueId(++gUniqueId),
m_texture(0),
- m_imageRef(0),
- m_imageTexture(0),
+ m_imageCRC(0),
m_scale(1),
m_lastComputeTextureSize(0),
m_owningLayer(0),
@@ -272,8 +269,9 @@
LayerAndroid::~LayerAndroid()
{
- if (m_imageTexture)
- ImagesManager::instance()->removeImage(m_imageTexture->imageRef());
+ if (m_imageCRC)
+ ImagesManager::instance()->releaseImage(m_imageCRC);
+
SkSafeUnref(m_recordingPicture);
m_animations.clear();
#ifdef DEBUG_COUNT
@@ -326,6 +324,17 @@
return hasRunningAnimations || m_hasRunningAnimations;
}
+void LayerAndroid::initAnimations() {
+ // tell auto-initializing animations to start now
+ for (int i = 0; i < countChildren(); i++)
+ getChild(i)->initAnimations();
+
+ KeyframesMap::const_iterator localBegin = m_animations.begin();
+ KeyframesMap::const_iterator localEnd = m_animations.end();
+ for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt)
+ (localIt->second)->suggestBeginTime(WTF::currentTime());
+}
+
void LayerAndroid::addDirtyArea()
{
IntSize layerSize(getSize().width(), getSize().height());
@@ -370,7 +379,7 @@
}
for (unsigned int i = 0; i < toDelete.size(); i++)
- m_animations.remove(toDelete[i]);
+ m_animations.remove(toDelete[i]);
}
// We only use the bounding rect of the layer as mask...
@@ -761,16 +770,14 @@
void LayerAndroid::setContentsImage(SkBitmapRef* img)
{
- m_imageRef = img;
- if (!img)
- return;
-
- ImagesManager::instance()->addImage(img);
+ ImageTexture* image = ImagesManager::instance()->setImage(img);
+ ImagesManager::instance()->releaseImage(m_imageCRC);
+ m_imageCRC = image ? image->imageCRC() : 0;
}
bool LayerAndroid::needsTexture()
{
- return m_imageRef || (m_recordingPicture
+ return m_imageCRC || (m_recordingPicture
&& m_recordingPicture->width() && m_recordingPicture->height());
}
@@ -841,10 +848,11 @@
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) "
+ XLOGC("%s [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
"clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d",
spaces, uniqueId(), m_owningLayer,
needsTexture() ? "needs a texture" : "no texture",
+ m_imageCRC ? "has an image" : "no image",
tr.x(), tr.y(), tr.width(), tr.height(),
visible.x(), visible.y(), visible.width(), visible.height(),
clip.x(), clip.y(), clip.width(), clip.height(),
@@ -889,7 +897,12 @@
for (int i = 0; i < count; i++)
this->getChild(i)->setIsPainting(drawingTree);
- obtainTextureForPainting(static_cast<LayerAndroid*>(drawingTree));
+
+ LayerAndroid* drawingLayer = 0;
+ if (drawingTree)
+ drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId());
+
+ obtainTextureForPainting(drawingLayer);
}
void LayerAndroid::mergeInvalsInto(Layer* replacementTree)
@@ -950,38 +963,31 @@
m_opacity = layer->m_opacity;
m_transform = layer->m_transform;
- if (m_imageRef != layer->m_imageRef)
+ if (m_imageCRC != layer->m_imageCRC)
m_visible = false;
if ((m_recordingPicture != layer->m_recordingPicture)
- || (m_imageRef != layer->m_imageRef))
+ || (m_imageCRC != layer->m_imageCRC))
return true;
return false;
}
-void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingTree)
+void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer)
{
if (!needsTexture())
return;
- if (m_imageRef) {
- if (!m_imageTexture) {
- m_imageTexture = ImagesManager::instance()->getTextureForImage(m_imageRef);
- m_dirtyRegion.setEmpty();
- }
+ if (m_imageCRC) {
if (m_texture) {
m_texture->setDrawingLayer(0);
m_texture->clearPaintingLayer();
m_texture = 0;
}
} else {
- if (drawingTree) {
- LayerAndroid* drawingLayer = drawingTree->findById(uniqueId());
- if (drawingLayer) {
- // if a previous tree had the same layer, paint with that painted surface
- m_texture = drawingLayer->m_texture;
- }
+ if (drawingLayer) {
+ // if a previous tree had the same layer, paint with that painted surface
+ m_texture = drawingLayer->m_texture;
}
if (!m_texture)
@@ -989,8 +995,8 @@
// pass the invalidated regions to the PaintedSurface
m_texture->setPaintingLayer(this, m_dirtyRegion);
- m_dirtyRegion.setEmpty();
}
+ m_dirtyRegion.setEmpty();
}
@@ -1032,9 +1038,6 @@
if (m_texture)
m_texture->prepare(m_state);
-
- if (m_imageTexture)
- m_imageTexture->prepareGL();
}
IntRect LayerAndroid::unclippedArea()
@@ -1115,11 +1118,16 @@
bool askScreenUpdate = false;
- if (m_texture)
- askScreenUpdate |= m_texture->draw();
-
- if (m_imageTexture)
- m_imageTexture->drawGL(this);
+ if (m_state->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers) {
+ if (m_texture)
+ askScreenUpdate |= m_texture->draw();
+ if (m_imageCRC) {
+ ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
+ if (imageTexture)
+ imageTexture->drawGL(this);
+ ImagesManager::instance()->releaseImage(m_imageCRC);
+ }
+ }
// When the layer is dirty, the UI thread should be notified to redraw.
askScreenUpdate |= drawChildrenGL();
@@ -1216,16 +1224,15 @@
if (canvasOpacity < 255)
canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
- if (m_imageRef) {
- if (!m_imageTexture) {
- m_imageTexture = ImagesManager::instance()->getTextureForImage(m_imageRef);
- m_dirtyRegion.setEmpty();
- }
- if (m_imageTexture) {
+ if (m_imageCRC) {
+ ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
+ m_dirtyRegion.setEmpty();
+ if (imageTexture) {
SkRect dest;
dest.set(0, 0, getSize().width(), getSize().height());
- m_imageTexture->drawCanvas(canvas, dest);
+ imageTexture->drawCanvas(canvas, dest);
}
+ ImagesManager::instance()->releaseImage(m_imageCRC);
}
contentDraw(canvas);
}
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index ae9dc88..c1f1bc9 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -214,6 +214,7 @@
void removeAnimationsForKeyframes(const String& name);
bool evaluateAnimations();
bool evaluateAnimations(double time);
+ void initAnimations();
bool hasAnimations() const;
void addDirtyArea();
@@ -260,7 +261,7 @@
/** This sets a content image -- calling it means we will use
the image directly when drawing the layer instead of using
the content painted by WebKit.
- Images are handled in TilesManager, as they can be shared
+ Images are handled in ImagesManager, as they can be shared
between layers.
*/
void setContentsImage(SkBitmapRef* img);
@@ -290,7 +291,7 @@
friend void android::cleanupImageRefs(LayerAndroid* layer);
PaintedSurface* texture() { return m_texture; }
- void obtainTextureForPainting(LayerAndroid* drawingTree);
+ void obtainTextureForPainting(LayerAndroid* drawingLayer);
// Update layers using another tree. Only works for basic properties
// such as the position, the transform. Return true if anything more
@@ -298,13 +299,13 @@
bool updateWithTree(LayerAndroid*);
virtual bool updateWithLayer(LayerAndroid*);
- SkBitmapRef* imageRef() { return m_imageRef; }
- ImageTexture* imageTexture() { return m_imageTexture; }
int type() { return m_type; }
bool hasText() { return m_hasText; }
void checkTextPresence();
+ void copyAnimationStartTimesRecursive(LayerAndroid* oldTree);
+
// rendering asset management
void swapTiles();
void setIsDrawing(bool isDrawing);
@@ -323,6 +324,7 @@
friend class CachedLayer::Debug; // debugging access only
#endif
+ void copyAnimationStartTimes(LayerAndroid* oldLayer);
void findInner(FindState&) const;
bool prepareContext(bool force = false);
void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const;
@@ -386,8 +388,7 @@
int m_uniqueId;
PaintedSurface* m_texture;
- SkBitmapRef* m_imageRef;
- ImageTexture* m_imageTexture;
+ unsigned m_imageCRC;
unsigned int m_pictureUsed;
diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
index 5d06ea3..2d69706 100644
--- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
@@ -25,12 +25,14 @@
#include "config.h"
#include "PaintTileOperation.h"
+#include "ImageTexture.h"
+#include "ImagesManager.h"
#include "LayerAndroid.h"
#include "PaintedSurface.h"
namespace WebCore {
-PaintTileOperation::PaintTileOperation(BaseTile* tile, PaintedSurface* surface)
+PaintTileOperation::PaintTileOperation(BaseTile* tile, SurfacePainter* surface)
: QueuedOperation(QueuedOperation::PaintTile, tile->page())
, m_tile(tile)
, m_surface(surface)
@@ -46,7 +48,13 @@
m_tile->setRepaintPending(false);
m_tile = 0;
}
- SkSafeUnref(m_surface);
+
+ if (m_surface && m_surface->type() == SurfacePainter::ImageSurface) {
+ ImageTexture* image = static_cast<ImageTexture*>(m_surface);
+ ImagesManager::instance()->releaseImage(image->imageCRC());
+ } else {
+ SkSafeUnref(m_surface);
+ }
}
bool PaintTileOperation::operator==(const QueuedOperation* operation)
diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h
index fabc2f7..bc74d03 100644
--- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h
@@ -28,15 +28,17 @@
#include "BaseTile.h"
#include "QueuedOperation.h"
+#include "SkRefCnt.h"
namespace WebCore {
class LayerAndroid;
-class PaintedSurface;
+class SurfacePainter;
+class ImageTexture;
class PaintTileOperation : public QueuedOperation {
public:
- PaintTileOperation(BaseTile* tile, PaintedSurface* surface = 0);
+ PaintTileOperation(BaseTile* tile, SurfacePainter* surface = 0);
virtual ~PaintTileOperation();
virtual bool operator==(const QueuedOperation* operation);
virtual void run();
@@ -47,7 +49,7 @@
private:
BaseTile* m_tile;
- PaintedSurface* m_surface;
+ SurfacePainter* m_surface;
};
class ScaleFilter : public OperationFilter {
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
index d3c1e15..45c7579 100644
--- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
@@ -52,9 +52,8 @@
#endif // DEBUG
-// Allows layers using less than MAX_UNCLIPPED_AREA tiles to
-// schedule all of them instead of clipping the area with the visible rect.
-#define MAX_UNCLIPPED_AREA 16
+// Layers with an area larger than 2048*2048 should never be unclipped
+#define MAX_UNCLIPPED_AREA 4194304
namespace WebCore {
@@ -203,10 +202,14 @@
return area;
if (!layer->contentIsScrollable()
- && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures)
+ && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures) {
area = layer->unclippedArea();
- else
+ double total = ((double) area.width()) * ((double) area.height());
+ if (total > MAX_UNCLIPPED_AREA)
+ area = layer->visibleArea();
+ } else {
area = layer->visibleArea();
+ }
return area;
}
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h
index b438111..b8ab7b8 100644
--- a/Source/WebCore/platform/graphics/android/PaintedSurface.h
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h
@@ -43,7 +43,7 @@
class DualTiledTexture;
-class PaintedSurface : public SkRefCnt {
+class PaintedSurface : public SurfacePainter {
public:
PaintedSurface();
virtual ~PaintedSurface();
@@ -71,10 +71,10 @@
// TilePainter methods for TiledTexture
virtual const TransformationMatrix* transform();
+ virtual float opacity();
// used by TiledTexture
float scale() { return m_scale; }
- float opacity();
unsigned int pictureUsed() { return m_pictureUsed; }
private:
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
index 2643d2c..3c2ced5 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
@@ -22,9 +22,6 @@
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 cc9c810..2a6a488 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
@@ -195,6 +195,8 @@
ShaderProgram::ShaderProgram()
: m_blendingEnabled(false)
, m_contrast(1)
+ , m_alphaLayer(false)
+ , m_currentScale(1.0f)
{
init();
}
@@ -286,13 +288,14 @@
// Drawing
/////////////////////////////////////////////////////////////////////////////////////////
-void ShaderProgram::setViewport(SkRect& viewport)
+void ShaderProgram::setViewport(SkRect& viewport, float scale)
{
TransformationMatrix ortho;
GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
viewport.fRight, viewport.fBottom, -1000, 1000);
m_projectionMatrix = ortho;
m_viewport = viewport;
+ m_currentScale = scale;
}
void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
@@ -302,7 +305,12 @@
TransformationMatrix scale;
scale.scale3d(geometry.width(), geometry.height(), 1.0);
- TransformationMatrix total = m_projectionMatrix * translate * scale;
+ TransformationMatrix total;
+ if (!m_alphaLayer)
+ total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix
+ * translate * scale;
+ else
+ total = m_projectionMatrix * translate * scale;
GLfloat projectionMatrix[16];
GLUtils::toGLMatrix(projectionMatrix, total);
@@ -560,7 +568,13 @@
// move the drawing depending on where the texture is on the layer
modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
- TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
+
+ TransformationMatrix renderMatrix;
+ if (!m_alphaLayer)
+ renderMatrix = m_projectionMatrix * m_repositionMatrix
+ * m_webViewMatrix * modifiedDrawMatrix;
+ else
+ renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
GLfloat projectionMatrix[16];
GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
@@ -627,6 +641,44 @@
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
+void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer)
+{
+ GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix);
+ m_alphaLayer = alphaLayer;
+}
+
+void ShaderProgram::calculateAnimationDelta()
+{
+ // The matrix contains the scrolling info, so this rect is starting from
+ // the m_viewport.
+ // So we just need to map the webview's visible rect using the matrix,
+ // calculate the difference b/t transformed rect and the webViewRect,
+ // then we can get the delta x , y caused by the animation.
+ // Note that the Y is for reporting back to GL viewport, so it is inverted.
+ // When it is alpha animation, then we rely on the framework implementation
+ // such that there is no matrix applied in native webkit.
+ if (!m_alphaLayer) {
+ FloatRect rect(m_viewport.fLeft * m_currentScale,
+ m_viewport.fTop * m_currentScale,
+ m_webViewRect.width(),
+ m_webViewRect.height());
+ rect = m_webViewMatrix.mapRect(rect);
+ m_animationDelta.setX(rect.x() - m_webViewRect.x() );
+ m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y()
+ - m_webViewRect.height() - m_titleBarHeight);
+
+ m_repositionMatrix.makeIdentity();
+ m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0);
+ m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0);
+ m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0);
+ } else {
+ m_animationDelta.setX(0);
+ m_animationDelta.setY(0);
+ m_repositionMatrix.makeIdentity();
+ }
+
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h
index b309872..9ab7a46 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h
@@ -36,7 +36,7 @@
int program() { return m_program; }
// Drawing
- void setViewport(SkRect& viewport);
+ void setViewport(SkRect& viewport, float scale);
float zValue(const TransformationMatrix& drawMatrix, float w, float h);
// For drawQuad and drawLayerQuad, they can handle 3 cases for now:
@@ -88,6 +88,18 @@
contrast = MAX_CONTRAST;
m_contrast = contrast;
}
+ void setWebViewMatrix(const float* matrix, bool alphaLayer);
+
+ // This delta is the delta from the layout pos and the current animation pos.
+ // Basically, in terms of layout, the webview is still in the original layout
+ // pos, as without animation. Such that the viewport and visible rect etc are
+ // still in that pos, too, except the clipping info.
+ // Our rendering approach is after applying all the matrix, webView is
+ // rendered as if it was at the original layout pos, but then offset the
+ // glViewport to match the animation.
+ void calculateAnimationDelta();
+ int getAnimationDeltaX() { return m_animationDelta.x(); }
+ int getAnimationDeltaY() { return m_animationDelta.y(); }
private:
GLuint loadShader(GLenum shaderType, const char* pSource);
@@ -158,6 +170,22 @@
GLint m_hPosition;
GLint m_hPositionInverted;
GLint m_hVideoPosition;
+
+ bool m_alphaLayer;
+ TransformationMatrix m_webViewMatrix;
+ float m_currentScale;
+
+ // After the webViewTranform, we need to reposition the rect to match our viewport.
+ // Basically, the webViewTransformMatrix should apply on the screen resolution.
+ // So we start by doing the scale and translate to get each tile into screen coordinates.
+ // After applying the webViewTransformMatrix, b/c the way it currently set up
+ // for scroll and titlebar, we need to offset both of them.
+ // Finally, map everything back to (-1, 1) by using the m_projectionMatrix.
+ // TODO: Given that m_webViewMatrix contains most of the tranformation
+ // information, we should be able to get rid of some parameter we got from
+ // Java side and simplify our code.
+ TransformationMatrix m_repositionMatrix;
+ IntPoint m_animationDelta;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp
index 0820688..bccb99b 100644
--- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp
+++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp
@@ -184,11 +184,10 @@
m_currentOperation->run();
}
+ QueuedOperation* oldOperation = m_currentOperation;
mRequestedOperationsLock.lock();
- if (m_currentOperation) {
- delete m_currentOperation;
+ if (m_currentOperation)
m_currentOperation = 0;
- }
if (!mRequestedOperations.size())
stop = true;
if (m_waitForCompletion) {
@@ -197,7 +196,8 @@
mRequestedOperationsCond.signal();
}
mRequestedOperationsLock.unlock();
-
+ if (oldOperation)
+ delete oldOperation; // delete outside lock
}
XLOG("threadLoop empty");
diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h
index 91030cb..4d0f5dc 100644
--- a/Source/WebCore/platform/graphics/android/TilePainter.h
+++ b/Source/WebCore/platform/graphics/android/TilePainter.h
@@ -27,6 +27,7 @@
#define TilePainter_h
#include "TransformationMatrix.h"
+#include "SkRefCnt.h"
class SkCanvas;
@@ -41,6 +42,15 @@
virtual const TransformationMatrix* transform() { return 0; }
};
+class SurfacePainter : public SkRefCnt {
+public:
+ virtual ~SurfacePainter() { }
+ virtual const TransformationMatrix* transform() { return 0; }
+ virtual float opacity() { return 1.0; }
+ enum SurfaceType { PaintedSurface, ImageSurface };
+ virtual SurfaceType type() { return PaintedSurface; }
+};
+
}
#endif // TilePainter_h
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp
index e33d39a..31a0593 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp
@@ -242,9 +242,6 @@
int nbTilesWidth = tileBounds.width();
int nbTilesHeight = tileBounds.height();
- int lastTileX = tileBounds.fRight - 1;
- int lastTileY = tileBounds.fBottom - 1;
-
// Expand number of tiles to allow tiles outside of viewport to be prepared for
// smoother scrolling.
int nTilesToPrepare = nbTilesWidth * nbTilesHeight;
@@ -256,21 +253,31 @@
int expandY = m_glWebViewState->expandedTileBoundsY();
firstTileX -= expandX;
- lastTileX += expandX;
nbTilesWidth += expandX * 2;
firstTileY -= expandY;
- lastTileY += expandY;
nbTilesHeight += expandY * 2;
}
- // crop the prepared region to the contents of the base layer
- float maxWidthTiles = m_glWebViewState->baseContentWidth() * m_scale / TilesManager::tileWidth();
- float maxHeightTiles = m_glWebViewState->baseContentHeight() * m_scale / TilesManager::tileHeight();
- firstTileX = std::max(0, firstTileX);
- firstTileY = std::max(0, firstTileY);
- lastTileX = std::min(lastTileX, static_cast<int>(ceilf(maxWidthTiles)) - 1);
- lastTileY = std::min(lastTileY, static_cast<int>(ceilf(maxHeightTiles)) - 1);
+ // crop the tile bounds in each dimension to the larger of the base layer or viewport
+ float maxBaseX = m_glWebViewState->baseContentWidth() * m_scale / TilesManager::tileWidth();
+ float maxBaseY = m_glWebViewState->baseContentHeight() * m_scale / TilesManager::tileHeight();
+ int maxX = std::max(static_cast<int>(ceilf(maxBaseX)),
+ m_glWebViewState->viewportTileBounds().width());
+ int maxY = std::max(static_cast<int>(ceilf(maxBaseY)),
+ m_glWebViewState->viewportTileBounds().height());
+
+ // adjust perimeter to not go outside cropped region
+ if (firstTileX < 0) {
+ nbTilesWidth += firstTileX;
+ firstTileX = 0;
+ }
+ if (firstTileY < 0) {
+ nbTilesHeight += firstTileY;
+ firstTileY = 0;
+ }
+ nbTilesWidth = std::min(nbTilesWidth, maxX - firstTileX);
+ nbTilesHeight = std::min(nbTilesHeight, maxY - firstTileY);
// check against corrupted scale values giving bad height/width (use float to avoid overflow)
float numTiles = static_cast<float>(nbTilesHeight) * static_cast<float>(nbTilesWidth);
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
index 5538e1b..d538416 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
@@ -204,6 +204,7 @@
if (tile->isDirty() || !tile->frontTexture())
tile->reserveTexture();
+
bool hasPicture = m_paintingPicture != 0; // safely read on UI thread, since only UI thread writes
if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending() && hasPicture) {
PaintTileOperation *operation = new PaintTileOperation(tile, m_surface);
@@ -223,12 +224,26 @@
int TiledTexture::nbTextures(IntRect& area, float scale)
{
- IntRect computedTilesArea = computeTilesArea(area, scale);
- return computedTilesArea.width() * computedTilesArea.height();
+ IntRect tileBounds = computeTilesArea(area, scale);
+ int numberTextures = tileBounds.width() * tileBounds.height();
+
+ // add the number of dirty tiles in the bounds, as they take up double
+ // textures for double buffering
+ for (unsigned int i = 0; i <m_tiles.size(); i++) {
+ BaseTile* tile = m_tiles[i];
+ if (tile->isDirty()
+ && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX()
+ && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY())
+ numberTextures++;
+ }
+ return numberTextures;
}
bool TiledTexture::draw()
{
+ if (!m_surface)
+ return true;
+
XLOG("TT %p draw", this);
#ifdef DEBUG
@@ -257,8 +272,8 @@
rect.fTop = tile->y() * tileHeight;
rect.fRight = rect.fLeft + tileWidth;
rect.fBottom = rect.fTop + tileHeight;
- XLOG("- [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d",
- i, this, tile->painter(), tile, tile->x(), tile->y(),
+ XLOG("- [%d], { painter %x vs %x }, tile %x (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d",
+ i, this, tile->painter(), tile, tile->isLayerTile(), tile->x(), tile->y(),
tile->scale(), m_scale, tile->isTileReady(), tile->isDirty());
tile->draw(m_surface->opacity(), rect, m_scale);
#ifdef DEBUG
@@ -283,7 +298,7 @@
return false;
}
- XLOG("TT %p painting with picture %p", this, picture);
+ XLOG("TT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), picture);
canvas->drawPicture(*picture);
@@ -294,6 +309,8 @@
const TransformationMatrix* TiledTexture::transform()
{
+ if (!m_surface)
+ return 0;
return m_surface->transform();
}
@@ -323,7 +340,7 @@
return false;
}
-DualTiledTexture::DualTiledTexture(PaintedSurface* surface)
+DualTiledTexture::DualTiledTexture(SurfacePainter* surface)
{
m_textureA = new TiledTexture(surface);
m_textureB = new TiledTexture(surface);
@@ -364,6 +381,7 @@
if (m_zooming && m_zoomUpdateTime < WTF::currentTime()) {
m_backTexture->prepare(state, m_futureScale, repaint, startFastSwap, visibleArea);
if (m_backTexture->ready()) {
+ m_backTexture->swapTiles();
swap();
m_zooming = false;
}
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h
index b761880..444ab14 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.h
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.h
@@ -39,11 +39,9 @@
namespace WebCore {
-class PaintedSurface;
-
class TiledTexture : public TilePainter {
public:
- TiledTexture(PaintedSurface* surface)
+ TiledTexture(SurfacePainter* surface)
: m_paintingPicture(0)
, m_surface(surface)
, m_prevTileX(0)
@@ -82,8 +80,6 @@
float scale() { return m_scale; }
bool ready();
- PaintedSurface* surface() { return m_surface; }
-
int nbTextures(IntRect& area, float scale);
private:
@@ -95,7 +91,7 @@
android::Mutex m_paintingPictureSync;
SkPicture* m_paintingPicture;
- PaintedSurface* m_surface;
+ SurfacePainter* m_surface;
Vector<BaseTile*> m_tiles;
// tile coordinates in viewport, set in prepare()
@@ -112,7 +108,7 @@
class DualTiledTexture {
public:
- DualTiledTexture(PaintedSurface* surface);
+ DualTiledTexture(SurfacePainter* surface);
~DualTiledTexture();
void prepare(GLWebViewState* state, float scale, bool repaint,
bool startFastSwap, IntRect& area);
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp
index 219435d..30bd8d0 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp
@@ -189,6 +189,23 @@
dealloc, max, maxLayer);
}
+void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
+ int* nbLayerTextures, int* nbAllocatedLayerTextures)
+{
+ *nbTextures = m_textures.size();
+ for (unsigned int i = 0; i < m_textures.size(); i++) {
+ BaseTileTexture* texture = m_textures[i];
+ if (texture->m_ownTextureId)
+ *nbAllocatedTextures += 1;
+ }
+ *nbLayerTextures = m_tilesTextures.size();
+ for (unsigned int i = 0; i < m_tilesTextures.size(); i++) {
+ BaseTileTexture* texture = m_tilesTextures[i];
+ if (texture->m_ownTextureId)
+ *nbAllocatedLayerTextures += 1;
+ }
+}
+
void TilesManager::printTextures()
{
#ifdef DEBUG
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h
index 0c3e900..9782fbb 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/TilesManager.h
@@ -88,6 +88,8 @@
void gatherLayerTextures();
void gatherTextures();
bool layerTexturesRemain() { return m_layerTexturesRemain; }
+ void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
+ int* nbLayerTextures, int* nbAllocatedLayerTextures);
BaseTileTexture* getAvailableTexture(BaseTile* owner);
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
index b92edaf..b20ec7a 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -50,7 +50,7 @@
#endif // DEBUG
-#define ST_BUFFER_NUMBER 4
+#define ST_BUFFER_NUMBER 6
// Set this to 1 if we would like to take the new GpuUpload approach which
// relied on the glCopyTexSubImage2D instead of a glDraw call
diff --git a/Source/WebCore/platform/graphics/android/TreeManager.cpp b/Source/WebCore/platform/graphics/android/TreeManager.cpp
index 5fd3b7c..b7eaacf 100644
--- a/Source/WebCore/platform/graphics/android/TreeManager.cpp
+++ b/Source/WebCore/platform/graphics/android/TreeManager.cpp
@@ -28,6 +28,7 @@
#include "Layer.h"
#include "BaseLayerAndroid.h"
+#include "ScrollableLayerAndroid.h"
#include "TilesManager.h"
#include <cutils/log.h>
@@ -87,6 +88,8 @@
// painting tree becomes the drawing tree
XLOG("drawing tree %p", m_paintingTree);
m_paintingTree->setIsDrawing(true);
+ if (m_paintingTree->countChildren())
+ static_cast<LayerAndroid*>(m_paintingTree->getChild(0))->initAnimations();
if (m_queuedTree) {
// start painting with the queued tree
@@ -132,6 +135,10 @@
// or start painting it if we aren't
void TreeManager::updateWithTree(Layer* newTree, bool brandNew)
{
+ XLOG("updateWithTree - %p, has children %d, has animations %d",
+ newTree, newTree && newTree->countChildren(),
+ newTree && newTree->countChildren()
+ ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0);
// can't have a queued tree unless have a painting tree too
ASSERT(m_paintingTree || !m_queuedTree);
@@ -143,10 +150,6 @@
if (!newTree || brandNew) {
clearTrees();
if (brandNew) {
- m_animationOffset = 0;
- m_isAnimating = false;
- m_lastFrameTime = WTF::currentTime();
-
m_paintingTree = newTree;
m_paintingTree->setIsPainting(m_drawingTree);
}
@@ -159,6 +162,11 @@
// have a queued tree, copy over invals so the regions are
// eventually repainted
m_queuedTree->mergeInvalsInto(newTree);
+
+ XLOG("DISCARDING tree - %p, has children %d, has animations %d",
+ newTree, newTree && newTree->countChildren(),
+ newTree && newTree->countChildren()
+ ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0);
}
SkSafeUnref(m_queuedTree);
m_queuedTree = newTree;
@@ -170,9 +178,26 @@
m_paintingTree->setIsPainting(m_drawingTree);
}
+void TreeManager::updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y)
+{
+ LayerAndroid* layer;
+ if (tree && tree->countChildren()) {
+ layer = static_cast<LayerAndroid*>(tree->getChild(0))->findById(layerId);
+ if (layer && layer->contentIsScrollable())
+ static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
+ }
+}
+
+void TreeManager::updateScrollableLayer(int layerId, int x, int y)
+{
+ updateScrollableLayerInTree(m_queuedTree, layerId, x, y);
+ updateScrollableLayerInTree(m_paintingTree, layerId, x, y);
+ updateScrollableLayerInTree(m_drawingTree, layerId, x, y);
+}
+
bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
SkRect& visibleRect, float scale,
- bool enterFastSwapMode, bool* buffersSwappedPtr,
+ bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
TexturesResult* texturesResultPtr)
{
m_fastSwapMode |= enterFastSwapMode;
@@ -183,19 +208,28 @@
bool ret = false;
bool didTreeSwap = false;
if (m_paintingTree) {
+ XLOG("preparing painting tree %p", m_paintingTree);
+
+ LayerAndroid* laTree = 0;
+ if (m_paintingTree->countChildren()) {
+ laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
+ ret |= laTree->evaluateAnimations(currentTime);
+ }
+
ret |= m_paintingTree->prepare(currentTime, viewRect,
visibleRect, scale);
- if (m_paintingTree->countChildren()) {
- LayerAndroid* laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
+ if (laTree)
laTree->computeTexturesAmount(texturesResultPtr);
- }
+
if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
XLOG("have painting tree %p ready, swapping!", m_paintingTree);
didTreeSwap = true;
swap();
- if (buffersSwappedPtr)
- *buffersSwappedPtr = true;
+ if (treesSwappedPtr)
+ *treesSwappedPtr = true;
+ if (laTree && newTreeHasAnimPtr)
+ *newTreeHasAnimPtr = laTree->hasAnimations();
}
} else if (m_drawingTree) {
XLOG("preparing drawing tree %p", m_drawingTree);
@@ -207,17 +241,11 @@
}
}
- if (!m_isAnimating) {
- m_animationOffset += currentTime - m_lastFrameTime;
-#ifdef ANIM_DEBUG
- XLOGC("adding to %f", m_animationOffset);
-#endif
- }
if (m_drawingTree) {
bool drawingReady = didTreeSwap || m_drawingTree->isReady();
- if (drawingReady || m_fastSwapMode)
+ if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree))
m_drawingTree->swapTiles();
if (drawingReady) {
@@ -229,18 +257,8 @@
}
if (m_drawingTree->countChildren()) {
-#ifdef ANIM_DEBUG
- XLOGC("drawing tree %p with animation time offset of %f, locked %d",
- m_drawingTree, m_animationOffset, m_isAnimating);
-#endif
LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
- m_isAnimating = laTree->evaluateAnimations(currentTime - m_animationOffset);
- if (!m_isAnimating)
- m_animationOffset = 0;
- ret |= m_isAnimating;
- } else if (!m_paintingTree) {
- m_animationOffset = 0;
- m_isAnimating = false;
+ ret |= laTree->evaluateAnimations(currentTime);
}
XLOG("drawing tree %p", m_drawingTree);
ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale);
@@ -250,8 +268,6 @@
m_paintingTree->state()->drawBackground(defaultBackground);
}
- m_lastFrameTime = currentTime;
-
if (m_paintingTree) {
XLOG("still have painting tree %p", m_paintingTree);
return true;
diff --git a/Source/WebCore/platform/graphics/android/TreeManager.h b/Source/WebCore/platform/graphics/android/TreeManager.h
index 09b1bd9..83d5300 100644
--- a/Source/WebCore/platform/graphics/android/TreeManager.h
+++ b/Source/WebCore/platform/graphics/android/TreeManager.h
@@ -28,6 +28,7 @@
#include "TestExport.h"
#include <utils/threads.h>
+#include "PerformanceMonitor.h"
class Layer;
class SkRect;
@@ -46,9 +47,11 @@
void updateWithTree(Layer* tree, bool brandNew);
+ void updateScrollableLayer(int layerId, int x, int y);
+
bool drawGL(double currentTime, IntRect& viewRect,
SkRect& visibleRect, float scale,
- bool enterFastSwapMode, bool* buffersSwappedPtr,
+ bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
TexturesResult* texturesResultPtr);
void drawCanvas(SkCanvas* canvas, bool drawLayers);
@@ -60,6 +63,8 @@
int baseContentHeight();
private:
+ static void updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y);
+
void swap();
void clearTrees();
@@ -70,10 +75,7 @@
Layer* m_queuedTree;
bool m_fastSwapMode;
-
- double m_animationOffset;
- double m_lastFrameTime;
- bool m_isAnimating;
+ PerformanceMonitor m_perf;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index d4e2aa3..df20063 100644
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -812,7 +812,7 @@
else {
#ifdef ANDROID_LAYOUT
// ignore text wrap for textField or menuList
- if (doTextWrap && (o->isTextField() || o->isMenuList() || o->isFloating()))
+ if (doTextWrap && (o->isTextField() || o->isMenuList()))
doTextWrap = false;
#endif
if (o->isFloating())
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 80d5699..fb1dd2c 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -1562,6 +1562,13 @@
// https://bugs.webkit.org/show_bug.cgi?id=46418
if (hasOverrideSize() && parent()->style()->boxOrient() == HORIZONTAL
&& parent()->isFlexibleBox() && parent()->isFlexingChildren()) {
+#if PLATFORM(ANDROID)
+ // Strangely, the slider is get overrided as width 0 on youtube.com
+ // The wrong width will cause the touch hit test for the slider failed.
+ // This WAR should be safe since it is only targeted to slider.
+ // TODO: root cause this and see if any webkit update fix this.
+ if (!(isSlider() && overrideSize() == 0))
+#endif
setLogicalWidth(overrideSize());
return;
}
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index 904b1b2..cdc4c05 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -1419,8 +1419,15 @@
}
// Just schedule a full repaint of our object.
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ // On android, scrollable areas are put on composited layers, so we
+ // do not need to repaint simply because we are scrolling
+ if (view && !hasOverflowScroll())
+ renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
+#else
if (view)
renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
+#endif
// Schedule the scroll DOM event.
renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 5827636..1ef3b77 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -1576,7 +1576,12 @@
return false;
if (AnimationController* animController = renderer->animation()) {
+#if PLATFORM(ANDROID)
+ // android renders an opacity animation much faster if it's composited
+ return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity))
+#else
return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
+#endif
|| animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
}
return false;
diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
index a6e58c8..43037ab 100644
--- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
@@ -324,16 +324,6 @@
this->Release();
}
-void WebUrlLoaderClient::sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain)
-{
- base::Thread* thread = ioThread();
- scoped_refptr<net::X509Certificate> scopedChain(chain);
- if (isActive() && thread)
- thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request.get(), &WebRequest::sslClientCert, pkey, scopedChain));
- this->Release();
-}
-
-
void WebUrlLoaderClient::finish()
{
m_finished = true;
@@ -492,12 +482,22 @@
m_webFrame->reportSslCertError(this, cert_error, chain_bytes[0], m_request->getUrl());
}
+void WebUrlLoaderClient::sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain)
+{
+ base::Thread* thread = ioThread();
+ scoped_refptr<net::X509Certificate> scopedChain(chain);
+ if (isActive() && thread)
+ thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request.get(), &WebRequest::sslClientCert, pkey, scopedChain));
+ this->Release();
+}
+
void WebUrlLoaderClient::requestClientCert(net::SSLCertRequestInfo* cert_request_info)
{
if (!isActive())
return;
std::string host_and_port = cert_request_info->host_and_port;
+ this->AddRef();
m_webFrame->requestClientCert(this, host_and_port);
}
diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
index 5f03339..4463dfb 100644
--- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
+++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
@@ -74,7 +74,6 @@
void cancelAuth();
void proceedSslCertError();
void cancelSslCertError(int cert_error);
- void sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain);
typedef void CallbackFunction(void*);
@@ -92,6 +91,8 @@
void willSendRequest(PassOwnPtr<WebResponse>);
void authRequired(scoped_refptr<net::AuthChallengeInfo>, bool firstTime, bool suppressDialog);
void reportSslCertError(int cert_error, net::X509Certificate* cert);
+
+ void sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain);
void requestClientCert(net::SSLCertRequestInfo* cert);
// Handle to the chrome IO thread
diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp
index 93f4375..6b473f5 100644
--- a/Source/WebKit/android/jni/ViewStateSerializer.cpp
+++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp
@@ -111,11 +111,6 @@
if (childLayer)
layer->addChild(childLayer);
}
- // Now double back and delete any imageRefs
- for (int i = 0; i < layer->countChildren(); i++) {
- LayerAndroid* childLayer = static_cast<LayerAndroid*>(layer->getChild(i));
- cleanupImageRefs(childLayer);
- }
delete stream;
return layer;
}
@@ -297,15 +292,16 @@
stream->writeBool(layer->m_preserves3D);
stream->writeScalar(layer->m_anchorPointZ);
stream->writeScalar(layer->m_drawOpacity);
- bool hasContentsImage = layer->m_imageRef != 0;
+ bool hasContentsImage = layer->m_imageCRC != 0;
stream->writeBool(hasContentsImage);
if (hasContentsImage) {
SkFlattenableWriteBuffer buffer(1024);
buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
ImageTexture* imagetexture =
- ImagesManager::instance()->getTextureForImage(layer->m_imageRef, false);
+ ImagesManager::instance()->retainImage(layer->m_imageCRC);
if (imagetexture && imagetexture->bitmap())
imagetexture->bitmap()->flatten(buffer);
+ ImagesManager::instance()->releaseImage(layer->m_imageCRC);
stream->write32(buffer.size());
buffer.writeToStream(stream);
}
@@ -388,8 +384,7 @@
contentsImage.unflatten(buffer);
SkBitmapRef* imageRef = new SkBitmapRef(contentsImage);
layer->setContentsImage(imageRef);
- // We delay deleting the imageRef until after deserialization to make
- // sure we have unique keys
+ delete imageRef;
}
bool hasRecordingPicture = stream->readBool();
if (hasRecordingPicture) {
@@ -418,17 +413,6 @@
return layer;
}
-void cleanupImageRefs(LayerAndroid* layer)
-{
- if (!layer)
- return;
- int count = layer->countChildren();
- for (int i = 0; i < count; i++)
- cleanupImageRefs(layer->getChild(i));
- if (layer->m_imageRef)
- delete layer->m_imageRef;
-}
-
/*
* JNI registration
*/
diff --git a/Source/WebKit/android/jni/WebHistory.cpp b/Source/WebKit/android/jni/WebHistory.cpp
index 7ec73a3..aa74b81 100644
--- a/Source/WebKit/android/jni/WebHistory.cpp
+++ b/Source/WebKit/android/jni/WebHistory.cpp
@@ -490,7 +490,7 @@
// Read the original url
// Read the expected length of the string.
- int l;
+ unsigned l;
memcpy(&l, data, sizeofUnsigned);
// Increment data pointer by the size of an unsigned int.
data += sizeofUnsigned;
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 7692de1..839c352 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -885,29 +885,37 @@
ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
if (root) {
- root->notifyClientAnimationStarted();
LayerAndroid* updatedLayer = root->contentLayer();
return layers->updateWithTree(updatedLayer);
}
return true;
}
+void WebViewCore::notifyAnimationStarted()
+{
+ // We notify webkit that the animations have begun
+ // TODO: handle case where not all have begun
+ ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
+ GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
+ if (root)
+ root->notifyClientAnimationStarted();
+
+}
+
BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region)
{
BaseLayerAndroid* base = new BaseLayerAndroid();
base->setContent(m_content);
- if (!region->isEmpty()) {
- m_skipContentDraw = true;
- bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
- m_skipContentDraw = false;
- // Layout only fails if called during a layout.
- LOG_ASSERT(layoutSucceeded, "Can never be called recursively");
- }
+ m_skipContentDraw = true;
+ bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
+ m_skipContentDraw = false;
+ // Layout only fails if called during a layout.
+ LOG_ASSERT(layoutSucceeded, "Can never be called recursively");
#if USE(ACCELERATED_COMPOSITING)
// We set the background color
- if (!region->isEmpty() && m_mainFrame && m_mainFrame->document()
+ if (m_mainFrame && m_mainFrame->document()
&& m_mainFrame->document()->body()) {
Document* document = m_mainFrame->document();
RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
@@ -922,7 +930,6 @@
ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
if (root) {
- root->notifyClientAnimationStarted();
LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
base->addChild(copyLayer);
copyLayer->unref();
@@ -4106,9 +4113,9 @@
m_groupForVisitedLinks->addVisitedLink(string, length);
}
-static bool UpdateLayers(JNIEnv *env, jobject obj, jint jbaseLayer)
+static bool UpdateLayers(JNIEnv *env, jobject obj, jint nativeClass, jint jbaseLayer)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = (WebViewCore*) nativeClass;
BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer;
if (baseLayer) {
LayerAndroid* root = static_cast<LayerAndroid*>(baseLayer->getChild(0));
@@ -4118,6 +4125,12 @@
return true;
}
+static void NotifyAnimationStarted(JNIEnv *env, jobject obj, jint nativeClass)
+{
+ WebViewCore* viewImpl = (WebViewCore*) nativeClass;
+ viewImpl->notifyAnimationStarted();
+}
+
static jint RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
{
#ifdef ANDROID_INSTRUMENT
@@ -4697,8 +4710,10 @@
(void*) UpdateFrameCache },
{ "nativeGetContentMinPrefWidth", "()I",
(void*) GetContentMinPrefWidth },
- { "nativeUpdateLayers", "(I)Z",
+ { "nativeUpdateLayers", "(II)Z",
(void*) UpdateLayers },
+ { "nativeNotifyAnimationStarted", "(I)V",
+ (void*) NotifyAnimationStarted },
{ "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)I",
(void*) RecordContent },
{ "setViewportSettingsFromNative", "()V",
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index acde590..a05c3ea 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -529,6 +529,7 @@
// as we are calling layersSync().
BaseLayerAndroid* createBaseLayer(SkRegion*);
bool updateLayers(LayerAndroid*);
+ void notifyAnimationStarted();
int textWrapWidth() const { return m_textWrapWidth; }
float scale() const { return m_scale; }
diff --git a/Source/WebKit/android/nav/CacheBuilder.cpp b/Source/WebKit/android/nav/CacheBuilder.cpp
index 0c9e85c..940991f 100644
--- a/Source/WebKit/android/nav/CacheBuilder.cpp
+++ b/Source/WebKit/android/nav/CacheBuilder.cpp
@@ -1161,8 +1161,6 @@
absBounds.move(globalOffsetX, globalOffsetY);
hasClip = nodeRenderer->hasOverflowClip();
- if (node->hasTagName(HTMLNames::canvasTag))
- mPictureSetDisabled = true;
if (checkForPluginViewThatWantsFocus(nodeRenderer)) {
bounds = absBounds;
isUnclipped = true;
@@ -1269,6 +1267,7 @@
type = TEXT_INPUT_CACHEDNODETYPE;
cachedInput.setFormPointer(area->form());
cachedInput.setIsTextArea(true);
+ cachedInput.setSpellcheck(area->spellcheck());
exported = area->value().threadsafeCopy();
} else if (node->hasTagName(HTMLNames::aTag)) {
const HTMLAnchorElement* anchorNode =
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index 13346b3..76f0fb8 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -172,7 +172,7 @@
m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V");
m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz,
"viewInvalidateDelayed", "(JIIII)V");
- m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "()V");
+ m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "(Z)V");
m_javaGlue.m_inFullScreenMode = GetJMethod(env, clazz, "inFullScreenMode", "()Z");
m_javaGlue.m_getTextHandleScale = GetJMethod(env, clazz, "getTextHandleScale", "()F");
env->DeleteLocalRef(clazz);
@@ -505,17 +505,18 @@
// once the correct scale is set
if (!m_visibleRect.hasValidCoordinates())
return false;
- bool pagesSwapped = false;
+ bool treesSwapped = false;
+ bool newTreeHasAnim = false;
bool ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect,
webViewRect, titleBarHeight, clip, scale,
- &pagesSwapped);
- if (m_pageSwapCallbackRegistered && pagesSwapped) {
+ &treesSwapped, &newTreeHasAnim);
+ if (treesSwapped && (m_pageSwapCallbackRegistered || newTreeHasAnim)) {
m_pageSwapCallbackRegistered = false;
LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue.object(env);
if (javaObject.get()) {
- env->CallVoidMethod(javaObject.get(), m_javaGlue.m_pageSwapCallback);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_pageSwapCallback, newTreeHasAnim);
checkException(env);
}
}
@@ -1092,6 +1093,12 @@
return 0;
}
+void scrollLayer(int layerId, int x, int y)
+{
+ if (m_glWebViewState)
+ m_glWebViewState->scrollLayer(layerId, x, y);
+}
+
int getBlockLeftEdge(int x, int y, float scale)
{
CachedRoot* root = getFrameCache(AllowNewer);
@@ -1458,6 +1465,7 @@
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
if (layer) {
+ // TODO: the below tree copies are only necessary in software rendering
LayerAndroid* newCompositeRoot = static_cast<LayerAndroid*>(layer->getChild(0));
copyScrollPositionRecursive(compositeRoot(), newCompositeRoot);
}
@@ -1584,6 +1592,7 @@
WebCore::IntRect clip(info->clipLeft, info->clipTop,
info->clipRight - info->clipLeft,
info->clipBottom - info->clipTop);
+ TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer);
bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect,
titlebarHeight, clip, scale, extras);
@@ -1904,10 +1913,13 @@
static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint nativeView)
{
+ // only call in software rendering, initialize and evaluate animations
#if USE(ACCELERATED_COMPOSITING)
LayerAndroid* root = ((WebView*)nativeView)->compositeRoot();
- if (root)
+ if (root) {
+ root->initAnimations();
return root->evaluateAnimations();
+ }
#endif
return false;
}
@@ -2094,6 +2106,18 @@
return input->getType();
}
+static int nativeFocusCandidateLayerId(JNIEnv *env, jobject obj)
+{
+ const CachedFrame* frame = 0;
+ const CachedNode* node = getFocusNode(env, obj, &frame);
+ if (!node || !frame)
+ return -1;
+ const CachedLayer* layer = frame->layer(node);
+ if (!layer)
+ return -1;
+ return layer->uniqueId();
+}
+
static bool nativeFocusIsPlugin(JNIEnv *env, jobject obj)
{
const CachedNode* node = getFocusNode(env, obj);
@@ -2657,6 +2681,9 @@
{
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
WebView* view = GET_NATIVE_VIEW(env, obj);
+ view->scrollLayer(layerId, x, y);
+
+ //TODO: the below only needed for the SW rendering path
LayerAndroid* root = view->compositeRoot();
if (!root)
return false;
@@ -2789,6 +2816,8 @@
(void*) nativeFocusCandidateTextSize },
{ "nativeFocusCandidateType", "()I",
(void*) nativeFocusCandidateType },
+ { "nativeFocusCandidateLayerId", "()I",
+ (void*) nativeFocusCandidateLayerId },
{ "nativeFocusIsPlugin", "()Z",
(void*) nativeFocusIsPlugin },
{ "nativeFocusNodeBounds", "()Landroid/graphics/Rect;",