HardwareLayer.java revision e4267ea4f20740c37c01bfb6aefcf61fddc4566a
1/* 2 * Copyright (C) 2011 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 android.view; 18 19import android.graphics.Bitmap; 20import android.graphics.Matrix; 21import android.graphics.Paint; 22import android.graphics.Rect; 23import android.graphics.SurfaceTexture; 24 25import com.android.internal.util.VirtualRefBasePtr; 26 27/** 28 * A hardware layer can be used to render graphics operations into a hardware 29 * friendly buffer. For instance, with an OpenGL backend a hardware layer 30 * would use a Frame Buffer Object (FBO.) The hardware layer can be used as 31 * a drawing cache when a complex set of graphics operations needs to be 32 * drawn several times. 33 * 34 * @hide 35 */ 36final class HardwareLayer { 37 private static final int LAYER_TYPE_TEXTURE = 1; 38 private static final int LAYER_TYPE_DISPLAY_LIST = 2; 39 40 private HardwareRenderer mRenderer; 41 private VirtualRefBasePtr mFinalizer; 42 private RenderNode mDisplayList; 43 private final int mLayerType; 44 45 private HardwareLayer(HardwareRenderer renderer, long deferredUpdater, int type) { 46 if (renderer == null || deferredUpdater == 0) { 47 throw new IllegalArgumentException("Either hardware renderer: " + renderer 48 + " or deferredUpdater: " + deferredUpdater + " is invalid"); 49 } 50 mRenderer = renderer; 51 mLayerType = type; 52 mFinalizer = new VirtualRefBasePtr(deferredUpdater); 53 } 54 55 private void assertType(int type) { 56 if (mLayerType != type) { 57 throw new IllegalAccessError("Method not appropriate for this layer type! " + mLayerType); 58 } 59 } 60 61 boolean hasDisplayList() { 62 return mDisplayList != null; 63 } 64 65 /** 66 * Update the paint used when drawing this layer. 67 * 68 * @param paint The paint used when the layer is drawn into the destination canvas. 69 * @see View#setLayerPaint(android.graphics.Paint) 70 */ 71 public void setLayerPaint(Paint paint) { 72 nSetLayerPaint(mFinalizer.get(), paint.mNativePaint); 73 mRenderer.pushLayerUpdate(this); 74 } 75 76 /** 77 * Indicates whether this layer can be rendered. 78 * 79 * @return True if the layer can be rendered into, false otherwise 80 */ 81 public boolean isValid() { 82 return mFinalizer != null && mFinalizer.get() != 0; 83 } 84 85 /** 86 * Destroys resources without waiting for a GC. 87 */ 88 public void destroy() { 89 if (!isValid()) { 90 // Already destroyed 91 return; 92 } 93 94 if (mDisplayList != null) { 95 mDisplayList.destroyDisplayListData(); 96 mDisplayList = null; 97 } 98 mRenderer.onLayerDestroyed(this); 99 mRenderer = null; 100 mFinalizer.release(); 101 mFinalizer = null; 102 } 103 104 public long getDeferredLayerUpdater() { 105 return mFinalizer.get(); 106 } 107 108 public RenderNode startRecording() { 109 assertType(LAYER_TYPE_DISPLAY_LIST); 110 111 if (mDisplayList == null) { 112 mDisplayList = RenderNode.create("HardwareLayer"); 113 } 114 return mDisplayList; 115 } 116 117 public void endRecording(Rect dirtyRect) { 118 nUpdateRenderLayer(mFinalizer.get(), mDisplayList.getNativeDisplayList(), 119 dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); 120 mRenderer.pushLayerUpdate(this); 121 } 122 123 /** 124 * Copies this layer into the specified bitmap. 125 * 126 * @param bitmap The bitmap to copy they layer into 127 * 128 * @return True if the copy was successful, false otherwise 129 */ 130 public boolean copyInto(Bitmap bitmap) { 131 return mRenderer.copyLayerInto(this, bitmap); 132 } 133 134 /** 135 * Update the layer's properties. Note that after calling this isValid() may 136 * return false if the requested width/height cannot be satisfied 137 * 138 * @param width The new width of this layer 139 * @param height The new height of this layer 140 * @param isOpaque Whether this layer is opaque 141 * 142 * @return true if the layer's properties will change, false if they already 143 * match the desired values. 144 */ 145 public boolean prepare(int width, int height, boolean isOpaque) { 146 return nPrepare(mFinalizer.get(), width, height, isOpaque); 147 } 148 149 /** 150 * Sets an optional transform on this layer. 151 * 152 * @param matrix The transform to apply to the layer. 153 */ 154 public void setTransform(Matrix matrix) { 155 nSetTransform(mFinalizer.get(), matrix.native_instance); 156 mRenderer.pushLayerUpdate(this); 157 } 158 159 /** 160 * Indicates that this layer has lost its texture. 161 */ 162 public void detachSurfaceTexture(final SurfaceTexture surface) { 163 assertType(LAYER_TYPE_TEXTURE); 164 mRenderer.safelyRun(new Runnable() { 165 @Override 166 public void run() { 167 surface.detachFromGLContext(); 168 // SurfaceTexture owns the texture name and detachFromGLContext 169 // should have deleted it 170 nOnTextureDestroyed(mFinalizer.get()); 171 } 172 }); 173 } 174 175 public long getLayer() { 176 return nGetLayer(mFinalizer.get()); 177 } 178 179 public void setSurfaceTexture(SurfaceTexture surface) { 180 assertType(LAYER_TYPE_TEXTURE); 181 nSetSurfaceTexture(mFinalizer.get(), surface, false); 182 mRenderer.pushLayerUpdate(this); 183 } 184 185 public void updateSurfaceTexture() { 186 assertType(LAYER_TYPE_TEXTURE); 187 nUpdateSurfaceTexture(mFinalizer.get()); 188 mRenderer.pushLayerUpdate(this); 189 } 190 191 /** 192 * This should only be used by HardwareRenderer! Do not call directly 193 */ 194 SurfaceTexture createSurfaceTexture() { 195 assertType(LAYER_TYPE_TEXTURE); 196 SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.get())); 197 nSetSurfaceTexture(mFinalizer.get(), st, true); 198 return st; 199 } 200 201 static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) { 202 return new HardwareLayer(renderer, layer, LAYER_TYPE_TEXTURE); 203 } 204 205 static HardwareLayer adoptDisplayListLayer(HardwareRenderer renderer, long layer) { 206 return new HardwareLayer(renderer, layer, LAYER_TYPE_DISPLAY_LIST); 207 } 208 209 private static native void nOnTextureDestroyed(long layerUpdater); 210 211 private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque); 212 private static native void nSetLayerPaint(long layerUpdater, long paint); 213 private static native void nSetTransform(long layerUpdater, long matrix); 214 private static native void nSetSurfaceTexture(long layerUpdater, 215 SurfaceTexture surface, boolean isAlreadyAttached); 216 private static native void nUpdateSurfaceTexture(long layerUpdater); 217 private static native void nUpdateRenderLayer(long layerUpdater, long displayList, 218 int left, int top, int right, int bottom); 219 220 private static native long nGetLayer(long layerUpdater); 221 private static native int nGetTexName(long layerUpdater); 222} 223