Home | History | Annotate | Download | only in view
      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