1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.webview.chromium;
18 
19 import android.view.View;
20 import android.graphics.Canvas;
21 import android.util.Log;
22 
23 import com.android.webview.chromium.WebViewDelegateFactory.WebViewDelegate;
24 
25 import org.chromium.content.common.CleanupReference;
26 
27 // Simple Java abstraction and wrapper for the native DrawGLFunctor flow.
28 // An instance of this class can be constructed, bound to a single view context (i.e. AwContennts)
29 // and then drawn and detached from the view tree any number of times (using requestDrawGL and
30 // detach respectively). Then when finished with, it can be explicitly released by calling
31 // destroy() or will clean itself up as required via finalizer / CleanupReference.
32 class DrawGLFunctor {
33 
34     private static final String TAG = DrawGLFunctor.class.getSimpleName();
35 
36     // Pointer to native side instance
37     private CleanupReference mCleanupReference;
38     private DestroyRunnable mDestroyRunnable;
39     private WebViewDelegate mWebViewDelegate;
40 
DrawGLFunctor(long viewContext, WebViewDelegate webViewDelegate)41     public DrawGLFunctor(long viewContext, WebViewDelegate webViewDelegate) {
42         mDestroyRunnable = new DestroyRunnable(nativeCreateGLFunctor(viewContext), webViewDelegate);
43         mCleanupReference = new CleanupReference(this, mDestroyRunnable);
44         mWebViewDelegate = webViewDelegate;
45     }
46 
destroy()47     public void destroy() {
48         detach();
49         if (mCleanupReference != null) {
50             mCleanupReference.cleanupNow();
51             mCleanupReference = null;
52             mDestroyRunnable = null;
53             mWebViewDelegate = null;
54         }
55     }
56 
detach()57     public void detach() {
58         mDestroyRunnable.detachNativeFunctor();
59     }
60 
requestDrawGL(Canvas canvas, View containerView, boolean waitForCompletion)61     public boolean requestDrawGL(Canvas canvas, View containerView,
62             boolean waitForCompletion) {
63         if (mDestroyRunnable.mNativeDrawGLFunctor == 0) {
64             throw new RuntimeException("requested DrawGL on already destroyed DrawGLFunctor");
65         }
66 
67         if (!mWebViewDelegate.canInvokeDrawGlFunctor(containerView)) {
68             return false;
69         }
70 
71         mDestroyRunnable.mContainerView = containerView;
72 
73         if (canvas == null) {
74             mWebViewDelegate.invokeDrawGlFunctor(containerView,
75                     mDestroyRunnable.mNativeDrawGLFunctor, waitForCompletion);
76             return true;
77         }
78 
79         mWebViewDelegate.callDrawGlFunction(canvas, mDestroyRunnable.mNativeDrawGLFunctor);
80         if (waitForCompletion) {
81             mWebViewDelegate.invokeDrawGlFunctor(containerView,
82                     mDestroyRunnable.mNativeDrawGLFunctor, waitForCompletion);
83         }
84         return true;
85     }
86 
setChromiumAwDrawGLFunction(long functionPointer)87     public static void setChromiumAwDrawGLFunction(long functionPointer) {
88         nativeSetChromiumAwDrawGLFunction(functionPointer);
89     }
90 
91     // Holds the core resources of the class, everything required to correctly cleanup.
92     // IMPORTANT: this class must not hold any reference back to the outer DrawGLFunctor
93     // instance, as that will defeat GC of that object.
94     private static final class DestroyRunnable implements Runnable {
95         private WebViewDelegate mWebViewDelegate;
96         View mContainerView;
97         long mNativeDrawGLFunctor;
DestroyRunnable(long nativeDrawGLFunctor, WebViewDelegate webViewDelegate)98         DestroyRunnable(long nativeDrawGLFunctor, WebViewDelegate webViewDelegate) {
99             mNativeDrawGLFunctor = nativeDrawGLFunctor;
100             mWebViewDelegate = webViewDelegate;
101         }
102 
103         // Called when the outer DrawGLFunctor instance has been GC'ed, i.e this is its finalizer.
104         @Override
run()105         public void run() {
106             detachNativeFunctor();
107             nativeDestroyGLFunctor(mNativeDrawGLFunctor);
108             mNativeDrawGLFunctor = 0;
109         }
110 
detachNativeFunctor()111         void detachNativeFunctor() {
112             if (mNativeDrawGLFunctor != 0 && mContainerView != null
113                     && mWebViewDelegate != null) {
114                 mWebViewDelegate.detachDrawGlFunctor(mContainerView, mNativeDrawGLFunctor);
115             }
116             mContainerView = null;
117             mWebViewDelegate = null;
118         }
119     }
120 
nativeCreateGLFunctor(long viewContext)121     private static native long nativeCreateGLFunctor(long viewContext);
nativeDestroyGLFunctor(long functor)122     private static native void nativeDestroyGLFunctor(long functor);
nativeSetChromiumAwDrawGLFunction(long functionPointer)123     private static native void nativeSetChromiumAwDrawGLFunction(long functionPointer);
124 }
125