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 17package com.android.webview.chromium; 18 19import android.view.DisplayList; 20import android.view.HardwareCanvas; 21import android.view.ViewRootImpl; 22import android.util.Log; 23 24import org.chromium.content.common.CleanupReference; 25 26// Simple Java abstraction and wrapper for the native DrawGLFunctor flow. 27// An instance of this class can be constructed, bound to a single view context (i.e. AwContennts) 28// and then drawn and detached from the view tree any number of times (using requestDrawGL and 29// detach respectively). Then when finished with, it can be explicitly released by calling 30// destroy() or will clean itself up as required via finalizer / CleanupReference. 31class DrawGLFunctor { 32 33 private static final String TAG = DrawGLFunctor.class.getSimpleName(); 34 35 // Pointer to native side instance 36 private CleanupReference mCleanupReference; 37 private DestroyRunnable mDestroyRunnable; 38 39 public DrawGLFunctor(int viewContext) { 40 mDestroyRunnable = new DestroyRunnable(nativeCreateGLFunctor(viewContext)); 41 mCleanupReference = new CleanupReference(this, mDestroyRunnable); 42 } 43 44 public void destroy() { 45 if (mCleanupReference != null) { 46 mCleanupReference.cleanupNow(); 47 mCleanupReference = null; 48 mDestroyRunnable = null; 49 } 50 } 51 52 public void detach() { 53 mDestroyRunnable.detachNativeFunctor(); 54 } 55 56 public boolean requestDrawGL(HardwareCanvas canvas, ViewRootImpl viewRootImpl) { 57 if (mDestroyRunnable.mNativeDrawGLFunctor == 0) { 58 throw new RuntimeException("requested DrawGL on already destroyed DrawGLFunctor"); 59 } 60 mDestroyRunnable.mViewRootImpl = viewRootImpl; 61 if (canvas != null) { 62 int ret = canvas.callDrawGLFunction(mDestroyRunnable.mNativeDrawGLFunctor); 63 if (ret != DisplayList.STATUS_DONE) { 64 Log.e(TAG, "callDrawGLFunction error: " + ret); 65 return false; 66 } 67 } else { 68 viewRootImpl.attachFunctor(mDestroyRunnable.mNativeDrawGLFunctor); 69 } 70 return true; 71 } 72 73 public static void setChromiumAwDrawGLFunction(int functionPointer) { 74 nativeSetChromiumAwDrawGLFunction(functionPointer); 75 } 76 77 // Holds the core resources of the class, everything required to correctly cleanup. 78 // IMPORTANT: this class must not hold any reference back to the outer DrawGLFunctor 79 // instance, as that will defeat GC of that object. 80 private static final class DestroyRunnable implements Runnable { 81 ViewRootImpl mViewRootImpl; 82 int mNativeDrawGLFunctor; 83 DestroyRunnable(int nativeDrawGLFunctor) { 84 mNativeDrawGLFunctor = nativeDrawGLFunctor; 85 } 86 87 // Called when the outer DrawGLFunctor instance has been GC'ed, i.e this is its finalizer. 88 @Override 89 public void run() { 90 detachNativeFunctor(); 91 nativeDestroyGLFunctor(mNativeDrawGLFunctor); 92 mNativeDrawGLFunctor = 0; 93 } 94 95 void detachNativeFunctor() { 96 if (mNativeDrawGLFunctor != 0 && mViewRootImpl != null) { 97 mViewRootImpl.detachFunctor(mNativeDrawGLFunctor); 98 } 99 mViewRootImpl = null; 100 } 101 } 102 103 private static native int nativeCreateGLFunctor(int viewContext); 104 private static native void nativeDestroyGLFunctor(int functor); 105 private static native void nativeSetChromiumAwDrawGLFunction(int functionPointer); 106} 107