summaryrefslogtreecommitdiffstats
path: root/Source/WebCore
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2012-03-14 21:06:41 -0700
committerJohn Reck <jreck@google.com>2012-03-20 09:56:23 -0700
commita144ac64329978c258faadf3bc484cf4ae6c5d0d (patch)
treeebc3fdbea6ac1561330d4a94e67305aae495c6b7 /Source/WebCore
parent640bfa989e82aad4ff79ff786f31a6962c37d8fd (diff)
downloadexternal_webkit-a144ac64329978c258faadf3bc484cf4ae6c5d0d.zip
external_webkit-a144ac64329978c258faadf3bc484cf4ae6c5d0d.tar.gz
external_webkit-a144ac64329978c258faadf3bc484cf4ae6c5d0d.tar.bz2
Canvas on a texture
Change-Id: I841b3e021298738c91701068992798a55290a520
Diffstat (limited to 'Source/WebCore')
-rw-r--r--Source/WebCore/Android.mk2
-rw-r--r--Source/WebCore/html/HTMLCanvasElement.cpp6
-rw-r--r--Source/WebCore/html/HTMLCanvasElement.h4
-rw-r--r--Source/WebCore/platform/graphics/android/CanvasLayer.cpp188
-rw-r--r--Source/WebCore/platform/graphics/android/CanvasLayer.h81
-rw-r--r--Source/WebCore/platform/graphics/android/CanvasTexture.cpp214
-rw-r--r--Source/WebCore/platform/graphics/android/CanvasTexture.h96
-rw-r--r--Source/WebCore/platform/graphics/android/GLUtils.cpp37
-rw-r--r--Source/WebCore/platform/graphics/android/GLUtils.h3
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp7
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp10
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h11
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp27
13 files changed, 653 insertions, 33 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 816b163..710408f 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -639,6 +639,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/BaseTile.cpp \
platform/graphics/android/BaseTileTexture.cpp \
platform/graphics/android/BitmapAllocatorAndroid.cpp \
+ platform/graphics/android/CanvasLayer.cpp \
+ platform/graphics/android/CanvasTexture.cpp \
platform/graphics/android/ClassTracker.cpp \
platform/graphics/android/DumpLayer.cpp \
platform/graphics/android/FixedPositioning.cpp \
diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp
index 9f51f10..e67cbf9 100644
--- a/Source/WebCore/html/HTMLCanvasElement.cpp
+++ b/Source/WebCore/html/HTMLCanvasElement.cpp
@@ -45,6 +45,7 @@
#include "MIMETypeRegistry.h"
#include "Page.h"
#include "RenderHTMLCanvas.h"
+#include "RenderLayer.h"
#include "Settings.h"
#include <math.h>
#include <stdio.h>
@@ -225,6 +226,11 @@ void HTMLCanvasElement::didDraw(const FloatRect& rect)
return;
m_dirtyRect.unite(r);
+#if PLATFORM(ANDROID)
+ // We handle invals ourselves and don't want webkit to repaint if we
+ // have put the canvas on a layer
+ if (!ro->hasLayer())
+#endif
ro->repaintRectangle(enclosingIntRect(m_dirtyRect));
}
diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h
index 207c384..e485835 100644
--- a/Source/WebCore/html/HTMLCanvasElement.h
+++ b/Source/WebCore/html/HTMLCanvasElement.h
@@ -128,6 +128,10 @@ public:
void makeRenderingResultsAvailable();
+#if PLATFORM(ANDROID)
+ void clearDirtyRect() { m_dirtyRect = FloatRect(); }
+#endif
+
private:
HTMLCanvasElement(const QualifiedName&, Document*);
diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp
new file mode 100644
index 0000000..98cd5ee
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2012, 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.
+ */
+
+#define LOG_TAG "CanvasLayer"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "CanvasLayer.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "AndroidLog.h"
+#include "CanvasTexture.h"
+#include "Image.h"
+#include "ImageBuffer.h"
+#include "RenderLayerCompositor.h"
+#include "SkBitmap.h"
+#include "SkBitmapRef.h"
+#include "SkCanvas.h"
+#include "TilesManager.h"
+
+namespace WebCore {
+
+CanvasLayer::CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas)
+ : LayerAndroid(owner)
+ , m_canvas(canvas)
+ , m_dirtyCanvas()
+ , m_bitmap(0)
+{
+ init();
+ m_canvas->addObserver(this);
+}
+
+CanvasLayer::CanvasLayer(const CanvasLayer& layer)
+ : LayerAndroid(layer)
+ , m_canvas(0)
+ , m_bitmap(0)
+{
+ init();
+ // We are making a copy for the UI, sync the interesting bits
+ m_contentRect = layer.contentRect();
+ m_offsetFromRenderer = layer.offsetFromRenderer();
+ m_texture->setSize(m_contentRect.size());
+ bool previousState = m_texture->hasValidTexture();
+ // Attempt to upload to a surface texture
+ if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) {
+ // Blargh, no surface texture - fall back to software
+ m_bitmap = layer.bitmap();
+ SkSafeRef(m_bitmap);
+ // Merge the canvas invals with the layer's invals to repaint the needed
+ // tiles.
+ SkRegion::Iterator iter(layer.m_dirtyCanvas);
+ const IntPoint& offset = m_contentRect.location();
+ for (; !iter.done(); iter.next()) {
+ SkIRect diff = iter.rect();
+ diff.fLeft += offset.x();
+ diff.fRight += offset.x();
+ diff.fTop += offset.y();
+ diff.fBottom += offset.y();
+ m_dirtyRegion.op(diff, SkRegion::kUnion_Op);
+ }
+ }
+ if (previousState != m_texture->hasValidTexture()) {
+ // Need to do a full inval of the canvas content as we are mode switching
+ m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(),
+ m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op);
+ }
+}
+
+CanvasLayer::~CanvasLayer()
+{
+ if (m_canvas)
+ m_canvas->removeObserver(this);
+ SkSafeUnref(m_bitmap);
+}
+
+void CanvasLayer::init()
+{
+ m_texture = CanvasTexture::getCanvasTexture(this);
+}
+
+void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect)
+{
+ SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(),
+ changedRect.width(), changedRect.height());
+ m_dirtyCanvas.op(irect, SkRegion::kUnion_Op);
+ owningLayer()->compositor()->scheduleLayerFlush();
+}
+
+void CanvasLayer::canvasResized(HTMLCanvasElement*)
+{
+ const IntSize& size = m_canvas->size();
+ SkIRect irect = SkIRect::MakeWH(size.width(), size.height());
+ m_dirtyCanvas.op(irect, SkRegion::kUnion_Op);
+}
+
+void CanvasLayer::canvasDestroyed(HTMLCanvasElement*)
+{
+}
+
+void CanvasLayer::clearDirtyRegion()
+{
+ LayerAndroid::clearDirtyRegion();
+ m_dirtyCanvas.setEmpty();
+ if (m_canvas)
+ m_canvas->clearDirtyRect();
+}
+
+SkBitmapRef* CanvasLayer::bitmap() const
+{
+ if (!m_canvas)
+ return 0;
+ return m_canvas->copiedImage()->nativeImageForCurrentFrame();
+}
+
+IntRect CanvasLayer::contentRect() const
+{
+ return m_canvas->renderBox()->contentBoxRect();
+}
+
+IntSize CanvasLayer::offsetFromRenderer() const
+{
+ return m_canvas->renderBox()->layer()->backing()->graphicsLayer()->offsetFromRenderer();
+}
+
+bool CanvasLayer::needsTexture()
+{
+ return m_bitmap || LayerAndroid::needsTexture();
+}
+
+void CanvasLayer::contentDraw(SkCanvas* canvas, PaintStyle style)
+{
+ LayerAndroid::contentDraw(canvas, style);
+ if (!m_bitmap)
+ return;
+ SkBitmap& bitmap = m_bitmap->bitmap();
+ SkRect dst = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(),
+ m_contentRect.y() - m_offsetFromRenderer.height(),
+ m_contentRect.width(), m_contentRect.height());
+ canvas->drawBitmapRect(bitmap, 0, dst, 0);
+}
+
+bool CanvasLayer::drawGL(bool layerTilesDisabled)
+{
+ bool ret = LayerAndroid::drawGL(layerTilesDisabled);
+ m_texture->requireTexture();
+ if (!m_bitmap && m_texture->updateTexImage()) {
+ SkRect rect = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(),
+ m_contentRect.y() - m_offsetFromRenderer.height(),
+ m_contentRect.width(), m_contentRect.height());
+ TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
+ m_texture->texture(), 1, true, GL_TEXTURE_EXTERNAL_OES);
+ }
+ return ret;
+}
+
+LayerAndroid::InvalidateFlags CanvasLayer::onSetHwAccelerated(bool hwAccelerated)
+{
+ if (m_texture->setHwAccelerated(hwAccelerated))
+ return LayerAndroid::InvalidateLayers;
+ return LayerAndroid::InvalidateNone;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.h b/Source/WebCore/platform/graphics/android/CanvasLayer.h
new file mode 100644
index 0000000..532dbf2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/CanvasLayer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012, 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 CanvasLayer_h
+#define CanvasLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "HTMLCanvasElement.h"
+#include "ImageData.h"
+#include "LayerAndroid.h"
+#include "RenderLayer.h"
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CanvasTexture;
+
+class CanvasLayer : public LayerAndroid, private CanvasObserver {
+public:
+ CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas);
+ CanvasLayer(const CanvasLayer& layer);
+ virtual ~CanvasLayer();
+
+ virtual LayerAndroid* copy() const { return new CanvasLayer(*this); }
+ virtual SubclassType subclassType() { return LayerAndroid::CanvasLayer; }
+ virtual void clearDirtyRegion();
+
+ virtual bool drawGL(bool layerTilesDisabled);
+ virtual void contentDraw(SkCanvas* canvas, PaintStyle style);
+ virtual bool needsTexture();
+
+protected:
+ virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated);
+
+private:
+ virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect);
+ virtual void canvasResized(HTMLCanvasElement*);
+ virtual void canvasDestroyed(HTMLCanvasElement*);
+
+ void init();
+ SkBitmapRef* bitmap() const;
+ IntRect contentRect() const;
+ IntSize offsetFromRenderer() const;
+
+ HTMLCanvasElement* m_canvas;
+ IntRect m_contentRect;
+ IntSize m_offsetFromRenderer;
+ SkRegion m_dirtyCanvas;
+ SkBitmapRef* m_bitmap;
+ RefPtr<CanvasTexture> m_texture;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // CanvasLayer_h
diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp
new file mode 100644
index 0000000..90a4798
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2012, 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.
+ */
+
+#define LOG_TAG "CanvasTexture"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "CanvasTexture.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "android_graphics.h"
+#include "AndroidLog.h"
+#include "GLUtils.h"
+#include "Image.h"
+#include "ImageBuffer.h"
+#include "SkBitmap.h"
+#include "SkBitmapRef.h"
+#include "SkDevice.h"
+#include "SkPixelRef.h"
+
+#include <android/native_window.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+namespace WebCore {
+
+static int s_maxTextureSize = 0;
+static HashMap<int, CanvasTexture*> s_textures;
+static android::Mutex s_texturesLock;
+
+/********************************************
+ * Called by both threads
+ ********************************************/
+
+PassRefPtr<CanvasTexture> CanvasTexture::getCanvasTexture(CanvasLayer* layer)
+{
+ android::Mutex::Autolock lock(s_texturesLock);
+ RefPtr<CanvasTexture> texture = s_textures.get(layer->uniqueId());
+ if (texture.get())
+ return texture.release();
+ return adoptRef(new CanvasTexture(layer->uniqueId()));
+}
+
+/********************************************
+ * Called by WebKit thread
+ ********************************************/
+
+void CanvasTexture::setSize(const IntSize& size)
+{
+ android::Mutex::Autolock lock(m_surfaceLock);
+ if (m_size == size)
+ return;
+ m_size = size;
+ if (m_ANW.get()) {
+ if (!useSurfaceTexture()) {
+ m_ANW.clear();
+ m_surfaceTexture->abandon();
+ m_surfaceTexture.clear();
+ } else {
+ int result = native_window_set_buffers_dimensions(m_ANW.get(),
+ m_size.width(), m_size.height());
+ GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result);
+ }
+ }
+}
+
+SurfaceTextureClient* CanvasTexture::nativeWindow()
+{
+ android::Mutex::Autolock lock(m_surfaceLock);
+ if (m_ANW.get())
+ return m_ANW.get();
+ if (!m_texture)
+ return 0;
+ if (!useSurfaceTexture())
+ return 0;
+ m_surfaceTexture = new android::SurfaceTexture(m_texture, false);
+ m_ANW = new android::SurfaceTextureClient(m_surfaceTexture);
+ int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888);
+ GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result);
+ result = native_window_set_buffers_dimensions(m_ANW.get(),
+ m_size.width(), m_size.height());
+ GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result);
+ return m_ANW.get();
+}
+
+bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer)
+{
+ m_hasValidTexture = false;
+ SurfaceTextureClient* anw = nativeWindow();
+ if (!anw)
+ return false;
+ GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0;
+ if (!gc)
+ return false;
+ const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false);
+ GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap);
+ m_hasValidTexture = true;
+ return true;
+}
+
+/********************************************
+ * Called by UI thread WITH GL context
+ ********************************************/
+
+CanvasTexture::~CanvasTexture()
+{
+ if (m_layerId) {
+ s_texturesLock.lock();
+ s_textures.remove(m_layerId);
+ s_texturesLock.unlock();
+ }
+ if (m_texture)
+ GLUtils::deleteTexture(&m_texture);
+}
+
+void CanvasTexture::requireTexture()
+{
+ android::Mutex::Autolock lock(m_surfaceLock);
+ if (!m_texture)
+ glGenTextures(1, &m_texture);
+ if (!s_maxTextureSize)
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_maxTextureSize);
+}
+
+bool CanvasTexture::updateTexImage()
+{
+ android::Mutex::Autolock lock(m_surfaceLock);
+ if (!m_surfaceTexture.get())
+ return false;
+ status_t result = m_surfaceTexture->updateTexImage();
+ if (result != OK) {
+ ALOGE("unexpected error: updateTexImage return %d", result);
+ return false;
+ }
+ return true;
+}
+
+/********************************************
+ * Called by UI thread (with or without GL context)
+ ********************************************/
+
+void CanvasTexture::destroySurfaceTexture()
+{
+ if (m_ANW.get()) {
+ m_ANW.clear();
+ m_surfaceTexture->abandon();
+ m_surfaceTexture.clear();
+ }
+}
+
+bool CanvasTexture::setHwAccelerated(bool hwAccelerated)
+{
+ android::Mutex::Autolock lock(m_surfaceLock);
+ if (m_useHwAcceleration == hwAccelerated)
+ return false;
+ m_useHwAcceleration = hwAccelerated;
+ if (!m_ANW.get())
+ return false;
+ destroySurfaceTexture();
+ return true;
+}
+
+/********************************************
+ * Called by WebKit thread
+ ********************************************/
+
+CanvasTexture::CanvasTexture(int layerId)
+ : m_size()
+ , m_layerId(layerId)
+ , m_texture(0)
+ , m_surfaceTexture(0)
+ , m_ANW(0)
+ , m_hasValidTexture(false)
+ , m_useHwAcceleration(true)
+{
+ s_textures.add(m_layerId, this);
+}
+
+// TODO: Have a global limit as well as a way to react to low memory situations
+bool CanvasTexture::useSurfaceTexture()
+{
+ if (!m_useHwAcceleration)
+ return false;
+ if (m_size.isEmpty())
+ return false;
+ return (m_size.width() < s_maxTextureSize) && (m_size.height() < s_maxTextureSize);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.h b/Source/WebCore/platform/graphics/android/CanvasTexture.h
new file mode 100644
index 0000000..5e54c77
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/CanvasTexture.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012, 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 CanvasTexture_h
+#define CanvasTexture_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayer.h"
+
+#include <wtf/RefPtr.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+class SurfaceTexture;
+class SurfaceTextureClient;
+}
+
+namespace WebCore {
+
+class CanvasTexture : public ThreadSafeRefCounted<CanvasTexture> {
+
+public:
+ /********************************************
+ * Called by both threads
+ ********************************************/
+ static PassRefPtr<CanvasTexture> getCanvasTexture(CanvasLayer* layer);
+
+ /********************************************
+ * Called by WebKit thread
+ ********************************************/
+ void setSize(const IntSize& size);
+ SurfaceTextureClient* nativeWindow();
+ bool uploadImageBuffer(ImageBuffer* imageBuffer);
+ bool hasValidTexture() { return m_hasValidTexture; }
+
+ /********************************************
+ * Called by UI thread WITH GL context
+ ********************************************/
+ virtual ~CanvasTexture();
+ void requireTexture();
+ GLuint texture() { requireTexture(); return m_texture; }
+ bool updateTexImage();
+
+ /********************************************
+ * Called by UI thread (with or without GL context)
+ ********************************************/
+ void destroySurfaceTexture();
+ bool setHwAccelerated(bool hwAccelerated);
+
+private:
+ /********************************************
+ * Called by WebKit thread
+ ********************************************/
+ CanvasTexture(int layerId);
+ bool useSurfaceTexture();
+
+ IntSize m_size;
+ int m_layerId;
+ GLuint m_texture;
+ android::Mutex m_surfaceLock;
+ sp<android::SurfaceTexture> m_surfaceTexture;
+ sp<android::SurfaceTextureClient> m_ANW;
+ bool m_hasValidTexture;
+ bool m_useHwAcceleration;
+
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // CanvasTexture_h
diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp
index ecd6bce..55d986f 100644
--- a/Source/WebCore/platform/graphics/android/GLUtils.cpp
+++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp
@@ -493,14 +493,14 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
return;
if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height))
- GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap);
+ GLUtils::updateQueueWithBitmap(renderInfo, bitmap);
else {
if (!requiredSize.equals(bitmap.width(), bitmap.height())) {
ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)",
bitmap.width(), bitmap.height(),
requiredSize.width(), requiredSize.height());
}
- GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap);
+ GLUtils::updateQueueWithBitmap(renderInfo, bitmap);
textureInfo->m_width = bitmap.width();
textureInfo->m_height = bitmap.height();
@@ -508,7 +508,7 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
}
}
-void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap)
+void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap)
{
if (!renderInfo
|| !renderInfo->textureInfo
@@ -518,6 +518,37 @@ void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderI
TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap);
}
+bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap)
+{
+ SkAutoLockPixels alp(bitmap);
+ if (!bitmap.getPixels())
+ return false;
+ ANativeWindow_Buffer buffer;
+ if (ANativeWindow_lock(anw, &buffer, 0))
+ return false;
+ if (buffer.width < bitmap.width() || buffer.height < bitmap.height())
+ return false;
+ uint8_t* img = (uint8_t*)buffer.bits;
+ int row;
+ int bpp = 4; // Now we only deal with RGBA8888 format.
+ bitmap.lockPixels();
+ uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
+
+ if (buffer.stride != bitmap.width())
+ // Copied line by line since we need to handle the offsets and stride.
+ for (row = 0 ; row < bitmap.height(); row ++) {
+ uint8_t* dst = &(img[buffer.stride * row * bpp]);
+ uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
+ memcpy(dst, src, bpp * bitmap.width());
+ }
+ else
+ memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height());
+
+ bitmap.unlockPixels();
+ ANativeWindow_unlockAndPost(anw);
+ return true;
+}
+
void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h
index e001aee..966f674 100644
--- a/Source/WebCore/platform/graphics/android/GLUtils.h
+++ b/Source/WebCore/platform/graphics/android/GLUtils.h
@@ -79,7 +79,8 @@ public:
static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR);
static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap);
- static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap);
+ static void updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap);
+ static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap);
static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix);
static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor);
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 2f9b379..fa620e0 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -25,6 +25,7 @@
#include "AndroidAnimation.h"
#include "AndroidLog.h"
#include "Animation.h"
+#include "CanvasLayer.h"
#include "FloatRect.h"
#include "FixedPositioning.h"
#include "GraphicsContext.h"
@@ -119,7 +120,11 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
m_foregroundClipLayer(0)
{
RenderLayer* renderLayer = renderLayerFromClient(m_client);
- m_contentLayer = new LayerAndroid(renderLayer);
+ if (renderLayer && renderLayer->renderer()->isCanvas()) {
+ m_contentLayer = new CanvasLayer(renderLayer,
+ static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node()));
+ } else
+ m_contentLayer = new LayerAndroid(renderLayer);
m_dirtyRegion.setEmpty();
gDebugGraphicsLayerAndroidInstances++;
}
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index 946d2a3..6d8dc34 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -791,6 +791,16 @@ void LayerAndroid::clearDirtyRegion()
m_dirtyRegion.setEmpty();
}
+int LayerAndroid::setHwAccelerated(bool hwAccelerated)
+{
+ int flags = InvalidateNone;
+ int count = this->countChildren();
+ for (int i = 0; i < count; i++)
+ flags |= this->getChild(i)->setHwAccelerated(hwAccelerated);
+
+ return flags | onSetHwAccelerated(hwAccelerated);
+}
+
IntRect LayerAndroid::unclippedArea()
{
IntRect area;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 7436676..43b4ff9 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -93,7 +93,9 @@ class TEST_EXPORT LayerAndroid : public Layer {
public:
typedef enum { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer } LayerType;
typedef enum { StandardLayer, ScrollableLayer,
- IFrameLayer, IFrameContentLayer } SubclassType;
+ IFrameLayer, IFrameContentLayer,
+ CanvasLayer } SubclassType;
+ typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags;
String subclassName()
{
@@ -106,6 +108,8 @@ public:
return "IFrameLayer";
case LayerAndroid::IFrameContentLayer:
return "IFrameContentLayer";
+ case LayerAndroid::CanvasLayer:
+ return "CanvasLayer";
}
return "Undefined";
}
@@ -230,7 +234,7 @@ public:
virtual LayerAndroid* copy() const { return new LayerAndroid(*this); }
- void clearDirtyRegion();
+ virtual void clearDirtyRegion();
virtual void contentDraw(SkCanvas* canvas, PaintStyle style);
@@ -277,8 +281,11 @@ public:
void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; }
+ int setHwAccelerated(bool hwAccelerated);
+
protected:
virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style);
+ virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; }
IntPoint m_offset;
TransformationMatrix m_drawTransform;
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
index ac45112..8e41d15 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -463,33 +463,8 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
return false;
}
- ANativeWindow_Buffer buffer;
- if (ANativeWindow_lock(m_ANW.get(), &buffer, 0))
+ if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap))
return false;
-
- uint8_t* img = (uint8_t*)buffer.bits;
- int row;
- int bpp = 4; // Now we only deal with RGBA8888 format.
- int width = TilesManager::instance()->tileWidth();
- int height = TilesManager::instance()->tileHeight();
- if (bitmap.width() == width && bitmap.height() == height) {
- bitmap.lockPixels();
- uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
-
- if (buffer.stride != bitmap.width())
- // Copied line by line since we need to handle the offsets and stride.
- for (row = 0 ; row < bitmap.height(); row ++) {
- uint8_t* dst = &(img[buffer.stride * row * bpp]);
- uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
- memcpy(dst, src, bpp * bitmap.width());
- }
- else
- memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height());
-
- bitmap.unlockPixels();
- }
-
- ANativeWindow_unlockAndPost(m_ANW.get());
}
// b) After update the Surface Texture, now udpate the transfer queue info.