summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/WebCore/Android.mk1
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp16
-rw-r--r--Source/WebCore/platform/graphics/android/ImageTexture.cpp128
-rw-r--r--Source/WebCore/platform/graphics/android/ImageTexture.h84
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp71
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h11
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.cpp46
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.h9
8 files changed, 323 insertions, 43 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 335915f..1250d91 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -655,6 +655,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/ImageAndroid.cpp \
platform/graphics/android/ImageBufferAndroid.cpp \
platform/graphics/android/ImageSourceAndroid.cpp \
+ platform/graphics/android/ImageTexture.cpp \
platform/graphics/android/Layer.cpp \
platform/graphics/android/LayerAndroid.cpp \
platform/graphics/android/MediaLayer.cpp \
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 40d25e4..7722e5a 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -630,6 +630,8 @@ bool GraphicsLayerAndroid::repaint()
if (m_needsRepaint && m_haveImage && 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);
+ m_dirtyRegion.setEmpty();
m_contentLayer->needsRepaint();
m_newImage = false;
m_needsRepaint = false;
@@ -656,13 +658,7 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context,
void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
{
- for (unsigned int i = 0; i < m_children.size(); i++) {
- GraphicsLayer* layer = m_children[i];
- if (layer) {
- FloatRect childrenRect = m_transform.mapRect(rect);
- layer->setNeedsDisplayInRect(childrenRect);
- }
- }
+ // rect is in the render object coordinates
if (!m_haveImage && !drawsContent()) {
LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
@@ -848,6 +844,12 @@ void GraphicsLayerAndroid::setContentsToImage(Image* image)
askForSync();
}
}
+ if (m_haveImage && !image) {
+ m_contentLayer->setContentsImage(0);
+ m_imageRef = 0;
+ setNeedsDisplay();
+ askForSync();
+ }
}
void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
new file mode 100644
index 0000000..7e71740
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageTexture.h"
+
+#include "SkDevice.h"
+#include "TilesManager.h"
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+ImageTexture::ImageTexture(SkBitmapRef* img)
+ : m_imageRef(img)
+ , m_image(0)
+ , m_textureId(0)
+ , m_refCount(0)
+{
+#ifdef DEBUG_COUNT
+ ClassTracker::instance()->increment("ImageTexture");
+#endif
+ if (!m_imageRef)
+ 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);
+}
+
+ImageTexture::~ImageTexture()
+{
+#ifdef DEBUG_COUNT
+ ClassTracker::instance()->decrement("ImageTexture");
+#endif
+ delete m_image;
+}
+
+void ImageTexture::prepare()
+{
+ if (m_textureId)
+ return;
+
+ glGenTextures(1, &m_textureId);
+ GLUtils::createTextureWithBitmap(m_textureId, *m_image);
+}
+
+void ImageTexture::draw(LayerAndroid* layer)
+{
+ if (!layer)
+ return;
+ if (!m_textureId)
+ return;
+ if (!m_image)
+ 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);
+}
+
+void ImageTexture::release()
+{
+ if (m_refCount >= 1)
+ m_refCount--;
+ if (!m_refCount)
+ deleteTexture();
+}
+
+void ImageTexture::deleteTexture()
+{
+ glDeleteTextures(1, &m_textureId);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/ImageTexture.h
new file mode 100644
index 0000000..7e51d2b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ImageTexture.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ImageTexture_h
+#define ImageTexture_h
+
+#include "ClassTracker.h"
+#include "GLUtils.h"
+#include "SkBitmap.h"
+#include "SkBitmapRef.h"
+#include "SkRefCnt.h"
+#include "LayerAndroid.h"
+
+namespace WebCore {
+
+class LayerAndroid;
+
+/////////////////////////////////////////////////////////////////////////////////
+// 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())
+//
+// 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.
+//
+// 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.
+//
+// TODO: limit how many ImageTextures can be uploaded in one draw cycle
+// TODO: limit the size of ImageTextures (use a TiledTexture when needed)
+//
+/////////////////////////////////////////////////////////////////////////////////
+class ImageTexture {
+public:
+ ImageTexture(SkBitmapRef* img);
+ virtual ~ImageTexture();
+
+ void prepare();
+ void draw(LayerAndroid* painter);
+ void deleteTexture();
+ void retain() { m_refCount++; }
+ void release();
+ unsigned int refCount() { return m_refCount; }
+ SkBitmapRef* imageRef() { return m_imageRef; }
+
+private:
+
+ SkBitmapRef* m_imageRef;
+ SkBitmap* m_image;
+ GLuint m_textureId;
+ unsigned int m_refCount;
+};
+
+} // namespace WebCore
+
+#endif // ImageTexture
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index a39614f..81f0ce7 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -64,10 +64,11 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
m_preserves3D(false),
m_anchorPointZ(0),
m_recordingPicture(0),
- m_contentsImage(0),
m_extra(0),
m_uniqueId(++gUniqueId),
m_texture(0),
+ m_imageRef(0),
+ m_imageTexture(0),
m_pictureUsed(0),
m_requestSent(false),
m_scale(1),
@@ -88,15 +89,17 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_haveClip(layer.m_haveClip),
m_isIframe(layer.m_isIframe),
- m_contentsImage(0),
m_extra(0), // deliberately not copied
m_uniqueId(layer.m_uniqueId),
m_texture(0),
+ m_imageTexture(0),
m_requestSent(false),
m_owningLayer(layer.m_owningLayer)
{
m_isFixed = layer.m_isFixed;
- copyBitmap(layer.m_contentsImage);
+ m_imageRef = layer.m_imageRef;
+ if (m_imageRef)
+ TilesManager::instance()->addImage(m_imageRef);
m_renderLayerPos = layer.m_renderLayerPos;
m_transform = layer.m_transform;
m_backfaceVisibility = layer.m_backfaceVisibility;
@@ -145,10 +148,11 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_isFixed(false),
m_isIframe(false),
m_recordingPicture(picture),
- m_contentsImage(0),
m_extra(0),
m_uniqueId(-1),
m_texture(0),
+ m_imageRef(0),
+ m_imageTexture(0),
m_requestSent(false),
m_scale(1),
m_lastComputeTextureSize(0),
@@ -169,9 +173,10 @@ LayerAndroid::~LayerAndroid()
if (m_texture)
m_texture->removeLayer(this);
SkSafeUnref(m_texture);
+ if (m_imageTexture)
+ TilesManager::instance()->removeImage(m_imageTexture->imageRef());
removeChildren();
delete m_extra;
- delete m_contentsImage;
SkSafeUnref(m_recordingPicture);
m_animations.clear();
#ifdef DEBUG_COUNT
@@ -646,28 +651,18 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM
this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale);
}
-void LayerAndroid::copyBitmap(SkBitmap* bitmap)
+void LayerAndroid::setContentsImage(SkBitmapRef* img)
{
- if (!bitmap)
+ m_imageRef = img;
+ if (!img)
return;
- delete m_contentsImage;
- m_contentsImage = new SkBitmap();
- SkBitmap::Config config = bitmap->config();
- int w = bitmap->width();
- int h = bitmap->height();
- m_contentsImage->setConfig(config, w, h);
- bitmap->copyTo(m_contentsImage, config);
-}
-
-void LayerAndroid::setContentsImage(SkBitmapRef* img)
-{
- copyBitmap(&img->bitmap());
+ TilesManager::instance()->addImage(img);
}
bool LayerAndroid::needsTexture()
{
- return m_contentsImage || (prepareContext()
+ return m_imageRef || (prepareContext()
&& m_recordingPicture->width() && m_recordingPicture->height());
}
@@ -727,7 +722,7 @@ void LayerAndroid::showLayer(int indent)
}
// We go through our tree, and if we have layer in the new
-// tree that is similar, we tranfer our texture to it.
+// tree that is similar, we transfer our texture to it.
// Otherwise, we remove ourselves from the texture so
// that TilesManager::swapLayersTextures() have a chance
// at deallocating the textures (PaintedSurfaces)
@@ -762,12 +757,23 @@ void LayerAndroid::createTexture()
if (!needsTexture())
return;
- if (!m_texture)
- m_texture = new PaintedSurface(this);
+ if (m_imageRef) {
+ if (!m_imageTexture) {
+ m_imageTexture = TilesManager::instance()->getTextureForImage(m_imageRef);
+ m_dirtyRegion.setEmpty();
+ }
+ if (m_texture) {
+ m_texture->removeLayer(this);
+ m_texture = 0;
+ }
+ } else {
+ if (!m_texture)
+ m_texture = new PaintedSurface(this);
- // pass the invalidated regions to the PaintedSurface
- m_texture->markAsDirty(m_dirtyRegion);
- m_dirtyRegion.setEmpty();
+ // pass the invalidated regions to the PaintedSurface
+ m_texture->markAsDirty(m_dirtyRegion);
+ m_dirtyRegion.setEmpty();
+ }
}
static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
@@ -811,6 +817,9 @@ void LayerAndroid::prepare(GLWebViewState* glWebViewState)
if (m_texture)
m_texture->prepare(glWebViewState);
+
+ if (m_imageTexture)
+ m_imageTexture->prepare();
}
bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
@@ -824,6 +833,9 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
if (m_texture)
askPaint |= m_texture->draw();
+ if (m_imageTexture)
+ m_imageTexture->draw(this);
+
// When the layer is dirty, the UI thread should be notified to redraw.
askPaint |= drawChildrenGL(glWebViewState, matrix);
m_atomicSync.lock();
@@ -865,13 +877,8 @@ void LayerAndroid::extraDraw(SkCanvas* canvas)
void LayerAndroid::contentDraw(SkCanvas* canvas)
{
- if (m_contentsImage) {
- SkRect dest;
- dest.set(0, 0, getSize().width(), getSize().height());
- canvas->drawBitmapRect(*m_contentsImage, 0, dest);
- } else {
+ if (m_recordingPicture)
canvas->drawPicture(*m_recordingPicture);
- }
if (TilesManager::instance()->getShowVisualIndicator()) {
float w = getSize().width();
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 8078762..2150a78 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -23,6 +23,7 @@
#include "FloatPoint3D.h"
#include "FloatRect.h"
#include "GraphicsLayerClient.h"
+#include "ImageTexture.h"
#include "Layer.h"
#include "RefPtr.h"
#include "SkBitmap.h"
@@ -49,6 +50,7 @@ class SkPicture;
namespace WebCore {
class LayerAndroid;
+class ImageTexture;
}
namespace android {
@@ -234,12 +236,11 @@ public:
/** 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. See comments below for
- m_recordingPicture and m_contentsImage.
+ the content painted by WebKit.
+ Images are handled in TilesManager, as they can be shared
+ between layers.
*/
void setContentsImage(SkBitmapRef* img);
- bool hasContentsImage() { return m_contentsImage; }
- void copyBitmap(SkBitmap*);
void bounds(SkRect*) const;
@@ -348,6 +349,8 @@ private:
int m_uniqueId;
PaintedSurface* m_texture;
+ SkBitmapRef* m_imageRef;
+ ImageTexture* m_imageTexture;
// used to signal that the tile is out-of-date and needs to be redrawn
bool m_dirty;
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp
index e1d7665..c16f945 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp
@@ -400,6 +400,52 @@ void TilesManager::unregisterGLWebViewState(GLWebViewState* state)
transferQueue()->discardQueue();
}
+void TilesManager::addImage(SkBitmapRef* imgRef)
+{
+ if (!imgRef)
+ return;
+
+ android::Mutex::Autolock lock(m_imagesLock);
+ if (!m_images.contains(imgRef))
+ m_images.set(imgRef, new ImageTexture(imgRef));
+}
+
+void TilesManager::removeImage(SkBitmapRef* imgRef)
+{
+ android::Mutex::Autolock lock(m_imagesLock);
+ if (!m_images.contains(imgRef))
+ return;
+
+ ImageTexture* image = m_images.get(imgRef);
+ image->release();
+
+ if (!image->refCount()) {
+ m_images.remove(imgRef);
+ delete image;
+ }
+}
+
+void TilesManager::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++;
+ }
+}
+
+ImageTexture* TilesManager::getTextureForImage(SkBitmapRef* img)
+{
+ android::Mutex::Autolock lock(m_imagesLock);
+ ImageTexture* image = m_images.get(img);
+ if (image)
+ image->retain();
+ return image;
+}
+
TilesManager* TilesManager::instance()
{
if (!gInstance) {
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h
index 3298c94..775af48 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/TilesManager.h
@@ -30,8 +30,10 @@
#include "BaseTile.h"
#include "BaseTileTexture.h"
+#include "ImageTexture.h"
#include "LayerAndroid.h"
#include "ShaderProgram.h"
+#include "SkBitmapRef.h"
#include "TexturesGenerator.h"
#include "TiledPage.h"
#include "TilesProfiler.h"
@@ -176,6 +178,10 @@ public:
{
return m_drawGLCount;
}
+ void addImage(SkBitmapRef* img);
+ void removeImage(SkBitmapRef* img);
+ ImageTexture* getTextureForImage(SkBitmapRef* img);
+ void showImages();
private:
TilesManager();
@@ -209,6 +215,7 @@ private:
android::Mutex m_texturesLock;
android::Mutex m_generatorLock;
+ android::Mutex m_imagesLock;
android::Condition m_generatorReadyCond;
static TilesManager* gInstance;
@@ -221,6 +228,8 @@ private:
TilesProfiler m_profiler;
TilesTracker m_tilesTracker;
unsigned long long m_drawGLCount;
+
+ HashMap<SkBitmapRef*, ImageTexture*> m_images;
};
} // namespace WebCore