blob: 8f9ae0e3f48c9d569f91c1f13c30f0df296c729b [file] [log] [blame]
Romain Guye4d01122010-06-16 18:44:05 -07001/*
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
Chris Craikc9070eb2015-03-09 18:50:14 -070019import android.annotation.NonNull;
John Reck4afbed12016-04-18 09:29:36 -070020import android.annotation.Nullable;
Romain Guye4d01122010-06-16 18:44:05 -070021import android.graphics.Bitmap;
John Reck52244ff2014-05-01 21:27:37 -070022import android.graphics.CanvasProperty;
Romain Guye4d01122010-06-16 18:44:05 -070023import android.graphics.Paint;
Chris Craikc9070eb2015-03-09 18:50:14 -070024import android.util.Pools.SynchronizedPool;
Romain Guye4d01122010-06-16 18:44:05 -070025
Chris Craikfc294242016-12-13 18:10:46 -080026import dalvik.annotation.optimization.CriticalNative;
John Reck5cb74bc2016-10-07 11:24:44 -070027import dalvik.annotation.optimization.FastNative;
28
Romain Guye4d01122010-06-16 18:44:05 -070029/**
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -040030 * A Canvas implementation that records view system drawing operations for deferred rendering.
Chris Craikc9070eb2015-03-09 18:50:14 -070031 * 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.
Chris Craikf6829a02015-03-10 10:28:59 -070034 *
35 * @hide
Romain Guye4d01122010-06-16 18:44:05 -070036 */
John Reckcaa08ff2016-10-07 13:21:36 -070037public final class DisplayListCanvas extends RecordingCanvas {
Chris Craikc9070eb2015-03-09 18:50:14 -070038 // The recording canvas pool should be large enough to handle a deeply nested
39 // view hierarchy because display lists are generated recursively.
40 private static final int POOL_LIMIT = 25;
41
sergeyv3d8298e2016-04-21 13:05:24 -070042 private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
43
Chris Craikc9070eb2015-03-09 18:50:14 -070044 private static final SynchronizedPool<DisplayListCanvas> sPool =
John Reckcaa08ff2016-10-07 13:21:36 -070045 new SynchronizedPool<>(POOL_LIMIT);
Chris Craikc9070eb2015-03-09 18:50:14 -070046
47 RenderNode mNode;
Romain Guye4d01122010-06-16 18:44:05 -070048 private int mWidth;
49 private int mHeight;
Raph Levien051910b2014-06-15 18:25:29 -070050
Derek Sollenbergercc882b62015-07-09 15:51:20 -040051 static DisplayListCanvas obtain(@NonNull RenderNode node, int width, int height) {
Chris Craikc9070eb2015-03-09 18:50:14 -070052 if (node == null) throw new IllegalArgumentException("node cannot be null");
53 DisplayListCanvas canvas = sPool.acquire();
54 if (canvas == null) {
Stan Ilievc0e7a902016-10-13 17:07:09 -040055 canvas = new DisplayListCanvas(node, width, height);
Derek Sollenbergercc882b62015-07-09 15:51:20 -040056 } else {
Stan Ilievc0e7a902016-10-13 17:07:09 -040057 nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, node.mNativeRenderNode,
58 width, height);
Chris Craikc9070eb2015-03-09 18:50:14 -070059 }
60 canvas.mNode = node;
Derek Sollenbergercc882b62015-07-09 15:51:20 -040061 canvas.mWidth = width;
62 canvas.mHeight = height;
Chris Craikc9070eb2015-03-09 18:50:14 -070063 return canvas;
64 }
65
66 void recycle() {
67 mNode = null;
68 sPool.release(this);
69 }
70
71 long finishRecording() {
72 return nFinishRecording(mNativeCanvasWrapper);
73 }
74
75 @Override
76 public boolean isRecordingFor(Object o) {
77 return o == mNode;
78 }
Romain Guy6926c722010-07-12 20:20:03 -070079
Romain Guy16393512010-08-08 00:14:31 -070080 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -070081 // Constructors
82 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -070083
Stan Ilievc0e7a902016-10-13 17:07:09 -040084 private DisplayListCanvas(@NonNull RenderNode node, int width, int height) {
85 super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
Chris Craik9c08ee02015-05-21 16:46:53 -070086 mDensity = 0; // disable bitmap density scaling
Romain Guye4d01122010-06-16 18:44:05 -070087 }
Romain Guye4d01122010-06-16 18:44:05 -070088
Romain Guye4d01122010-06-16 18:44:05 -070089 ///////////////////////////////////////////////////////////////////////////
90 // Canvas management
91 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -070092
Chris Craik9c08ee02015-05-21 16:46:53 -070093
94 @Override
95 public void setDensity(int density) {
96 // drop silently, since DisplayListCanvas doesn't perform density scaling
97 }
98
Romain Guye4d01122010-06-16 18:44:05 -070099 @Override
Chris Craikf6829a02015-03-10 10:28:59 -0700100 public boolean isHardwareAccelerated() {
101 return true;
102 }
103
104 @Override
105 public void setBitmap(Bitmap bitmap) {
106 throw new UnsupportedOperationException();
107 }
108
109 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700110 public boolean isOpaque() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500111 return false;
Romain Guye4d01122010-06-16 18:44:05 -0700112 }
113
114 @Override
115 public int getWidth() {
116 return mWidth;
117 }
118
119 @Override
120 public int getHeight() {
121 return mHeight;
122 }
123
Romain Guyf61970fc2011-07-07 14:10:06 -0700124 @Override
125 public int getMaximumBitmapWidth() {
126 return nGetMaximumTextureWidth();
127 }
128
129 @Override
130 public int getMaximumBitmapHeight() {
131 return nGetMaximumTextureHeight();
132 }
133
Romain Guye4d01122010-06-16 18:44:05 -0700134 ///////////////////////////////////////////////////////////////////////////
135 // Setup
136 ///////////////////////////////////////////////////////////////////////////
137
138 @Override
Chris Craik8afd0f22014-08-21 17:41:57 -0700139 public void insertReorderBarrier() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500140 nInsertReorderBarrier(mNativeCanvasWrapper, true);
Chris Craik8afd0f22014-08-21 17:41:57 -0700141 }
142
143 @Override
144 public void insertInorderBarrier() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500145 nInsertReorderBarrier(mNativeCanvasWrapper, false);
Chris Craik8afd0f22014-08-21 17:41:57 -0700146 }
147
Romain Guy530041d2012-01-25 18:56:29 -0800148 ///////////////////////////////////////////////////////////////////////////
149 // Functor
150 ///////////////////////////////////////////////////////////////////////////
151
Chris Craikf6829a02015-03-10 10:28:59 -0700152 /**
John Reckcd1c3eb2016-04-14 10:38:54 -0700153 * Records the functor specified with the drawGLFunction function pointer. This is
154 * functionality used by webview for calling into their renderer from our display lists.
Chris Craikf6829a02015-03-10 10:28:59 -0700155 *
156 * @param drawGLFunction A native function pointer
157 */
Narayan Kamath57616d3e2014-11-21 11:57:07 +0000158 public void callDrawGLFunction2(long drawGLFunction) {
John Reckcd1c3eb2016-04-14 10:38:54 -0700159 nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction, null);
Chet Haasedaf98e92011-01-10 14:10:36 -0800160 }
161
John Reckcd1c3eb2016-04-14 10:38:54 -0700162 /**
163 * Records the functor specified with the drawGLFunction function pointer. This is
164 * functionality used by webview for calling into their renderer from our display lists.
165 *
166 * @param drawGLFunction A native function pointer
167 * @param releasedCallback Called when the display list is destroyed, and thus
168 * the functor is no longer referenced by this canvas's display list.
169 *
170 * NOTE: The callback does *not* necessarily mean that there are no longer
171 * any references to the functor, just that the reference from this specific
172 * canvas's display list has been released.
173 */
John Reck4afbed12016-04-18 09:29:36 -0700174 public void drawGLFunctor2(long drawGLFunctor, @Nullable Runnable releasedCallback) {
John Reckcd1c3eb2016-04-14 10:38:54 -0700175 nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
176 }
177
Romain Guybdf76092011-07-18 15:00:43 -0700178 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -0700179 // Display list
180 ///////////////////////////////////////////////////////////////////////////
181
Chris Craikf6829a02015-03-10 10:28:59 -0700182 /**
183 * Draws the specified display list onto this canvas. The display list can only
184 * be drawn if {@link android.view.RenderNode#isValid()} returns true.
185 *
Chris Craik956f3402015-04-27 16:41:00 -0700186 * @param renderNode The RenderNode to draw.
Chris Craikf6829a02015-03-10 10:28:59 -0700187 */
188 public void drawRenderNode(RenderNode renderNode) {
Chris Craik956f3402015-04-27 16:41:00 -0700189 nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());
Chris Craikf6829a02015-03-10 10:28:59 -0700190 }
191
Romain Guye4d01122010-06-16 18:44:05 -0700192 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800193 // Hardware layer
194 ///////////////////////////////////////////////////////////////////////////
Raph Levien051910b2014-06-15 18:25:29 -0700195
Chris Craikf6829a02015-03-10 10:28:59 -0700196 /**
197 * Draws the specified layer onto this canvas.
198 *
199 * @param layer The layer to composite on this canvas
Chris Craikf6829a02015-03-10 10:28:59 -0700200 */
Chris Craik3aadd602015-08-20 12:41:40 -0700201 void drawHardwareLayer(HardwareLayer layer) {
202 nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle());
Romain Guy6c319ca2011-01-11 14:29:25 -0800203 }
204
Romain Guy6c319ca2011-01-11 14:29:25 -0800205 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700206 // Drawing
207 ///////////////////////////////////////////////////////////////////////////
208
John Reck52244ff2014-05-01 21:27:37 -0700209 public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
210 CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500211 nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
John Reck52244ff2014-05-01 21:27:37 -0700212 radius.getNativeContainer(), paint.getNativeContainer());
213 }
214
Jorim Jaggi072707d2014-09-15 17:20:08 +0200215 public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
216 CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
217 CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500218 nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
Jorim Jaggi072707d2014-09-15 17:20:08 +0200219 right.getNativeContainer(), bottom.getNativeContainer(),
220 rx.getNativeContainer(), ry.getNativeContainer(),
221 paint.getNativeContainer());
222 }
223
sergeyv3d8298e2016-04-21 13:05:24 -0700224 @Override
225 protected void throwIfCannotDraw(Bitmap bitmap) {
226 super.throwIfCannotDraw(bitmap);
227 int bitmapSize = bitmap.getByteCount();
228 if (bitmapSize > MAX_BITMAP_SIZE) {
229 throw new RuntimeException(
230 "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
231 }
232 }
John Reck5cb74bc2016-10-07 11:24:44 -0700233
Chris Craikfc294242016-12-13 18:10:46 -0800234
235 // ------------------ Fast JNI ------------------------
236
John Reck5cb74bc2016-10-07 11:24:44 -0700237 @FastNative
238 private static native void nCallDrawGLFunction(long renderer,
239 long drawGLFunction, Runnable releasedCallback);
Chris Craikfc294242016-12-13 18:10:46 -0800240
241
242 // ------------------ Critical JNI ------------------------
243
244 @CriticalNative
245 private static native long nCreateDisplayListCanvas(long node, int width, int height);
246 @CriticalNative
247 private static native void nResetDisplayListCanvas(long canvas, long node,
248 int width, int height);
249 @CriticalNative
250 private static native int nGetMaximumTextureWidth();
251 @CriticalNative
252 private static native int nGetMaximumTextureHeight();
253 @CriticalNative
254 private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
255 @CriticalNative
John Reck5cb74bc2016-10-07 11:24:44 -0700256 private static native long nFinishRecording(long renderer);
Chris Craikfc294242016-12-13 18:10:46 -0800257 @CriticalNative
John Reck5cb74bc2016-10-07 11:24:44 -0700258 private static native void nDrawRenderNode(long renderer, long renderNode);
Chris Craikfc294242016-12-13 18:10:46 -0800259 @CriticalNative
John Reck5cb74bc2016-10-07 11:24:44 -0700260 private static native void nDrawLayer(long renderer, long layer);
Chris Craikfc294242016-12-13 18:10:46 -0800261 @CriticalNative
John Reck5cb74bc2016-10-07 11:24:44 -0700262 private static native void nDrawCircle(long renderer, long propCx,
263 long propCy, long propRadius, long propPaint);
Chris Craikfc294242016-12-13 18:10:46 -0800264 @CriticalNative
John Reck5cb74bc2016-10-07 11:24:44 -0700265 private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
266 long propRight, long propBottom, long propRx, long propRy, long propPaint);
Romain Guye4d01122010-06-16 18:44:05 -0700267}