Add hooks for hardware accelerated WebView.

Change-Id: I907cdec8a67594f87749ac46bda85f04af5a2003
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index b058685..65cb182 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -55,7 +55,9 @@
     private final Rect mClipBounds = new Rect();
 
     private DrawFilter mFilter;
-    
+
+    private boolean mContextLocked;
+
     ///////////////////////////////////////////////////////////////////////////
     // JNI
     ///////////////////////////////////////////////////////////////////////////
@@ -149,6 +151,27 @@
     
     private native void nPrepare(int renderer);
 
+    @Override
+    public boolean acquireContext() {
+        if (!mContextLocked) {
+            nAcquireContext(mRenderer);
+            mContextLocked = true;
+        }
+        return mContextLocked;
+    }
+
+    private native void nAcquireContext(int renderer);
+
+    @Override
+    public void releaseContext() {
+        if (mContextLocked) {
+            nReleaseContext(mRenderer);
+            mContextLocked = false;
+        }
+    }
+
+    private native void nReleaseContext(int renderer);
+
     ///////////////////////////////////////////////////////////////////////////
     // Clipping
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 98c03a6..aa71746 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -84,6 +84,16 @@
     renderer->prepare();
 }
 
+static void android_view_GLES20Canvas_acquireContext(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer) {
+    renderer->acquireContext();
+}
+
+static void android_view_GLES20Canvas_releaseContext(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer) {
+    renderer->releaseContext();
+}
+
 // ----------------------------------------------------------------------------
 // State
 // ----------------------------------------------------------------------------
@@ -374,6 +384,8 @@
     { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
     { "nSetViewport",       "(III)V",          (void*) android_view_GLES20Canvas_setViewport },
     { "nPrepare",           "(I)V",            (void*) android_view_GLES20Canvas_prepare },
+    { "nAcquireContext",    "(I)V",            (void*) android_view_GLES20Canvas_acquireContext },
+    { "nReleaseContext",    "(I)V",            (void*) android_view_GLES20Canvas_releaseContext },
 
     { "nSave",              "(II)I",           (void*) android_view_GLES20Canvas_save },
     { "nRestore",           "(I)V",            (void*) android_view_GLES20Canvas_restore },
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 36a8e57..e75a19e 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1551,7 +1551,52 @@
         drawPicture(picture);
         restore();
     }
-    
+
+    /**
+     * <p>Acquires the Canvas context. After invoking this method, the Canvas
+     * context  can be modified by the caller. For instance, if you acquire
+     * the context of an OpenGL Canvas you can reset the GL viewport, scissor,
+     * etc.</p>
+     * 
+     * <p>A call to {@link #acquireContext()} should aways be followed by
+     * a call to {@link #releaseContext()}, preferrably using a try block:</p>
+     * 
+     * <pre>
+     * try {
+     *     if (canvas.acquireContext()) {
+     *         // Use the canvas and/or its context
+     *     }
+     * } finally {
+     *     canvas.releaseContext();
+     * }
+     * </pre>
+     * 
+     * <p>Acquiring the context can be an expensive operation and should not
+     * be done unless absolutely necessary.</p>
+     * 
+     * <p>Applications should never invoke this method directly.</p>
+     * 
+     * @return True if the context could be acquired successfully, false
+     *         otherwise (if the context is already acquired for instance.)
+     * 
+     * @see #releaseContext() 
+     * 
+     * @hide
+     */
+    public boolean acquireContext() {
+        return false;
+    }
+
+    /**
+     * <p>Release the context acquired with {@link #acquireContext()}.</p>
+     * 
+     * @see #acquireContext() 
+     * 
+     * @hide
+     */
+    public void releaseContext() {
+    }
+
     @Override
     protected void finalize() throws Throwable {
         try {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4ce30b0..02f5dc5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -143,6 +143,29 @@
     mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
 }
 
+void OpenGLRenderer::acquireContext() {
+    if (mCaches.currentProgram) {
+        if (mCaches.currentProgram->isInUse()) {
+            mCaches.currentProgram->remove();
+            mCaches.currentProgram = NULL;
+        }
+    }
+}
+
+void OpenGLRenderer::releaseContext() {
+    glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
+
+    glEnable(GL_SCISSOR_TEST);
+    setScissorFromClip();
+
+    if (mCaches.blend) {
+        glEnable(GL_BLEND);
+        glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
+    } else {
+        glDisable(GL_BLEND);
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // State management
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 5748d57..d0e04b2 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -58,6 +58,8 @@
 
     void setViewport(int width, int height);
     void prepare();
+    void acquireContext();
+    void releaseContext();
 
     int getSaveCount() const;
     int save(int flags);