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 } 80 81 int end(int nativeDisplayList) { 82 return getDisplayList(nativeDisplayList); 83 } 84 85 private void recordShaderBitmap(Paint paint) { 86 if (paint != null) { 87 final Shader shader = paint.getShader(); 88 if (shader instanceof BitmapShader) { 89 mDisplayList.mBitmaps.add(((BitmapShader) shader).mBitmap); 90 } 91 } 92 } 93 94 @Override 95 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) { 96 super.drawPatch(bitmap, chunks, dst, paint); 97 mDisplayList.mBitmaps.add(bitmap); 98 // Shaders in the Paint are ignored when drawing a Bitmap 99 } 100 101 @Override 102 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { 103 super.drawBitmap(bitmap, left, top, paint); 104 mDisplayList.mBitmaps.add(bitmap); 105 // Shaders in the Paint are ignored when drawing a Bitmap 106 } 107 108 @Override 109 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { 110 super.drawBitmap(bitmap, matrix, paint); 111 mDisplayList.mBitmaps.add(bitmap); 112 // Shaders in the Paint are ignored when drawing a Bitmap 113 } 114 115 @Override 116 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { 117 super.drawBitmap(bitmap, src, dst, paint); 118 mDisplayList.mBitmaps.add(bitmap); 119 // Shaders in the Paint are ignored when drawing a Bitmap 120 } 121 122 @Override 123 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { 124 super.drawBitmap(bitmap, src, dst, paint); 125 mDisplayList.mBitmaps.add(bitmap); 126 // Shaders in the Paint are ignored when drawing a Bitmap 127 } 128 129 @Override 130 public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, 131 int height, boolean hasAlpha, Paint paint) { 132 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 133 // Shaders in the Paint are ignored when drawing a Bitmap 134 } 135 136 @Override 137 public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, 138 int height, boolean hasAlpha, Paint paint) { 139 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 140 // Shaders in the Paint are ignored when drawing a Bitmap 141 } 142 143 @Override 144 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, 145 int vertOffset, int[] colors, int colorOffset, Paint paint) { 146 super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, 147 paint); 148 mDisplayList.mBitmaps.add(bitmap); 149 // Shaders in the Paint are ignored when drawing a Bitmap 150 } 151 152 @Override 153 public void drawCircle(float cx, float cy, float radius, Paint paint) { 154 super.drawCircle(cx, cy, radius, paint); 155 recordShaderBitmap(paint); 156 } 157 158 @Override 159 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { 160 super.drawLine(startX, startY, stopX, stopY, paint); 161 recordShaderBitmap(paint); 162 } 163 164 @Override 165 public void drawLines(float[] pts, int offset, int count, Paint paint) { 166 super.drawLines(pts, offset, count, paint); 167 recordShaderBitmap(paint); 168 } 169 170 @Override 171 public void drawLines(float[] pts, Paint paint) { 172 super.drawLines(pts, paint); 173 recordShaderBitmap(paint); 174 } 175 176 @Override 177 public void drawOval(RectF oval, Paint paint) { 178 super.drawOval(oval, paint); 179 recordShaderBitmap(paint); 180 } 181 182 @Override 183 public void drawPaint(Paint paint) { 184 super.drawPaint(paint); 185 recordShaderBitmap(paint); 186 } 187 188 @Override 189 public void drawPath(Path path, Paint paint) { 190 super.drawPath(path, paint); 191 recordShaderBitmap(paint); 192 } 193 194 @Override 195 public void drawPoint(float x, float y, Paint paint) { 196 super.drawPoint(x, y, paint); 197 recordShaderBitmap(paint); 198 } 199 200 @Override 201 public void drawPoints(float[] pts, int offset, int count, Paint paint) { 202 super.drawPoints(pts, offset, count, paint); 203 recordShaderBitmap(paint); 204 } 205 206 @Override 207 public void drawPoints(float[] pts, Paint paint) { 208 super.drawPoints(pts, paint); 209 recordShaderBitmap(paint); 210 } 211 212 @Override 213 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { 214 super.drawPosText(text, index, count, pos, paint); 215 recordShaderBitmap(paint); 216 } 217 218 @Override 219 public void drawPosText(String text, float[] pos, Paint paint) { 220 super.drawPosText(text, pos, paint); 221 recordShaderBitmap(paint); 222 } 223 224 @Override 225 public void drawRect(float left, float top, float right, float bottom, Paint paint) { 226 super.drawRect(left, top, right, bottom, paint); 227 recordShaderBitmap(paint); 228 } 229 230 @Override 231 public void drawRect(Rect r, Paint paint) { 232 super.drawRect(r, paint); 233 recordShaderBitmap(paint); 234 } 235 236 @Override 237 public void drawRect(RectF r, Paint paint) { 238 super.drawRect(r, paint); 239 recordShaderBitmap(paint); 240 } 241 242 @Override 243 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { 244 super.drawRoundRect(rect, rx, ry, paint); 245 recordShaderBitmap(paint); 246 } 247 248 @Override 249 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { 250 super.drawText(text, index, count, x, y, paint); 251 recordShaderBitmap(paint); 252 } 253 254 @Override 255 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { 256 super.drawText(text, start, end, x, y, paint); 257 recordShaderBitmap(paint); 258 } 259 260 @Override 261 public void drawText(String text, int start, int end, float x, float y, Paint paint) { 262 super.drawText(text, start, end, x, y, paint); 263 recordShaderBitmap(paint); 264 } 265 266 @Override 267 public void drawText(String text, float x, float y, Paint paint) { 268 super.drawText(text, x, y, paint); 269 recordShaderBitmap(paint); 270 } 271 272 @Override 273 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, 274 float vOffset, Paint paint) { 275 super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint); 276 recordShaderBitmap(paint); 277 } 278 279 @Override 280 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { 281 super.drawTextOnPath(text, path, hOffset, vOffset, paint); 282 recordShaderBitmap(paint); 283 } 284 285 @Override 286 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, 287 float x, float y, int dir, Paint paint) { 288 super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, dir, paint); 289 recordShaderBitmap(paint); 290 } 291 292 @Override 293 public void drawTextRun(CharSequence text, int start, int end, int contextStart, 294 int contextEnd, float x, float y, int dir, Paint paint) { 295 super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, dir, paint); 296 recordShaderBitmap(paint); 297 } 298 299 @Override 300 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, 301 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, 302 int indexOffset, int indexCount, Paint paint) { 303 super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, 304 colorOffset, indices, indexOffset, indexCount, paint); 305 recordShaderBitmap(paint); 306 } 307 308 @Override 309 public GLES20RecordingCanvas getNextPoolable() { 310 return mNextPoolable; 311 } 312 313 @Override 314 public void setNextPoolable(GLES20RecordingCanvas element) { 315 mNextPoolable = element; 316 } 317 318 @Override 319 public boolean isPooled() { 320 return mIsPooled; 321 } 322 323 @Override 324 public void setPooled(boolean isPooled) { 325 mIsPooled = isPooled; 326 } 327} 328