diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/android/CanvasTexture.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/android/CanvasTexture.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
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) |