ThreadedRenderer.java revision 767e25ed613201d93d293a4c8ead5a21c0fb2b22
1/*
2 * Copyright (C) 2013 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
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.app.ActivityManager;
22import android.content.Context;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
25import android.graphics.Point;
26import android.graphics.Rect;
27import android.graphics.drawable.AnimatedVectorDrawable;
28import android.os.IBinder;
29import android.os.ParcelFileDescriptor;
30import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.os.SystemProperties;
33import android.os.Trace;
34import android.util.Log;
35import android.view.Surface.OutOfResourcesException;
36import android.view.View.AttachInfo;
37import android.view.animation.AnimationUtils;
38
39import com.android.internal.R;
40import com.android.internal.util.VirtualRefBasePtr;
41
42import java.io.File;
43import java.io.FileDescriptor;
44import java.io.PrintWriter;
45import java.lang.annotation.Retention;
46import java.lang.annotation.RetentionPolicy;
47
48/**
49 * Threaded renderer that proxies the rendering to a render thread. Most calls
50 * are currently synchronous.
51 *
52 * The UI thread can block on the RenderThread, but RenderThread must never
53 * block on the UI thread.
54 *
55 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
56 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
57 * by the lifecycle of the RenderProxy.
58 *
59 * Note that although currently the EGL context & surfaces are created & managed
60 * by the render thread, the goal is to move that into a shared structure that can
61 * be managed by both threads. EGLSurface creation & deletion should ideally be
62 * done on the UI thread and not the RenderThread to avoid stalling the
63 * RenderThread with surface buffer allocation.
64 *
65 * @hide
66 */
67public final class ThreadedRenderer {
68    private static final String LOG_TAG = "ThreadedRenderer";
69
70    /**
71     * Name of the file that holds the shaders cache.
72     */
73    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
74    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
75
76    /**
77     * System property used to enable or disable threaded rendering profiling.
78     * The default value of this property is assumed to be false.
79     *
80     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
81     * output extra information about the time taken to execute by the last
82     * frames.
83     *
84     * Possible values:
85     * "true", to enable profiling
86     * "visual_bars", to enable profiling and visualize the results on screen
87     * "false", to disable profiling
88     *
89     * @see #PROFILE_PROPERTY_VISUALIZE_BARS
90     *
91     * @hide
92     */
93    public static final String PROFILE_PROPERTY = "debug.hwui.profile";
94
95    /**
96     * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
97     * value, profiling data will be visualized on screen as a bar chart.
98     *
99     * @hide
100     */
101    public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
102
103    /**
104     * System property used to specify the number of frames to be used
105     * when doing threaded rendering profiling.
106     * The default value of this property is #PROFILE_MAX_FRAMES.
107     *
108     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
109     * output extra information about the time taken to execute by the last
110     * frames.
111     *
112     * Possible values:
113     * "60", to set the limit of frames to 60
114     */
115    static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
116
117    /**
118     * System property used to debug EGL configuration choice.
119     *
120     * Possible values:
121     * "choice", print the chosen configuration only
122     * "all", print all possible configurations
123     */
124    static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
125
126    /**
127     * Turn on to draw dirty regions every other frame.
128     *
129     * Possible values:
130     * "true", to enable dirty regions debugging
131     * "false", to disable dirty regions debugging
132     *
133     * @hide
134     */
135    public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
136
137    /**
138     * Turn on to flash hardware layers when they update.
139     *
140     * Possible values:
141     * "true", to enable hardware layers updates debugging
142     * "false", to disable hardware layers updates debugging
143     *
144     * @hide
145     */
146    public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
147            "debug.hwui.show_layers_updates";
148
149    /**
150     * Controls overdraw debugging.
151     *
152     * Possible values:
153     * "false", to disable overdraw debugging
154     * "show", to show overdraw areas on screen
155     * "count", to display an overdraw counter
156     *
157     * @hide
158     */
159    public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
160
161    /**
162     * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
163     * value, overdraw will be shown on screen by coloring pixels.
164     *
165     * @hide
166     */
167    public static final String OVERDRAW_PROPERTY_SHOW = "show";
168
169    /**
170     * Turn on to debug non-rectangular clip operations.
171     *
172     * Possible values:
173     * "hide", to disable this debug mode
174     * "highlight", highlight drawing commands tested against a non-rectangular clip
175     * "stencil", renders the clip region on screen when set
176     *
177     * @hide
178     */
179    public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
180            "debug.hwui.show_non_rect_clip";
181
182    /**
183     * Sets the FPS devisor to lower the FPS.
184     *
185     * Sets a positive integer as a divisor. 1 (the default value) menas the full FPS, and 2
186     * means half the full FPS.
187     *
188     *
189     * @hide
190     */
191    public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
192
193    public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
194    public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
195    public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
196
197    static {
198        // Try to check OpenGL support early if possible.
199        isAvailable();
200    }
201
202    /**
203     * A process can set this flag to false to prevent the use of threaded
204     * rendering.
205     *
206     * @hide
207     */
208    public static boolean sRendererDisabled = false;
209
210    /**
211     * Further threaded renderer disabling for the system process.
212     *
213     * @hide
214     */
215    public static boolean sSystemRendererDisabled = false;
216
217    /**
218     * Invoke this method to disable threaded rendering in the current process.
219     *
220     * @hide
221     */
222    public static void disable(boolean system) {
223        sRendererDisabled = true;
224        if (system) {
225            sSystemRendererDisabled = true;
226        }
227    }
228
229    public static boolean sTrimForeground = false;
230
231    /**
232     * Controls whether or not the renderer should aggressively trim
233     * memory. Note that this must not be set for any process that uses
234     * WebView! This should be only used by system_process or similar
235     * that do not go into the background.
236     */
237    public static void enableForegroundTrimming() {
238        sTrimForeground = true;
239    }
240
241    private static Boolean sSupportsOpenGL;
242
243    /**
244     * Indicates whether threaded rendering is available under any form for
245     * the view hierarchy.
246     *
247     * @return True if the view hierarchy can potentially be defer rendered,
248     *         false otherwise
249     */
250    public static boolean isAvailable() {
251        if (sSupportsOpenGL != null) {
252            return sSupportsOpenGL.booleanValue();
253        }
254        if (SystemProperties.getInt("ro.kernel.qemu", 0) == 0) {
255            // Device is not an emulator.
256            sSupportsOpenGL = true;
257            return true;
258        }
259        int qemu_gles = SystemProperties.getInt("qemu.gles", -1);
260        if (qemu_gles == -1) {
261            // In this case, the value of the qemu.gles property is not ready
262            // because the SurfaceFlinger service may not start at this point.
263            return false;
264        }
265        // In the emulator this property will be set > 0 when OpenGL ES 2.0 is
266        // enabled, 0 otherwise. On old emulator versions it will be undefined.
267        sSupportsOpenGL = qemu_gles > 0;
268        return sSupportsOpenGL.booleanValue();
269    }
270
271    /**
272     * Sets the directory to use as a persistent storage for threaded rendering
273     * resources.
274     *
275     * @param cacheDir A directory the current process can write to
276     *
277     * @hide
278     */
279    public static void setupDiskCache(File cacheDir) {
280        ThreadedRenderer.setupShadersDiskCache(
281                new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
282                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
283    }
284
285    /**
286     * Creates a threaded renderer using OpenGL.
287     *
288     * @param translucent True if the surface is translucent, false otherwise
289     *
290     * @return A threaded renderer backed by OpenGL.
291     */
292    public static ThreadedRenderer create(Context context, boolean translucent, String name) {
293        ThreadedRenderer renderer = null;
294        if (isAvailable()) {
295            renderer = new ThreadedRenderer(context, translucent, name);
296        }
297        return renderer;
298    }
299
300    /**
301     * Invoke this method when the system is running out of memory. This
302     * method will attempt to recover as much memory as possible, based on
303     * the specified hint.
304     *
305     * @param level Hint about the amount of memory that should be trimmed,
306     *              see {@link android.content.ComponentCallbacks}
307     */
308    public static void trimMemory(int level) {
309        nTrimMemory(level);
310    }
311
312    public static void overrideProperty(@NonNull String name, @NonNull String value) {
313        if (name == null || value == null) {
314            throw new IllegalArgumentException("name and value must be non-null");
315        }
316        nOverrideProperty(name, value);
317    }
318
319    // Keep in sync with DrawFrameTask.h SYNC_* flags
320    // Nothing interesting to report
321    private static final int SYNC_OK = 0;
322    // Needs a ViewRoot invalidate
323    private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
324    // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
325    private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
326    // setStopped is true, drawing is false
327    // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
328    // This flag isn't really used as there's nothing that we care to do
329    // in response, so it really just exists to differentiate from LOST_SURFACE
330    // but possibly both can just be deleted.
331    private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
332
333    private static final String[] VISUALIZERS = {
334        PROFILE_PROPERTY_VISUALIZE_BARS,
335    };
336
337    private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
338    private static final int FLAG_DUMP_RESET        = 1 << 1;
339    private static final int FLAG_DUMP_ALL          = FLAG_DUMP_FRAMESTATS;
340
341    @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
342            FLAG_DUMP_FRAMESTATS,
343            FLAG_DUMP_RESET
344    })
345    @Retention(RetentionPolicy.SOURCE)
346    public @interface DumpFlags {}
347
348    // Size of the rendered content.
349    private int mWidth, mHeight;
350
351    // Actual size of the drawing surface.
352    private int mSurfaceWidth, mSurfaceHeight;
353
354    // Insets between the drawing surface and rendered content. These are
355    // applied as translation when updating the root render node.
356    private int mInsetTop, mInsetLeft;
357
358    // Whether the surface has insets. Used to protect opacity.
359    private boolean mHasInsets;
360
361    // Light and shadow properties specified by the theme.
362    private final float mLightY;
363    private final float mLightZ;
364    private final float mLightRadius;
365    private final int mAmbientShadowAlpha;
366    private final int mSpotShadowAlpha;
367
368    private long mNativeProxy;
369    private boolean mInitialized = false;
370    private RenderNode mRootNode;
371    private boolean mRootNodeNeedsUpdate;
372
373    private boolean mEnabled;
374    private boolean mRequested = true;
375    private boolean mIsOpaque = false;
376
377    ThreadedRenderer(Context context, boolean translucent, String name) {
378        final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
379        mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
380        mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
381        mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
382        mAmbientShadowAlpha =
383                (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
384        mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
385        a.recycle();
386
387        long rootNodePtr = nCreateRootRenderNode();
388        mRootNode = RenderNode.adopt(rootNodePtr);
389        mRootNode.setClipToBounds(false);
390        mIsOpaque = !translucent;
391        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
392        nSetName(mNativeProxy, name);
393
394        ProcessInitializer.sInstance.init(context, mNativeProxy);
395
396        loadSystemProperties();
397    }
398
399    /**
400     * Destroys the threaded rendering context.
401     */
402    void destroy() {
403        mInitialized = false;
404        updateEnabledState(null);
405        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
406    }
407
408    /**
409     * Indicates whether threaded rendering is currently enabled.
410     *
411     * @return True if threaded rendering  is in use, false otherwise.
412     */
413    boolean isEnabled() {
414        return mEnabled;
415    }
416
417    /**
418     * Indicates whether threaded rendering  is currently enabled.
419     *
420     * @param enabled True if the threaded renderer is in use, false otherwise.
421     */
422    void setEnabled(boolean enabled) {
423        mEnabled = enabled;
424    }
425
426    /**
427     * Indicates whether threaded rendering is currently request but not
428     * necessarily enabled yet.
429     *
430     * @return True if requested, false otherwise.
431     */
432    boolean isRequested() {
433        return mRequested;
434    }
435
436    /**
437     * Indicates whether threaded rendering is currently requested but not
438     * necessarily enabled yet.
439     */
440    void setRequested(boolean requested) {
441        mRequested = requested;
442    }
443
444    private void updateEnabledState(Surface surface) {
445        if (surface == null || !surface.isValid()) {
446            setEnabled(false);
447        } else {
448            setEnabled(mInitialized);
449        }
450    }
451
452    /**
453     * Initializes the threaded renderer for the specified surface.
454     *
455     * @param surface The surface to render
456     *
457     * @return True if the initialization was successful, false otherwise.
458     */
459    boolean initialize(Surface surface) throws OutOfResourcesException {
460        boolean status = !mInitialized;
461        mInitialized = true;
462        updateEnabledState(surface);
463        nInitialize(mNativeProxy, surface);
464        return status;
465    }
466
467    /**
468     * Initializes the threaded renderer for the specified surface and setup the
469     * renderer for drawing, if needed. This is invoked when the ViewAncestor has
470     * potentially lost the threaded renderer. The threaded renderer should be
471     * reinitialized and setup when the render {@link #isRequested()} and
472     * {@link #isEnabled()}.
473     *
474     * @param width The width of the drawing surface.
475     * @param height The height of the drawing surface.
476     * @param attachInfo Information about the window.
477     * @param surface The surface to render
478     * @param surfaceInsets The drawing surface insets to apply
479     *
480     * @return true if the surface was initialized, false otherwise. Returning
481     *         false might mean that the surface was already initialized.
482     */
483    boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
484            Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
485        if (isRequested()) {
486            // We lost the gl context, so recreate it.
487            if (!isEnabled()) {
488                if (initialize(surface)) {
489                    setup(width, height, attachInfo, surfaceInsets);
490                    return true;
491                }
492            }
493        }
494        return false;
495    }
496
497    /**
498     * Updates the threaded renderer for the specified surface.
499     *
500     * @param surface The surface to render
501     */
502    void updateSurface(Surface surface) throws OutOfResourcesException {
503        updateEnabledState(surface);
504        nUpdateSurface(mNativeProxy, surface);
505    }
506
507    /**
508     * Halts any current rendering into the surface. Use this if it is unclear whether
509     * or not the surface used by the ThreadedRenderer will be changing. It
510     * Suspends any rendering into the surface, but will not do any destruction.
511     *
512     * Any subsequent draws will override the pause, resuming normal operation.
513     */
514    boolean pauseSurface(Surface surface) {
515        return nPauseSurface(mNativeProxy, surface);
516    }
517
518    /**
519     * Hard stops or resumes rendering into the surface. This flag is used to
520     * determine whether or not it is safe to use the given surface *at all*
521     */
522    void setStopped(boolean stopped) {
523        nSetStopped(mNativeProxy, stopped);
524    }
525
526    /**
527     * Destroys all hardware rendering resources associated with the specified
528     * view hierarchy.
529     *
530     * @param view The root of the view hierarchy
531     */
532    void destroyHardwareResources(View view) {
533        destroyResources(view);
534        nDestroyHardwareResources(mNativeProxy);
535    }
536
537    private static void destroyResources(View view) {
538        view.destroyHardwareResources();
539    }
540
541    /**
542     * Detaches the layer's surface texture from the GL context and releases
543     * the texture id
544     */
545    void detachSurfaceTexture(long hardwareLayer) {
546        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
547    }
548
549    /**
550     * Sets up the renderer for drawing.
551     *
552     * @param width The width of the drawing surface.
553     * @param height The height of the drawing surface.
554     * @param attachInfo Information about the window.
555     * @param surfaceInsets The drawing surface insets to apply
556     */
557    void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
558        mWidth = width;
559        mHeight = height;
560
561        if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
562                || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
563            mHasInsets = true;
564            mInsetLeft = surfaceInsets.left;
565            mInsetTop = surfaceInsets.top;
566            mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
567            mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
568
569            // If the surface has insets, it can't be opaque.
570            setOpaque(false);
571        } else {
572            mHasInsets = false;
573            mInsetLeft = 0;
574            mInsetTop = 0;
575            mSurfaceWidth = width;
576            mSurfaceHeight = height;
577        }
578
579        mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
580        nSetup(mNativeProxy, mLightRadius,
581                mAmbientShadowAlpha, mSpotShadowAlpha);
582
583        setLightCenter(attachInfo);
584    }
585
586    /**
587     * Updates the light position based on the position of the window.
588     *
589     * @param attachInfo Information about the window.
590     */
591    void setLightCenter(AttachInfo attachInfo) {
592        // Adjust light position for window offsets.
593        final Point displaySize = attachInfo.mPoint;
594        attachInfo.mDisplay.getRealSize(displaySize);
595        final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
596        final float lightY = mLightY - attachInfo.mWindowTop;
597
598        nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
599    }
600
601    /**
602     * Change the ThreadedRenderer's opacity
603     */
604    void setOpaque(boolean opaque) {
605        mIsOpaque = opaque && !mHasInsets;
606        nSetOpaque(mNativeProxy, mIsOpaque);
607    }
608
609    boolean isOpaque() {
610        return mIsOpaque;
611    }
612
613    /**
614     * Enable/disable wide gamut rendering on this renderer.
615     */
616    void setWideGamut(boolean wideGamut) {
617        nSetWideGamut(mNativeProxy, wideGamut);
618    }
619
620    /**
621     * Gets the current width of the surface. This is the width that the surface
622     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
623     *
624     * @return the current width of the surface
625     */
626    int getWidth() {
627        return mWidth;
628    }
629
630    /**
631     * Gets the current height of the surface. This is the height that the surface
632     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
633     *
634     * @return the current width of the surface
635     */
636    int getHeight() {
637        return mHeight;
638    }
639
640    /**
641     * Outputs extra debugging information in the specified file descriptor.
642     */
643    void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
644        pw.flush();
645        // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
646        // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
647        // dump the summary information
648        int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
649        for (int i = 0; i < args.length; i++) {
650            switch (args[i]) {
651                case "framestats":
652                    flags |= FLAG_DUMP_FRAMESTATS;
653                    break;
654                case "reset":
655                    flags |= FLAG_DUMP_RESET;
656                    break;
657                case "-a": // magic option passed when dumping a bugreport.
658                    flags = FLAG_DUMP_ALL;
659                    break;
660            }
661        }
662        nDumpProfileInfo(mNativeProxy, fd, flags);
663    }
664
665    /**
666     * Loads system properties used by the renderer. This method is invoked
667     * whenever system properties are modified. Implementations can use this
668     * to trigger live updates of the renderer based on properties.
669     *
670     * @return True if a property has changed.
671     */
672    boolean loadSystemProperties() {
673        boolean changed = nLoadSystemProperties(mNativeProxy);
674        if (changed) {
675            invalidateRoot();
676        }
677        return changed;
678    }
679
680    private void updateViewTreeDisplayList(View view) {
681        view.mPrivateFlags |= View.PFLAG_DRAWN;
682        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
683                == View.PFLAG_INVALIDATED;
684        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
685        view.updateDisplayListIfDirty();
686        view.mRecreateDisplayList = false;
687    }
688
689    private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
690        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
691        updateViewTreeDisplayList(view);
692
693        if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
694            DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
695            try {
696                final int saveCount = canvas.save();
697                canvas.translate(mInsetLeft, mInsetTop);
698                callbacks.onPreDraw(canvas);
699
700                canvas.insertReorderBarrier();
701                canvas.drawRenderNode(view.updateDisplayListIfDirty());
702                canvas.insertInorderBarrier();
703
704                callbacks.onPostDraw(canvas);
705                canvas.restoreToCount(saveCount);
706                mRootNodeNeedsUpdate = false;
707            } finally {
708                mRootNode.end(canvas);
709            }
710        }
711        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
712    }
713
714    /**
715     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
716     * rendernode of the UI thread.
717     * @param node The node to add.
718     * @param placeFront If true, the render node will be placed in front of the content node,
719     *                   otherwise behind the content node.
720     */
721    public void addRenderNode(RenderNode node, boolean placeFront) {
722        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
723    }
724
725    /**
726     * Only especially added render nodes can be removed.
727     * @param node The node which was added via addRenderNode which should get removed again.
728     */
729    public void removeRenderNode(RenderNode node) {
730        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
731    }
732
733    /**
734     * Draws a particular render node. If the node is not the content node, only the additional
735     * nodes will get drawn and the content remains untouched.
736     * @param node The node to be drawn.
737     */
738    public void drawRenderNode(RenderNode node) {
739        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
740    }
741
742    /**
743     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
744     * will be prevented to overdraw this area. It will be synchronized with the draw call.
745     * This should be updated in the content view's draw call.
746     * @param left The left side of the protected bounds.
747     * @param top The top side of the protected bounds.
748     * @param right The right side of the protected bounds.
749     * @param bottom The bottom side of the protected bounds.
750     */
751    public void setContentDrawBounds(int left, int top, int right, int bottom) {
752        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
753    }
754
755    /**
756     * Interface used to receive callbacks whenever a view is drawn by
757     * a threaded renderer instance.
758     */
759    interface DrawCallbacks {
760        /**
761         * Invoked before a view is drawn by a threaded renderer.
762         * This method can be used to apply transformations to the
763         * canvas but no drawing command should be issued.
764         *
765         * @param canvas The Canvas used to render the view.
766         */
767        void onPreDraw(DisplayListCanvas canvas);
768
769        /**
770         * Invoked after a view is drawn by a threaded renderer.
771         * It is safe to invoke drawing commands from this method.
772         *
773         * @param canvas The Canvas used to render the view.
774         */
775        void onPostDraw(DisplayListCanvas canvas);
776    }
777
778    /**
779     *  Indicates that the content drawn by DrawCallbacks needs to
780     *  be updated, which will be done by the next call to draw()
781     */
782    void invalidateRoot() {
783        mRootNodeNeedsUpdate = true;
784    }
785
786    /**
787     * Draws the specified view.
788     *
789     * @param view The view to draw.
790     * @param attachInfo AttachInfo tied to the specified view.
791     * @param callbacks Callbacks invoked when drawing happens.
792     */
793    void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
794        attachInfo.mIgnoreDirtyState = true;
795
796        final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
797        choreographer.mFrameInfo.markDrawStart();
798
799        updateRootDisplayList(view, callbacks);
800
801        attachInfo.mIgnoreDirtyState = false;
802
803        // register animating rendernodes which started animating prior to renderer
804        // creation, which is typical for animators started prior to first draw
805        if (attachInfo.mPendingAnimatingRenderNodes != null) {
806            final int count = attachInfo.mPendingAnimatingRenderNodes.size();
807            for (int i = 0; i < count; i++) {
808                registerAnimatingRenderNode(
809                        attachInfo.mPendingAnimatingRenderNodes.get(i));
810            }
811            attachInfo.mPendingAnimatingRenderNodes.clear();
812            // We don't need this anymore as subsequent calls to
813            // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
814            attachInfo.mPendingAnimatingRenderNodes = null;
815        }
816
817        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
818        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
819        if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
820            setEnabled(false);
821            attachInfo.mViewRootImpl.mSurface.release();
822            // Invalidate since we failed to draw. This should fetch a Surface
823            // if it is still needed or do nothing if we are no longer drawing
824            attachInfo.mViewRootImpl.invalidate();
825        }
826        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
827            attachInfo.mViewRootImpl.invalidate();
828        }
829    }
830
831    static void invokeFunctor(long functor, boolean waitForCompletion) {
832        nInvokeFunctor(functor, waitForCompletion);
833    }
834
835    /**
836     * Creates a new hardware layer. A hardware layer built by calling this
837     * method will be treated as a texture layer, instead of as a render target.
838     *
839     * @return A hardware layer
840     */
841    TextureLayer createTextureLayer() {
842        long layer = nCreateTextureLayer(mNativeProxy);
843        return TextureLayer.adoptTextureLayer(this, layer);
844    }
845
846
847    void buildLayer(RenderNode node) {
848        nBuildLayer(mNativeProxy, node.getNativeDisplayList());
849    }
850
851
852    boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
853        return nCopyLayerInto(mNativeProxy,
854                layer.getDeferredLayerUpdater(), bitmap);
855    }
856
857    /**
858     * Indicates that the specified hardware layer needs to be updated
859     * as soon as possible.
860     *
861     * @param layer The hardware layer that needs an update
862     */
863    void pushLayerUpdate(TextureLayer layer) {
864        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
865    }
866
867    /**
868     * Tells the HardwareRenderer that the layer is destroyed. The renderer
869     * should remove the layer from any update queues.
870     */
871    void onLayerDestroyed(TextureLayer layer) {
872        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
873    }
874
875    /**
876     * Blocks until all previously queued work has completed.
877     */
878    void fence() {
879        nFence(mNativeProxy);
880    }
881
882    /**
883     * Prevents any further drawing until draw() is called. This is a signal
884     * that the contents of the RenderNode tree are no longer safe to play back.
885     * In practice this usually means that there are Functor pointers in the
886     * display list that are no longer valid.
887     */
888    void stopDrawing() {
889        nStopDrawing(mNativeProxy);
890    }
891
892    /**
893     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
894     */
895    public void notifyFramePending() {
896        nNotifyFramePending(mNativeProxy);
897    }
898
899
900    void registerAnimatingRenderNode(RenderNode animator) {
901        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
902    }
903
904    void registerVectorDrawableAnimator(
905        AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) {
906        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
907                animator.getAnimatorNativePtr());
908    }
909
910    public void serializeDisplayListTree() {
911        nSerializeDisplayListTree(mNativeProxy);
912    }
913
914    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
915        if (srcRect == null) {
916            // Empty rect means entire surface
917            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
918        } else {
919            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
920                    srcRect.right, srcRect.bottom, bitmap);
921        }
922    }
923
924    /**
925     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
926     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
927     * not the RenderNode from a View.
928     **/
929    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
930        return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height);
931    }
932
933    /**
934     * Sets whether or not high contrast text rendering is enabled. The setting is global
935     * but only affects content rendered after the change is made.
936     */
937    public static void setHighContrastText(boolean highContrastText) {
938        nSetHighContrastText(highContrastText);
939    }
940
941    /**
942     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
943     */
944    public static void setIsolatedProcess(boolean isIsolated) {
945        nSetIsolatedProcess(isIsolated);
946    }
947
948    /**
949     * If set extra graphics debugging abilities will be enabled such as dumping skp
950     */
951    public static void setDebuggingEnabled(boolean enable) {
952        nSetDebuggingEnabled(enable);
953    }
954
955    @Override
956    protected void finalize() throws Throwable {
957        try {
958            nDeleteProxy(mNativeProxy);
959            mNativeProxy = 0;
960        } finally {
961            super.finalize();
962        }
963    }
964
965    /**
966     * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
967     * TODO: deduplicate against ThreadedRenderer.
968     *
969     * @hide
970     */
971    public static class SimpleRenderer {
972        private final RenderNode mRootNode;
973        private long mNativeProxy;
974        private final float mLightY, mLightZ;
975        private Surface mSurface;
976        private final FrameInfo mFrameInfo = new FrameInfo();
977
978        public SimpleRenderer(final Context context, final String name, final Surface surface) {
979            final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
980            mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
981            mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
982            final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
983            final int ambientShadowAlpha =
984                    (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
985            final int spotShadowAlpha =
986                    (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
987            a.recycle();
988
989            final long rootNodePtr = nCreateRootRenderNode();
990            mRootNode = RenderNode.adopt(rootNodePtr);
991            mRootNode.setClipToBounds(false);
992            mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
993            nSetName(mNativeProxy, name);
994
995            ProcessInitializer.sInstance.init(context, mNativeProxy);
996            nLoadSystemProperties(mNativeProxy);
997
998            nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
999
1000            mSurface = surface;
1001            nUpdateSurface(mNativeProxy, surface);
1002        }
1003
1004        /**
1005         * Set the light center.
1006         */
1007        public void setLightCenter(final Display display,
1008                final int windowLeft, final int windowTop) {
1009            // Adjust light position for window offsets.
1010            final Point displaySize = new Point();
1011            display.getRealSize(displaySize);
1012            final float lightX = displaySize.x / 2f - windowLeft;
1013            final float lightY = mLightY - windowTop;
1014
1015            nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
1016        }
1017
1018        public RenderNode getRootNode() {
1019            return mRootNode;
1020        }
1021
1022        /**
1023         * Draw the surface.
1024         */
1025        public void draw(final FrameDrawingCallback callback) {
1026            final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
1027            mFrameInfo.setVsync(vsync, vsync);
1028            mFrameInfo.addFlags(1 << 2 /* VSYNC */);
1029            if (callback != null) {
1030                nSetFrameCallback(mNativeProxy, callback);
1031            }
1032            nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
1033        }
1034
1035        /**
1036         * Destroy the renderer.
1037         */
1038        public void destroy() {
1039            mSurface = null;
1040            nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
1041        }
1042
1043        @Override
1044        protected void finalize() throws Throwable {
1045            try {
1046                nDeleteProxy(mNativeProxy);
1047                mNativeProxy = 0;
1048            } finally {
1049                super.finalize();
1050            }
1051        }
1052    }
1053
1054    /**
1055     * Interface used to receive callbacks when a frame is being drawn.
1056     */
1057    public interface FrameDrawingCallback {
1058        /**
1059         * Invoked during a frame drawing.
1060         *
1061         * @param frame The id of the frame being drawn.
1062         */
1063        void onFrameDraw(long frame);
1064    }
1065
1066    private static class ProcessInitializer {
1067        static ProcessInitializer sInstance = new ProcessInitializer();
1068
1069        private boolean mInitialized = false;
1070
1071        private Context mAppContext;
1072        private IGraphicsStats mGraphicsStatsService;
1073        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
1074            @Override
1075            public void onRotateGraphicsStatsBuffer() throws RemoteException {
1076                rotateBuffer();
1077            }
1078        };
1079
1080        private ProcessInitializer() {}
1081
1082        synchronized void init(Context context, long renderProxy) {
1083            if (mInitialized) return;
1084            mInitialized = true;
1085            mAppContext = context.getApplicationContext();
1086
1087            initSched(renderProxy);
1088
1089            if (mAppContext != null) {
1090                initGraphicsStats();
1091            }
1092        }
1093
1094        private void initSched(long renderProxy) {
1095            try {
1096                int tid = nGetRenderThreadTid(renderProxy);
1097                ActivityManager.getService().setRenderThread(tid);
1098            } catch (Throwable t) {
1099                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
1100            }
1101        }
1102
1103        private void initGraphicsStats() {
1104            try {
1105                IBinder binder = ServiceManager.getService("graphicsstats");
1106                if (binder == null) return;
1107                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
1108                requestBuffer();
1109            } catch (Throwable t) {
1110                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
1111            }
1112        }
1113
1114        private void rotateBuffer() {
1115            nRotateProcessStatsBuffer();
1116            requestBuffer();
1117        }
1118
1119        private void requestBuffer() {
1120            try {
1121                final String pkg = mAppContext.getApplicationInfo().packageName;
1122                ParcelFileDescriptor pfd = mGraphicsStatsService
1123                        .requestBufferForProcess(pkg, mGraphicsStatsCallback);
1124                nSetProcessStatsBuffer(pfd.getFd());
1125                pfd.close();
1126            } catch (Throwable t) {
1127                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
1128            }
1129        }
1130    }
1131
1132    void addFrameMetricsObserver(FrameMetricsObserver observer) {
1133        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
1134        observer.mNative = new VirtualRefBasePtr(nativeObserver);
1135    }
1136
1137    void removeFrameMetricsObserver(FrameMetricsObserver observer) {
1138        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
1139        observer.mNative = null;
1140    }
1141
1142    /** b/68769804: For low FPS experiments. */
1143    public static void setFPSDivisor(int divisor) {
1144        nHackySetRTAnimationsEnabled(divisor <= 1);
1145    }
1146
1147    /**
1148     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
1149     * called before any OpenGL context is created.
1150     *
1151     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
1152     */
1153    public static void setContextPriority(int priority) {
1154        nSetContextPriority(priority);
1155    }
1156
1157    /** Not actually public - internal use only. This doc to make lint happy */
1158    public static native void disableVsync();
1159
1160    static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
1161
1162    private static native void nRotateProcessStatsBuffer();
1163    private static native void nSetProcessStatsBuffer(int fd);
1164    private static native int nGetRenderThreadTid(long nativeProxy);
1165
1166    private static native long nCreateRootRenderNode();
1167    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
1168    private static native void nDeleteProxy(long nativeProxy);
1169
1170    private static native boolean nLoadSystemProperties(long nativeProxy);
1171    private static native void nSetName(long nativeProxy, String name);
1172
1173    private static native void nInitialize(long nativeProxy, Surface window);
1174    private static native void nUpdateSurface(long nativeProxy, Surface window);
1175    private static native boolean nPauseSurface(long nativeProxy, Surface window);
1176    private static native void nSetStopped(long nativeProxy, boolean stopped);
1177    private static native void nSetup(long nativeProxy,
1178            float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
1179    private static native void nSetLightCenter(long nativeProxy,
1180            float lightX, float lightY, float lightZ);
1181    private static native void nSetOpaque(long nativeProxy, boolean opaque);
1182    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
1183    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
1184    private static native void nDestroy(long nativeProxy, long rootRenderNode);
1185    private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
1186    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
1187
1188    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
1189
1190    private static native long nCreateTextureLayer(long nativeProxy);
1191    private static native void nBuildLayer(long nativeProxy, long node);
1192    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
1193    private static native void nPushLayerUpdate(long nativeProxy, long layer);
1194    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
1195    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
1196
1197    private static native void nDestroyHardwareResources(long nativeProxy);
1198    private static native void nTrimMemory(int level);
1199    private static native void nOverrideProperty(String name, String value);
1200
1201    private static native void nFence(long nativeProxy);
1202    private static native void nStopDrawing(long nativeProxy);
1203    private static native void nNotifyFramePending(long nativeProxy);
1204
1205    private static native void nSerializeDisplayListTree(long nativeProxy);
1206
1207    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
1208            @DumpFlags int dumpFlags);
1209
1210    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
1211             boolean placeFront);
1212    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
1213    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
1214    private static native void nSetContentDrawBounds(long nativeProxy, int left,
1215             int top, int right, int bottom);
1216    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
1217
1218    private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
1219    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
1220
1221    private static native int nCopySurfaceInto(Surface surface,
1222            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
1223
1224    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
1225    private static native void nSetHighContrastText(boolean enabled);
1226    // For temporary experimentation b/66945974
1227    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
1228    private static native void nSetDebuggingEnabled(boolean enabled);
1229    private static native void nSetIsolatedProcess(boolean enabled);
1230    private static native void nSetContextPriority(int priority);
1231}
1232