DisplayListCanvas.java revision 45faba516e200760e977e8ceb76f079ee8aa7415
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.annotation.NonNull;
20import android.annotation.Nullable;
21import android.graphics.Bitmap;
22import android.graphics.Canvas;
23import android.graphics.CanvasProperty;
24import android.graphics.Paint;
25import android.util.Pools.SynchronizedPool;
26
27/**
28 * A Canvas implementation that records drawing operations for deferred rendering.
29 * This is intended for use with a DisplayList. This class keeps a list of all the Paint and
30 * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
31 * the DisplayList is still holding a native reference to the memory.
32 *
33 * @hide
34 */
35public class DisplayListCanvas extends Canvas {
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 int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
41
42    private static final SynchronizedPool<DisplayListCanvas> sPool =
43            new SynchronizedPool<DisplayListCanvas>(POOL_LIMIT);
44
45    RenderNode mNode;
46    private int mWidth;
47    private int mHeight;
48
49    static DisplayListCanvas obtain(@NonNull RenderNode node, int width, int height) {
50        if (node == null) throw new IllegalArgumentException("node cannot be null");
51        DisplayListCanvas canvas = sPool.acquire();
52        if (canvas == null) {
53            canvas = new DisplayListCanvas(width, height);
54        } else {
55            nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, width, height);
56        }
57        canvas.mNode = node;
58        canvas.mWidth = width;
59        canvas.mHeight = height;
60        return canvas;
61    }
62
63    void recycle() {
64        mNode = null;
65        sPool.release(this);
66    }
67
68    long finishRecording() {
69        return nFinishRecording(mNativeCanvasWrapper);
70    }
71
72    @Override
73    public boolean isRecordingFor(Object o) {
74        return o == mNode;
75    }
76
77    ///////////////////////////////////////////////////////////////////////////
78    // JNI
79    ///////////////////////////////////////////////////////////////////////////
80
81    private static native boolean nIsAvailable();
82    private static boolean sIsAvailable = nIsAvailable();
83
84    static boolean isAvailable() {
85        return sIsAvailable;
86    }
87
88    ///////////////////////////////////////////////////////////////////////////
89    // Constructors
90    ///////////////////////////////////////////////////////////////////////////
91
92    private DisplayListCanvas(int width, int height) {
93        super(nCreateDisplayListCanvas(width, height));
94        mDensity = 0; // disable bitmap density scaling
95    }
96
97    private static native long nCreateDisplayListCanvas(int width, int height);
98    private static native void nResetDisplayListCanvas(long canvas, int width, int height);
99
100    ///////////////////////////////////////////////////////////////////////////
101    // Canvas management
102    ///////////////////////////////////////////////////////////////////////////
103
104
105    @Override
106    public void setDensity(int density) {
107        // drop silently, since DisplayListCanvas doesn't perform density scaling
108    }
109
110    @Override
111    public boolean isHardwareAccelerated() {
112        return true;
113    }
114
115    @Override
116    public void setBitmap(Bitmap bitmap) {
117        throw new UnsupportedOperationException();
118    }
119
120    @Override
121    public boolean isOpaque() {
122        return false;
123    }
124
125    @Override
126    public int getWidth() {
127        return mWidth;
128    }
129
130    @Override
131    public int getHeight() {
132        return mHeight;
133    }
134
135    @Override
136    public int getMaximumBitmapWidth() {
137        return nGetMaximumTextureWidth();
138    }
139
140    @Override
141    public int getMaximumBitmapHeight() {
142        return nGetMaximumTextureHeight();
143    }
144
145    private static native int nGetMaximumTextureWidth();
146    private static native int nGetMaximumTextureHeight();
147
148    ///////////////////////////////////////////////////////////////////////////
149    // Setup
150    ///////////////////////////////////////////////////////////////////////////
151
152    @Override
153    public void insertReorderBarrier() {
154        nInsertReorderBarrier(mNativeCanvasWrapper, true);
155    }
156
157    @Override
158    public void insertInorderBarrier() {
159        nInsertReorderBarrier(mNativeCanvasWrapper, false);
160    }
161
162    private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
163
164    ///////////////////////////////////////////////////////////////////////////
165    // Functor
166    ///////////////////////////////////////////////////////////////////////////
167
168    /**
169     * Records the functor specified with the drawGLFunction function pointer. This is
170     * functionality used by webview for calling into their renderer from our display lists.
171     *
172     * @param drawGLFunction A native function pointer
173     */
174    public void callDrawGLFunction2(long drawGLFunction) {
175        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction, null);
176    }
177
178    /**
179     * Records the functor specified with the drawGLFunction function pointer. This is
180     * functionality used by webview for calling into their renderer from our display lists.
181     *
182     * @param drawGLFunction A native function pointer
183     * @param releasedCallback Called when the display list is destroyed, and thus
184     * the functor is no longer referenced by this canvas's display list.
185     *
186     * NOTE: The callback does *not* necessarily mean that there are no longer
187     * any references to the functor, just that the reference from this specific
188     * canvas's display list has been released.
189     */
190    public void drawGLFunctor2(long drawGLFunctor, @Nullable Runnable releasedCallback) {
191        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
192    }
193
194    private static native void nCallDrawGLFunction(long renderer,
195            long drawGLFunction, Runnable releasedCallback);
196
197    ///////////////////////////////////////////////////////////////////////////
198    // Display list
199    ///////////////////////////////////////////////////////////////////////////
200
201    protected static native long nFinishRecording(long renderer);
202
203    /**
204     * Draws the specified display list onto this canvas. The display list can only
205     * be drawn if {@link android.view.RenderNode#isValid()} returns true.
206     *
207     * @param renderNode The RenderNode to draw.
208     */
209    public void drawRenderNode(RenderNode renderNode) {
210        nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());
211    }
212
213    private static native void nDrawRenderNode(long renderer, long renderNode);
214
215    ///////////////////////////////////////////////////////////////////////////
216    // Hardware layer
217    ///////////////////////////////////////////////////////////////////////////
218
219    /**
220     * Draws the specified layer onto this canvas.
221     *
222     * @param layer The layer to composite on this canvas
223     */
224    void drawHardwareLayer(HardwareLayer layer) {
225        nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle());
226    }
227
228    private static native void nDrawLayer(long renderer, long layer);
229
230    ///////////////////////////////////////////////////////////////////////////
231    // Drawing
232    ///////////////////////////////////////////////////////////////////////////
233
234    public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
235            CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
236        nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
237                radius.getNativeContainer(), paint.getNativeContainer());
238    }
239
240    private static native void nDrawCircle(long renderer, long propCx,
241            long propCy, long propRadius, long propPaint);
242
243    public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
244            CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
245            CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
246        nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
247                right.getNativeContainer(), bottom.getNativeContainer(),
248                rx.getNativeContainer(), ry.getNativeContainer(),
249                paint.getNativeContainer());
250    }
251
252    private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
253            long propRight, long propBottom, long propRx, long propRy, long propPaint);
254
255    @Override
256    protected void throwIfCannotDraw(Bitmap bitmap) {
257        super.throwIfCannotDraw(bitmap);
258        int bitmapSize = bitmap.getByteCount();
259        if (bitmapSize > MAX_BITMAP_SIZE) {
260            throw new RuntimeException(
261                    "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
262        }
263    }
264}
265