blob: eedbc707218b0bcdc9ef4009969a35eb2b4d7682 [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;
Romain Guye4d01122010-06-16 18:44:05 -070020import android.graphics.Bitmap;
Chris Craikf6829a02015-03-10 10:28:59 -070021import android.graphics.Canvas;
John Reck52244ff2014-05-01 21:27:37 -070022import android.graphics.CanvasProperty;
Romain Guy3b748a42013-04-17 18:54:38 -070023import android.graphics.NinePatch;
Romain Guye4d01122010-06-16 18:44:05 -070024import android.graphics.Paint;
25import android.graphics.Path;
26import android.graphics.Picture;
Romain Guye4d01122010-06-16 18:44:05 -070027import android.graphics.Rect;
28import android.graphics.RectF;
Chris Craikc9070eb2015-03-09 18:50:14 -070029import android.util.Pools.SynchronizedPool;
Romain Guye4d01122010-06-16 18:44:05 -070030
Romain Guye4d01122010-06-16 18:44:05 -070031/**
Chris Craikc9070eb2015-03-09 18:50:14 -070032 * An implementation of a GL canvas that records drawing operations.
33 * This is intended for use with a DisplayList. This class keeps a list of all the Paint and
34 * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
35 * the DisplayList is still holding a native reference to the memory.
Chris Craikf6829a02015-03-10 10:28:59 -070036 *
37 * @hide
Romain Guye4d01122010-06-16 18:44:05 -070038 */
Chris Craikf6829a02015-03-10 10:28:59 -070039public class DisplayListCanvas extends Canvas {
Chris Craikc9070eb2015-03-09 18:50:14 -070040 // The recording canvas pool should be large enough to handle a deeply nested
41 // view hierarchy because display lists are generated recursively.
42 private static final int POOL_LIMIT = 25;
43
44 private static final SynchronizedPool<DisplayListCanvas> sPool =
45 new SynchronizedPool<DisplayListCanvas>(POOL_LIMIT);
46
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
Chris Craikc9070eb2015-03-09 18:50:14 -070051 static DisplayListCanvas obtain(@NonNull RenderNode node) {
52 if (node == null) throw new IllegalArgumentException("node cannot be null");
53 DisplayListCanvas canvas = sPool.acquire();
54 if (canvas == null) {
55 canvas = new DisplayListCanvas();
56 }
57 canvas.mNode = node;
58 return canvas;
59 }
60
61 void recycle() {
62 mNode = null;
63 sPool.release(this);
64 }
65
66 long finishRecording() {
67 return nFinishRecording(mNativeCanvasWrapper);
68 }
69
70 @Override
71 public boolean isRecordingFor(Object o) {
72 return o == mNode;
73 }
Romain Guy6926c722010-07-12 20:20:03 -070074
Romain Guy16393512010-08-08 00:14:31 -070075 ///////////////////////////////////////////////////////////////////////////
76 // JNI
77 ///////////////////////////////////////////////////////////////////////////
78
79 private static native boolean nIsAvailable();
80 private static boolean sIsAvailable = nIsAvailable();
81
82 static boolean isAvailable() {
83 return sIsAvailable;
84 }
Romain Guye4d01122010-06-16 18:44:05 -070085
86 ///////////////////////////////////////////////////////////////////////////
87 // Constructors
88 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -070089
Chris Craikc9070eb2015-03-09 18:50:14 -070090 private DisplayListCanvas() {
Chris Craikdb663fe2015-04-20 13:34:45 -070091 super(nCreateDisplayListCanvas());
Romain Guye4d01122010-06-16 18:44:05 -070092 }
Romain Guye4d01122010-06-16 18:44:05 -070093
Chris Craikdb663fe2015-04-20 13:34:45 -070094 private static native long nCreateDisplayListCanvas();
Romain Guyce0537b2010-06-29 21:05:21 -070095
Chris Craikba9b6132013-12-15 17:10:19 -080096 public static void setProperty(String name, String value) {
97 nSetProperty(name, value);
98 }
99
100 private static native void nSetProperty(String name, String value);
101
Romain Guye4d01122010-06-16 18:44:05 -0700102 ///////////////////////////////////////////////////////////////////////////
103 // Canvas management
104 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700105
106 @Override
Chris Craikf6829a02015-03-10 10:28:59 -0700107 public boolean isHardwareAccelerated() {
108 return true;
109 }
110
111 @Override
112 public void setBitmap(Bitmap bitmap) {
113 throw new UnsupportedOperationException();
114 }
115
116 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700117 public boolean isOpaque() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500118 return false;
Romain Guye4d01122010-06-16 18:44:05 -0700119 }
120
121 @Override
122 public int getWidth() {
123 return mWidth;
124 }
125
126 @Override
127 public int getHeight() {
128 return mHeight;
129 }
130
Romain Guyf61970fc2011-07-07 14:10:06 -0700131 @Override
132 public int getMaximumBitmapWidth() {
133 return nGetMaximumTextureWidth();
134 }
135
136 @Override
137 public int getMaximumBitmapHeight() {
138 return nGetMaximumTextureHeight();
139 }
140
141 private static native int nGetMaximumTextureWidth();
Romain Guy530041d2012-01-25 18:56:29 -0800142 private static native int nGetMaximumTextureHeight();
Romain Guyf61970fc2011-07-07 14:10:06 -0700143
Romain Guy2bf68f02012-03-02 13:37:47 -0800144 /**
145 * Returns the native OpenGLRenderer object.
146 */
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000147 long getRenderer() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500148 return mNativeCanvasWrapper;
Romain Guy2bf68f02012-03-02 13:37:47 -0800149 }
150
Romain Guye4d01122010-06-16 18:44:05 -0700151 ///////////////////////////////////////////////////////////////////////////
152 // Setup
153 ///////////////////////////////////////////////////////////////////////////
154
155 @Override
156 public void setViewport(int width, int height) {
157 mWidth = width;
158 mHeight = height;
159
Tom Hudson8dfaa492014-12-09 15:03:44 -0500160 nSetViewport(mNativeCanvasWrapper, width, height);
Romain Guye4d01122010-06-16 18:44:05 -0700161 }
Raph Levien051910b2014-06-15 18:25:29 -0700162
Chris Craikcce47eb2014-07-16 15:12:15 -0700163 private static native void nSetViewport(long renderer,
164 int width, int height);
165
166 @Override
167 public void setHighContrastText(boolean highContrastText) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500168 nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
Chris Craikcce47eb2014-07-16 15:12:15 -0700169 }
170
171 private static native void nSetHighContrastText(long renderer, boolean highContrastText);
Romain Guye4d01122010-06-16 18:44:05 -0700172
Romain Guy7d7b5492011-01-24 16:33:45 -0800173 @Override
Chris Craik8afd0f22014-08-21 17:41:57 -0700174 public void insertReorderBarrier() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500175 nInsertReorderBarrier(mNativeCanvasWrapper, true);
Chris Craik8afd0f22014-08-21 17:41:57 -0700176 }
177
178 @Override
179 public void insertInorderBarrier() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500180 nInsertReorderBarrier(mNativeCanvasWrapper, false);
Chris Craik8afd0f22014-08-21 17:41:57 -0700181 }
182
183 private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
184
Chris Craikf6829a02015-03-10 10:28:59 -0700185 /**
186 * Invoked before any drawing operation is performed in this canvas.
187 *
188 * @param dirty The dirty rectangle to update, can be null.
189 */
Tom Hudson107843d2014-09-08 11:26:26 -0400190 public void onPreDraw(Rect dirty) {
Romain Guy7d7b5492011-01-24 16:33:45 -0800191 if (dirty != null) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500192 nPrepareDirty(mNativeCanvasWrapper, dirty.left, dirty.top, dirty.right, dirty.bottom);
Romain Guy7d7b5492011-01-24 16:33:45 -0800193 } else {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500194 nPrepare(mNativeCanvasWrapper);
Romain Guy7d7b5492011-01-24 16:33:45 -0800195 }
196 }
197
Tom Hudson8dfaa492014-12-09 15:03:44 -0500198 private static native void nPrepare(long renderer);
199 private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700200
Chris Craikf6829a02015-03-10 10:28:59 -0700201 /**
202 * Invoked after all drawing operation have been performed.
203 */
Gilles Debunneb35ab7b2011-12-05 15:54:00 -0800204 public void onPostDraw() {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500205 nFinish(mNativeCanvasWrapper);
Romain Guyb025b9c2010-09-16 14:16:48 -0700206 }
Romain Guy9ace8f52011-07-07 20:50:11 -0700207
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000208 private static native void nFinish(long renderer);
Romain Guyb025b9c2010-09-16 14:16:48 -0700209
Romain Guy530041d2012-01-25 18:56:29 -0800210 ///////////////////////////////////////////////////////////////////////////
211 // Functor
212 ///////////////////////////////////////////////////////////////////////////
213
Chris Craikf6829a02015-03-10 10:28:59 -0700214 /**
215 * Calls the function specified with the drawGLFunction function pointer. This is
216 * functionality used by webkit for calling into their renderer from our display lists.
217 * This function may return true if an invalidation is needed after the call.
218 *
219 * @param drawGLFunction A native function pointer
220 */
Narayan Kamath57616d3e2014-11-21 11:57:07 +0000221 public void callDrawGLFunction2(long drawGLFunction) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500222 nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction);
Chet Haasedaf98e92011-01-10 14:10:36 -0800223 }
224
Tom Hudson107843d2014-09-08 11:26:26 -0400225 private static native void nCallDrawGLFunction(long renderer, long drawGLFunction);
Chet Haasedaf98e92011-01-10 14:10:36 -0800226
Romain Guybdf76092011-07-18 15:00:43 -0700227 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -0700228 // Display list
229 ///////////////////////////////////////////////////////////////////////////
230
John Reck44fd8d22014-02-26 11:00:11 -0800231 protected static native long nFinishRecording(long renderer);
Romain Guy52036b12013-02-14 18:03:37 -0800232
Chris Craikf6829a02015-03-10 10:28:59 -0700233 /**
234 * Draws the specified display list onto this canvas. The display list can only
235 * be drawn if {@link android.view.RenderNode#isValid()} returns true.
236 *
237 * @param renderNode The RenderNode to replay.
238 */
239 public void drawRenderNode(RenderNode renderNode) {
240 drawRenderNode(renderNode, RenderNode.FLAG_CLIP_CHILDREN);
241 }
242
243 /**
244 * Draws the specified display list onto this canvas.
245 *
246 * @param renderNode The RenderNode to replay.
247 * @param flags Optional flags about drawing, see {@link RenderNode} for
248 * the possible flags.
249 */
Tom Hudson107843d2014-09-08 11:26:26 -0400250 public void drawRenderNode(RenderNode renderNode, int flags) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500251 nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList(), flags);
Romain Guyb051e892010-09-28 19:09:36 -0700252 }
253
Tom Hudson107843d2014-09-08 11:26:26 -0400254 private static native void nDrawRenderNode(long renderer, long renderNode,
255 int flags);
Romain Guyda8532c2010-08-31 11:50:35 -0700256
Romain Guye4d01122010-06-16 18:44:05 -0700257 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800258 // Hardware layer
259 ///////////////////////////////////////////////////////////////////////////
Raph Levien051910b2014-06-15 18:25:29 -0700260
Chris Craikf6829a02015-03-10 10:28:59 -0700261 /**
262 * Draws the specified layer onto this canvas.
263 *
264 * @param layer The layer to composite on this canvas
265 * @param x The left coordinate of the layer
266 * @param y The top coordinate of the layer
267 * @param paint The paint used to draw the layer
268 */
Romain Guyada830f2011-01-13 12:13:20 -0800269 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
Chris Craika4e16c52013-03-22 10:00:48 -0700270 layer.setLayerPaint(paint);
Tom Hudson8dfaa492014-12-09 15:03:44 -0500271 nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
Romain Guy6c319ca2011-01-11 14:29:25 -0800272 }
273
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000274 private static native void nDrawLayer(long renderer, long layer, float x, float y);
Romain Guyaa6c24c2011-04-28 18:40:04 -0700275
Romain Guy6c319ca2011-01-11 14:29:25 -0800276 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700277 // Drawing
278 ///////////////////////////////////////////////////////////////////////////
279
Tom Hudson8dfaa492014-12-09 15:03:44 -0500280 // TODO: move to Canvas.java
Romain Guye4d01122010-06-16 18:44:05 -0700281 @Override
Romain Guyf3187b72013-06-07 12:17:11 -0700282 public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
283 Bitmap bitmap = patch.getBitmap();
Chris Craik1abf5d62013-08-16 12:47:03 -0700284 throwIfCannotDraw(bitmap);
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -0400285 final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
John Reck1ff961d2015-04-17 20:45:15 +0000286 nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk,
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500287 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
Romain Guyf3187b72013-06-07 12:17:11 -0700288 }
289
Tom Hudson8dfaa492014-12-09 15:03:44 -0500290 // TODO: move to Canvas.java
Romain Guyf3187b72013-06-07 12:17:11 -0700291 @Override
Romain Guy3b748a42013-04-17 18:54:38 -0700292 public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
293 Bitmap bitmap = patch.getBitmap();
Chris Craik1abf5d62013-08-16 12:47:03 -0700294 throwIfCannotDraw(bitmap);
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -0400295 final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
John Reck1ff961d2015-04-17 20:45:15 +0000296 nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk,
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500297 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
Romain Guydeba7852010-07-07 17:54:48 -0700298 }
299
John Reck1ff961d2015-04-17 20:45:15 +0000300 private static native void nDrawPatch(long renderer, long bitmap, long chunk,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000301 float left, float top, float right, float bottom, long paint);
Romain Guydeba7852010-07-07 17:54:48 -0700302
John Reck52244ff2014-05-01 21:27:37 -0700303 public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
304 CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500305 nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
John Reck52244ff2014-05-01 21:27:37 -0700306 radius.getNativeContainer(), paint.getNativeContainer());
307 }
308
309 private static native void nDrawCircle(long renderer, long propCx,
310 long propCy, long propRadius, long propPaint);
311
Jorim Jaggi072707d2014-09-15 17:20:08 +0200312 public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
313 CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
314 CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500315 nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
Jorim Jaggi072707d2014-09-15 17:20:08 +0200316 right.getNativeContainer(), bottom.getNativeContainer(),
317 rx.getNativeContainer(), ry.getNativeContainer(),
318 paint.getNativeContainer());
319 }
320
321 private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
322 long propRight, long propBottom, long propRx, long propRy, long propPaint);
323
Tom Hudson8dfaa492014-12-09 15:03:44 -0500324 // TODO: move this optimization to Canvas.java
Romain Guye4d01122010-06-16 18:44:05 -0700325 @Override
326 public void drawPath(Path path, Paint paint) {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400327 if (path.isSimplePath) {
328 if (path.rects != null) {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500329 nDrawRects(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
Romain Guya48a1a82010-08-10 14:59:15 -0700330 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400331 } else {
Tom Hudson8dfaa492014-12-09 15:03:44 -0500332 super.drawPath(path, paint);
Romain Guya48a1a82010-08-10 14:59:15 -0700333 }
Romain Guye4d01122010-06-16 18:44:05 -0700334 }
335
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000336 private static native void nDrawRects(long renderer, long region, long paint);
Romain Guy7fbcc042010-08-04 15:40:07 -0700337
Romain Guye4d01122010-06-16 18:44:05 -0700338 @Override
339 public void drawPicture(Picture picture) {
Romain Guy75582e82012-01-18 18:13:35 -0800340 picture.endRecording();
341 // TODO: Implement rendering
Romain Guye4d01122010-06-16 18:44:05 -0700342 }
Romain Guye4d01122010-06-16 18:44:05 -0700343}