1a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon/*
2a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * Copyright (C) 2012 The Android Open Source Project
3a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *
4a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * Licensed under the Apache License, Version 2.0 (the "License");
5a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * you may not use this file except in compliance with the License.
6a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * You may obtain a copy of the License at
7a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *
8a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *      http://www.apache.org/licenses/LICENSE-2.0
9a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *
10a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * Unless required by applicable law or agreed to in writing, software
11a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * distributed under the License is distributed on an "AS IS" BASIS,
12a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * See the License for the specific language governing permissions and
14a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * limitations under the License.
15a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon */
16a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
17a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonpackage com.android.webview.chromium;
18a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
19a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonimport android.view.DisplayList;
20a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonimport android.view.HardwareCanvas;
21a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonimport android.view.ViewRootImpl;
22a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonimport android.util.Log;
23a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
24a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonimport org.chromium.content.common.CleanupReference;
25a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
26a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// Simple Java abstraction and wrapper for the native DrawGLFunctor flow.
27a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// An instance of this class can be constructed, bound to a single view context (i.e. AwContennts)
28a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// and then drawn and detached from the view tree any number of times (using requestDrawGL and
29a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// detach respectively). Then when finished with, it can be explicitly released by calling
30a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// destroy() or will clean itself up as required via finalizer / CleanupReference.
31a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonclass DrawGLFunctor {
32a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
33a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private static final String TAG = DrawGLFunctor.class.getSimpleName();
34a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
35a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Pointer to native side instance
36a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private CleanupReference mCleanupReference;
37a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private DestroyRunnable mDestroyRunnable;
38a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
39a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    public DrawGLFunctor(int viewContext) {
40a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        mDestroyRunnable = new DestroyRunnable(nativeCreateGLFunctor(viewContext));
41a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        mCleanupReference = new CleanupReference(this, mDestroyRunnable);
42a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
43a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
44a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    public void destroy() {
45a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        if (mCleanupReference != null) {
46a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            mCleanupReference.cleanupNow();
47a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            mCleanupReference = null;
48a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            mDestroyRunnable = null;
49a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        }
50a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
51a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
52a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    public void detach() {
53a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        mDestroyRunnable.detachNativeFunctor();
54a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
55a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
5651f7cf16cd02f14050bb723175a2a57570e8486dTao Bai    public boolean requestDrawGL(HardwareCanvas canvas, ViewRootImpl viewRootImpl) {
57a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        if (mDestroyRunnable.mNativeDrawGLFunctor == 0) {
58a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            throw new RuntimeException("requested DrawGL on already destroyed DrawGLFunctor");
59a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        }
60a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        mDestroyRunnable.mViewRootImpl = viewRootImpl;
6151f7cf16cd02f14050bb723175a2a57570e8486dTao Bai        if (canvas != null) {
6251f7cf16cd02f14050bb723175a2a57570e8486dTao Bai            int ret = canvas.callDrawGLFunction(mDestroyRunnable.mNativeDrawGLFunctor);
6351f7cf16cd02f14050bb723175a2a57570e8486dTao Bai            if (ret != DisplayList.STATUS_DONE) {
6451f7cf16cd02f14050bb723175a2a57570e8486dTao Bai                Log.e(TAG, "callDrawGLFunction error: " + ret);
6551f7cf16cd02f14050bb723175a2a57570e8486dTao Bai                return false;
6651f7cf16cd02f14050bb723175a2a57570e8486dTao Bai            }
6751f7cf16cd02f14050bb723175a2a57570e8486dTao Bai        } else {
6851f7cf16cd02f14050bb723175a2a57570e8486dTao Bai            viewRootImpl.attachFunctor(mDestroyRunnable.mNativeDrawGLFunctor);
6951f7cf16cd02f14050bb723175a2a57570e8486dTao Bai        }
7051f7cf16cd02f14050bb723175a2a57570e8486dTao Bai        return true;
71a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
72a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
73a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    public static void setChromiumAwDrawGLFunction(int functionPointer) {
74a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        nativeSetChromiumAwDrawGLFunction(functionPointer);
75a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
76a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
77a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Holds the core resources of the class, everything required to correctly cleanup.
78a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // IMPORTANT: this class must not hold any reference back to the outer DrawGLFunctor
79a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // instance, as that will defeat GC of that object.
80a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private static final class DestroyRunnable implements Runnable {
81a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        ViewRootImpl mViewRootImpl;
82a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        int mNativeDrawGLFunctor;
83a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        DestroyRunnable(int nativeDrawGLFunctor) {
84a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            mNativeDrawGLFunctor = nativeDrawGLFunctor;
85a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        }
86a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
87a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        // Called when the outer DrawGLFunctor instance has been GC'ed, i.e this is its finalizer.
88a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        @Override
89a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        public void run() {
90a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            detachNativeFunctor();
91a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            nativeDestroyGLFunctor(mNativeDrawGLFunctor);
92a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            mNativeDrawGLFunctor = 0;
93a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        }
94a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
95a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        void detachNativeFunctor() {
96a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            if (mNativeDrawGLFunctor != 0 && mViewRootImpl != null) {
97a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon                mViewRootImpl.detachFunctor(mNativeDrawGLFunctor);
98a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            }
99a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon            mViewRootImpl = null;
100a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        }
101a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
102a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
103a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private static native int nativeCreateGLFunctor(int viewContext);
104a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private static native void nativeDestroyGLFunctor(int functor);
105a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    private static native void nativeSetChromiumAwDrawGLFunction(int functionPointer);
106a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}
107