Home | History | Annotate | Download | only in view
      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.annotation.Nullable;
     21 import android.graphics.Bitmap;
     22 import android.graphics.CanvasProperty;
     23 import android.graphics.Paint;
     24 import android.util.Pools.SynchronizedPool;
     25 
     26 import dalvik.annotation.optimization.CriticalNative;
     27 import dalvik.annotation.optimization.FastNative;
     28 
     29 /**
     30  * A Canvas implementation that records view system drawing operations for deferred rendering.
     31  * 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.
     34  *
     35  * @hide
     36  */
     37 public final class DisplayListCanvas extends RecordingCanvas {
     38     // 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 
     42     private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
     43 
     44     private static final SynchronizedPool<DisplayListCanvas> sPool =
     45             new SynchronizedPool<>(POOL_LIMIT);
     46 
     47     RenderNode mNode;
     48     private int mWidth;
     49     private int mHeight;
     50 
     51     static DisplayListCanvas obtain(@NonNull RenderNode node, int width, int height) {
     52         if (node == null) throw new IllegalArgumentException("node cannot be null");
     53         DisplayListCanvas canvas = sPool.acquire();
     54         if (canvas == null) {
     55             canvas = new DisplayListCanvas(node, width, height);
     56         } else {
     57             nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, node.mNativeRenderNode,
     58                     width, height);
     59         }
     60         canvas.mNode = node;
     61         canvas.mWidth = width;
     62         canvas.mHeight = height;
     63         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     }
     79 
     80     ///////////////////////////////////////////////////////////////////////////
     81     // Constructors
     82     ///////////////////////////////////////////////////////////////////////////
     83 
     84     private DisplayListCanvas(@NonNull RenderNode node, int width, int height) {
     85         super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
     86         mDensity = 0; // disable bitmap density scaling
     87     }
     88 
     89     ///////////////////////////////////////////////////////////////////////////
     90     // Canvas management
     91     ///////////////////////////////////////////////////////////////////////////
     92 
     93 
     94     @Override
     95     public void setDensity(int density) {
     96         // drop silently, since DisplayListCanvas doesn't perform density scaling
     97     }
     98 
     99     @Override
    100     public boolean isHardwareAccelerated() {
    101         return true;
    102     }
    103 
    104     @Override
    105     public void setBitmap(Bitmap bitmap) {
    106         throw new UnsupportedOperationException();
    107     }
    108 
    109     @Override
    110     public boolean isOpaque() {
    111         return false;
    112     }
    113 
    114     @Override
    115     public int getWidth() {
    116         return mWidth;
    117     }
    118 
    119     @Override
    120     public int getHeight() {
    121         return mHeight;
    122     }
    123 
    124     @Override
    125     public int getMaximumBitmapWidth() {
    126         return nGetMaximumTextureWidth();
    127     }
    128 
    129     @Override
    130     public int getMaximumBitmapHeight() {
    131         return nGetMaximumTextureHeight();
    132     }
    133 
    134     ///////////////////////////////////////////////////////////////////////////
    135     // Setup
    136     ///////////////////////////////////////////////////////////////////////////
    137 
    138     @Override
    139     public void insertReorderBarrier() {
    140         nInsertReorderBarrier(mNativeCanvasWrapper, true);
    141     }
    142 
    143     @Override
    144     public void insertInorderBarrier() {
    145         nInsertReorderBarrier(mNativeCanvasWrapper, false);
    146     }
    147 
    148     ///////////////////////////////////////////////////////////////////////////
    149     // Functor
    150     ///////////////////////////////////////////////////////////////////////////
    151 
    152     /**
    153      * 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.
    155      *
    156      * @param drawGLFunction A native function pointer
    157      */
    158     public void callDrawGLFunction2(long drawGLFunction) {
    159         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction, null);
    160     }
    161 
    162     /**
    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      */
    174     public void drawGLFunctor2(long drawGLFunctor, @Nullable Runnable releasedCallback) {
    175         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
    176     }
    177 
    178     ///////////////////////////////////////////////////////////////////////////
    179     // Display list
    180     ///////////////////////////////////////////////////////////////////////////
    181 
    182     /**
    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      *
    186      * @param renderNode The RenderNode to draw.
    187      */
    188     public void drawRenderNode(RenderNode renderNode) {
    189         nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());
    190     }
    191 
    192     ///////////////////////////////////////////////////////////////////////////
    193     // Hardware layer
    194     ///////////////////////////////////////////////////////////////////////////
    195 
    196     /**
    197      * Draws the specified layer onto this canvas.
    198      *
    199      * @param layer The layer to composite on this canvas
    200      */
    201     void drawTextureLayer(TextureLayer layer) {
    202         nDrawTextureLayer(mNativeCanvasWrapper, layer.getLayerHandle());
    203     }
    204 
    205     ///////////////////////////////////////////////////////////////////////////
    206     // Drawing
    207     ///////////////////////////////////////////////////////////////////////////
    208 
    209     public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
    210             CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
    211         nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
    212                 radius.getNativeContainer(), paint.getNativeContainer());
    213     }
    214 
    215     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) {
    218         nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
    219                 right.getNativeContainer(), bottom.getNativeContainer(),
    220                 rx.getNativeContainer(), ry.getNativeContainer(),
    221                 paint.getNativeContainer());
    222     }
    223 
    224     @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     }
    233 
    234 
    235     // ------------------ Fast JNI ------------------------
    236 
    237     @FastNative
    238     private static native void nCallDrawGLFunction(long renderer,
    239             long drawGLFunction, Runnable releasedCallback);
    240 
    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
    256     private static native long nFinishRecording(long renderer);
    257     @CriticalNative
    258     private static native void nDrawRenderNode(long renderer, long renderNode);
    259     @CriticalNative
    260     private static native void nDrawTextureLayer(long renderer, long layer);
    261     @CriticalNative
    262     private static native void nDrawCircle(long renderer, long propCx,
    263             long propCy, long propRadius, long propPaint);
    264     @CriticalNative
    265     private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
    266             long propRight, long propBottom, long propRx, long propRy, long propPaint);
    267 }
    268