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