ThreadedRenderer.java revision 945961f78a78eced823d5ba78505c781b079703d
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.content.Context;
22import android.content.res.TypedArray;
23import android.graphics.Bitmap;
24import android.graphics.Point;
25import android.graphics.Rect;
26import android.os.Binder;
27import android.os.Handler;
28import android.os.IBinder;
29import android.os.Message;
30import android.os.ParcelFileDescriptor;
31import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.Trace;
34import android.util.Log;
35import android.view.Surface.OutOfResourcesException;
36import android.view.View.AttachInfo;
37
38import com.android.internal.R;
39import com.android.internal.util.VirtualRefBasePtr;
40
41import java.io.File;
42import java.io.FileDescriptor;
43import java.io.PrintWriter;
44import java.lang.annotation.Retention;
45import java.lang.annotation.RetentionPolicy;
46import java.util.HashSet;
47
48/**
49 * Hardware 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
75    /**
76     * System property used to enable or disable dirty regions invalidation.
77     * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
78     * The default value of this property is assumed to be true.
79     *
80     * Possible values:
81     * "true", to enable partial invalidates
82     * "false", to disable partial invalidates
83     */
84    static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
85
86    /**
87     * System property used to enable or disable hardware rendering profiling.
88     * The default value of this property is assumed to be false.
89     *
90     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
91     * output extra information about the time taken to execute by the last
92     * frames.
93     *
94     * Possible values:
95     * "true", to enable profiling
96     * "visual_bars", to enable profiling and visualize the results on screen
97     * "false", to disable profiling
98     *
99     * @see #PROFILE_PROPERTY_VISUALIZE_BARS
100     *
101     * @hide
102     */
103    public static final String PROFILE_PROPERTY = "debug.hwui.profile";
104
105    /**
106     * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
107     * value, profiling data will be visualized on screen as a bar chart.
108     *
109     * @hide
110     */
111    public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
112
113    /**
114     * System property used to specify the number of frames to be used
115     * when doing hardware rendering profiling.
116     * The default value of this property is #PROFILE_MAX_FRAMES.
117     *
118     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
119     * output extra information about the time taken to execute by the last
120     * frames.
121     *
122     * Possible values:
123     * "60", to set the limit of frames to 60
124     */
125    static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
126
127    /**
128     * System property used to debug EGL configuration choice.
129     *
130     * Possible values:
131     * "choice", print the chosen configuration only
132     * "all", print all possible configurations
133     */
134    static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
135
136    /**
137     * Turn on to draw dirty regions every other frame.
138     *
139     * Possible values:
140     * "true", to enable dirty regions debugging
141     * "false", to disable dirty regions debugging
142     *
143     * @hide
144     */
145    public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
146
147    /**
148     * Turn on to flash hardware layers when they update.
149     *
150     * Possible values:
151     * "true", to enable hardware layers updates debugging
152     * "false", to disable hardware layers updates debugging
153     *
154     * @hide
155     */
156    public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
157            "debug.hwui.show_layers_updates";
158
159    /**
160     * Controls overdraw debugging.
161     *
162     * Possible values:
163     * "false", to disable overdraw debugging
164     * "show", to show overdraw areas on screen
165     * "count", to display an overdraw counter
166     *
167     * @hide
168     */
169    public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
170
171    /**
172     * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
173     * value, overdraw will be shown on screen by coloring pixels.
174     *
175     * @hide
176     */
177    public static final String OVERDRAW_PROPERTY_SHOW = "show";
178
179    /**
180     * Turn on to debug non-rectangular clip operations.
181     *
182     * Possible values:
183     * "hide", to disable this debug mode
184     * "highlight", highlight drawing commands tested against a non-rectangular clip
185     * "stencil", renders the clip region on screen when set
186     *
187     * @hide
188     */
189    public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
190            "debug.hwui.show_non_rect_clip";
191
192    /**
193     * A process can set this flag to false to prevent the use of hardware
194     * rendering.
195     *
196     * @hide
197     */
198    public static boolean sRendererDisabled = false;
199
200    /**
201     * Further hardware renderer disabling for the system process.
202     *
203     * @hide
204     */
205    public static boolean sSystemRendererDisabled = false;
206
207    /**
208     * Invoke this method to disable hardware rendering in the current process.
209     *
210     * @hide
211     */
212    public static void disable(boolean system) {
213        sRendererDisabled = true;
214        if (system) {
215            sSystemRendererDisabled = true;
216        }
217    }
218
219    public static boolean sTrimForeground = false;
220
221    /**
222     * Controls whether or not the hardware renderer should aggressively
223     * trim memory. Note that this must not be set for any process that
224     * uses WebView! This should be only used by system_process or similar
225     * that do not go into the background.
226     */
227    public static void enableForegroundTrimming() {
228        sTrimForeground = true;
229    }
230
231    /**
232     * Indicates whether hardware acceleration is available under any form for
233     * the view hierarchy.
234     *
235     * @return True if the view hierarchy can potentially be hardware accelerated,
236     *         false otherwise
237     */
238    public static boolean isAvailable() {
239        return DisplayListCanvas.isAvailable();
240    }
241
242    /**
243     * Sets the directory to use as a persistent storage for hardware rendering
244     * resources.
245     *
246     * @param cacheDir A directory the current process can write to
247     *
248     * @hide
249     */
250    public static void setupDiskCache(File cacheDir) {
251        ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
252    }
253
254    /**
255     * Sets the library directory to use as a search path for vulkan layers.
256     *
257     * @param libDir A directory that contains vulkan layers
258     *
259     * @hide
260     */
261    public static void setLibDir(String libDir) {
262        ThreadedRenderer.setupVulkanLayerPath(libDir);
263    }
264
265    /**
266     * Creates a hardware renderer using OpenGL.
267     *
268     * @param translucent True if the surface is translucent, false otherwise
269     *
270     * @return A hardware renderer backed by OpenGL.
271     */
272    public static ThreadedRenderer create(Context context, boolean translucent) {
273        ThreadedRenderer renderer = null;
274        if (DisplayListCanvas.isAvailable()) {
275            renderer = new ThreadedRenderer(context, translucent);
276        }
277        return renderer;
278    }
279
280    /**
281     * Invoke this method when the system is running out of memory. This
282     * method will attempt to recover as much memory as possible, based on
283     * the specified hint.
284     *
285     * @param level Hint about the amount of memory that should be trimmed,
286     *              see {@link android.content.ComponentCallbacks}
287     */
288    public static void trimMemory(int level) {
289        nTrimMemory(level);
290    }
291
292    public static void overrideProperty(@NonNull String name, @NonNull String value) {
293        if (name == null || value == null) {
294            throw new IllegalArgumentException("name and value must be non-null");
295        }
296        nOverrideProperty(name, value);
297    }
298
299    public static void dumpProfileData(byte[] data, FileDescriptor fd) {
300        nDumpProfileData(data, fd);
301    }
302
303    // Keep in sync with DrawFrameTask.h SYNC_* flags
304    // Nothing interesting to report
305    private static final int SYNC_OK = 0;
306    // Needs a ViewRoot invalidate
307    private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
308    // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
309    private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
310
311    private static final String[] VISUALIZERS = {
312        PROFILE_PROPERTY_VISUALIZE_BARS,
313    };
314
315    private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
316    private static final int FLAG_DUMP_RESET        = 1 << 1;
317
318    @IntDef(flag = true, value = {
319            FLAG_DUMP_FRAMESTATS, FLAG_DUMP_RESET })
320    @Retention(RetentionPolicy.SOURCE)
321    public @interface DumpFlags {}
322
323    // Size of the rendered content.
324    private int mWidth, mHeight;
325
326    // Actual size of the drawing surface.
327    private int mSurfaceWidth, mSurfaceHeight;
328
329    // Insets between the drawing surface and rendered content. These are
330    // applied as translation when updating the root render node.
331    private int mInsetTop, mInsetLeft;
332
333    // Whether the surface has insets. Used to protect opacity.
334    private boolean mHasInsets;
335
336    // Light and shadow properties specified by the theme.
337    private final float mLightY;
338    private final float mLightZ;
339    private final float mLightRadius;
340    private final int mAmbientShadowAlpha;
341    private final int mSpotShadowAlpha;
342
343    private long mNativeProxy;
344    private boolean mInitialized = false;
345    private RenderNode mRootNode;
346    private Choreographer mChoreographer;
347    private boolean mRootNodeNeedsUpdate;
348
349    // In case of multi threaded render nodes, these bounds indicate the content bounds against
350    // which the backdrop needs to be cropped against.
351    private final Rect mCurrentContentBounds = new Rect();
352    private final Rect mStagedContentBounds = new Rect();
353
354    private boolean mEnabled;
355    private boolean mRequested = true;
356
357    ThreadedRenderer(Context context, boolean translucent) {
358        final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
359        mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
360        mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
361        mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
362        mAmbientShadowAlpha =
363                (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
364        mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
365        a.recycle();
366
367        long rootNodePtr = nCreateRootRenderNode();
368        mRootNode = RenderNode.adopt(rootNodePtr);
369        mRootNode.setClipToBounds(false);
370        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
371
372        ProcessInitializer.sInstance.init(context, mNativeProxy);
373
374        loadSystemProperties();
375    }
376
377    /**
378     * Destroys the hardware rendering context.
379     */
380    void destroy() {
381        mInitialized = false;
382        updateEnabledState(null);
383        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
384    }
385
386    /**
387     * Indicates whether hardware acceleration is currently enabled.
388     *
389     * @return True if hardware acceleration is in use, false otherwise.
390     */
391    boolean isEnabled() {
392        return mEnabled;
393    }
394
395    /**
396     * Indicates whether hardware acceleration is currently enabled.
397     *
398     * @param enabled True if the hardware renderer is in use, false otherwise.
399     */
400    void setEnabled(boolean enabled) {
401        mEnabled = enabled;
402    }
403
404    /**
405     * Indicates whether hardware acceleration is currently request but not
406     * necessarily enabled yet.
407     *
408     * @return True if requested, false otherwise.
409     */
410    boolean isRequested() {
411        return mRequested;
412    }
413
414    /**
415     * Indicates whether hardware acceleration is currently requested but not
416     * necessarily enabled yet.
417     *
418     * @return True to request hardware acceleration, false otherwise.
419     */
420    void setRequested(boolean requested) {
421        mRequested = requested;
422    }
423
424    private void updateEnabledState(Surface surface) {
425        if (surface == null || !surface.isValid()) {
426            setEnabled(false);
427        } else {
428            setEnabled(mInitialized);
429        }
430    }
431
432    /**
433     * Initializes the hardware renderer for the specified surface.
434     *
435     * @param surface The surface to hardware accelerate
436     *
437     * @return True if the initialization was successful, false otherwise.
438     */
439    boolean initialize(Surface surface) throws OutOfResourcesException {
440        boolean status = !mInitialized;
441        mInitialized = true;
442        updateEnabledState(surface);
443        nInitialize(mNativeProxy, surface);
444        return status;
445    }
446
447    /**
448     * Initializes the hardware renderer for the specified surface and setup the
449     * renderer for drawing, if needed. This is invoked when the ViewAncestor has
450     * potentially lost the hardware renderer. The hardware renderer should be
451     * reinitialized and setup when the render {@link #isRequested()} and
452     * {@link #isEnabled()}.
453     *
454     * @param width The width of the drawing surface.
455     * @param height The height of the drawing surface.
456     * @param attachInfo Information about the window.
457     * @param surface The surface to hardware accelerate
458     * @param surfaceInsets The drawing surface insets to apply
459     *
460     * @return true if the surface was initialized, false otherwise. Returning
461     *         false might mean that the surface was already initialized.
462     */
463    boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
464            Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
465        if (isRequested()) {
466            // We lost the gl context, so recreate it.
467            if (!isEnabled()) {
468                if (initialize(surface)) {
469                    setup(width, height, attachInfo, surfaceInsets);
470                    return true;
471                }
472            }
473        }
474        return false;
475    }
476
477    /**
478     * Updates the hardware renderer for the specified surface.
479     *
480     * @param surface The surface to hardware accelerate
481     */
482    void updateSurface(Surface surface) throws OutOfResourcesException {
483        updateEnabledState(surface);
484        nUpdateSurface(mNativeProxy, surface);
485    }
486
487    /**
488     * Halts any current rendering into the surface. Use this if it is unclear whether
489     * or not the surface used by the HardwareRenderer will be changing. It
490     * Suspends any rendering into the surface, but will not do any destruction.
491     *
492     * Any subsequent draws will override the pause, resuming normal operation.
493     */
494    boolean pauseSurface(Surface surface) {
495        return nPauseSurface(mNativeProxy, surface);
496    }
497
498    /**
499     * Hard stops or resumes rendering into the surface. This flag is used to
500     * determine whether or not it is safe to use the given surface *at all*
501     */
502    void setStopped(boolean stopped) {
503        nSetStopped(mNativeProxy, stopped);
504    }
505
506    /**
507     * Destroys all hardware rendering resources associated with the specified
508     * view hierarchy.
509     *
510     * @param view The root of the view hierarchy
511     */
512    void destroyHardwareResources(View view) {
513        destroyResources(view);
514        nDestroyHardwareResources(mNativeProxy);
515    }
516
517    private static void destroyResources(View view) {
518        view.destroyHardwareResources();
519
520        if (view instanceof ViewGroup) {
521            ViewGroup group = (ViewGroup) view;
522
523            int count = group.getChildCount();
524            for (int i = 0; i < count; i++) {
525                destroyResources(group.getChildAt(i));
526            }
527        }
528    }
529
530    /**
531     * This method should be invoked whenever the current hardware renderer
532     * context should be reset.
533     *
534     * @param surface The surface to hardware accelerate
535     */
536    void invalidate(Surface surface) {
537        updateSurface(surface);
538    }
539
540    /**
541     * Detaches the layer's surface texture from the GL context and releases
542     * the texture id
543     */
544    void detachSurfaceTexture(long hardwareLayer) {
545        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
546    }
547
548    /**
549     * Sets up the renderer for drawing.
550     *
551     * @param width The width of the drawing surface.
552     * @param height The height of the drawing surface.
553     * @param attachInfo Information about the window.
554     * @param surfaceInsets The drawing surface insets to apply
555     */
556    void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
557        mWidth = width;
558        mHeight = height;
559
560        if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
561                || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
562            mHasInsets = true;
563            mInsetLeft = surfaceInsets.left;
564            mInsetTop = surfaceInsets.top;
565            mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
566            mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
567
568            // If the surface has insets, it can't be opaque.
569            setOpaque(false);
570        } else {
571            mHasInsets = false;
572            mInsetLeft = 0;
573            mInsetTop = 0;
574            mSurfaceWidth = width;
575            mSurfaceHeight = height;
576        }
577
578        mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
579        nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight, mLightRadius,
580                mAmbientShadowAlpha, mSpotShadowAlpha);
581
582        setLightCenter(attachInfo);
583    }
584
585    /**
586     * Updates the light position based on the position of the window.
587     *
588     * @param attachInfo Information about the window.
589     */
590    void setLightCenter(AttachInfo attachInfo) {
591        // Adjust light position for window offsets.
592        final Point displaySize = attachInfo.mPoint;
593        attachInfo.mDisplay.getRealSize(displaySize);
594        final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
595        final float lightY = mLightY - attachInfo.mWindowTop;
596
597        nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
598    }
599
600    /**
601     * Change the HardwareRenderer's opacity
602     */
603    void setOpaque(boolean opaque) {
604        nSetOpaque(mNativeProxy, opaque && !mHasInsets);
605    }
606
607    /**
608     * Gets the current width of the surface. This is the width that the surface
609     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
610     *
611     * @return the current width of the surface
612     */
613    int getWidth() {
614        return mWidth;
615    }
616
617    /**
618     * Gets the current height of the surface. This is the height that the surface
619     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
620     *
621     * @return the current width of the surface
622     */
623    int getHeight() {
624        return mHeight;
625    }
626
627    /**
628     * Outputs extra debugging information in the specified file descriptor.
629     */
630    void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
631        pw.flush();
632        int flags = 0;
633        for (int i = 0; i < args.length; i++) {
634            switch (args[i]) {
635                case "framestats":
636                    flags |= FLAG_DUMP_FRAMESTATS;
637                    break;
638                case "reset":
639                    flags |= FLAG_DUMP_RESET;
640                    break;
641            }
642        }
643        nDumpProfileInfo(mNativeProxy, fd, flags);
644    }
645
646    /**
647     * Loads system properties used by the renderer. This method is invoked
648     * whenever system properties are modified. Implementations can use this
649     * to trigger live updates of the renderer based on properties.
650     *
651     * @return True if a property has changed.
652     */
653    boolean loadSystemProperties() {
654        boolean changed = nLoadSystemProperties(mNativeProxy);
655        if (changed) {
656            invalidateRoot();
657        }
658        return changed;
659    }
660
661    private void updateViewTreeDisplayList(View view) {
662        view.mPrivateFlags |= View.PFLAG_DRAWN;
663        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
664                == View.PFLAG_INVALIDATED;
665        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
666        view.updateDisplayListIfDirty();
667        view.mRecreateDisplayList = false;
668    }
669
670    private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
671        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
672        updateViewTreeDisplayList(view);
673
674        if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
675            DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
676            try {
677                final int saveCount = canvas.save();
678                canvas.translate(mInsetLeft, mInsetTop);
679                callbacks.onHardwarePreDraw(canvas);
680
681                canvas.insertReorderBarrier();
682                canvas.drawRenderNode(view.updateDisplayListIfDirty());
683                canvas.insertInorderBarrier();
684
685                callbacks.onHardwarePostDraw(canvas);
686                canvas.restoreToCount(saveCount);
687                mRootNodeNeedsUpdate = false;
688            } finally {
689                mRootNode.end(canvas);
690            }
691        }
692        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
693    }
694
695    /**
696     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
697     * rendernode of the UI thread.
698     * @param node The node to add.
699     * @param placeFront If true, the render node will be placed in front of the content node,
700     *                   otherwise behind the content node.
701     */
702    public void addRenderNode(RenderNode node, boolean placeFront) {
703        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
704    }
705
706    /**
707     * Only especially added render nodes can be removed.
708     * @param node The node which was added via addRenderNode which should get removed again.
709     */
710    public void removeRenderNode(RenderNode node) {
711        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
712    }
713
714    /**
715     * Draws a particular render node. If the node is not the content node, only the additional
716     * nodes will get drawn and the content remains untouched.
717     * @param node The node to be drawn.
718     */
719    public void drawRenderNode(RenderNode node) {
720        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
721    }
722
723    /**
724     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
725     * will be prevented to overdraw this area. It will be synchronized with the draw call.
726     * This should be updated in the content view's draw call.
727     * @param left The left side of the protected bounds.
728     * @param top The top side of the protected bounds.
729     * @param right The right side of the protected bounds.
730     * @param bottom The bottom side of the protected bounds.
731     */
732    public void setContentDrawBounds(int left, int top, int right, int bottom) {
733        mStagedContentBounds.set(left, top, right, bottom);
734    }
735
736    /**
737     * Interface used to receive callbacks whenever a view is drawn by
738     * a hardware renderer instance.
739     */
740    interface HardwareDrawCallbacks {
741        /**
742         * Invoked before a view is drawn by a hardware renderer.
743         * This method can be used to apply transformations to the
744         * canvas but no drawing command should be issued.
745         *
746         * @param canvas The Canvas used to render the view.
747         */
748        void onHardwarePreDraw(DisplayListCanvas canvas);
749
750        /**
751         * Invoked after a view is drawn by a hardware renderer.
752         * It is safe to invoke drawing commands from this method.
753         *
754         * @param canvas The Canvas used to render the view.
755         */
756        void onHardwarePostDraw(DisplayListCanvas canvas);
757    }
758
759    /**
760     *  Indicates that the content drawn by HardwareDrawCallbacks needs to
761     *  be updated, which will be done by the next call to draw()
762     */
763    void invalidateRoot() {
764        mRootNodeNeedsUpdate = true;
765    }
766
767    /**
768     * Draws the specified view.
769     *
770     * @param view The view to draw.
771     * @param attachInfo AttachInfo tied to the specified view.
772     * @param callbacks Callbacks invoked when drawing happens.
773     */
774    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
775        attachInfo.mIgnoreDirtyState = true;
776
777        final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
778        choreographer.mFrameInfo.markDrawStart();
779
780        updateRootDisplayList(view, callbacks);
781        // The main content view was updating the content bounds and we transfer them to the
782        // renderer.
783        if (!mCurrentContentBounds.equals(mStagedContentBounds)) {
784            mCurrentContentBounds.set(mStagedContentBounds);
785            nSetContentDrawBounds(mNativeProxy, mCurrentContentBounds.left,
786                    mCurrentContentBounds.top, mCurrentContentBounds.right,
787                    mCurrentContentBounds.bottom);
788        }
789
790        attachInfo.mIgnoreDirtyState = false;
791
792        // register animating rendernodes which started animating prior to renderer
793        // creation, which is typical for animators started prior to first draw
794        if (attachInfo.mPendingAnimatingRenderNodes != null) {
795            final int count = attachInfo.mPendingAnimatingRenderNodes.size();
796            for (int i = 0; i < count; i++) {
797                registerAnimatingRenderNode(
798                        attachInfo.mPendingAnimatingRenderNodes.get(i));
799            }
800            attachInfo.mPendingAnimatingRenderNodes.clear();
801            // We don't need this anymore as subsequent calls to
802            // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
803            attachInfo.mPendingAnimatingRenderNodes = null;
804        }
805
806        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
807        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length,
808                mRootNode.mNativeRenderNode);
809        if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
810            setEnabled(false);
811            attachInfo.mViewRootImpl.mSurface.release();
812            // Invalidate since we failed to draw. This should fetch a Surface
813            // if it is still needed or do nothing if we are no longer drawing
814            attachInfo.mViewRootImpl.invalidate();
815        }
816        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
817            attachInfo.mViewRootImpl.invalidate();
818        }
819    }
820
821    static void invokeFunctor(long functor, boolean waitForCompletion) {
822        nInvokeFunctor(functor, waitForCompletion);
823    }
824
825    /**
826     * Creates a new hardware layer. A hardware layer built by calling this
827     * method will be treated as a texture layer, instead of as a render target.
828     *
829     * @return A hardware layer
830     */
831    HardwareLayer createTextureLayer() {
832        long layer = nCreateTextureLayer(mNativeProxy);
833        return HardwareLayer.adoptTextureLayer(this, layer);
834    }
835
836
837    void buildLayer(RenderNode node) {
838        nBuildLayer(mNativeProxy, node.getNativeDisplayList());
839    }
840
841
842    boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
843        return nCopyLayerInto(mNativeProxy,
844                layer.getDeferredLayerUpdater(), bitmap);
845    }
846
847    /**
848     * Indicates that the specified hardware layer needs to be updated
849     * as soon as possible.
850     *
851     * @param layer The hardware layer that needs an update
852     */
853    void pushLayerUpdate(HardwareLayer layer) {
854        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
855    }
856
857    /**
858     * Tells the HardwareRenderer that the layer is destroyed. The renderer
859     * should remove the layer from any update queues.
860     */
861    void onLayerDestroyed(HardwareLayer layer) {
862        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
863    }
864
865    /**
866     * Optional, sets the name of the renderer. Useful for debugging purposes.
867     *
868     * @param name The name of this renderer, can be null
869     */
870    void setName(String name) {
871        nSetName(mNativeProxy, name);
872    }
873
874    /**
875     * Blocks until all previously queued work has completed.
876     */
877    void fence() {
878        nFence(mNativeProxy);
879    }
880
881    /**
882     * Prevents any further drawing until draw() is called. This is a signal
883     * that the contents of the RenderNode tree are no longer safe to play back.
884     * In practice this usually means that there are Functor pointers in the
885     * display list that are no longer valid.
886     */
887    void stopDrawing() {
888        nStopDrawing(mNativeProxy);
889    }
890
891    /**
892     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
893     */
894    public void notifyFramePending() {
895        nNotifyFramePending(mNativeProxy);
896    }
897
898
899    void registerAnimatingRenderNode(RenderNode animator) {
900        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
901    }
902
903    public void serializeDisplayListTree() {
904        nSerializeDisplayListTree(mNativeProxy);
905    }
906
907    @Override
908    protected void finalize() throws Throwable {
909        try {
910            nDeleteProxy(mNativeProxy);
911            mNativeProxy = 0;
912        } finally {
913            super.finalize();
914        }
915    }
916
917    private static class ProcessInitializer {
918        static ProcessInitializer sInstance = new ProcessInitializer();
919        private static IBinder sProcToken;
920
921        private boolean mInitialized = false;
922
923        private ProcessInitializer() {}
924
925        synchronized void init(Context context, long renderProxy) {
926            if (mInitialized) return;
927            mInitialized = true;
928            initGraphicsStats(context, renderProxy);
929            initAssetAtlas(context, renderProxy);
930        }
931
932        private static void initGraphicsStats(Context context, long renderProxy) {
933            try {
934                IBinder binder = ServiceManager.getService("graphicsstats");
935                if (binder == null) return;
936                IGraphicsStats graphicsStatsService = IGraphicsStats.Stub
937                        .asInterface(binder);
938                sProcToken = new Binder();
939                final String pkg = context.getApplicationInfo().packageName;
940                ParcelFileDescriptor pfd = graphicsStatsService.
941                        requestBufferForProcess(pkg, sProcToken);
942                nSetProcessStatsBuffer(renderProxy, pfd.getFd());
943                pfd.close();
944            } catch (Throwable t) {
945                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
946            }
947        }
948
949        private static void initAssetAtlas(Context context, long renderProxy) {
950            IBinder binder = ServiceManager.getService("assetatlas");
951            if (binder == null) return;
952
953            IAssetAtlas atlas = IAssetAtlas.Stub.asInterface(binder);
954            try {
955                if (atlas.isCompatible(android.os.Process.myPpid())) {
956                    GraphicBuffer buffer = atlas.getBuffer();
957                    if (buffer != null) {
958                        long[] map = atlas.getMap();
959                        if (map != null) {
960                            nSetAtlas(renderProxy, buffer, map);
961                        }
962                        // If IAssetAtlas is not the same class as the IBinder
963                        // we are using a remote service and we can safely
964                        // destroy the graphic buffer
965                        if (atlas.getClass() != binder.getClass()) {
966                            buffer.destroy();
967                        }
968                    }
969                }
970            } catch (RemoteException e) {
971                Log.w(LOG_TAG, "Could not acquire atlas", e);
972            }
973        }
974    }
975
976    void addFrameMetricsObserver(FrameMetricsObserver observer) {
977        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
978        observer.mNative = new VirtualRefBasePtr(nativeObserver);
979    }
980
981    void removeFrameMetricsObserver(FrameMetricsObserver observer) {
982        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
983        observer.mNative = null;
984    }
985
986    static native void setupShadersDiskCache(String cacheFile);
987    static native void setupVulkanLayerPath(String layerPath);
988
989    private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
990    private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
991
992    private static native long nCreateRootRenderNode();
993    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
994    private static native void nDeleteProxy(long nativeProxy);
995
996    private static native boolean nLoadSystemProperties(long nativeProxy);
997    private static native void nSetName(long nativeProxy, String name);
998
999    private static native void nInitialize(long nativeProxy, Surface window);
1000    private static native void nUpdateSurface(long nativeProxy, Surface window);
1001    private static native boolean nPauseSurface(long nativeProxy, Surface window);
1002    private static native void nSetStopped(long nativeProxy, boolean stopped);
1003    private static native void nSetup(long nativeProxy, int width, int height,
1004            float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
1005    private static native void nSetLightCenter(long nativeProxy,
1006            float lightX, float lightY, float lightZ);
1007    private static native void nSetOpaque(long nativeProxy, boolean opaque);
1008    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size,
1009            long rootRenderNode);
1010    private static native void nDestroy(long nativeProxy, long rootRenderNode);
1011    private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
1012
1013    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
1014
1015    private static native long nCreateTextureLayer(long nativeProxy);
1016    private static native void nBuildLayer(long nativeProxy, long node);
1017    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
1018    private static native void nPushLayerUpdate(long nativeProxy, long layer);
1019    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
1020    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
1021
1022    private static native void nDestroyHardwareResources(long nativeProxy);
1023    private static native void nTrimMemory(int level);
1024    private static native void nOverrideProperty(String name, String value);
1025
1026    private static native void nFence(long nativeProxy);
1027    private static native void nStopDrawing(long nativeProxy);
1028    private static native void nNotifyFramePending(long nativeProxy);
1029
1030    private static native void nSerializeDisplayListTree(long nativeProxy);
1031
1032    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
1033            @DumpFlags int dumpFlags);
1034    private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
1035
1036    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
1037             boolean placeFront);
1038    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
1039    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
1040    private static native void nSetContentDrawBounds(long nativeProxy, int left,
1041             int top, int right, int bottom);
1042
1043    private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
1044    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
1045}
1046