summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics
diff options
context:
space:
mode:
authorNicolas Roard <nicolasroard@google.com>2011-08-19 11:46:09 -0700
committerNicolas Roard <nicolasroard@google.com>2011-08-19 13:39:26 -0700
commit77e5b594dd717e27b1a8be2b521f738cf5941ae1 (patch)
treef088b9113d8a9043638a0bcd99156e2d5ffc8287 /Source/WebCore/platform/graphics
parent03721d93591244128ff918202425d381e2fedf50 (diff)
downloadexternal_webkit-77e5b594dd717e27b1a8be2b521f738cf5941ae1.zip
external_webkit-77e5b594dd717e27b1a8be2b521f738cf5941ae1.tar.gz
external_webkit-77e5b594dd717e27b1a8be2b521f738cf5941ae1.tar.bz2
Refactoring of BaseLayerAndroid and GLWebViewState:
- we extract the GL set up GLWebViewState - we extract the zoom management to a new ZoomManager class bug:3392331 Change-Id: If42523a7192bab2f8c9d1f00a50721380340230d
Diffstat (limited to 'Source/WebCore/platform/graphics')
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp160
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.h5
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp140
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.h57
-rw-r--r--Source/WebCore/platform/graphics/android/ZoomManager.cpp201
-rw-r--r--Source/WebCore/platform/graphics/android/ZoomManager.h118
6 files changed, 430 insertions, 251 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index 3aa325f..e3e41bc 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -115,51 +115,23 @@ void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
double currentTime, bool* pagesSwapped)
{
- if (!m_glWebViewState)
- return false;
+ ZoomManager* zoomManager = m_glWebViewState->zoomManager();
- bool goingDown = m_previousVisible.fTop - viewport.fTop <= 0;
- bool goingLeft = m_previousVisible.fLeft - viewport.fLeft >= 0;
-
- m_glWebViewState->setViewport(viewport, scale);
+ bool goingDown = m_glWebViewState->goingDown();
+ bool goingLeft = m_glWebViewState->goingLeft();
const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds();
XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft,
viewportTileBounds.fTop, scale);
- if (scale == m_glWebViewState->currentScale()
- || m_glWebViewState->preZoomBounds().isEmpty())
- m_glWebViewState->setPreZoomBounds(viewportTileBounds);
-
- bool prepareNextTiledPage = false;
- // 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->futureScale() != scale))
- || m_glWebViewState->scaleRequestState() == GLWebViewState::kWillScheduleRequest) {
-
- // schedule the new request
- m_glWebViewState->scheduleUpdate(currentTime, viewportTileBounds, scale);
-
- // If it's a new request, we will have to prepare the page.
- if (m_glWebViewState->scaleRequestState() == GLWebViewState::kRequestNewScale)
- prepareNextTiledPage = true;
- }
-
- // If the viewport has changed since we scheduled the request, we also need to prepare.
- if ((m_glWebViewState->scaleRequestState() == GLWebViewState::kRequestNewScale || m_glWebViewState->scaleRequestState() == GLWebViewState::kReceivedNewScale)
- && m_glWebViewState->futureViewport() != viewportTileBounds)
- prepareNextTiledPage = true;
-
- bool zooming = false;
- if (m_glWebViewState->scaleRequestState() != GLWebViewState::kNoScaleRequest) {
- prepareNextTiledPage = true;
- zooming = true;
- }
+ // Query the resulting state from the zoom manager
+ bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage();
+ bool zooming = zoomManager->zooming();
// Display the current page
TiledPage* tiledPage = m_glWebViewState->frontPage();
- tiledPage->setScale(m_glWebViewState->currentScale());
+ TiledPage* nextTiledPage = m_glWebViewState->backPage();
+ tiledPage->setScale(zoomManager->currentScale());
// Let's prepare the page if needed
if (prepareNextTiledPage) {
@@ -172,42 +144,27 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
}
- float transparency = 1;
- bool doSwap = false;
-
// If we fired a request, let's check if it's ready to use
- if (m_glWebViewState->scaleRequestState() == GLWebViewState::kRequestNewScale) {
- TiledPage* nextTiledPage = m_glWebViewState->backPage();
- if (nextTiledPage->ready(viewportTileBounds, m_glWebViewState->futureScale()))
- m_glWebViewState->setScaleRequestState(GLWebViewState::kReceivedNewScale);
+ if (zoomManager->didFireRequest()) {
+ if (nextTiledPage->ready(viewportTileBounds, zoomManager->futureScale()))
+ zoomManager->setReceivedRequest(); // transition to received request state
}
+ float transparency = 1;
+ bool doSwap = false;
+
// 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) {
- TiledPage* nextTiledPage = m_glWebViewState->backPage();
- double transitionTime = (scale < m_glWebViewState->currentScale()) ?
- m_glWebViewState->zoomOutTransitionTime(currentTime) :
- m_glWebViewState->zoomInTransitionTime(currentTime);
-
- float newTilesTransparency = 1;
- if (scale < m_glWebViewState->currentScale())
- newTilesTransparency = 1 - m_glWebViewState->zoomOutTransparency(currentTime);
- else
- transparency = m_glWebViewState->zoomInTransparency(currentTime);
+ if (zoomManager->didReceivedRequest()) {
+ float nextTiledPageTransparency = 1;
+ zoomManager->processTransition(currentTime, scale, &doSwap,
+ &nextTiledPageTransparency, &transparency);
- nextTiledPage->draw(newTilesTransparency, viewportTileBounds);
-
- // The transition between the two pages is finished, swap them
- if (currentTime > transitionTime) {
- m_glWebViewState->resetTransitionTime();
- doSwap = true;
- }
+ nextTiledPage->draw(nextTiledPageTransparency, viewportTileBounds);
}
const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
- TiledPage* nextTiledPage = m_glWebViewState->backPage();
bool needsRedraw = false;
// We are now using an hybrid model -- during scrolling,
@@ -216,12 +173,12 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
// the back page is ready before swapping the pages, ensuring that the
// displayed content is in sync.
if (!doSwap && !zooming && !m_glWebViewState->moving()) {
- if (!tiledPage->ready(preZoomBounds, m_glWebViewState->currentScale())) {
+ if (!tiledPage->ready(preZoomBounds, zoomManager->currentScale())) {
m_glWebViewState->lockBaseLayerUpdate();
- nextTiledPage->setScale(m_glWebViewState->currentScale());
+ nextTiledPage->setScale(zoomManager->currentScale());
nextTiledPage->prepare(goingDown, goingLeft, preZoomBounds);
}
- if (nextTiledPage->ready(preZoomBounds, m_glWebViewState->currentScale())) {
+ if (nextTiledPage->ready(preZoomBounds, zoomManager->currentScale())) {
nextTiledPage->draw(transparency, preZoomBounds);
m_glWebViewState->resetFrameworkInval();
m_glWebViewState->unlockBaseLayerUpdate();
@@ -230,7 +187,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
tiledPage->draw(transparency, preZoomBounds);
}
} else {
- if (tiledPage->ready(preZoomBounds, m_glWebViewState->currentScale()))
+ if (tiledPage->ready(preZoomBounds, zoomManager->currentScale()))
m_glWebViewState->resetFrameworkInval();
// Ask for the tiles and draw -- tiles may be out of date.
@@ -242,12 +199,12 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
tiledPage->draw(transparency, preZoomBounds);
}
- if (m_glWebViewState->scaleRequestState() != GLWebViewState::kNoScaleRequest
- || !tiledPage->ready(preZoomBounds, m_glWebViewState->currentScale()))
+ if (zoomManager->scaleRequestState() != ZoomManager::kNoScaleRequest
+ || !tiledPage->ready(preZoomBounds, zoomManager->currentScale()))
needsRedraw = true;
if (doSwap) {
- m_glWebViewState->setCurrentScale(scale);
+ zoomManager->setCurrentScale(scale);
m_glWebViewState->swapPages();
m_glWebViewState->unlockBaseLayerUpdate();
if (pagesSwapped)
@@ -264,55 +221,16 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
}
#endif // USE(ACCELERATED_COMPOSITING)
-bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot,
- IntRect& viewRect, SkRect& visibleRect,
- IntRect& webViewRect, int titleBarHeight,
- IntRect& screenClip, float scale,
- bool* pagesSwapped, SkColor color)
+bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
+ IntRect& viewRect, SkRect& visibleRect, float scale,
+ bool* pagesSwapped)
{
bool needsRedraw = 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 - %.2f",
- left, top, width, height, scale);
-
- m_glWebViewState->setBackgroundColor(color);
- if (TilesManager::instance()->invertedScreen()) {
- float color = 1.0 - ((((float) m_color.red() / 255.0) +
- ((float) m_color.green() / 255.0) +
- ((float) m_color.blue() / 255.0)) / 3.0);
- glClearColor(color, color, color, 1);
- } else {
- glClearColor((float)m_color.red() / 255.0,
- (float)m_color.green() / 255.0,
- (float)m_color.blue() / 255.0, 1);
- }
- glClear(GL_COLOR_BUFFER_BIT);
- glViewport(left, top, width, height);
- ShaderProgram* shader = TilesManager::instance()->shader();
- if (shader->program() == -1) {
- XLOG("Reinit shader");
- shader->init();
- }
- glUseProgram(shader->program());
- glUniform1i(shader->textureSampler(), 0);
- shader->setViewRect(viewRect);
- shader->setViewport(visibleRect);
- shader->setWebViewRect(webViewRect);
- shader->setTitleBarHeight(titleBarHeight);
- shader->setScreenClip(screenClip);
- shader->resetBlending();
-
- double currentTime = WTF::currentTime();
needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime,
pagesSwapped);
- bool goingDown = m_previousVisible.fTop - visibleRect.fTop <= 0;
- bool goingLeft = m_previousVisible.fLeft - visibleRect.fLeft >= 0;
- m_glWebViewState->setDirection(goingDown, goingLeft);
+
if (!needsRedraw)
m_glWebViewState->resetFrameworkInval();
@@ -327,19 +245,10 @@ bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot,
FloatRect clip(0, 0, viewRect.width(), viewRect.height());
compositedRoot->updateGLPositions(ident, clip, 1);
SkMatrix matrix;
- matrix.setTranslate(left, top);
-
- // Get the current scale; if we are zooming, we don't change the scale
- // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but
- // we change the scaleRequestState. When the state is kReceivedNewScale
- // we can use the future scale instead of the current scale to request
- // new textures. After a transition time, the scaleRequestState will be
- // reset and the current scale will be set to the future scale.
- float scale = m_glWebViewState->currentScale();
- if (m_glWebViewState->scaleRequestState() == GLWebViewState::kReceivedNewScale) {
- scale = m_glWebViewState->futureScale();
- }
- compositedRoot->setScale(scale);
+ matrix.setTranslate(viewRect.x(), viewRect.y());
+
+ // get the scale factor from the zoom manager
+ compositedRoot->setScale(m_glWebViewState->zoomManager()->layersScale());
#ifdef DEBUG
compositedRoot->showLayer(0);
@@ -358,7 +267,6 @@ bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot,
}
- glBindBuffer(GL_ARRAY_BUFFER, 0);
m_previousVisible = visibleRect;
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
index 62aabb6..35ce24c 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
@@ -55,9 +55,8 @@ public:
// we are running in different threads.
void drawCanvas(SkCanvas* canvas);
- bool drawGL(LayerAndroid* compositedRoot, IntRect& rect, SkRect& viewport,
- IntRect& webViewRect, int titleBarHeight, IntRect& screenClip,
- float scale, bool* pagesSwapped, SkColor color = SK_ColorWHITE);
+ bool drawGL(double currentTime, LayerAndroid* compositedRoot, IntRect& rect,
+ SkRect& viewport, float scale, bool* pagesSwapped);
void swapExtra(BaseLayerAndroid* base) { m_extra.swap(base->m_extra); }
private:
#if USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 53d32f7..e600b04 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -64,12 +64,7 @@ namespace WebCore {
using namespace android;
GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
- : m_scaleRequestState(kNoScaleRequest)
- , m_currentScale(-1)
- , m_futureScale(-1)
- , m_updateTime(-1)
- , m_transitionTime(-1)
- , m_baseLayer(0)
+ : m_baseLayer(0)
, m_currentBaseLayer(0)
, m_previouslyUsedRoot(0)
, m_currentPictureCounter(0)
@@ -85,6 +80,7 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
, m_goingLeft(false)
, m_expandedTileBoundsX(0)
, m_expandedTileBoundsY(0)
+ , m_zoomManager(this)
{
m_viewport.setEmpty();
m_previousViewport.setEmpty();
@@ -94,6 +90,7 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this);
m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this);
+
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("GLWebViewState");
#endif
@@ -243,7 +240,7 @@ void GLWebViewState::inval(const IntRect& rect)
// base layer is locked, so defer invalidation until unlockBaseLayerUpdate()
m_invalidateRegion.op(rect.x(), rect.y(), rect.maxX(), rect.maxY(), SkRegion::kUnion_Op);
}
- TilesManager::instance()->getProfiler()->nextInval(rect, m_currentScale);
+ TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale());
}
void GLWebViewState::resetRings()
@@ -338,66 +335,6 @@ unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
return m_currentPictureCounter;
}
-void GLWebViewState::scheduleUpdate(const double& currentTime,
- const SkIRect& viewport, float scale)
-{
- // if no update time, set it
- if (updateTime() == -1) {
- m_scaleRequestState = kWillScheduleRequest;
- setUpdateTime(currentTime + s_updateInitialDelay);
- setFutureScale(scale);
- setFutureViewport(viewport);
- 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);
- setFutureViewport(viewport);
- }
-}
-
-double GLWebViewState::zoomInTransitionTime(double currentTime)
-{
- if (m_transitionTime == -1)
- m_transitionTime = currentTime + s_zoomInTransitionDelay;
- return m_transitionTime;
-}
-
-double GLWebViewState::zoomOutTransitionTime(double currentTime)
-{
- if (m_transitionTime == -1)
- m_transitionTime = currentTime + s_zoomOutTransitionDelay;
- return m_transitionTime;
-}
-
-
-float GLWebViewState::zoomInTransparency(double currentTime)
-{
- float t = zoomInTransitionTime(currentTime) - currentTime;
- t *= s_invZoomInTransitionDelay;
- return fmin(1, fmax(0, t));
-}
-
-float GLWebViewState::zoomOutTransparency(double currentTime)
-{
- float t = zoomOutTransitionTime(currentTime) - currentTime;
- t *= s_invZoomOutTransitionDelay;
- return fmin(1, fmax(0, t));
-}
-
TiledPage* GLWebViewState::sibling(TiledPage* page)
{
return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA;
@@ -420,10 +357,8 @@ void GLWebViewState::swapPages()
android::Mutex::Autolock lock(m_tiledPageLock);
m_usePageA ^= true;
TiledPage* working = m_usePageA ? m_tiledPageB : m_tiledPageA;
- if (m_scaleRequestState != kNoScaleRequest)
+ if (zoomManager()->swapPages())
TilesManager::instance()->resetTextureUsage(working);
-
- m_scaleRequestState = kNoScaleRequest;
}
int GLWebViewState::baseContentWidth()
@@ -439,13 +374,17 @@ void GLWebViewState::setViewport(SkRect& viewport, float scale)
{
m_previousViewport = m_viewport;
if ((m_viewport == viewport) &&
- (m_futureScale == scale))
+ (zoomManager()->futureScale() == scale))
return;
+ m_goingDown = m_previousViewport.fTop - viewport.fTop <= 0;
+ m_goingLeft = m_previousViewport.fLeft - viewport.fLeft >= 0;
m_viewport = viewport;
+
XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)",
m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom,
- m_viewport.width(), m_viewport.height(), scale, m_currentScale, m_futureScale);
+ m_viewport.width(), m_viewport.height(), scale,
+ zoomManager()->currentScale(), zoomManager()->futureScale());
const float invTileContentWidth = scale / TilesManager::tileWidth();
const float invTileContentHeight = scale / TilesManager::tileHeight();
@@ -505,10 +444,54 @@ void GLWebViewState::resetLayersDirtyArea()
m_frameworkLayersInval.setHeight(0);
}
+double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
+ IntRect& webViewRect, int titleBarHeight,
+ IntRect& screenClip, float scale)
+{
+ int left = viewRect.x();
+ int top = viewRect.y();
+ int width = viewRect.width();
+ int height = viewRect.height();
+
+ if (TilesManager::instance()->invertedScreen()) {
+ float color = 1.0 - ((((float) m_backgroundColor.red() / 255.0) +
+ ((float) m_backgroundColor.green() / 255.0) +
+ ((float) m_backgroundColor.blue() / 255.0)) / 3.0);
+ glClearColor(color, color, color, 1);
+ } else {
+ glClearColor((float)m_backgroundColor.red() / 255.0,
+ (float)m_backgroundColor.green() / 255.0,
+ (float)m_backgroundColor.blue() / 255.0, 1);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glViewport(left, top, width, height);
+
+ ShaderProgram* shader = TilesManager::instance()->shader();
+ if (shader->program() == -1) {
+ XLOG("Reinit shader");
+ shader->init();
+ }
+ glUseProgram(shader->program());
+ glUniform1i(shader->textureSampler(), 0);
+ shader->setViewRect(viewRect);
+ shader->setViewport(visibleRect);
+ shader->setWebViewRect(webViewRect);
+ shader->setTitleBarHeight(titleBarHeight);
+ shader->setScreenClip(screenClip);
+ shader->resetBlending();
+
+ double currentTime = WTF::currentTime();
+
+ setViewport(visibleRect, scale);
+ m_zoomManager.processNewScale(currentTime, scale);
+
+ return currentTime;
+}
+
bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
- IntRect& clip, float scale, bool* pagesSwapped,
- SkColor color)
+ IntRect& clip, float scale, bool* pagesSwapped)
{
glFinish();
TilesManager::instance()->registerGLWebViewState(this);
@@ -568,8 +551,13 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
if (compositedRoot != m_previouslyUsedRoot)
TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, compositedRoot);
- bool ret = baseLayer->drawGL(compositedRoot, rect, viewport, webViewRect,
- titleBarHeight, clip, scale, pagesSwapped, color);
+ // set up zoom manager, shaders, etc.
+ m_backgroundColor = baseLayer->getBackgroundColor();
+ double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
+ bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect, viewport, scale, pagesSwapped);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
SkSafeRef(compositedRoot);
SkSafeUnref(m_previouslyUsedRoot);
m_previouslyUsedRoot = compositedRoot;
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h
index 34af317..421b25f 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h
@@ -28,12 +28,14 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "Color.h"
#include "DrawExtra.h"
#include "IntRect.h"
#include "SkCanvas.h"
#include "SkRect.h"
#include "SkRegion.h"
#include "TiledPage.h"
+#include "ZoomManager.h"
#include <utils/threads.h>
// Performance measurements probe
@@ -160,37 +162,17 @@ class LayerAndroid;
class GLWebViewState {
public:
- enum GLScaleStates {
- kNoScaleRequest = 0,
- kWillScheduleRequest = 1,
- kRequestNewScale = 2,
- kReceivedNewScale = 3
- };
- typedef int32_t GLScaleState;
-
GLWebViewState(android::Mutex* globalButtonMutex);
~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; }
+
+ ZoomManager* zoomManager() { return &m_zoomManager; }
const SkIRect& futureViewport() const { return m_futureViewportTileBounds; }
void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; }
- double updateTime() const { return m_updateTime; }
- void setUpdateTime(double value) { m_updateTime = value; }
- double zoomInTransitionTime(double currentTime);
- double zoomOutTransitionTime(double currentTime);
- float zoomInTransparency(double currentTime);
- float zoomOutTransparency(double currentTime);
- void resetTransitionTime() { m_transitionTime = -1; }
unsigned int paintBaseLayerContent(SkCanvas* canvas);
void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator,
bool isPictureAfterFirstLayout);
void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame);
- void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale);
void paintExtras();
void setRings(Vector<IntRect>& rings, bool isPressed);
@@ -230,13 +212,13 @@ public:
return false;
}
+ double setupDrawing(IntRect& rect, SkRect& viewport, IntRect& webViewRect,
+ int titleBarHeight, IntRect& screenClip,
+ float scale);
+
bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
- IntRect& clip, float scale, bool* pagesSwapped,
- SkColor color = SK_ColorWHITE);
-
- void setBackgroundColor(SkColor color) { m_backgroundColor = color; }
- SkColor getBackgroundColor() { return m_backgroundColor; }
+ IntRect& clip, float scale, bool* pagesSwapped);
#ifdef MEASURES_PERF
void dumpMeasures();
@@ -261,24 +243,7 @@ private:
void inval(const IntRect& rect); // caller must hold m_baseLayerLock
void invalRegion(const SkRegion& region);
- // 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_zoomInTransitionDelay = 0.1; // 100 ms
- static const double s_invZoomInTransitionDelay = 10;
- static const double s_zoomOutTransitionDelay = 0.2; // 200 ms
- static const double s_invZoomOutTransitionDelay = 5;
-
- GLScaleState m_scaleRequestState;
- float m_currentScale;
- float m_futureScale;
- double m_updateTime;
- double m_transitionTime;
+ ZoomManager m_zoomManager;
android::Mutex m_tiledPageLock;
SkRect m_viewport;
SkRect m_previousViewport;
@@ -302,7 +267,7 @@ private:
bool m_baseLayerUpdate;
SkRegion m_invalidateRegion;
- SkColor m_backgroundColor;
+ Color m_backgroundColor;
#ifdef MEASURES_PERF
unsigned int m_totalTimeCounter;
diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.cpp b/Source/WebCore/platform/graphics/android/ZoomManager.cpp
new file mode 100644
index 0000000..2cf9f06
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ZoomManager.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ZoomManager.h"
+
+#include "GLWebViewState.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <wtf/CurrentTime.h>
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+using namespace android;
+
+ZoomManager::ZoomManager(GLWebViewState* state)
+ : m_scaleRequestState(kNoScaleRequest)
+ , m_currentScale(-1)
+ , m_futureScale(-1)
+ , m_layersScale(-1)
+ , m_updateTime(-1)
+ , m_transitionTime(-1)
+ , m_glWebViewState(state)
+{
+}
+
+void ZoomManager::scheduleUpdate(const double& currentTime,
+ const SkIRect& viewport, float scale)
+{
+ // if no update time, set it
+ if (updateTime() == -1) {
+ m_scaleRequestState = kWillScheduleRequest;
+ setUpdateTime(currentTime + s_updateInitialDelay);
+ setFutureScale(scale);
+ m_glWebViewState->setFutureViewport(viewport);
+ 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);
+ m_glWebViewState->setFutureViewport(viewport);
+ }
+}
+
+double ZoomManager::zoomInTransitionTime(double currentTime)
+{
+ if (m_transitionTime == -1)
+ m_transitionTime = currentTime + s_zoomInTransitionDelay;
+ return m_transitionTime;
+}
+
+double ZoomManager::zoomOutTransitionTime(double currentTime)
+{
+ if (m_transitionTime == -1)
+ m_transitionTime = currentTime + s_zoomOutTransitionDelay;
+ return m_transitionTime;
+}
+
+float ZoomManager::zoomInTransparency(double currentTime)
+{
+ float t = zoomInTransitionTime(currentTime) - currentTime;
+ t *= s_invZoomInTransitionDelay;
+ return fmin(1, fmax(0, t));
+}
+
+float ZoomManager::zoomOutTransparency(double currentTime)
+{
+ float t = zoomOutTransitionTime(currentTime) - currentTime;
+ t *= s_invZoomOutTransitionDelay;
+ return fmin(1, fmax(0, t));
+}
+
+bool ZoomManager::swapPages()
+{
+ bool reset = m_scaleRequestState != kNoScaleRequest;
+ m_scaleRequestState = kNoScaleRequest;
+ return reset;
+}
+
+void ZoomManager::processNewScale(double currentTime, float scale)
+{
+ m_prepareNextTiledPage = false;
+ m_zooming = false;
+ const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds();
+
+ if (scale == m_currentScale
+ || m_glWebViewState->preZoomBounds().isEmpty())
+ m_glWebViewState->setPreZoomBounds(viewportTileBounds);
+
+ // 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_currentScale != scale
+ && (m_scaleRequestState == ZoomManager::kNoScaleRequest
+ || m_futureScale != scale))
+ || m_scaleRequestState == ZoomManager::kWillScheduleRequest) {
+
+ // schedule the new Zoom request
+ scheduleUpdate(currentTime, viewportTileBounds, scale);
+
+ // If it's a new request, we will have to prepare the page.
+ if (m_scaleRequestState == ZoomManager::kRequestNewScale)
+ m_prepareNextTiledPage = true;
+ }
+
+ // If the viewport has changed since we scheduled the request, we also need
+ // to prepare.
+ if ((m_scaleRequestState == ZoomManager::kRequestNewScale
+ || m_scaleRequestState == ZoomManager::kReceivedNewScale)
+ && m_glWebViewState->futureViewport() != viewportTileBounds)
+ m_prepareNextTiledPage = true;
+
+ // Checking if we are zooming...
+ if (m_scaleRequestState != ZoomManager::kNoScaleRequest) {
+ m_prepareNextTiledPage = true;
+ m_zooming = true;
+ }
+
+ // Get the current scale; if we are zooming, we don't change the scale
+ // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but
+ // we change the scaleRequestState. When the state is kReceivedNewScale
+ // (see setReceivedRequest()), we can use the future scale instead of
+ // the current scale to request new textures. After a transition time,
+ // the scaleRequestState will be reset and the current scale will be set
+ // to the future scale.
+ m_layersScale = m_currentScale;
+}
+
+void ZoomManager::processTransition(double currentTime, float scale,
+ bool* doSwap, float* backPageTransparency,
+ float* frontPageTransparency)
+{
+ if (scale < m_currentScale)
+ *backPageTransparency = 1 - zoomOutTransparency(currentTime);
+ else
+ *frontPageTransparency = zoomInTransparency(currentTime);
+
+ // The transition between the two page is finished
+ if (currentTime > transitionTime(currentTime, scale)) {
+ resetTransitionTime();
+ *doSwap = true;
+ }
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.h b/Source/WebCore/platform/graphics/android/ZoomManager.h
new file mode 100644
index 0000000..dd04c5d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ZoomManager.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ZoomManager_h
+#define ZoomManager_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "SkRect.h"
+
+namespace WebCore {
+
+class GLWebViewState;
+
+class ZoomManager {
+public:
+ enum GLScaleStates {
+ kNoScaleRequest = 0,
+ kWillScheduleRequest = 1,
+ kRequestNewScale = 2,
+ kReceivedNewScale = 3
+ };
+ typedef int32_t GLScaleState;
+
+ ZoomManager(GLWebViewState* state);
+
+ void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale);
+
+ 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; }
+ float layersScale() const { return m_layersScale; }
+ double zoomInTransitionTime(double currentTime);
+ double zoomOutTransitionTime(double currentTime);
+ float zoomInTransparency(double currentTime);
+ float zoomOutTransparency(double currentTime);
+ void resetTransitionTime() { m_transitionTime = -1; }
+ double updateTime() const { return m_updateTime; }
+ void setUpdateTime(double value) { m_updateTime = value; }
+
+ // state used by BaseLayerAndroid
+ bool needPrepareNextTiledPage() { return m_prepareNextTiledPage; }
+ bool zooming() { return m_zooming; }
+
+ bool didFireRequest() { return m_scaleRequestState == ZoomManager::kRequestNewScale; }
+ void setReceivedRequest() {
+ m_scaleRequestState = ZoomManager::kReceivedNewScale;
+ m_layersScale = m_futureScale;
+ }
+ bool didReceivedRequest() { return m_scaleRequestState == ZoomManager::kReceivedNewScale; }
+
+ double transitionTime(double currentTime, float scale) {
+ return (scale < m_currentScale) ? zoomOutTransitionTime(currentTime)
+ : zoomInTransitionTime(currentTime);
+ }
+ void processTransition(double currentTime, float scale, bool* doSwap,
+ float* backPageTransparency, float* frontPageTransparency);
+
+ bool swapPages();
+
+ void processNewScale(double currentTime, float scale);
+
+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_zoomInTransitionDelay = 0.1; // 100 ms
+ static const double s_invZoomInTransitionDelay = 10;
+ static const double s_zoomOutTransitionDelay = 0.2; // 200 ms
+ static const double s_invZoomOutTransitionDelay = 5;
+
+ GLScaleState m_scaleRequestState;
+ float m_currentScale;
+ float m_futureScale;
+ float m_layersScale;
+ double m_updateTime;
+ double m_transitionTime;
+
+ bool m_prepareNextTiledPage;
+ bool m_zooming;
+
+ GLWebViewState* m_glWebViewState;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#endif // ZoomManager_h