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