1/* 2 * Copyright (C) 2010 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.BitmapShader; 21import android.graphics.Matrix; 22import android.graphics.Paint; 23import android.graphics.Path; 24import android.graphics.Rect; 25import android.graphics.RectF; 26import android.graphics.Shader; 27import android.util.Pool; 28import android.util.Poolable; 29import android.util.PoolableManager; 30import android.util.Pools; 31 32/** 33 * An implementation of a GL canvas that records drawing operations. 34 * This is intended for use with a DisplayList. This class keeps a list of all the Paint and 35 * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while 36 * the DisplayList is still holding a native reference to the memory. 37 */ 38class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> { 39 // The recording canvas pool should be large enough to handle a deeply nested 40 // view hierarchy because display lists are generated recursively. 41 private static final int POOL_LIMIT = 25; 42 43 private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool( 44 Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() { 45 public GLES20RecordingCanvas newInstance() { 46 return new GLES20RecordingCanvas(); 47 } 48 @Override 49 public void onAcquired(GLES20RecordingCanvas element) { 50 } 51 @Override 52 public void onReleased(GLES20RecordingCanvas element) { 53 } 54 }, POOL_LIMIT)); 55 56 private GLES20RecordingCanvas mNextPoolable; 57 private boolean mIsPooled; 58 59 private GLES20DisplayList mDisplayList; 60 61 private GLES20RecordingCanvas() { 62 super(true /*record*/, true /*translucent*/); 63 } 64 65 static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) { 66 GLES20RecordingCanvas canvas = sPool.acquire(); 67 canvas.mDisplayList = displayList; 68 return canvas; 69 } 70 71 void recycle() { 72 mDisplayList = null; 73 resetDisplayListRenderer(); 74 sPool.release(this); 75 } 76 77 void start() { 78 mDisplayList.mBitmaps.clear(); 79 mDisplayList.mChildDisplayLists.clear(); 80 } 81 82 int end(int nativeDisplayList) { 83 return getDisplayList(nativeDisplayList); 84 } 85 86 private void recordShaderBitmap(Paint paint) { 87 if (paint != null) { 88 final Shader shader = paint.getShader(); 89 if (shader instanceof BitmapShader) { 90 mDisplayList.mBitmaps.add(((BitmapShader) shader).mBitmap); 91 } 92 } 93 } 94 95 @Override 96 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) { 97 super.drawPatch(bitmap, chunks, dst, paint); 98 mDisplayList.mBitmaps.add(bitmap); 99 // Shaders in the Paint are ignored when drawing a Bitmap 100 } 101 102 @Override 103 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { 104 super.drawBitmap(bitmap, left, top, paint); 105 mDisplayList.mBitmaps.add(bitmap); 106 // Shaders in the Paint are ignored when drawing a Bitmap 107 } 108 109 @Override 110 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { 111 super.drawBitmap(bitmap, matrix, paint); 112 mDisplayList.mBitmaps.add(bitmap); 113 // Shaders in the Paint are ignored when drawing a Bitmap 114 } 115 116 @Override 117 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { 118 super.drawBitmap(bitmap, src, dst, paint); 119 mDisplayList.mBitmaps.add(bitmap); 120 // Shaders in the Paint are ignored when drawing a Bitmap 121 } 122 123 @Override 124 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { 125 super.drawBitmap(bitmap, src, dst, paint); 126 mDisplayList.mBitmaps.add(bitmap); 127 // Shaders in the Paint are ignored when drawing a Bitmap 128 } 129 130 @Override 131 public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, 132 int height, boolean hasAlpha, Paint paint) { 133 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 134 // Shaders in the Paint are ignored when drawing a Bitmap 135 } 136 137 @Override 138 public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, 139 int height, boolean hasAlpha, Paint paint) { 140 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 141 // Shaders in the Paint are ignored when drawing a Bitmap 142 } 143 144 @Override 145 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, 146 int vertOffset, int[] colors, int colorOffset, Paint paint) { 147 super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, 148 colors, colorOffset, paint); 149 mDisplayList.mBitmaps.add(bitmap); 150 // Shaders in the Paint are ignored when drawing a Bitmap 151 } 152 153 @Override 154 public void drawCircle(float cx, float cy, float radius, Paint paint) { 155 super.drawCircle(cx, cy, radius, paint); 156 recordShaderBitmap(paint); 157 } 158 159 @Override 160 public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) { 161 int status = super.drawDisplayList(displayList, dirty, flags); 162 mDisplayList.mChildDisplayLists.add(displayList); 163 return status; 164 } 165 166 @Override 167 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { 168 super.drawLine(startX, startY, stopX, stopY, paint); 169 recordShaderBitmap(paint); 170 } 171 172 @Override 173 public void drawLines(float[] pts, int offset, int count, Paint paint) { 174 super.drawLines(pts, offset, count, paint); 175 recordShaderBitmap(paint); 176 } 177 178 @Override 179 public void drawLines(float[] pts, Paint paint) { 180 super.drawLines(pts, paint); 181 recordShaderBitmap(paint); 182 } 183 184 @Override 185 public void drawOval(RectF oval, Paint paint) { 186 super.drawOval(oval, paint); 187 recordShaderBitmap(paint); 188 } 189 190 @Override 191 public void drawPaint(Paint paint) { 192 super.drawPaint(paint); 193 recordShaderBitmap(paint); 194 } 195 196 @Override 197 public void drawPath(Path path, Paint paint) { 198 super.drawPath(path, paint); 199 recordShaderBitmap(paint); 200 } 201 202 @Override 203 public void drawPoint(float x, float y, Paint paint) { 204 super.drawPoint(x, y, paint); 205 recordShaderBitmap(paint); 206 } 207 208 @Override 209 public void drawPoints(float[] pts, int offset, int count, Paint paint) { 210 super.drawPoints(pts, offset, count, paint); 211 recordShaderBitmap(paint); 212 } 213 214 @Override 215 public void drawPoints(float[] pts, Paint paint) { 216 super.drawPoints(pts, paint); 217 recordShaderBitmap(paint); 218 } 219 220 @Override 221 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { 222 super.drawPosText(text, index, count, pos, paint); 223 recordShaderBitmap(paint); 224 } 225 226 @Override 227 public void drawPosText(String text, float[] pos, Paint paint) { 228 super.drawPosText(text, pos, paint); 229 recordShaderBitmap(paint); 230 } 231 232 @Override 233 public void drawRect(float left, float top, float right, float bottom, Paint paint) { 234 super.drawRect(left, top, right, bottom, paint); 235 recordShaderBitmap(paint); 236 } 237 238 @Override 239 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { 240 super.drawRoundRect(rect, rx, ry, paint); 241 recordShaderBitmap(paint); 242 } 243 244 @Override 245 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { 246 super.drawText(text, index, count, x, y, paint); 247 recordShaderBitmap(paint); 248 } 249 250 @Override 251 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { 252 super.drawText(text, start, end, x, y, paint); 253 recordShaderBitmap(paint); 254 } 255 256 @Override 257 public void drawText(String text, int start, int end, float x, float y, Paint paint) { 258 super.drawText(text, start, end, x, y, paint); 259 recordShaderBitmap(paint); 260 } 261 262 @Override 263 public void drawText(String text, float x, float y, Paint paint) { 264 super.drawText(text, x, y, paint); 265 recordShaderBitmap(paint); 266 } 267 268 @Override 269 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, 270 float vOffset, Paint paint) { 271 super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint); 272 recordShaderBitmap(paint); 273 } 274 275 @Override 276 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { 277 super.drawTextOnPath(text, path, hOffset, vOffset, paint); 278 recordShaderBitmap(paint); 279 } 280 281 @Override 282 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, 283 float x, float y, int dir, Paint paint) { 284 super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, dir, paint); 285 recordShaderBitmap(paint); 286 } 287 288 @Override 289 public void drawTextRun(CharSequence text, int start, int end, int contextStart, 290 int contextEnd, float x, float y, int dir, Paint paint) { 291 super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, dir, paint); 292 recordShaderBitmap(paint); 293 } 294 295 @Override 296 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, 297 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, 298 int indexOffset, int indexCount, Paint paint) { 299 super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, 300 colorOffset, indices, indexOffset, indexCount, paint); 301 recordShaderBitmap(paint); 302 } 303 304 @Override 305 public GLES20RecordingCanvas getNextPoolable() { 306 return mNextPoolable; 307 } 308 309 @Override 310 public void setNextPoolable(GLES20RecordingCanvas element) { 311 mNextPoolable = element; 312 } 313 314 @Override 315 public boolean isPooled() { 316 return mIsPooled; 317 } 318 319 @Override 320 public void setPooled(boolean isPooled) { 321 mIsPooled = isPooled; 322 } 323} 324