diff options
author | Nicolas Roard <nicolasroard@google.com> | 2011-08-19 11:46:09 -0700 |
---|---|---|
committer | Nicolas Roard <nicolasroard@google.com> | 2011-08-19 13:39:26 -0700 |
commit | 77e5b594dd717e27b1a8be2b521f738cf5941ae1 (patch) | |
tree | f088b9113d8a9043638a0bcd99156e2d5ffc8287 /Source/WebCore/platform/graphics | |
parent | 03721d93591244128ff918202425d381e2fedf50 (diff) | |
download | external_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')
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 |