• 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.view;
18 
19 import android.annotation.NonNull;
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import android.graphics.CanvasProperty;
23 import android.graphics.NinePatch;
24 import android.graphics.Paint;
25 import android.graphics.Path;
26 import android.graphics.Picture;
27 import android.graphics.Rect;
28 import android.graphics.RectF;
29 import android.util.Pools.SynchronizedPool;
30 
31 /**
32  * 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.
36  *
37  * @hide
38  */
39 public class DisplayListCanvas extends Canvas {
40     // 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;
48     private int mWidth;
49     private int mHeight;
50 
obtain(@onNull RenderNode node)51     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 
recycle()61     void recycle() {
62         mNode = null;
63         sPool.release(this);
64     }
65 
finishRecording()66     long finishRecording() {
67         return nFinishRecording(mNativeCanvasWrapper);
68     }
69 
70     @Override
isRecordingFor(Object o)71     public boolean isRecordingFor(Object o) {
72         return o == mNode;
73     }
74 
75     ///////////////////////////////////////////////////////////////////////////
76     // JNI
77     ///////////////////////////////////////////////////////////////////////////
78 
nIsAvailable()79     private static native boolean nIsAvailable();
80     private static boolean sIsAvailable = nIsAvailable();
81 
isAvailable()82     static boolean isAvailable() {
83         return sIsAvailable;
84     }
85 
86     ///////////////////////////////////////////////////////////////////////////
87     // Constructors
88     ///////////////////////////////////////////////////////////////////////////
89 
DisplayListCanvas()90     private DisplayListCanvas() {
91         super(nCreateDisplayListCanvas());
92         mDensity = 0; // disable bitmap density scaling
93     }
94 
nCreateDisplayListCanvas()95     private static native long nCreateDisplayListCanvas();
96 
97     ///////////////////////////////////////////////////////////////////////////
98     // Canvas management
99     ///////////////////////////////////////////////////////////////////////////
100 
101 
102     @Override
setDensity(int density)103     public void setDensity(int density) {
104         // drop silently, since DisplayListCanvas 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 
nGetMaximumTextureWidth()142     private static native int nGetMaximumTextureWidth();
nGetMaximumTextureHeight()143     private static native int nGetMaximumTextureHeight();
144 
145     /**
146      * Returns the native OpenGLRenderer object.
147      */
getRenderer()148     long getRenderer() {
149         return mNativeCanvasWrapper;
150     }
151 
152     ///////////////////////////////////////////////////////////////////////////
153     // Setup
154     ///////////////////////////////////////////////////////////////////////////
155 
156     @Override
setViewport(int width, int height)157     public void setViewport(int width, int height) {
158         mWidth = width;
159         mHeight = height;
160 
161         nSetViewport(mNativeCanvasWrapper, width, height);
162     }
163 
nSetViewport(long renderer, int width, int height)164     private static native void nSetViewport(long renderer,
165             int width, int height);
166 
167     @Override
setHighContrastText(boolean highContrastText)168     public void setHighContrastText(boolean highContrastText) {
169         nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
170     }
171 
nSetHighContrastText(long renderer, boolean highContrastText)172     private static native void nSetHighContrastText(long renderer, boolean highContrastText);
173 
174     @Override
insertReorderBarrier()175     public void insertReorderBarrier() {
176         nInsertReorderBarrier(mNativeCanvasWrapper, true);
177     }
178 
179     @Override
insertInorderBarrier()180     public void insertInorderBarrier() {
181         nInsertReorderBarrier(mNativeCanvasWrapper, false);
182     }
183 
nInsertReorderBarrier(long renderer, boolean enableReorder)184     private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
185 
186     /**
187      * Invoked before any drawing operation is performed in this canvas.
188      *
189      * @param dirty The dirty rectangle to update, can be null.
190      */
onPreDraw(Rect dirty)191     public void onPreDraw(Rect dirty) {
192         if (dirty != null) {
193             nPrepareDirty(mNativeCanvasWrapper, dirty.left, dirty.top, dirty.right, dirty.bottom);
194         } else {
195             nPrepare(mNativeCanvasWrapper);
196         }
197     }
198 
nPrepare(long renderer)199     private static native void nPrepare(long renderer);
nPrepareDirty(long renderer, int left, int top, int right, int bottom)200     private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom);
201 
202     /**
203      * Invoked after all drawing operation have been performed.
204      */
onPostDraw()205     public void onPostDraw() {
206         nFinish(mNativeCanvasWrapper);
207     }
208 
nFinish(long renderer)209     private static native void nFinish(long renderer);
210 
211     ///////////////////////////////////////////////////////////////////////////
212     // Functor
213     ///////////////////////////////////////////////////////////////////////////
214 
215     /**
216      * Calls the function specified with the drawGLFunction function pointer. This is
217      * functionality used by webkit for calling into their renderer from our display lists.
218      * This function may return true if an invalidation is needed after the call.
219      *
220      * @param drawGLFunction A native function pointer
221      */
callDrawGLFunction2(long drawGLFunction)222     public void callDrawGLFunction2(long drawGLFunction) {
223         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction);
224     }
225 
nCallDrawGLFunction(long renderer, long drawGLFunction)226     private static native void nCallDrawGLFunction(long renderer, long drawGLFunction);
227 
228     ///////////////////////////////////////////////////////////////////////////
229     // Display list
230     ///////////////////////////////////////////////////////////////////////////
231 
nFinishRecording(long renderer)232     protected static native long nFinishRecording(long renderer);
233 
234     /**
235      * Draws the specified display list onto this canvas. The display list can only
236      * be drawn if {@link android.view.RenderNode#isValid()} returns true.
237      *
238      * @param renderNode The RenderNode to draw.
239      */
drawRenderNode(RenderNode renderNode)240     public void drawRenderNode(RenderNode renderNode) {
241         nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());
242     }
243 
nDrawRenderNode(long renderer, long renderNode)244     private static native void nDrawRenderNode(long renderer, long renderNode);
245 
246     ///////////////////////////////////////////////////////////////////////////
247     // Hardware layer
248     ///////////////////////////////////////////////////////////////////////////
249 
250     /**
251      * Draws the specified layer onto this canvas.
252      *
253      * @param layer The layer to composite on this canvas
254      * @param x The left coordinate of the layer
255      * @param y The top coordinate of the layer
256      * @param paint The paint used to draw the layer
257      */
drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint)258     void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
259         layer.setLayerPaint(paint);
260         nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
261     }
262 
nDrawLayer(long renderer, long layer, float x, float y)263     private static native void nDrawLayer(long renderer, long layer, float x, float y);
264 
265     ///////////////////////////////////////////////////////////////////////////
266     // Drawing
267     ///////////////////////////////////////////////////////////////////////////
268 
269     // TODO: move to Canvas.java
270     @Override
drawPatch(NinePatch patch, Rect dst, Paint paint)271     public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
272         Bitmap bitmap = patch.getBitmap();
273         throwIfCannotDraw(bitmap);
274         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
275         nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk,
276                 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
277     }
278 
279     // TODO: move to Canvas.java
280     @Override
drawPatch(NinePatch patch, RectF dst, Paint paint)281     public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
282         Bitmap bitmap = patch.getBitmap();
283         throwIfCannotDraw(bitmap);
284         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
285         nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk,
286                 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
287     }
288 
nDrawPatch(long renderer, Bitmap bitmap, long chunk, float left, float top, float right, float bottom, long paint)289     private static native void nDrawPatch(long renderer, Bitmap bitmap, long chunk,
290             float left, float top, float right, float bottom, long paint);
291 
drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy, CanvasProperty<Float> radius, CanvasProperty<Paint> paint)292     public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
293             CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
294         nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
295                 radius.getNativeContainer(), paint.getNativeContainer());
296     }
297 
nDrawCircle(long renderer, long propCx, long propCy, long propRadius, long propPaint)298     private static native void nDrawCircle(long renderer, long propCx,
299             long propCy, long propRadius, long propPaint);
300 
drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top, CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx, CanvasProperty<Float> ry, CanvasProperty<Paint> paint)301     public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
302             CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
303             CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
304         nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
305                 right.getNativeContainer(), bottom.getNativeContainer(),
306                 rx.getNativeContainer(), ry.getNativeContainer(),
307                 paint.getNativeContainer());
308     }
309 
nDrawRoundRect(long renderer, long propLeft, long propTop, long propRight, long propBottom, long propRx, long propRy, long propPaint)310     private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
311             long propRight, long propBottom, long propRx, long propRy, long propPaint);
312 
313     // TODO: move this optimization to Canvas.java
314     @Override
drawPath(Path path, Paint paint)315     public void drawPath(Path path, Paint paint) {
316         if (path.isSimplePath) {
317             if (path.rects != null) {
318                 nDrawRects(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
319             }
320         } else {
321             super.drawPath(path, paint);
322         }
323     }
324 
nDrawRects(long renderer, long region, long paint)325     private static native void nDrawRects(long renderer, long region, long paint);
326 }
327