OSDN Git Service

WebView Animation support
authorTeng-Hui Zhu <ztenghui@google.com>
Mon, 14 Nov 2011 19:05:16 +0000 (11:05 -0800)
committerTeng-Hui Zhu <ztenghui@google.com>
Tue, 29 Nov 2011 17:35:34 +0000 (09:35 -0800)
bug:4982054
Change-Id: I1e8ea5ed7043a7140254a99053cf241de1b0ef3e

Source/WebCore/platform/graphics/android/GLUtils.cpp
Source/WebCore/platform/graphics/android/GLUtils.h
Source/WebCore/platform/graphics/android/GLWebViewState.cpp
Source/WebCore/platform/graphics/android/ShaderProgram.cpp
Source/WebCore/platform/graphics/android/ShaderProgram.h
Source/WebKit/android/nav/WebView.cpp

index d1fe51a..97a53fe 100644 (file)
@@ -562,6 +562,15 @@ void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
 }
 
+void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix)
+{
+    transformMatrix.setMatrix(
+        matrix[0], matrix[1], matrix[2], matrix[3],
+        matrix[4], matrix[5], matrix[6], matrix[7],
+        matrix[8], matrix[9], matrix[10], matrix[11],
+        matrix[12], matrix[13], matrix[14], matrix[15]);
+}
+
 } // namespace WebCore
 
 #endif // USE(ACCELERATED_COMPOSITING)
index b952513..68acbab 100644 (file)
@@ -83,6 +83,7 @@ public:
     static void updateSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap, GLint filter  = GL_LINEAR);
 #endif
     static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap);
+    static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix);
 };
 
 } // namespace WebCore
index a33c3d0..a3c82ce 100644 (file)
@@ -335,7 +335,6 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
     int top = viewRect.y();
     int width = viewRect.width();
     int height = viewRect.height();
-    glViewport(left, top, width, height);
 
     ShaderProgram* shader = TilesManager::instance()->shader();
     if (shader->program() == -1) {
@@ -343,12 +342,18 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
         shader->init();
     }
     shader->setViewRect(viewRect);
-    shader->setViewport(visibleRect);
+    shader->setViewport(visibleRect, scale);
     shader->setWebViewRect(webViewRect);
     shader->setTitleBarHeight(titleBarHeight);
     shader->setScreenClip(screenClip);
     shader->resetBlending();
 
+    shader->calculateAnimationDelta();
+
+    glViewport(left + shader->getAnimationDeltaX(),
+               top - shader->getAnimationDeltaY(),
+               width, height);
+
     double currentTime = WTF::currentTime();
 
     setViewport(visibleRect, scale);
index cc9c810..2a6a488 100644 (file)
@@ -195,6 +195,8 @@ GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFrag
 ShaderProgram::ShaderProgram()
     : m_blendingEnabled(false)
     , m_contrast(1)
+    , m_alphaLayer(false)
+    , m_currentScale(1.0f)
 {
     init();
 }
@@ -286,13 +288,14 @@ void ShaderProgram::setBlendingState(bool enableBlending)
 // Drawing
 /////////////////////////////////////////////////////////////////////////////////////////
 
-void ShaderProgram::setViewport(SkRect& viewport)
+void ShaderProgram::setViewport(SkRect& viewport, float scale)
 {
     TransformationMatrix ortho;
     GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
                                    viewport.fRight, viewport.fBottom, -1000, 1000);
     m_projectionMatrix = ortho;
     m_viewport = viewport;
+    m_currentScale = scale;
 }
 
 void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
@@ -302,7 +305,12 @@ void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrix
     TransformationMatrix scale;
     scale.scale3d(geometry.width(), geometry.height(), 1.0);
 
-    TransformationMatrix total = m_projectionMatrix * translate * scale;
+    TransformationMatrix total;
+    if (!m_alphaLayer)
+        total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix
+                * translate * scale;
+    else
+        total = m_projectionMatrix * translate * scale;
 
     GLfloat projectionMatrix[16];
     GLUtils::toGLMatrix(projectionMatrix, total);
@@ -560,7 +568,13 @@ void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
     // move the drawing depending on where the texture is on the layer
     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
-    TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
+
+    TransformationMatrix renderMatrix;
+    if (!m_alphaLayer)
+        renderMatrix = m_projectionMatrix * m_repositionMatrix
+                       * m_webViewMatrix * modifiedDrawMatrix;
+    else
+        renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
 
     GLfloat projectionMatrix[16];
     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
