summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp')
-rw-r--r--Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
new file mode 100644
index 0000000..e4b2bc6
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
@@ -0,0 +1,225 @@
+/*
+ * 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()));
+}
+
+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;
+ destroySurfaceTextureLocked();
+ return true;
+}
+
+/********************************************
+ * 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()) {
+ int result = native_window_set_buffers_dimensions(m_ANW.get(),
+ m_size.width(), m_size.height());
+ GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result);
+ if (result != NO_ERROR)
+ m_useHwAcceleration = false; // On error, drop out of HWA
+ }
+ if (!useSurfaceTexture())
+ destroySurfaceTextureLocked();
+ }
+}
+
+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);
+ if (result == NO_ERROR) {
+ result = native_window_set_buffers_dimensions(m_ANW.get(),
+ m_size.width(), m_size.height());
+ GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result);
+ }
+ if (result != NO_ERROR) {
+ m_useHwAcceleration = false;
+ destroySurfaceTextureLocked();
+ return 0;
+ }
+ return m_ANW.get();
+}
+
+bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer)
+{
+ m_hasValidTexture = false;
+ SurfaceTextureClient* anw = nativeWindow();
+ if (!anw)
+ return false;
+ // Size mismatch, early abort (will fall back to software)
+ if (imageBuffer->size() != m_size)
+ return false;
+ GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0;
+ if (!gc)
+ return false;
+ const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false);
+ if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap))
+ return false;
+ 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 both threads
+ ********************************************/
+
+void CanvasTexture::destroySurfaceTextureLocked()
+{
+ if (m_ANW.get()) {
+ m_ANW.clear();
+ m_surfaceTexture->abandon();
+ m_surfaceTexture.clear();
+ }
+}
+
+/********************************************
+ * 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)