From a5ffb7c279df240a07658953e1bd5df6d0480cb6 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Mon, 4 Oct 2010 13:37:38 -0700 Subject: GL rendering (without layers) This is a two-parts CL, Its counterpart is https://android-git.corp.google.com/g/#change,64863 Change-Id: I40fcf3b7b6d28b887b101219c973070aeefbb777 --- Android.mk | 7 +- CleanSpec.mk | 1 + WebCore/Android.mk | 12 + WebCore/config.h | 1 - .../android/BackedDoubleBufferedTexture.cpp | 164 +++++++++++++ .../graphics/android/BackedDoubleBufferedTexture.h | 120 ++++++++++ .../platform/graphics/android/BaseLayerAndroid.cpp | 214 +++++++++++++++++ .../platform/graphics/android/BaseLayerAndroid.h | 29 ++- WebCore/platform/graphics/android/BaseTile.cpp | 229 ++++++++++++++++++ WebCore/platform/graphics/android/BaseTile.h | 83 +++++++ .../graphics/android/DoubleBufferedTexture.cpp | 45 ++-- .../graphics/android/DoubleBufferedTexture.h | 31 ++- .../platform/graphics/android/GLWebViewState.cpp | 219 ++++++++++++++++++ WebCore/platform/graphics/android/GLWebViewState.h | 218 +++++++++++++++++ .../graphics/android/TexturesGenerator.cpp | 118 ++++++++++ .../platform/graphics/android/TexturesGenerator.h | 57 +++++ WebCore/platform/graphics/android/TiledPage.cpp | 257 +++++++++++++++++++++ WebCore/platform/graphics/android/TiledPage.h | 64 +++++ WebCore/platform/graphics/android/TilesManager.cpp | 254 ++++++++++++++++++++ WebCore/platform/graphics/android/TilesManager.h | 97 ++++++++ WebCore/platform/graphics/android/TilesSet.cpp | 104 +++++++++ WebCore/platform/graphics/android/TilesSet.h | 76 ++++++ WebKit/android/nav/WebView.cpp | 76 +++++- 23 files changed, 2428 insertions(+), 48 deletions(-) create mode 100644 WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp create mode 100644 WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h create mode 100644 WebCore/platform/graphics/android/BaseLayerAndroid.cpp create mode 100644 WebCore/platform/graphics/android/BaseTile.cpp create mode 100644 WebCore/platform/graphics/android/BaseTile.h create mode 100644 WebCore/platform/graphics/android/GLWebViewState.cpp create mode 100644 WebCore/platform/graphics/android/GLWebViewState.h create mode 100644 WebCore/platform/graphics/android/TexturesGenerator.cpp create mode 100644 WebCore/platform/graphics/android/TexturesGenerator.h create mode 100644 WebCore/platform/graphics/android/TiledPage.cpp create mode 100644 WebCore/platform/graphics/android/TiledPage.h create mode 100644 WebCore/platform/graphics/android/TilesManager.cpp create mode 100644 WebCore/platform/graphics/android/TilesManager.h create mode 100644 WebCore/platform/graphics/android/TilesSet.cpp create mode 100644 WebCore/platform/graphics/android/TilesSet.h diff --git a/Android.mk b/Android.mk index d0a1813..074e087 100644 --- a/Android.mk +++ b/Android.mk @@ -292,6 +292,9 @@ LOCAL_CFLAGS += -DGOOGLEURL LOCAL_CFLAGS += -DWTF_USE_CHROME_NETWORK_STACK endif # HTTP_STACK == chrome +# Adds GL and EGL extensions for the GL backend +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + # Enable JSC JIT if JSC is used and ENABLE_JSC_JIT environment # variable is set to true ifeq ($(JAVASCRIPT_ENGINE),jsc) @@ -344,7 +347,9 @@ LOCAL_SHARED_LIBRARIES := \ libicuuc \ libicui18n \ libmedia \ - libsurfaceflinger_client + libsurfaceflinger_client \ + libEGL \ + libGLESv2 ifeq ($(WEBCORE_INSTRUMENTATION),true) LOCAL_SHARED_LIBRARIES += libhardware_legacy diff --git a/CleanSpec.mk b/CleanSpec.mk index 587af0f..e35aa64 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -66,6 +66,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_int $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates) # ************************************************ diff --git a/WebCore/Android.mk b/WebCore/Android.mk index a7c3754..9f84b10 100644 --- a/WebCore/Android.mk +++ b/WebCore/Android.mk @@ -556,12 +556,18 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/WidthIterator.cpp \ \ platform/graphics/android/AndroidAnimation.cpp \ + platform/graphics/android/BackedDoubleBufferedTexture.cpp \ + platform/graphics/android/BaseLayerAndroid.cpp \ + platform/graphics/android/BaseTile.cpp \ platform/graphics/android/BitmapAllocatorAndroid.cpp \ + platform/graphics/android/DoubleBufferedTexture.cpp \ platform/graphics/android/FontAndroid.cpp \ platform/graphics/android/FontCacheAndroid.cpp \ platform/graphics/android/FontCustomPlatformData.cpp \ platform/graphics/android/FontDataAndroid.cpp \ platform/graphics/android/FontPlatformDataAndroid.cpp \ + platform/graphics/android/GLUtils.cpp \ + platform/graphics/android/GLWebViewState.cpp \ platform/graphics/android/GlyphMapAndroid.cpp \ platform/graphics/android/GradientAndroid.cpp \ platform/graphics/android/GraphicsContextAndroid.cpp \ @@ -574,6 +580,12 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/PatternAndroid.cpp \ platform/graphics/android/PlatformGraphicsContext.cpp \ platform/graphics/android/SharedBufferStream.cpp \ + platform/graphics/android/ShaderProgram.cpp \ + platform/graphics/android/SharedTexture.cpp \ + platform/graphics/android/TexturesGenerator.cpp \ + platform/graphics/android/TilesManager.cpp \ + platform/graphics/android/TiledPage.cpp \ + platform/graphics/android/TilesSet.cpp \ platform/graphics/android/android_graphics.cpp \ ifeq ($(ENABLE_SVG), true) diff --git a/WebCore/config.h b/WebCore/config.h index b259f9e..70f8a20 100644 --- a/WebCore/config.h +++ b/WebCore/config.h @@ -99,7 +99,6 @@ #ifndef ENABLE_SVG #define ENABLE_SVG 0 #endif -#define ENABLE_3D_RENDERING 0 #define ENABLE_VIDEO 1 #if ENABLE_SVG diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp new file mode 100644 index 0000000..448be78 --- /dev/null +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2010, 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 "BackedDoubleBufferedTexture.h" + +#include "BaseTile.h" +#include "GLUtils.h" + +#define LOG_NDEBUG 1 +#define LOG_TAG "BackedDoubleBufferedTexture.cpp" +#include + +namespace WebCore { + +BackedDoubleBufferedTexture::BackedDoubleBufferedTexture(uint32_t w, uint32_t h, + SkBitmap::Config config) + : DoubleBufferedTexture(eglGetCurrentContext()), + m_canvas(0), + m_width(0), + m_height(0), + m_usedLevel(-1), + m_owner(0), + m_painter(0), + m_busy(false) +{ + setBitmap(w, h, config); +} + +BackedDoubleBufferedTexture::~BackedDoubleBufferedTexture() +{ + m_bitmap.reset(); + delete m_canvas; +} + +void BackedDoubleBufferedTexture::setBitmap(uint32_t w, uint32_t h, SkBitmap::Config config) +{ + if ((m_width == w) && (m_height == h)) + return; + m_width = w; + m_height = h; + m_bitmap.reset(); + m_bitmap.setConfig(config, m_width, m_height); + m_bitmap.allocPixels(); + m_bitmap.eraseColor(0); + m_bitmap.eraseARGB(255, 255, 0, 0); + delete m_canvas; + m_canvas = new SkCanvas(m_bitmap); +} + +void BackedDoubleBufferedTexture::update(TextureInfo* textureInfo, PaintingInfo& info) +{ + if (!m_width && !m_height) + return; + + if (textureInfo && textureInfo->m_textureId) { + if (textureInfo->m_width && textureInfo->m_height + && (m_width != textureInfo->m_width) + && (m_height != textureInfo->m_height)) { + GLUtils::deleteTexture(&textureInfo->m_textureId); + glGenTextures(1, &textureInfo->m_textureId); + textureInfo->m_width = 0; + textureInfo->m_height = 0; + } + + if (!textureInfo->m_width && !textureInfo->m_height) + GLUtils::createTextureWithBitmap(textureInfo->m_textureId, m_bitmap); + else + GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, m_bitmap); + + if ((m_width != textureInfo->m_width) + && (m_height != textureInfo->m_height)) { + textureInfo->m_width = m_width; + textureInfo->m_height = m_height; + } + } + m_varLock.lock(); + if (textureInfo->m_textureId == m_textureA.getSourceTextureId()) + m_paintingInfoA = info; + if (textureInfo->m_textureId == m_textureB.getSourceTextureId()) + m_paintingInfoB = info; + m_varLock.unlock(); +} + +// Compare the current texture displayed with some PaintingInfo. +bool BackedDoubleBufferedTexture::consumerTextureUpToDate(PaintingInfo& info) +{ + android::Mutex::Autolock lock(m_varLock); + if (getReadableTexture() == &m_textureA) + return info == m_paintingInfoA; + return info == m_paintingInfoB; +} + +bool BackedDoubleBufferedTexture::consumerTextureSimilar(PaintingInfo& info) +{ + android::Mutex::Autolock lock(m_varLock); + if (getReadableTexture() == &m_textureA) + return info.similar(m_paintingInfoA); + return info.similar(m_paintingInfoB); +} + +void BackedDoubleBufferedTexture::setOwner(BaseTile* owner) +{ + android::Mutex::Autolock lock(m_varLock); + if (m_owner != owner) { + if (m_owner) + m_owner->removeTexture(); + m_owner = owner; + } +} + +bool BackedDoubleBufferedTexture::acquire(BaseTile* owner) +{ + android::Mutex::Autolock lock(m_varLock); + if (m_busy) + return false; + + if (m_owner != owner) { + if (m_owner) + m_owner->removeTexture(); + m_owner = owner; + } + return true; +} + +void BackedDoubleBufferedTexture::setPainter(BaseTile* painter) +{ + android::Mutex::Autolock lock(m_varLock); + m_painter = painter; +} + +bool BackedDoubleBufferedTexture::acquireForPainting() +{ + android::Mutex::Autolock lock(m_varLock); + if (!m_busy) { + m_busy = true; + return true; + } + return false; +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h new file mode 100644 index 0000000..d59cc52 --- /dev/null +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h @@ -0,0 +1,120 @@ +/* + * Copyright 2010, 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 BackedDoubleBufferedTexture_h +#define BackedDoubleBufferedTexture_h + +#include "DoubleBufferedTexture.h" +#include + +class SkCanvas; + +namespace WebCore { + +class BaseTile; +class GLWebViewState; + +class PaintingInfo { +public: + PaintingInfo() : m_x(-1), m_y(-1), m_webview(0), m_picture(0) { } + PaintingInfo(int x, int y, GLWebViewState* webview, unsigned int picture) + : m_x(x) + , m_y(y) + , m_webview(webview) + , m_picture(picture) + { + } + bool operator==(const PaintingInfo& info) + { + return m_webview == info.m_webview + && m_x == info.m_x + && m_y == info.m_y + && m_picture == info.m_picture; + } + bool similar(const PaintingInfo& info) + { + return m_webview == info.m_webview + && m_x == info.m_x + && m_y == info.m_y; + } + void setPosition(int x, int y) { m_x = x; m_y = y; } + void setGLWebViewState(GLWebViewState* webview) { m_webview = webview; } + void setPictureUsed(unsigned int picture) { m_picture = picture; } + +private: + int m_x; + int m_y; + GLWebViewState* m_webview; + unsigned int m_picture; +}; + +// DoubleBufferedTexture using a SkBitmap as backing mechanism +class BackedDoubleBufferedTexture : public DoubleBufferedTexture { +public: + // ctor called on consumer thread + BackedDoubleBufferedTexture(uint32_t w, uint32_t h, + SkBitmap::Config config = SkBitmap::kARGB_8888_Config); + virtual ~BackedDoubleBufferedTexture(); + + void setBitmap(uint32_t w, uint32_t h, SkBitmap::Config config = SkBitmap::kARGB_8888_Config); + void update(TextureInfo* textureInfo, PaintingInfo& info); + SkCanvas* canvas() { return m_canvas; } + + // Level can be -1 (unused texture), 0 (the 9 tiles intersecting with the + // viewport), then the distance between the viewport and the tile. + // we use this to prioritize which texture we want to pick (see + // TilesManager::getAvailableTexture()) + int usedLevel() { android::Mutex::Autolock lock(m_varLock); return m_usedLevel; } + void setUsedLevel(int used) { android::Mutex::Autolock lock(m_varLock); m_usedLevel = used; } + + BaseTile* owner() { android::Mutex::Autolock lock(m_varLock); return m_owner; } + void setOwner(BaseTile* owner); + BaseTile* painter() { return m_painter; } + void setPainter(BaseTile* painter); + bool busy() { android::Mutex::Autolock lock(m_varLock); return m_busy; } + void setBusy(bool value) { android::Mutex::Autolock lock(m_varLock); m_busy = value; } + uint32_t width() { return m_width; } + uint32_t height() { return m_height; } + bool consumerTextureUpToDate(PaintingInfo& info); + bool consumerTextureSimilar(PaintingInfo& info); + bool acquire(BaseTile* owner); + bool acquireForPainting(); + +private: + SkBitmap m_bitmap; + SkCanvas* m_canvas; + uint32_t m_width; + uint32_t m_height; + int m_usedLevel; + BaseTile* m_owner; + BaseTile* m_painter; + PaintingInfo m_paintingInfoA; + PaintingInfo m_paintingInfoB; + bool m_busy; +}; + +} // namespace WebCore + +#endif // BackedDoubleBufferedTexture_h diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp new file mode 100644 index 0000000..0bb2928 --- /dev/null +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -0,0 +1,214 @@ +/* + * Copyright 2010, 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 "BaseLayerAndroid.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "GLUtils.h" +#include "ShaderProgram.h" +#include "SkCanvas.h" +#include "TilesManager.h" +#include +#include +#endif // USE(ACCELERATED_COMPOSITING) + +#ifdef DEBUG + +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +using namespace android; + +#ifdef DEBUG_COUNT +static int gBaseLayerAndroidCount = 0; +int BaseLayerAndroid::count() +{ + return gBaseLayerAndroidCount; +} +#endif + +BaseLayerAndroid::BaseLayerAndroid() +{ +#ifdef DEBUG_COUNT + gBaseLayerAndroidCount++; +#endif +} + +BaseLayerAndroid::~BaseLayerAndroid() +{ + m_content.clear(); +#ifdef DEBUG_COUNT + gBaseLayerAndroidCount--; +#endif +} + +void BaseLayerAndroid::setContent(const PictureSet& src) +{ + m_content.set(src); +} + +#if USE(ACCELERATED_COMPOSITING) +bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale) +{ + if (m_content.isEmpty()) + return false; + if (!m_glWebViewState) + return false; + + double currentTime = WTF::currentTime(); + bool goingDown = m_previousVisible.fTop - viewport.fTop <= 0; + bool goingLeft = m_previousVisible.fLeft - viewport.fLeft >= 0; + + m_glWebViewState->setViewport(viewport, scale); + + int firstTileX = m_glWebViewState->firstTileX(); + int firstTileY = m_glWebViewState->firstTileY(); + + XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", firstTileX, firstTileY, scale); + if (scale == m_glWebViewState->currentScale()) { + m_glWebViewState->setOriginalTilesPosX(firstTileX); + m_glWebViewState->setOriginalTilesPosY(firstTileY); + } + + // If we have a different scale than the current one, we have to + // decide what to do. The current behaviour is to delay an update, + // so that we do not slow down zooming unnecessarily. + if (m_glWebViewState->currentScale() != scale + && (m_glWebViewState->scaleRequestState() == GLWebViewState::kNoScaleRequest + || m_glWebViewState->scaleRequestState() == GLWebViewState::kWillScheduleRequest + || m_glWebViewState->futureScale() != scale)) { + m_glWebViewState->scheduleUpdate(currentTime, scale); + } + + float transparency = 1; + bool doSwap = false; + + // Here we have to schedule the painting of the tiles corresponding + // to the new tiles for the new scale factor (see above) + if (m_glWebViewState->scaleRequestState() == GLWebViewState::kRequestNewScale + || m_glWebViewState->scaleRequestState() == GLWebViewState::kReceivedNewScale) { + TiledPage* nextTiledPage = m_glWebViewState->backPage(); + nextTiledPage->setScale(scale); + + // Check if the page is ready... + if (m_glWebViewState->scaleRequestState() == GLWebViewState::kRequestNewScale + && nextTiledPage->ready(firstTileX, firstTileY)) { + m_glWebViewState->setScaleRequestState(GLWebViewState::kReceivedNewScale); + } + + // If the page is ready, display it. We do a short transition between + // the two pages (current one and future one with the new scale factor) + if (m_glWebViewState->scaleRequestState() == GLWebViewState::kReceivedNewScale) { + double transitionTime = m_glWebViewState->transitionTime(currentTime); + transparency = m_glWebViewState->transparency(currentTime); + + float newTilesTransparency = 1; + if (scale < m_glWebViewState->currentScale()) + newTilesTransparency = 1 - transparency; + + nextTiledPage->draw(newTilesTransparency, viewport, + firstTileX, firstTileY); + + // The transition between the two pages is finished, swap them + if (currentTime > transitionTime) { + m_glWebViewState->setCurrentScale(scale); + m_glWebViewState->resetTransitionTime(); + doSwap = true; + } + } else { + // If the page is not ready, schedule it if needed. + nextTiledPage->prepare(goingDown, goingLeft, firstTileX, firstTileY); + } + } + + // Display the current page + TiledPage* tiledPage = m_glWebViewState->frontPage(); + tiledPage->setScale(m_glWebViewState->currentScale()); + int originalTX = m_glWebViewState->originalTilesPosX(); + int originalTY = m_glWebViewState->originalTilesPosY(); + tiledPage->prepare(goingDown, goingLeft, originalTX, originalTY); + tiledPage->draw(transparency, viewport, originalTX, originalTY); + + bool ret = false; + if (!tiledPage->ready(originalTX, originalTY) + || m_glWebViewState->scaleRequestState() != GLWebViewState::kNoScaleRequest) + ret = true; + + if (doSwap) + m_glWebViewState->swapPages(); + + return ret; +} +#endif // USE(ACCELERATED_COMPOSITING) + +bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, + float scale, SkColor color) +{ + bool ret = false; +#if USE(ACCELERATED_COMPOSITING) + int left = viewRect.x(); + int top = viewRect.y(); + int width = viewRect.width(); + int height = viewRect.height(); + XLOG("drawBasePicture drawGL() viewRect: %d, %d, %d, %d", + left, top, width, height); + + glEnable(GL_SCISSOR_TEST); + + glScissor(left, top, width, height); + glClearColor((float)SkColorGetR(color) / 255.0, + (float)SkColorGetG(color) / 255.0, + (float)SkColorGetB(color) / 255.0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(left, top, width, height); + ShaderProgram* shader = TilesManager::instance()->shader(); + glUseProgram(shader->program()); + glUniform1i(shader->textureSampler(), 0); + + ret = drawBasePictureInGL(visibleRect, scale); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + m_previousVisible = visibleRect; +#endif // USE(ACCELERATED_COMPOSITING) + return ret; +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.h b/WebCore/platform/graphics/android/BaseLayerAndroid.h index b9e2f4e..408549a 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.h @@ -23,9 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BASELAYERANDROID_H_ -#define BASELAYERANDROID_H_ +#ifndef BaseLayerAndroid_h +#define BaseLayerAndroid_h +#include "GLWebViewState.h" +#include "IntRect.h" #include "PictureSet.h" #include "SkLayer.h" @@ -34,16 +36,31 @@ namespace WebCore { class BaseLayerAndroid : public SkLayer { public: - BaseLayerAndroid() { } - virtual ~BaseLayerAndroid() { } +#ifdef DEBUG_COUNT + static int count(); +#endif + BaseLayerAndroid(); + virtual ~BaseLayerAndroid(); - void setContent(const android::PictureSet& src) { m_content.set(src); } +#if USE(ACCELERATED_COMPOSITING) + void setGLWebViewState(GLWebViewState* infos) { m_glWebViewState = infos; } +#endif + void setContent(const android::PictureSet& src); android::PictureSet* content() { return &m_content; } + bool drawGL(IntRect& rect, SkRect& viewport, + float scale, SkColor color = SK_ColorWHITE); + private: +#if USE(ACCELERATED_COMPOSITING) + bool drawBasePictureInGL(SkRect& viewport, float scale); + + GLWebViewState* m_glWebViewState; +#endif android::PictureSet m_content; + SkRect m_previousVisible; }; } // namespace WebCore -#endif /* BASELAYERANDROID_H_ */ +#endif // BaseLayerAndroid_h diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp new file mode 100644 index 0000000..6f20643 --- /dev/null +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -0,0 +1,229 @@ +/* + * Copyright 2010, 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 "BaseTile.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "GLUtils.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkCanvas.h" +#include "TilesManager.h" + +#include +#include +#include +#include + +#ifdef DEBUG + +#include +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +#ifdef DEBUG_COUNT +static int gBaseTextureCount = 0; +int BaseTile::count() +{ + return gBaseTextureCount; +} +#endif + +BaseTile::BaseTile(TiledPage* page, int x, int y, int quality) + : m_page(page) + , m_texture(0) + , m_x(x) + , m_y(y) + , m_quality(quality) + , m_scale(1) +{ +#ifdef DEBUG_COUNT + gBaseTextureCount++; +#endif +} + +BaseTile::~BaseTile() +{ + removeTexture(); + setUsedLevel(-1); +#ifdef DEBUG_COUNT + gBaseTextureCount--; +#endif +} + +void BaseTile::reserveTexture() +{ + android::Mutex::Autolock lock(m_varLock); + m_texture = TilesManager::instance()->getAvailableTexture(this); + XLOG("%x (%d, %d) reserveTexture res: %x...", this, x(), y(), m_texture); +} + +void BaseTile::removeTexture() +{ + android::Mutex::Autolock lock(m_varLock); + XLOG("%x removeTexture res: %x...", this, m_texture); + m_texture = 0; +} + +void BaseTile::setUsedLevel(int usedLevel) +{ + if (m_texture) + m_texture->setUsedLevel(usedLevel); +} + +// Called from the main GL thread +void BaseTile::draw(float transparency, SkRect& rect) +{ + m_varLock.lock(); + BackedDoubleBufferedTexture* texture = m_texture; + m_varLock.unlock(); + + if (!m_texture) { + XLOG("%x (%d, %d) trying to draw, but no m_texture!", this, x(), y()); + return; + } + + PaintingInfo info(m_x, m_y, m_page->glWebViewState(), + m_page->currentPictureCounter()); + + TextureInfo* textureInfo = texture->consumerLock(); + if (!textureInfo) { + XLOG("%x (%d, %d) trying to draw, but no textureInfo!", this, x(), y()); + texture->consumerRelease(); + return; + } + + if (texture->consumerTextureSimilar(info)) { + TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, + transparency); + } + + texture->consumerRelease(); +} + +bool BaseTile::isBitmapReady() +{ + if (!m_texture) + return false; + if (m_texture->owner() != this) + return false; + PaintingInfo info(m_x, m_y, m_page->glWebViewState(), + m_page->currentPictureCounter()); + return m_texture->consumerTextureUpToDate(info); +} + +// Called from the texture generation thread +bool BaseTile::paintBitmap() +{ + m_varLock.lock(); + BackedDoubleBufferedTexture* texture = m_texture; + bool available = false; + if (texture) + available = texture->acquireForPainting(); + m_varLock.unlock(); + + if (!texture || !available) + return false; + + // at this point we can safely check the ownership + // (if the texture got transferred to another BaseTile + // under us) + if (texture->owner() != this + || texture->usedLevel() > 1) { + texture->setBusy(false); + return false; + } + + int pictureUsed = m_page->currentPictureCounter(); + PaintingInfo info(m_x, m_y, m_page->glWebViewState(), pictureUsed); + if (texture->consumerTextureUpToDate(info)) { + texture->setBusy(false); + return true; + } + + TextureInfo* textureInfo = texture->producerLock(); + + if (!textureInfo) { + texture->setBusy(false); + return false; + } + + float tileWidth = textureInfo->m_width; + float tileHeight = textureInfo->m_height; + + float scale = m_scale / m_quality; + float invScale = 1 / scale; + + float w = tileWidth * invScale; + float h = tileHeight * invScale; + + SkCanvas* canvas = texture->canvas(); + + canvas->save(); + + canvas->scale(scale, scale); + canvas->translate(-m_x*w, -m_y*h); + + bool didPaint = m_page->paintBaseLayerContent(canvas); + + canvas->restore(); + +#ifdef DEBUG + SkPaint paint; + paint.setARGB(128, 255, 0, 0); + paint.setStrokeWidth(3); + canvas->drawLine(0, 0, tileWidth, tileHeight, paint); + paint.setARGB(128, 0, 255, 0); + canvas->drawLine(0, tileHeight, tileWidth, 0, paint); + paint.setARGB(128, 0, 0, 255); + canvas->drawLine(0, 0, tileWidth, 0, paint); + canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint); +#endif + + texture->update(textureInfo, info); + texture->setPainter(this); + texture->setBusy(false); + texture->producerRelease(); + + return didPaint; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h new file mode 100644 index 0000000..38f5b10 --- /dev/null +++ b/WebCore/platform/graphics/android/BaseTile.h @@ -0,0 +1,83 @@ +/* + * Copyright 2010, 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 BaseTile_h +#define BaseTile_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BackedDoubleBufferedTexture.h" +#include "HashMap.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkRect.h" + +#include +#include +#include + +namespace WebCore { + +class TiledPage; + +class BaseTile { +public: +#ifdef DEBUG_COUNT + static int count(); +#endif + BaseTile(TiledPage* page, int x, int y, int quality = 1); + ~BaseTile(); + + void reserveTexture(); + void removeTexture(); + void setUsedLevel(int); + bool paintBitmap(); + bool isBitmapReady(); + float scale() const { return m_scale; } + void setScale(float scale) { m_scale = scale; } + void draw(float transparency, SkRect& rect); + TiledPage* page() { return m_page; } + int quality() const { return m_quality; } + int x() const { return m_x; } + int y() const { return m_y; } + BackedDoubleBufferedTexture* texture() { return m_texture; } + +private: + TiledPage* m_page; + BackedDoubleBufferedTexture* m_texture; + int m_x; + int m_y; + int m_quality; + float m_scale; + android::Mutex m_varLock; +}; + +typedef std::pair TileKey; +typedef HashMap TileMap; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // BaseTile_h diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp index 7746603..7cd69d6 100644 --- a/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "DoubleBufferedTexture.h" + #include "GLUtils.h" #define LOG_NDEBUG 1 @@ -33,28 +34,31 @@ namespace WebCore { -DoubleBufferedTexture::DoubleBufferedTexture(EGLContext sharedContext) { - +DoubleBufferedTexture::DoubleBufferedTexture(EGLContext sharedContext) +{ // the mutex ensures that the variables are not used in any other thread // until the constructor has the opportunity to initialize them android::Mutex::Autolock lock(m_varLock); m_display = eglGetCurrentDisplay(); m_pContext = EGL_NO_CONTEXT; m_cContext = sharedContext; - m_frontTexture = GL_NO_TEXTURE; + m_writeableTexture = GL_NO_TEXTURE; m_lockedConsumerTexture = GL_NO_TEXTURE; m_supportsEGLImage = GLUtils::isEGLImageSupported(); } -SharedTexture* DoubleBufferedTexture::getFrontTexture() { - return (m_frontTexture == &m_textureA) ? &m_textureA : &m_textureB; +SharedTexture* DoubleBufferedTexture::getWriteableTexture() +{ + return (m_writeableTexture == &m_textureA) ? &m_textureA : &m_textureB; } -SharedTexture* DoubleBufferedTexture::getBackTexture() { - return (m_frontTexture != &m_textureA) ? &m_textureA : &m_textureB; +SharedTexture* DoubleBufferedTexture::getReadableTexture() +{ + return (m_writeableTexture != &m_textureA) ? &m_textureA : &m_textureB; } -EGLContext DoubleBufferedTexture::producerAcquireContext() { +EGLContext DoubleBufferedTexture::producerAcquireContext() +{ // ensure that the constructor has completed and all values are initialized android::Mutex::Autolock lock(m_varLock); @@ -88,14 +92,15 @@ EGLContext DoubleBufferedTexture::producerAcquireContext() { m_textureB.unlock(); // select a front buffer - m_frontTexture = &m_textureA; + m_writeableTexture = &m_textureA; m_pContext = context; return context; } -TextureInfo* DoubleBufferedTexture::producerLock() { - SharedTexture* sharedTex = getFrontTexture(); +TextureInfo* DoubleBufferedTexture::producerLock() +{ + SharedTexture* sharedTex = getWriteableTexture(); LOGV("Acquiring P Lock (%d)", sharedTex->getSourceTextureId()); TextureInfo* texInfo = sharedTex->lockSource(); LOGV("Acquired P Lock"); @@ -103,23 +108,25 @@ TextureInfo* DoubleBufferedTexture::producerLock() { return texInfo; } -void DoubleBufferedTexture::producerRelease() { +void DoubleBufferedTexture::producerRelease() +{ // get the front texture and cache the id - SharedTexture* sharedTex = getFrontTexture(); + SharedTexture* sharedTex = getWriteableTexture(); LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId()); sharedTex->releaseSource(); // swap the front and back buffers m_varLock.lock(); - m_frontTexture = (sharedTex == &m_textureA) ? &m_textureB : &m_textureA; + m_writeableTexture = (sharedTex == &m_textureA) ? &m_textureB : &m_textureA; LOGV("Released P Lock (%d)", sharedTex->getSourceTextureId()); m_varLock.unlock(); } -TextureInfo* DoubleBufferedTexture::consumerLock() { +TextureInfo* DoubleBufferedTexture::consumerLock() +{ m_varLock.lock(); - SharedTexture* sharedTex = getBackTexture(); + SharedTexture* sharedTex = getReadableTexture(); LOGV("Acquiring C Lock (%d)", sharedTex->getSourceTextureId()); m_lockedConsumerTexture = sharedTex; m_varLock.unlock(); @@ -127,14 +134,14 @@ TextureInfo* DoubleBufferedTexture::consumerLock() { TextureInfo* texInfo = sharedTex->lockTarget(); LOGV("Acquired C Lock"); - if (!texInfo) { + if (!texInfo) LOGV("Released C Lock (Empty)"); - } return texInfo; } -void DoubleBufferedTexture::consumerRelease() { +void DoubleBufferedTexture::consumerRelease() +{ android::Mutex::Autolock lock(m_varLock); // we must check to see what texture the consumer had locked since the // producer may have swapped out the front buffer diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/WebCore/platform/graphics/android/DoubleBufferedTexture.h index 1c629a7..d6d06ab 100644 --- a/WebCore/platform/graphics/android/DoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.h @@ -23,16 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DoubleBufferedTexture__DEFINED -#define DoubleBufferedTexture__DEFINED - -#include -#include -#include -#include -#include +#ifndef DoubleBufferedTexture_h +#define DoubleBufferedTexture_h #include "SharedTexture.h" +#include namespace WebCore { @@ -40,6 +35,7 @@ class DoubleBufferedTexture { public: // consumer thread functions DoubleBufferedTexture(EGLContext sharedContext); + virtual ~DoubleBufferedTexture() { } // provider thread functions TextureInfo* producerLock(); @@ -50,26 +46,27 @@ public: TextureInfo* consumerLock(); void consumerRelease(); +protected: + SharedTexture m_textureA; + SharedTexture m_textureB; + SharedTexture* m_writeableTexture; + android::Mutex m_varLock; + + SharedTexture* getReadableTexture(); + private: - SharedTexture* getFrontTexture(); - SharedTexture* getBackTexture(); + SharedTexture* getWriteableTexture(); EGLDisplay m_display; EGLContext m_pContext; EGLContext m_cContext; - SharedTexture m_textureA; - SharedTexture m_textureB; - SharedTexture* m_frontTexture; SharedTexture* m_lockedConsumerTexture; // only used by the consumer - android::Mutex m_varLock; - bool m_supportsEGLImage; }; - } // namespace WebCore -#endif // DoubleBufferedTexture__DEFINED +#endif // DoubleBufferedTexture_h diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp new file mode 100644 index 0000000..1a7ba6c --- /dev/null +++ b/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -0,0 +1,219 @@ +/* + * Copyright 2010, 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 "GLWebViewState.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseLayerAndroid.h" +#include "LayerAndroid.h" +#include "TilesManager.h" + +#ifdef DEBUG + +#include +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +#define FIRST_TILED_PAGE_ID 1 +#define SECOND_TILED_PAGE_ID 2 + +namespace WebCore { + +using namespace android; + +GLWebViewState::GLWebViewState() + : m_scaleRequestState(kNoScaleRequest) + , m_currentScale(1) + , m_futureScale(1) + , m_updateTime(-1) + , m_transitionTime(-1) + , m_originalTilesPosX(0) + , m_originalTilesPosY(0) + , m_nbTilesWidth(0) + , m_nbTilesHeight(0) + , m_firstTileX(0) + , m_firstTileY(0) + , m_baseLayer(0) + , m_currentPictureCounter(0) + , m_usePageA(true) + , m_extra(0) + , m_navLayer(0) +{ + m_invalidatedRect.setEmpty(); + m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this); + m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this); +} + +GLWebViewState::~GLWebViewState() +{ + delete m_tiledPageA; + delete m_tiledPageB; + delete m_navLayer; +} + +void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, IntRect& rect) +{ + android::Mutex::Autolock lock(m_baseLayerLock); + m_baseLayer = layer; + m_baseLayer->setGLWebViewState(this); + m_invalidatedRect.set(rect); + m_currentPictureCounter++; + m_extra = 0; + delete m_navLayer; + m_navLayer = 0; + XLOG("%x setBaseLayer %x (%d)", this, layer, m_currentPictureCounter); +} + +void GLWebViewState::setExtra(android::DrawExtra* extra, LayerAndroid* navLayer) +{ + android::Mutex::Autolock lock(m_baseLayerLock); + m_extra = extra; + delete m_navLayer; + m_navLayer = navLayer; + m_currentPictureCounter++; +} + +void GLWebViewState::resetExtra(bool repaint) +{ + android::Mutex::Autolock lock(m_baseLayerLock); + if (m_extra && repaint) + m_currentPictureCounter++; + m_extra = 0; + delete m_navLayer; + m_navLayer = 0; +} + +bool GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) +{ + android::Mutex::Autolock lock(m_baseLayerLock); + if (m_baseLayer && m_baseLayer->content() + && !m_baseLayer->content()->isEmpty()) { + m_baseLayer->content()->draw(canvas); + if (m_extra && m_navLayer) + m_extra->draw(canvas, m_navLayer); + return true; + } + return false; +} + +void GLWebViewState::scheduleUpdate(const double& currentTime, float scale) +{ + // if no update time, set it + if (updateTime() == -1) { + m_scaleRequestState = kWillScheduleRequest; + setUpdateTime(currentTime + s_updateInitialDelay); + setFutureScale(scale); + return; + } + + if (currentTime < updateTime()) + return; + + // we reached the scheduled update time, check if we can update + if (futureScale() == scale) { + // we are still with the previous scale, let's go + // with the update + m_scaleRequestState = kRequestNewScale; + setUpdateTime(-1); + } else { + // we reached the update time, but the planned update was for + // a different scale factor -- meaning the user is still probably + // in the process of zooming. Let's push the update time a bit. + setUpdateTime(currentTime + s_updateDelay); + setFutureScale(scale); + } +} + +double GLWebViewState::transitionTime(double currentTime) +{ + if (m_transitionTime == -1) + m_transitionTime = currentTime + s_transitionDelay; + return m_transitionTime; +} + +float GLWebViewState::transparency(double currentTime) +{ + float t = transitionTime(currentTime) - currentTime; + t *= s_invTransitionDelay; + return fmin(1, fmax(0, t)); +} + +TiledPage* GLWebViewState::frontPage() +{ + android::Mutex::Autolock lock(m_tiledPageLock); + return m_usePageA ? m_tiledPageA : m_tiledPageB; +} + +TiledPage* GLWebViewState::backPage() +{ + android::Mutex::Autolock lock(m_tiledPageLock); + return m_usePageA ? m_tiledPageB : m_tiledPageA; +} + +void GLWebViewState::swapPages() +{ + android::Mutex::Autolock lock(m_tiledPageLock); + m_usePageA ^= true; + TiledPage* working = m_usePageA ? m_tiledPageB : m_tiledPageA; + TilesManager::instance()->resetTextureUsage(working); + + m_scaleRequestState = kNoScaleRequest; +} + +void GLWebViewState::setViewport(SkRect& viewport, float scale) +{ + if (m_viewport == viewport) + return; + + m_viewport = viewport; + float fnbw = m_viewport.width() * scale / TilesManager::instance()->tileWidth(); + int nbw = static_cast(ceilf(fnbw)); + float fnbh = m_viewport.height() * scale / TilesManager::instance()->tileHeight(); + int nbh = static_cast(ceilf(fnbh)); + m_nbTilesWidth = nbw + 1; + m_nbTilesHeight = nbh + 1; + XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f), nbw: %d nbh: %d", + m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom, + m_viewport.width(), m_viewport.height(), scale, + m_nbTilesWidth, m_nbTilesHeight); + m_firstTileX = static_cast(m_viewport.fLeft * scale / TilesManager::instance()->tileWidth()); + m_firstTileY = static_cast(m_viewport.fTop * scale / TilesManager::instance()->tileHeight()); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h new file mode 100644 index 0000000..ac3943e --- /dev/null +++ b/WebCore/platform/graphics/android/GLWebViewState.h @@ -0,0 +1,218 @@ +/* + * Copyright 2010, 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 GLWebViewState_h +#define GLWebViewState_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "DrawExtra.h" +#include "IntRect.h" +#include "SkCanvas.h" +#include "SkRect.h" +#include "TiledPage.h" +#include + +namespace WebCore { + +class BaseLayerAndroid; +class LayerAndroid; + +///////////////////////////////////////////////////////////////////////////////// +// GL Architecture +///////////////////////////////////////////////////////////////////////////////// +// +// To draw things, WebView use a tree of layers. The root of that tree is a +// BaseLayerAndroid, which may have numerous LayerAndroid over it. The content +// of those layers are SkPicture, the content of the BaseLayer is an PictureSet. +// +// When drawing, we therefore have one large "surface" that is the BaseLayer, +// and (possibly) additional surfaces (usually smaller), which are the +// LayerAndroids. The BaseLayer usually corresponds to the normal web page +// content, the Layers are used for some parts such as specific divs (e.g. fixed +// position divs, or elements using CSS3D transforms, or containing video, +// plugins, etc.). +// +// *** NOTE: The GL drawing architecture only paints the BaseLayer for now. +// +// The rendering model is to use tiles to display the BaseLayer (as obviously a +// BaseLayer's area can be arbitrarly large). The idea is to compute a set of +// tiles covering the viewport's area, paint those tiles using the webview's +// content (i.e. the BaseLayer's PictureSet), then display those tiles. +// We check which tile we should use at every frame. +// +// Overview +// --------- +// +// The tiles are grouped into a TiledPage -- basically a map of tiles covering +// the BaseLayer's surface. When drawing, we ask the TiledPage to prepare() +// itself then draw itself on screen. The prepare() function is the one +// that schedules tiles to be painted -- i.e. the subset of tiles that intersect +// with the current viewport. When they are ready, we can display +// the TiledPage. +// +// Note that BaseLayerAndroid::drawGL() will return true to the java side if +// there is a need to be called again (i.e. if we do not have up to date +// textures or a transition is going on). +// +// Tiles are implemented as a BaseTile. It knows how to paint itself with the +// PictureSet, and to display itself. A GL texture is usually associated to it. +// +// We also works with two TiledPages -- one to display the page at the +// current scale factor, and another we use to paint the page at a different +// scale factor. I.e. when we zoom, we use TiledPage A, with its tiles scaled +// accordingly (and therefore possible loss of quality): this is fast as it's +// purely a hardware operation. When the user is done zooming, we ask for +// TiledPage B to be painted at the new scale factor, covering the +// viewport's area. When B is ready, we swap it with A. +// +// Texture allocation +// ------------------ +// +// Obviously we cannot have every BaseTile having a GL texture -- we need to +// get the GL textures from an existing pool, and reuse them. +// +// The way we do it is that when we call TiledPage::prepare(), we group the +// tiles we need into a TilesSet, call TilesSet::reserveTextures() (which +// associates the GL textures to the BaseTiles). +// +// reserveTexture() will ask the TilesManager for a texture. The allocation +// mechanism goal is to (in order): +// - prefers to allocate the same texture as the previous time +// - prefers to allocate textures that are as far from the viewport as possible +// - prefers to allocate textures that are used by different TiledPages +// +// Note that to compute the distance of tiles, each time we prepare() a +// TiledPage, we compute the distance of the tiles in it from the viewport. +// +// Painting scheduling +// ------------------- +// +// The next operation is to schedule this TilesSet to be painted +// (TilesManager::schedulePaintForTilesSet()). TexturesGenerator +// will get the TilesSet and ask the BaseTiles in it to be painted. +// +// BaseTile::paintBitmap() will paint the texture using the BaseLayer's +// PictureSet (calling TiledPage::paintBaseLayerContent() which in turns +// calls GLWebViewState::paintBaseLayerContent()). +// +// Note that TexturesGenerator is running in a separate thread, the textures +// are shared using EGLImages (this is necessary to not slow down the rendering +// speed -- updating GL textures in the main GL thread would slow things down). +// +///////////////////////////////////////////////////////////////////////////////// + +class GLWebViewState { +public: + enum GLScaleStates { + kNoScaleRequest = 0, + kWillScheduleRequest = 1, + kRequestNewScale = 2, + kReceivedNewScale = 3 + }; + typedef int32_t GLScaleState; + + GLWebViewState(); + ~GLWebViewState(); + GLScaleState scaleRequestState() const { return m_scaleRequestState; } + void setScaleRequestState(GLScaleState state) { m_scaleRequestState = state; } + float currentScale() const { return m_currentScale; } + void setCurrentScale(float scale) { m_currentScale = scale; } + float futureScale() const { return m_futureScale; } + void setFutureScale(float scale) { m_futureScale = scale; } + double updateTime() const { return m_updateTime; } + void setUpdateTime(double value) { m_updateTime = value; } + double transitionTime(double currentTime); + float transparency(double currentTime); + void resetTransitionTime() { m_transitionTime = -1; } + int originalTilesPosX() const { return m_originalTilesPosX; } + void setOriginalTilesPosX(int pos) { m_originalTilesPosX = pos; } + int originalTilesPosY() const { return m_originalTilesPosY; } + void setOriginalTilesPosY(int pos) { m_originalTilesPosY = pos; } + + bool paintBaseLayerContent(SkCanvas* canvas); + void setBaseLayer(BaseLayerAndroid* layer, IntRect& rect); + void setExtra(android::DrawExtra* extra, LayerAndroid* navLayer); + void resetExtra(bool repaint); + + void scheduleUpdate(const double& currentTime, float scale); + + TiledPage* frontPage(); + TiledPage* backPage(); + void swapPages(); + + void setViewport(SkRect& viewport, float scale); + + // returns the number of tiles needed to cover the viewport + int nbTilesWidth() const { return m_nbTilesWidth; } + int nbTilesHeight() const { return m_nbTilesHeight; } + + int firstTileX() const { return m_firstTileX; } + int firstTileY() const { return m_firstTileY; } + + unsigned int currentPictureCounter() const { return m_currentPictureCounter; } + SkRect& invalidatedRect() { return m_invalidatedRect; } + +private: + + // Delay between scheduling a new page when the scale + // factor changes (i.e. zooming in or out) + static const double s_updateInitialDelay = 0.3; // 300 ms + // If the scale factor continued to change and we completed + // the original delay, we push back the update by this value + static const double s_updateDelay = 0.1; // 100 ms + + // Delay for the transition between the two pages + static const double s_transitionDelay = 0.5; // 500 ms + static const double s_invTransitionDelay = 2; + + GLScaleState m_scaleRequestState; + float m_currentScale; + float m_futureScale; + double m_updateTime; + double m_transitionTime; + int m_originalTilesPosX; + int m_originalTilesPosY; + android::Mutex m_tiledPageLock; + SkRect m_viewport; + int m_nbTilesWidth; + int m_nbTilesHeight; + int m_firstTileX; + int m_firstTileY; + android::Mutex m_baseLayerLock; + BaseLayerAndroid* m_baseLayer; + unsigned int m_currentPictureCounter; + SkRect m_invalidatedRect; + bool m_usePageA; + TiledPage* m_tiledPageA; + TiledPage* m_tiledPageB; + android::DrawExtra* m_extra; + LayerAndroid* m_navLayer; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // GLWebViewState_h diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp new file mode 100644 index 0000000..ca05d10 --- /dev/null +++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2010, 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 "TexturesGenerator.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "GLUtils.h" +#include "TilesManager.h" + +#ifdef DEBUG + +#include +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TexturesGenerator", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +void TexturesGenerator::schedulePaintForTilesSet(TilesSet* set) +{ + android::Mutex::Autolock lock(mRequestedPixmapsLock); + for (unsigned int i = 0; i < mRequestedPixmaps.size(); i++) { + TilesSet* s = mRequestedPixmaps[i]; + if (s && *s == *set) { + // Similar set already in the queue + delete set; + return; + } + } + + XLOG("%x schedulePaintForTilesSet (%x) %d, %d, %d, %d", this, set, + set->firstTileX(), set->firstTileY(), set->nbRows(), set->nbCols()); + mRequestedPixmaps.append(set); + m_newRequestLock.lock(); + m_newRequestCond.signal(); + m_newRequestLock.unlock(); +} + +status_t TexturesGenerator::readyToRun() +{ + TilesManager::instance()->enableTextures(); + XLOG("Textures enabled (context acquired...)"); + TilesManager::instance()->paintTexturesDefault(); + XLOG("Textures painted"); + TilesManager::instance()->markGeneratorAsReady(); + XLOG("Thread ready to run"); + return NO_ERROR; +} + +bool TexturesGenerator::threadLoop() +{ + XLOG("threadLoop, waiting for signal"); + m_newRequestLock.lock(); + m_newRequestCond.wait(m_newRequestLock); + m_newRequestLock.unlock(); + XLOG("threadLoop, got signal"); + + bool stop = false; + while (!stop) { + mRequestedPixmapsLock.lock(); + TilesSet* set = 0; + if (mRequestedPixmaps.size()) + set = mRequestedPixmaps.first(); + mRequestedPixmapsLock.unlock(); + + if (set) { + set->paint(); + mRequestedPixmapsLock.lock(); + mRequestedPixmaps.remove(0); + mRequestedPixmapsLock.unlock(); + delete set; + } + + mRequestedPixmapsLock.lock(); + if (!mRequestedPixmaps.size()) + stop = true; + mRequestedPixmapsLock.unlock(); + } + + return true; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/TexturesGenerator.h b/WebCore/platform/graphics/android/TexturesGenerator.h new file mode 100644 index 0000000..b68fcb1 --- /dev/null +++ b/WebCore/platform/graphics/android/TexturesGenerator.h @@ -0,0 +1,57 @@ +/* + * Copyright 2010, 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 TexturesGenerator_h +#define TexturesGenerator_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "TilesSet.h" +#include + +namespace WebCore { + +using namespace android; + +class TexturesGenerator : public Thread { +public: + TexturesGenerator() : Thread() { } + virtual ~TexturesGenerator() { } + virtual status_t readyToRun(); + + void schedulePaintForTilesSet(TilesSet* set); + +private: + virtual bool threadLoop(); + Vector mRequestedPixmaps; + android::Mutex mRequestedPixmapsLock; + android::Mutex m_newRequestLock; + android::Condition m_newRequestCond; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TexturesGenerator_h diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp new file mode 100644 index 0000000..666c00f --- /dev/null +++ b/WebCore/platform/graphics/android/TiledPage.cpp @@ -0,0 +1,257 @@ +/* + * Copyright 2010, 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 "TiledPage.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "GLUtils.h" +#include "TilesManager.h" + +#ifdef DEBUG + +#include +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledPage", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +using namespace android; + +TiledPage::TiledPage(int id, GLWebViewState* state) + : m_id(id) + , m_scale(1) + , m_glWebViewState(state) +{ +} + +BaseTile* TiledPage::getBaseTile(int x, int y, int quality) +{ + TileKey key(x + 1, y + 1); + return m_baseTextures.get(key); +} + +void TiledPage::prepareRow(bool goingLeft, int firstTileX, int y, TilesSet* set, int quality) +{ + if (y < 0) + return; + if (!set) + return; + + int nbCols = set->nbCols(); + for (int i = 0; i < nbCols; i++) { + int x = firstTileX; + + // If we are goingLeft, we want to schedule the tiles + // starting from the left (and to the right if not) + if (goingLeft) + x += i; + else + x += (nbCols - 1) - i; + + TileKey key(x + 1, y + 1); + BaseTile* tile = 0; + if (!m_baseTextures.contains(key)) { + tile = new BaseTile(this, x, y); + m_baseTextures.set(key, tile); + } + tile = m_baseTextures.get(key); + tile->setUsedLevel(0); + tile->setScale(m_scale); + set->add(tile); + } +} + +void TiledPage::setTileLevel(BaseTile* tile, int firstTileX, int firstTileY) +{ + if (!tile) + return; + + if (!m_glWebViewState) + return; + + int nbTilesWidth = m_glWebViewState->nbTilesWidth(); + int nbTilesHeight = m_glWebViewState->nbTilesHeight(); + int dx = 0; + int dy = 0; + + if (firstTileX > tile->x()) + dx = firstTileX - tile->x(); + else if (firstTileX + (nbTilesWidth - 1) < tile->x()) + dx = tile->x() - firstTileX - (nbTilesWidth - 1); + + if (firstTileY > tile->y()) + dy = firstTileY - tile->y(); + else if (firstTileY + (nbTilesHeight - 1) < tile->y()) + dy = tile->y() - firstTileY - (nbTilesHeight - 1); + + int d = std::max(dx, dy); + + XLOG("setTileLevel tile: %x, fxy(%d, %d), level: %d", tile, firstTileX, firstTileY, d); + tile->setUsedLevel(d); +} + +void TiledPage::prepare(bool goingDown, bool goingLeft, int firstTileX, int firstTileY) +{ + if (!m_glWebViewState) + return; + + int nbTilesWidth = m_glWebViewState->nbTilesWidth(); + int nbTilesHeight = m_glWebViewState->nbTilesHeight(); + + TilesSet* highResSet = new TilesSet(m_id + 1, scale(), firstTileX, firstTileY, + nbTilesHeight, nbTilesWidth); + + // We chose to display tiles depending on the scroll direction: + if (goingDown) { + for (int i = 0; i < nbTilesHeight; i++) + prepareRow(goingLeft, firstTileX, firstTileY + i, highResSet, 1); + } else { + for (int i = 0; i < nbTilesHeight; i++) + prepareRow(goingLeft, firstTileX, firstTileY + (nbTilesHeight - 1) - i, highResSet, 1); + } + + TileMap::const_iterator end = m_baseTextures.end(); + for (TileMap::const_iterator it = m_baseTextures.begin(); it != end; ++it) { + BaseTile* tile = it->second; + setTileLevel(tile, firstTileX, firstTileY); + } + +#ifdef DEBUG + XLOG("+++ BEFORE RESERVE TEXTURES (%d x %d) at (%d, %d), TiledPage %x", + nbTilesWidth, nbTilesHeight, firstTileX, firstTileY, this); + TilesManager::instance()->printTextures(); +#endif // DEBUG + + highResSet->reserveTextures(); + +#ifdef DEBUG + TilesManager::instance()->printTextures(); + XLOG("--- AFTER RESERVE TEXTURES (%d x %d) at (%d, %d), TiledPage %x", + nbTilesWidth, nbTilesHeight, firstTileX, firstTileY, this); +#endif // DEBUG + + // schedulePaintForTilesSet will take ownership of the highResSet here, + // so no delete necessary. + TilesManager::instance()->schedulePaintForTilesSet(highResSet); +} + +bool TiledPage::ready(int firstTileX, int firstTileY) +{ + if (!m_glWebViewState) + return false; + + int nbTilesWidth = m_glWebViewState->nbTilesWidth(); + int nbTilesHeight = m_glWebViewState->nbTilesHeight(); + + for (int i = 0; i < nbTilesHeight; i++) { + for (int j = 0; j < nbTilesWidth; j++) { + int x = j + firstTileX; + int y = i + firstTileY; + BaseTile* t = getBaseTile(x, y, 1); + if (!t || !t->isBitmapReady()) + return false; + } + } + return true; +} + +void TiledPage::draw(float transparency, SkRect& viewport, + int firstTileX, int firstTileY) +{ + if (!m_glWebViewState) + return; + + float w = TilesManager::instance()->tileWidth() / m_scale; + float h = TilesManager::instance()->tileHeight() / m_scale; + int nbTilesWidth = m_glWebViewState->nbTilesWidth(); + int nbTilesHeight = m_glWebViewState->nbTilesHeight(); + + XLOG("WE DRAW %x (%.2f) with transparency %.2f", this, scale(), transparency); + for (int i = 0; i < nbTilesHeight; i++) { + for (int j = 0; j < nbTilesWidth; j++) { + int x = j + firstTileX; + int y = i + firstTileY; + + BaseTile* tile = getBaseTile(x, y, 1); + + if (!tile) { + XLOG("NO TILE AT %d, %d", x, y); + continue; + } + + SkRect rect; + rect.fLeft = x * w; + rect.fTop = y * h; + rect.fRight = rect.fLeft + w; + rect.fBottom = rect.fTop + h; + + TilesManager::instance()->shader()->setViewport(viewport); + tile->draw(transparency, rect); + } + } + + XLOG("FINISHED WE DRAW %x (%.2f) with transparency %.2f", this, scale(), transparency); + TilesManager::instance()->printTextures(); +} + +bool TiledPage::paintBaseLayerContent(SkCanvas* canvas) +{ + if (m_glWebViewState) + return m_glWebViewState->paintBaseLayerContent(canvas); + return false; +} + +unsigned int TiledPage::currentPictureCounter() +{ + if (m_glWebViewState) + return m_glWebViewState->currentPictureCounter(); + return 0; +} + +TiledPage* TiledPage::sibling() +{ + if (!m_glWebViewState) + return 0; + + if (m_glWebViewState->frontPage() == this) + return m_glWebViewState->backPage(); + return m_glWebViewState->frontPage(); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/TiledPage.h b/WebCore/platform/graphics/android/TiledPage.h new file mode 100644 index 0000000..712566c --- /dev/null +++ b/WebCore/platform/graphics/android/TiledPage.h @@ -0,0 +1,64 @@ +/* + * Copyright 2010, 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 TiledPage_h +#define TiledPage_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseTile.h" +#include "GLWebViewState.h" +#include "SkCanvas.h" +#include "TilesSet.h" + +namespace WebCore { + +class TiledPage { +public: + TiledPage(int id, GLWebViewState* state); + ~TiledPage() { } + BaseTile* getBaseTile(int x, int y, int quality); + void prepare(bool goingDown, bool goingLeft, int firstTileX, int firstTileY); + void setScale(float scale) { m_scale = scale; } + bool ready(int firstTileX, int firstTileY); + void draw(float transparency, SkRect& viewport, int firstTileX, int firstTileY); + float scale() const { return m_scale; } + bool paintBaseLayerContent(SkCanvas*); + unsigned int currentPictureCounter(); + TiledPage* sibling(); + GLWebViewState* glWebViewState() { return m_glWebViewState; } +private: + void setTileLevel(BaseTile* tile, int firstTileX, int firstTileY); + void prepareRow(bool goingLeft, int firstTileX, int y, TilesSet* set, int quality); + TileMap m_baseTextures; + int m_id; + float m_scale; + GLWebViewState* m_glWebViewState; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TiledPage_h diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp new file mode 100644 index 0000000..a600f39 --- /dev/null +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -0,0 +1,254 @@ +/* + * Copyright 2010, 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 "TilesManager.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseTile.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +#ifdef DEBUG + +#include +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +// Important: We need at least twice as much textures as is needed to cover +// one viewport, otherwise the allocation may stall. +// We need n textures for one TiledPage, and another n textures for the +// second page used when scaling. +// In our case, we use 300x300 textures. On the tablet, this equals to +// at least 24 (6 * 4) textures, hence 48. +#define DEFAULT_TEXTURES_ALLOCATION 48 +#define DEFAULT_TEXTURE_SIZE_WIDTH 300 +#define DEFAULT_TEXTURE_SIZE_HEIGHT 300 + +namespace WebCore { + +TilesManager::TilesManager() + : m_generatorReady(false) +{ + m_textures.reserveCapacity(DEFAULT_TEXTURES_ALLOCATION); + for (int i = 0; i < DEFAULT_TEXTURES_ALLOCATION; i++) { + BackedDoubleBufferedTexture* texture = new BackedDoubleBufferedTexture( + tileWidth(), tileHeight()); + m_textures.append(texture); + } + + m_pixmapsGenerationThread = new TexturesGenerator(); + m_pixmapsGenerationThread->run("TexturesGenerator"); +} + +// Has to be run on the texture generation threads +void TilesManager::enableTextures() +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i < m_textures.size(); i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + texture->producerAcquireContext(); + } +} + +void TilesManager::printTextures() +{ +#ifdef DEBUG + XLOG("++++++"); + for (unsigned int i = 0; i < m_textures.size(); i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + BaseTile* o = 0; + if (texture->owner()) + o = (BaseTile*) texture->owner(); + int x = -1; + int y = -1; + if (o) { + x = o->x(); + y = o->y(); + } + XLOG("[%d] texture %x (picture: %d) usedLevel: %d busy: %d owner: %x (%d, %d) page: %x scale: %.2f", + i, texture, texture->pictureUsed(), texture->usedLevel(), + texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0); + } + XLOG("------"); +#endif // DEBUG +} + +void TilesManager::paintTexturesDefault() +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i < m_textures.size(); i++) { + for (int j = 0; j < 2; j++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + TextureInfo* textureInfo = texture->producerLock(); + SkCanvas* canvas = texture->canvas(); +#ifdef DEBUG + if (j) + canvas->drawARGB(255, 0, 0, 255); + else + canvas->drawARGB(255, 255, 0, 255); + SkPaint paint; + paint.setARGB(128, 255, 0, 0); + paint.setStrokeWidth(3); + canvas->drawLine(0, 0, tileWidth(), tileHeight(), paint); + paint.setARGB(128, 0, 255, 0); + canvas->drawLine(0, tileHeight(), tileWidth(), 0, paint); + paint.setARGB(128, 0, 0, 255); + canvas->drawLine(0, 0, tileWidth(), 0, paint); + canvas->drawLine(tileWidth(), 0, tileWidth(), tileHeight(), paint); +#else + canvas->drawARGB(255, 255, 255, 255); +#endif // DEBUG + PaintingInfo info; + texture->update(textureInfo, info); + texture->producerRelease(); + } + } +} + +void TilesManager::resetTextureUsage(TiledPage* page) +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i < m_textures.size(); i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->owner()) { + if (texture->owner()->page() == page) + texture->setUsedLevel(-1); + } + } +} + +BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner) +{ + android::Mutex::Autolock lock(m_texturesLock); + unsigned int max = m_textures.size(); + // First see if we have something already painted for this tile + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->painter() == owner) { + if (texture->acquire(owner)) { + texture->setUsedLevel(0); + XLOG("same painter, getAvailableTexture(%x) => texture %x", owner, texture); + return texture; + } + } + } + // Then, let's return an owned texture if any + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->owner() == owner) { + texture->setUsedLevel(0); + XLOG("same owner, getAvailableTexture(%x) => texture %x", owner, texture); + return texture; + } + } + // Ok... at this point we need to decide which texture to grab + // The texture level indicates their closeness to the current viewport; + // let's just grab the texture that is as far as possible, or any + // texture that is unused. + BackedDoubleBufferedTexture* farthestTexture = 0; + int farthestTextureLevel = 0; + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->usedLevel() == -1) { // found an unused texture, grab it + farthestTexture = texture; + break; + } + if (farthestTextureLevel < texture->usedLevel()) { + farthestTextureLevel = texture->usedLevel(); + farthestTexture = texture; + } + } + if (farthestTexture && farthestTexture->acquire(owner)) { + farthestTexture->setUsedLevel(0); + XLOG("farthest texture, getAvailableTexture(%x) => texture %x (level %d)", + owner, farthestTexture, farthestTexture->usedLevel()); + return farthestTexture; + } + // At this point, all textures are used. Let's just grab one + // that is not ours... + // First, get the two tiled page associated to this, to be sure + // we won't starve ourselves + TiledPage* currentPage = owner->page(); + TiledPage* nextPage = currentPage->sibling(); + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->owner() + && texture->owner()->page() != currentPage + && texture->owner()->page() != nextPage) { + if (texture->acquire(owner)) { + XLOG("grab a texture that wasn't ours, (%x != %x) at %d => texture %x", + owner->page(), texture->owner()->page(), i, texture); + texture->setUsedLevel(0); + return texture; + } + } + } + + XLOG("Couldn't find an available texture for BaseTile %x (%d, %d) !!!", + owner, owner->x(), owner->y()); +#ifdef DEBUG + printTextures(); +#endif // DEBUG + return 0; +} + +float TilesManager::tileWidth() const +{ + return DEFAULT_TEXTURE_SIZE_WIDTH; +} + +float TilesManager::tileHeight() const +{ + return DEFAULT_TEXTURE_SIZE_HEIGHT; +} + +TilesManager* TilesManager::instance() +{ + if (!gInstance) { + gInstance = new TilesManager(); + XLOG("Waiting for the generator..."); + gInstance->waitForGenerator(); + XLOG("Generator ready!"); + } + return gInstance; +} + +TilesManager* TilesManager::gInstance = 0; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h new file mode 100644 index 0000000..2ac0ca6 --- /dev/null +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -0,0 +1,97 @@ +/* + * Copyright 2010, 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 TilesManager_h +#define TilesManager_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BackedDoubleBufferedTexture.h" +#include "BaseTile.h" +#include "ShaderProgram.h" +#include "TexturesGenerator.h" +#include "TiledPage.h" +#include "TilesSet.h" +#include + +namespace WebCore { + +class TilesManager { +public: + static TilesManager* instance(); + + void schedulePaintForTilesSet(TilesSet* set) + { + m_pixmapsGenerationThread->schedulePaintForTilesSet(set); + } + + ShaderProgram* shader() { return &m_shader; } + + BackedDoubleBufferedTexture* getAvailableTexture(BaseTile* owner); + + void markGeneratorAsReady() + { + android::Mutex::Autolock lock(m_generatorLock); + m_generatorReadyCond.signal(); + } + + void printTextures(); + void enableTextures(); + + void resetTextureUsage(TiledPage* page); + void paintTexturesDefault(); + + float tileWidth() const; + float tileHeight() const; + +private: + + TilesManager(); + + void waitForGenerator() + { + android::Mutex::Autolock lock(m_generatorLock); + m_generatorReadyCond.wait(m_generatorLock); + } + + Vector m_textures; + + bool m_generatorReady; + + sp m_pixmapsGenerationThread; + + android::Mutex m_texturesLock; + android::Mutex m_generatorLock; + android::Condition m_generatorReadyCond; + + static TilesManager* gInstance; + + ShaderProgram m_shader; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TilesManager_h diff --git a/WebCore/platform/graphics/android/TilesSet.cpp b/WebCore/platform/graphics/android/TilesSet.cpp new file mode 100644 index 0000000..25f93e5 --- /dev/null +++ b/WebCore/platform/graphics/android/TilesSet.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2010, 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 "TilesSet.h" + +#if USE(ACCELERATED_COMPOSITING) + +#ifdef DEBUG + +#include +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesSet", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +#ifdef DEBUG +static int gTilesSetCount = 0; +int TilesSet::count() +{ + return gTilesSetCount; +} +#endif + +TilesSet::TilesSet(int id, float scale, int firstTileX, int firstTileY, int rows, int cols) + : m_id(id) + , m_scale(scale) + , m_firstTileX(firstTileX) + , m_firstTileY(firstTileY) + , m_nbRows(rows) + , m_nbCols(cols) + , m_painting(false) +{ +#ifdef DEBUG + gTilesSetCount++; +#endif +} + +TilesSet::~TilesSet() +{ +#ifdef DEBUG + gTilesSetCount--; +#endif +} + +bool TilesSet::operator==(const TilesSet& set) +{ + return (id() == set.id()) + && (firstTileX() == set.firstTileX()) + && (firstTileY() == set.firstTileY()) + && (nbRows() == set.nbRows()) + && (nbCols() == set.nbCols()); +} + +void TilesSet::reserveTextures() +{ + XLOG("reserveTextures (%d tiles)", mTiles.size()); + for (unsigned int i = 0; i < mTiles.size(); i++) + mTiles[i]->reserveTexture(); +} + +void TilesSet::paint() +{ + XLOG("%x, painting %d tiles", this, mTiles.size()); + for (unsigned int i = 0; i < mTiles.size(); i++) + mTiles[i]->paintBitmap(); + XLOG("%x, end of painting %d tiles", this, mTiles.size()); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/TilesSet.h b/WebCore/platform/graphics/android/TilesSet.h new file mode 100644 index 0000000..0e2ebb5 --- /dev/null +++ b/WebCore/platform/graphics/android/TilesSet.h @@ -0,0 +1,76 @@ +/* + * Copyright 2010, 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 TilesSet_h +#define TilesSet_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseTile.h" +#include "Vector.h" + +namespace WebCore { + +class TilesSet { +public: +#ifdef DEBUG + static int count(); +#endif + TilesSet(int id, float scale, int firstTileX, int firstTileY, int rows, int cols); + ~TilesSet(); + + int id() const { return m_id; } + float scale() const { return m_scale; } + int firstTileX() const { return m_firstTileX; } + int firstTileY() const { return m_firstTileY; } + int nbRows() const { return m_nbRows; } + int nbCols() const { return m_nbCols; } + bool operator==(const TilesSet& set); + void reserveTextures(); + + void paint(); + void setPainting(bool state) { m_painting = state; } + + void add(BaseTile* texture) + { + mTiles.append(texture); + } + +private: + Vector mTiles; + + int m_id; + float m_scale; + int m_firstTileX; + int m_firstTileY; + int m_nbRows; + int m_nbCols; + bool m_painting; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TilesSet_h diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 841434f..4093fa5 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -53,6 +53,7 @@ #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" #endif +#include "TilesManager.h" #include "WebCoreJni.h" #include "WebRequestContext.h" #include "WebViewCore.h" @@ -384,6 +385,56 @@ void drawCursorPostamble() } } +bool drawGL(WebCore::IntRect& viewRect, float scale, int extras) +{ +#if USE(ACCELERATED_COMPOSITING) + if (!m_baseLayer) + return false; + + m_glWebViewState.resetExtra(false); + CachedRoot* root = getFrameCache(AllowNewer); + if (!root) { + DBG_NAV_LOG("!root"); + if (extras == DrawExtrasCursorRing) + resetCursorRing(); + return false; + } + DrawExtra* extra = 0; + switch (extras) { + case DrawExtrasFind: + extra = &m_findOnPage; + break; + case DrawExtrasSelection: + extra = &m_selectText; + break; + case DrawExtrasCursorRing: + if (drawCursorPreamble(root) && m_ring.setup()) { + if (!m_ring.m_isButton) + extra = &m_ring; + drawCursorPostamble(); + } + break; + default: + ; + } + + unsigned int pic = m_glWebViewState.currentPictureCounter(); + if (extra) { + LayerAndroid* mainPicture = new LayerAndroid(m_navPictureUI); + m_glWebViewState.setExtra(extra, mainPicture); + } else { + m_glWebViewState.resetExtra(true); + } + + SkRect visibleRect; + calcOurContentVisibleRect(&visibleRect); + bool ret = m_baseLayer->drawGL(viewRect, visibleRect, scale); + if (ret || m_glWebViewState.currentPictureCounter() != pic) + return true; +#endif + return false; +} + PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split) { PictureSet* ret = 0; @@ -1207,8 +1258,12 @@ static void copyScrollPositionRecursive(const LayerAndroid* from, } } -void setBaseLayer(BaseLayerAndroid* layer) +void setBaseLayer(BaseLayerAndroid* layer, WebCore::IntRect& rect) { +#if USE(ACCELERATED_COMPOSITING) + m_glWebViewState.setBaseLayer(layer, rect); +#endif + if (layer) { copyScrollPositionRecursive(compositeRoot(), static_cast(layer->getChild(0))); @@ -1261,6 +1316,9 @@ private: // local state for WebView FindOnPage m_findOnPage; CursorRing m_ring; BaseLayerAndroid* m_baseLayer; +#if USE(ACCELERATED_COMPOSITING) + GLWebViewState m_glWebViewState; +#endif }; // end of WebView class /* @@ -1497,6 +1555,13 @@ static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv, jint color, return reinterpret_cast(GET_NATIVE_VIEW(env, obj)->draw(canvas, color, extras, split)); } +static bool nativeDrawGL(JNIEnv *env, jobject obj, jobject jrect, + jfloat scale, jint extras) +{ + WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); + return GET_NATIVE_VIEW(env, obj)->drawGL(viewRect, scale, extras); +} + static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj) { #if USE(ACCELERATED_COMPOSITING) @@ -1507,10 +1572,11 @@ static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj) return false; } -static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer) +static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer, jobject jrect) { BaseLayerAndroid* layerImpl = reinterpret_cast(layer); - GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl); + WebCore::IntRect rect = jrect_to_webrect(env, jrect); + GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl, rect); } static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content) @@ -2165,6 +2231,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeDestroy }, { "nativeDraw", "(Landroid/graphics/Canvas;IIZ)I", (void*) nativeDraw }, + { "nativeDrawGL", "(Landroid/graphics/Rect;FI)Z", + (void*) nativeDrawGL }, { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", (void*) nativeDumpDisplayTree }, { "nativeEvaluateLayersAnimations", "()Z", @@ -2257,7 +2325,7 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetFindIsUp }, { "nativeSetHeightCanMeasure", "(Z)V", (void*) nativeSetHeightCanMeasure }, - { "nativeSetBaseLayer", "(I)V", + { "nativeSetBaseLayer", "(ILandroid/graphics/Rect;)V", (void*) nativeSetBaseLayer }, { "nativeReplaceBaseContent", "(I)V", (void*) nativeReplaceBaseContent }, -- cgit v1.1