• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.graphics;
18 
19 import android.annotation.ColorInt;
20 import android.annotation.NonNull;
21 import android.os.SystemProperties;
22 import android.util.Pools.SynchronizedPool;
23 
24 import dalvik.annotation.optimization.CriticalNative;
25 
26 /**
27  * A Canvas implementation that records view system drawing operations for deferred rendering.
28  * This is used in combination with RenderNode. This class keeps a list of all the Paint and
29  * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being released while
30  * the RecordingCanvas is still holding a native reference to the memory.
31  *
32  * This is obtained by calling {@link RenderNode#beginRecording()} and is valid until the matching
33  * {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is
34  * internally reused.
35  */
36 public final class RecordingCanvas extends BaseRecordingCanvas {
37     // The recording canvas pool should be large enough to handle a deeply nested
38     // view hierarchy because display lists are generated recursively.
39     private static final int POOL_LIMIT = 25;
40 
41     /** @hide */
getPanelFrameSize()42     private static int getPanelFrameSize() {
43         final int DefaultSize = 100 * 1024 * 1024; // 100 MB;
44         return Math.max(SystemProperties.getInt("ro.hwui.max_texture_allocation_size", DefaultSize),
45                 DefaultSize);
46     }
47 
48     /** @hide */
49     public static final int MAX_BITMAP_SIZE = getPanelFrameSize();
50 
51     private static final SynchronizedPool<RecordingCanvas> sPool =
52             new SynchronizedPool<>(POOL_LIMIT);
53 
54     /**
55      * TODO: Temporarily exposed for RenderNodeAnimator(Set)
56      * @hide */
57     public RenderNode mNode;
58     private int mWidth;
59     private int mHeight;
60 
61     /*package*/
obtain(@onNull RenderNode node, int width, int height)62     static RecordingCanvas obtain(@NonNull RenderNode node, int width, int height) {
63         if (node == null) throw new IllegalArgumentException("node cannot be null");
64         RecordingCanvas canvas = sPool.acquire();
65         if (canvas == null) {
66             canvas = new RecordingCanvas(node, width, height);
67         } else {
68             nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, node.mNativeRenderNode,
69                     width, height);
70         }
71         canvas.mNode = node;
72         canvas.mWidth = width;
73         canvas.mHeight = height;
74         return canvas;
75     }
76 
77     /*package*/
recycle()78     void recycle() {
79         mNode = null;
80         sPool.release(this);
81     }
82 
83     /*package*/
finishRecording(RenderNode node)84     void finishRecording(RenderNode node) {
85         nFinishRecording(mNativeCanvasWrapper, node.mNativeRenderNode);
86     }
87 
88     ///////////////////////////////////////////////////////////////////////////
89     // Constructors
90     ///////////////////////////////////////////////////////////////////////////
91 
RecordingCanvas(@onNull RenderNode node, int width, int height)92     private RecordingCanvas(@NonNull RenderNode node, int width, int height) {
93         super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
94         mDensity = 0; // disable bitmap density scaling
95     }
96 
97     ///////////////////////////////////////////////////////////////////////////
98     // Canvas management
99     ///////////////////////////////////////////////////////////////////////////
100 
101 
102     @Override
setDensity(int density)103     public void setDensity(int density) {
104         // drop silently, since RecordingCanvas doesn't perform density scaling
105     }
106 
107     @Override
isHardwareAccelerated()108     public boolean isHardwareAccelerated() {
109         return true;
110     }
111 
112     @Override
setBitmap(Bitmap bitmap)113     public void setBitmap(Bitmap bitmap) {
114         throw new UnsupportedOperationException();
115     }
116 
117     @Override
isOpaque()118     public boolean isOpaque() {
119         return false;
120     }
121 
122     @Override
getWidth()123     public int getWidth() {
124         return mWidth;
125     }
126 
127     @Override
getHeight()128     public int getHeight() {
129         return mHeight;
130     }
131 
132     @Override
getMaximumBitmapWidth()133     public int getMaximumBitmapWidth() {
134         return nGetMaximumTextureWidth();
135     }
136 
137     @Override
getMaximumBitmapHeight()138     public int getMaximumBitmapHeight() {
139         return nGetMaximumTextureHeight();
140     }
141 
142     ///////////////////////////////////////////////////////////////////////////
143     // Setup
144     ///////////////////////////////////////////////////////////////////////////
145 
146     @Override
enableZ()147     public void enableZ() {
148         nEnableZ(mNativeCanvasWrapper, true);
149     }
150 
151     @Override
disableZ()152     public void disableZ() {
153         nEnableZ(mNativeCanvasWrapper, false);
154     }
155 
156     ///////////////////////////////////////////////////////////////////////////
157     // WebView
158     ///////////////////////////////////////////////////////////////////////////
159 
160     /**
161      * Calls the provided functor that was created via WebViewFunctor_create()
162      * @hide
163      */
drawWebViewFunctor(int functor)164     public void drawWebViewFunctor(int functor) {
165         nDrawWebViewFunctor(mNativeCanvasWrapper, functor);
166     }
167 
168     ///////////////////////////////////////////////////////////////////////////
169     // Display list
170     ///////////////////////////////////////////////////////////////////////////
171 
172     /**
173      * Draws the specified display list onto this canvas.
174      *
175      * @param renderNode The RenderNode to draw.
176      */
177     @Override
drawRenderNode(@onNull RenderNode renderNode)178     public void drawRenderNode(@NonNull RenderNode renderNode) {
179         nDrawRenderNode(mNativeCanvasWrapper, renderNode.mNativeRenderNode);
180     }
181 
182     ///////////////////////////////////////////////////////////////////////////
183     // Hardware layer
184     ///////////////////////////////////////////////////////////////////////////
185 
186     /**
187      * Draws the specified layer onto this canvas.
188      *
189      * @param layer The layer to composite on this canvas
190      * @hide TODO: Make this a SystemApi for b/155905258
191      */
drawTextureLayer(@onNull TextureLayer layer)192     public void drawTextureLayer(@NonNull TextureLayer layer) {
193         nDrawTextureLayer(mNativeCanvasWrapper, layer.getLayerHandle());
194     }
195 
196     ///////////////////////////////////////////////////////////////////////////
197     // Drawing
198     ///////////////////////////////////////////////////////////////////////////
199 
200     /**
201      * Draws a circle
202      *
203      * @param cx
204      * @param cy
205      * @param radius
206      * @param paint
207      *
208      * @hide
209      */
drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy, CanvasProperty<Float> radius, CanvasProperty<Paint> paint)210     public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
211             CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
212         nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
213                 radius.getNativeContainer(), paint.getNativeContainer());
214     }
215 
216     /**
217      * Draws a ripple
218      *
219      * @param cx
220      * @param cy
221      * @param radius
222      * @param paint
223      * @param progress
224      * @param shader
225      *
226      * @hide
227      */
drawRipple(CanvasProperty<Float> cx, CanvasProperty<Float> cy, CanvasProperty<Float> radius, CanvasProperty<Paint> paint, CanvasProperty<Float> progress, CanvasProperty<Float> turbulencePhase, @ColorInt int color, RuntimeShader shader)228     public void drawRipple(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
229             CanvasProperty<Float> radius, CanvasProperty<Paint> paint,
230             CanvasProperty<Float> progress, CanvasProperty<Float> turbulencePhase,
231             @ColorInt int color, RuntimeShader shader) {
232         nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
233                 radius.getNativeContainer(), paint.getNativeContainer(),
234                 progress.getNativeContainer(), turbulencePhase.getNativeContainer(),
235                 color, shader.getNativeShaderBuilder());
236     }
237 
238     /**
239      * Draws a round rect
240      *
241      * @param left
242      * @param top
243      * @param right
244      * @param bottom
245      * @param rx
246      * @param ry
247      * @param paint
248      *
249      * @hide
250      */
drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top, CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx, CanvasProperty<Float> ry, CanvasProperty<Paint> paint)251     public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
252             CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
253             CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
254         nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
255                 right.getNativeContainer(), bottom.getNativeContainer(),
256                 rx.getNativeContainer(), ry.getNativeContainer(),
257                 paint.getNativeContainer());
258     }
259 
260     /** @hide */
261     @Override
throwIfCannotDraw(Bitmap bitmap)262     protected void throwIfCannotDraw(Bitmap bitmap) {
263         super.throwIfCannotDraw(bitmap);
264         int bitmapSize = bitmap.getByteCount();
265         if (bitmapSize > MAX_BITMAP_SIZE) {
266             throw new RuntimeException(
267                     "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
268         }
269     }
270 
271 
272     // ------------------ Critical JNI ------------------------
273 
274     @CriticalNative
nCreateDisplayListCanvas(long node, int width, int height)275     private static native long nCreateDisplayListCanvas(long node, int width, int height);
276     @CriticalNative
nResetDisplayListCanvas(long canvas, long node, int width, int height)277     private static native void nResetDisplayListCanvas(long canvas, long node,
278             int width, int height);
279     @CriticalNative
nGetMaximumTextureWidth()280     private static native int nGetMaximumTextureWidth();
281     @CriticalNative
nGetMaximumTextureHeight()282     private static native int nGetMaximumTextureHeight();
283     @CriticalNative
nEnableZ(long renderer, boolean enableZ)284     private static native void nEnableZ(long renderer, boolean enableZ);
285     @CriticalNative
nFinishRecording(long renderer, long renderNode)286     private static native void nFinishRecording(long renderer, long renderNode);
287     @CriticalNative
nDrawRenderNode(long renderer, long renderNode)288     private static native void nDrawRenderNode(long renderer, long renderNode);
289     @CriticalNative
nDrawTextureLayer(long renderer, long layer)290     private static native void nDrawTextureLayer(long renderer, long layer);
291     @CriticalNative
nDrawCircle(long renderer, long propCx, long propCy, long propRadius, long propPaint)292     private static native void nDrawCircle(long renderer, long propCx,
293             long propCy, long propRadius, long propPaint);
294     @CriticalNative
nDrawRipple(long renderer, long propCx, long propCy, long propRadius, long propPaint, long propProgress, long turbulencePhase, int color, long runtimeEffect)295     private static native void nDrawRipple(long renderer, long propCx, long propCy, long propRadius,
296             long propPaint, long propProgress, long turbulencePhase, int color, long runtimeEffect);
297     @CriticalNative
nDrawRoundRect(long renderer, long propLeft, long propTop, long propRight, long propBottom, long propRx, long propRy, long propPaint)298     private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
299             long propRight, long propBottom, long propRx, long propRy, long propPaint);
300     @CriticalNative
nDrawWebViewFunctor(long canvas, int functor)301     private static native void nDrawWebViewFunctor(long canvas, int functor);
302 }
303