@@ -627,6 +641,44 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 
+void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer)
+{
+    GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix);
+    m_alphaLayer = alphaLayer;
+}
+
+void ShaderProgram::calculateAnimationDelta()
+{
+    // The matrix contains the scrolling info, so this rect is starting from
+    // the m_viewport.
+    // So we just need to map the webview's visible rect using the matrix,
+    // calculate the difference b/t transformed rect and the webViewRect,
+    // then we can get the delta x , y caused by the animation.
+    // Note that the Y is for reporting back to GL viewport, so it is inverted.
+    // When it is alpha animation, then we rely on the framework implementation
+    // such that there is no matrix applied in native webkit.
+    if (!m_alphaLayer) {
+        FloatRect rect(m_viewport.fLeft * m_currentScale,
+                       m_viewport.fTop * m_currentScale,
+                       m_webViewRect.width(),
+                       m_webViewRect.height());
+        rect = m_webViewMatrix.mapRect(rect);
+        m_animationDelta.setX(rect.x() - m_webViewRect.x() );
+        m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y()
+                              - m_webViewRect.height() - m_titleBarHeight);
+
+        m_repositionMatrix.makeIdentity();
+        m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0);
+        m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0);
+        m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0);
+    } else {
+        m_animationDelta.setX(0);
+        m_animationDelta.setY(0);
+        m_repositionMatrix.makeIdentity();
+    }
+
+}
+
 } // namespace WebCore
 
 #endif // USE(ACCELERATED_COMPOSITING)
index b309872..9ab7a46 100644 (file)
@@ -36,7 +36,7 @@ public:
     int program() { return m_program; }
 
     // Drawing
-    void setViewport(SkRect& viewport);
+    void setViewport(SkRect& viewport, float scale);
     float zValue(const TransformationMatrix& drawMatrix, float w, float h);
 
     // For drawQuad and drawLayerQuad, they can handle 3 cases for now:
@@ -88,6 +88,18 @@ public:
             contrast = MAX_CONTRAST;
         m_contrast = contrast;
     }
+    void setWebViewMatrix(const float* matrix, bool alphaLayer);
+
+    // This delta is the delta from the layout pos and the current animation pos.
+    // Basically, in terms of layout, the webview is still in the original layout
+    // pos, as without animation. Such that the viewport and visible rect etc are
+    // still in that pos, too, except the clipping info.
+    // Our rendering approach is after applying all the matrix, webView is
+    // rendered as if it was at the original layout pos, but then offset the
+    // glViewport to match the animation.
+    void calculateAnimationDelta();
+    int getAnimationDeltaX() { return m_animationDelta.x(); }
+    int getAnimationDeltaY() { return m_animationDelta.y(); }
 
 private:
     GLuint loadShader(GLenum shaderType, const char* pSource);
@@ -158,6 +170,22 @@ private:
     GLint m_hPosition;
     GLint m_hPositionInverted;
     GLint m_hVideoPosition;
+
+    bool  m_alphaLayer;
+    TransformationMatrix m_webViewMatrix;
+    float m_currentScale;
+
+    // After the webViewTranform, we need to reposition the rect to match our viewport.
+    // Basically, the webViewTransformMatrix should apply on the screen resolution.
+    // So we start by doing the scale and translate to get each tile into screen coordinates.
+    // After applying the webViewTransformMatrix, b/c the way it currently set up
+    // for scroll and titlebar, we need to offset both of them.
+    // Finally, map everything back to (-1, 1) by using the m_projectionMatrix.
+    // TODO: Given that m_webViewMatrix contains most of the tranformation
+    // information, we should be able to get rid of some parameter we got from
+    // Java side and simplify our code.
+    TransformationMatrix  m_repositionMatrix;
+    IntPoint m_animationDelta;
 };
 
 } // namespace WebCore
index 13346b3..1dfa385 100644 (file)
@@ -1584,6 +1584,7 @@ class GLDrawFunctor : Functor {
         WebCore::IntRect clip(info->clipLeft, info->clipTop,
                               info->clipRight - info->clipLeft,
                               info->clipBottom - info->clipTop);
+        TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer);
 
         bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect,
                 titlebarHeight, clip, scale, extras);