ThreadedRenderer.java revision 84a4c887a07c1c2939443f4e0587d7f1ac109e4b
1cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck/*
2cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Copyright (C) 2013 The Android Open Source Project
3cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
4cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
5cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * you may not use this file except in compliance with the License.
6cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * You may obtain a copy of the License at
7cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
8cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
9cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
10cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Unless required by applicable law or agreed to in writing, software
11cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
12cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * See the License for the specific language governing permissions and
14cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * limitations under the License.
15cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck */
16cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
17cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckpackage android.view;
18cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
1904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reckimport android.graphics.Bitmap;
20cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckimport android.graphics.Rect;
21cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckimport android.graphics.SurfaceTexture;
2266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckimport android.os.IBinder;
2366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckimport android.os.RemoteException;
2466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckimport android.os.ServiceManager;
25fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckimport android.os.SystemProperties;
26cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckimport android.os.Trace;
2766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckimport android.util.Log;
28315c329544d7c593d1072b071cbb92d9afe74021John Reckimport android.util.TimeUtils;
29cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckimport android.view.Surface.OutOfResourcesException;
30cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckimport android.view.View.AttachInfo;
31cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
32fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckimport java.io.FileDescriptor;
33cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckimport java.io.PrintWriter;
34cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
35cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck/**
36cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Hardware renderer that proxies the rendering to a render thread. Most calls
374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * are currently synchronous.
38cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
39cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * The UI thread can block on the RenderThread, but RenderThread must never
40cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * block on the UI thread.
41cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
424f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
434f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
444f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * by the lifecycle of the RenderProxy.
454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck *
46cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * Note that although currently the EGL context & surfaces are created & managed
47cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * by the render thread, the goal is to move that into a shared structure that can
48cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * be managed by both threads. EGLSurface creation & deletion should ideally be
49cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * done on the UI thread and not the RenderThread to avoid stalling the
50cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * RenderThread with surface buffer allocation.
51cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck *
52cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck * @hide
53cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck */
54cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reckpublic class ThreadedRenderer extends HardwareRenderer {
55cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    private static final String LOGTAG = "ThreadedRenderer";
56cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
57e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    private static final Rect NULL_RECT = new Rect();
58cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
59f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    // Keep in sync with DrawFrameTask.h SYNC_* flags
60f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    // Nothing interesting to report
61f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    private static final int SYNC_OK = 0x0;
62f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    // Needs a ViewRoot invalidate
63f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    private static final int SYNC_INVALIDATE_REQUIRED = 0x1;
64f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck
65fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    private static final String[] VISUALIZERS = {
66fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        PROFILE_PROPERTY_VISUALIZE_BARS,
67fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    };
68fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
69cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    private int mWidth, mHeight;
704f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    private long mNativeProxy;
71f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    private boolean mInitialized = false;
72bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck    private RenderNode mRootNode;
7318f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    private Choreographer mChoreographer;
74fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    private boolean mProfilingEnabled;
75cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
763dfe19f72cbd95b201e89376ae1810c5c9229b00John Reck    ThreadedRenderer(boolean translucent) {
7766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        AtlasInitializer.sInstance.init();
7866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
79e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        long rootNodePtr = nCreateRootRenderNode();
80e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        mRootNode = RenderNode.adopt(rootNodePtr);
81bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck        mRootNode.setClipToBounds(false);
82e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
8318f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck
8418f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck        // Setup timing
8518f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck        mChoreographer = Choreographer.getInstance();
8618f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck        nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos());
87fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
88fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        loadSystemProperties();
89cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
90cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
91cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
92cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    void destroy(boolean full) {
93f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        mInitialized = false;
94f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        updateEnabledState(null);
95fae904d63947fe1687d1d44be29234cc3d538f24John Reck        nDestroyCanvasAndSurface(mNativeProxy);
96cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
97cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
98f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    private void updateEnabledState(Surface surface) {
99f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        if (surface == null || !surface.isValid()) {
100f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck            setEnabled(false);
101f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        } else {
102f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck            setEnabled(mInitialized);
103f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        }
104f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    }
105f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
106cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
107cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    boolean initialize(Surface surface) throws OutOfResourcesException {
108f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        mInitialized = true;
109f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        updateEnabledState(surface);
1104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        return nInitialize(mNativeProxy, surface);
111cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
112cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
113cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
114cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    void updateSurface(Surface surface) throws OutOfResourcesException {
115f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        updateEnabledState(surface);
1164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        nUpdateSurface(mNativeProxy, surface);
117cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
118cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
119cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
120f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    void pauseSurface(Surface surface) {
121f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        nPauseSurface(mNativeProxy, surface);
122f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    }
123f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
124f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    @Override
125cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    void destroyHardwareResources(View view) {
1264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        destroyResources(view);
127e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck        nFlushCaches(mNativeProxy, GLES20Canvas.FLUSH_CACHES_LAYERS);
1284f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
1294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
1304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    private static void destroyResources(View view) {
1314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        view.destroyHardwareResources();
1324f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
1334f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        if (view instanceof ViewGroup) {
1344f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            ViewGroup group = (ViewGroup) view;
1354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
1364f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            int count = group.getChildCount();
1374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            for (int i = 0; i < count; i++) {
1384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                destroyResources(group.getChildAt(i));
1394f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            }
1404f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        }
141cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
142cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
143cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
144cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    void invalidate(Surface surface) {
1454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        updateSurface(surface);
146cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
147cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
148cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
149cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    boolean safelyRun(Runnable action) {
150fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        nRunWithGlContext(mNativeProxy, action);
151fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        return true;
152cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
153cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
154cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
155797b95b26bbb7557678af78b9a2a61830158920fChris Craik    void setup(int width, int height, float lightX, float lightY, float lightZ, float lightRadius) {
156cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        mWidth = width;
157cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        mHeight = height;
158bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck        mRootNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
159797b95b26bbb7557678af78b9a2a61830158920fChris Craik        nSetup(mNativeProxy, width, height, lightX, lightY, lightZ, lightRadius);
160cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
161cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
162cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
16363a06673253914510bbeebd500655008682dade1John Reck    void setOpaque(boolean opaque) {
16463a06673253914510bbeebd500655008682dade1John Reck        nSetOpaque(mNativeProxy, opaque);
16563a06673253914510bbeebd500655008682dade1John Reck    }
16663a06673253914510bbeebd500655008682dade1John Reck
16763a06673253914510bbeebd500655008682dade1John Reck    @Override
168cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    int getWidth() {
169cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        return mWidth;
170cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
171cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
172cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
173cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    int getHeight() {
174cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        return mHeight;
175cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
176cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
177cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
178fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    void dumpGfxInfo(PrintWriter pw, FileDescriptor fd) {
179fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        pw.flush();
180fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        nDumpProfileInfo(mNativeProxy, fd);
181cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
182cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
183fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    private static int search(String[] values, String value) {
184fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        for (int i = 0; i < values.length; i++) {
185fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            if (values[i].equals(value)) return i;
186fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
187fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        return -1;
188fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
189fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
190fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    private static boolean checkIfProfilingRequested() {
191fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        String profiling = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
192fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        int graphType = search(VISUALIZERS, profiling);
193fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        return (graphType >= 0) || Boolean.parseBoolean(profiling);
194cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
195cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
196cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
197cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    boolean loadSystemProperties() {
198fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        boolean changed = nLoadSystemProperties(mNativeProxy);
199fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        boolean wantProfiling = checkIfProfilingRequested();
200fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        if (wantProfiling != mProfilingEnabled) {
201fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            mProfilingEnabled = wantProfiling;
202fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            changed = true;
203fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
204fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        return changed;
205cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
206cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
207bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck    private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
208cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        view.mPrivateFlags |= View.PFLAG_DRAWN;
209cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
210cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
211cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck                == View.PFLAG_INVALIDATED;
212cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
213cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
214cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
215bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck        HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
21605e858400adee0f579b1e27e321b48bd55843fbdJohn Reck        try {
21786faf9ec3edc24a9d04548e151bca3a2510396a4John Reck            canvas.save();
218d5b2ec4ff15f828298290534c9d322c82f8d130cAlan Viverette            callbacks.onHardwarePreDraw(canvas);
21905e858400adee0f579b1e27e321b48bd55843fbdJohn Reck            canvas.drawDisplayList(view.getDisplayList());
22005e858400adee0f579b1e27e321b48bd55843fbdJohn Reck            callbacks.onHardwarePostDraw(canvas);
22186faf9ec3edc24a9d04548e151bca3a2510396a4John Reck            canvas.restore();
22205e858400adee0f579b1e27e321b48bd55843fbdJohn Reck        } finally {
22305e858400adee0f579b1e27e321b48bd55843fbdJohn Reck            mRootNode.end(canvas);
22405e858400adee0f579b1e27e321b48bd55843fbdJohn Reck            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
22505e858400adee0f579b1e27e321b48bd55843fbdJohn Reck        }
226cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
227cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        view.mRecreateDisplayList = false;
228bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck    }
229bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck
230bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck    @Override
231bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
232bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck        attachInfo.mIgnoreDirtyState = true;
23318f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck        long frameTimeNanos = mChoreographer.getFrameTimeNanos();
234315c329544d7c593d1072b071cbb92d9afe74021John Reck        attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS;
235bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck
236fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        long recordDuration = 0;
237fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        if (mProfilingEnabled) {
238fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            recordDuration = System.nanoTime();
239fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
240fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
241bc0cc0220b830df54c8ed41d0b53daffd7f6c991John Reck        updateRootDisplayList(view, callbacks);
242cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
243fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        if (mProfilingEnabled) {
244fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            recordDuration = System.nanoTime() - recordDuration;
245fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
246fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
2476313b9259d37b59f3402058e197637aa3014516cJohn Reck        attachInfo.mIgnoreDirtyState = false;
2486313b9259d37b59f3402058e197637aa3014516cJohn Reck
2494f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        if (dirty == null) {
2504f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            dirty = NULL_RECT;
2514f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        }
252f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
253fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck                recordDuration, view.getResources().getDisplayMetrics().density,
25418f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck                dirty.left, dirty.top, dirty.right, dirty.bottom);
255f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
256f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck            attachInfo.mViewRootImpl.invalidate();
257f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        }
258cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
259cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
260cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
261ae738a7a45d710115f8aedacf218d4bfa0b25698Bo Liu    void invokeFunctor(long functor, boolean waitForCompletion) {
2620d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck        nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
2630d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    }
2640d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
2650d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    @Override
26604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    HardwareLayer createDisplayListLayer(int width, int height) {
26719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
26819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        return HardwareLayer.adoptDisplayListLayer(this, layer);
269cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
270cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
271cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
27219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    HardwareLayer createTextureLayer() {
27319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        long layer = nCreateTextureLayer(mNativeProxy);
27419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        return HardwareLayer.adoptTextureLayer(this, layer);
275cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
276cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
277cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
27819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    SurfaceTexture createSurfaceTexture(final HardwareLayer layer) {
27919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        final SurfaceTexture[] ret = new SurfaceTexture[1];
28019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        nRunWithGlContext(mNativeProxy, new Runnable() {
28119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            @Override
28219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            public void run() {
28319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck                ret[0] = layer.createSurfaceTexture();
28419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            }
28519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        });
28619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        return ret[0];
287cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
288cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
289cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
29019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
29119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        return nCopyLayerInto(mNativeProxy,
29219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck                layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
293cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
294cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
295cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
29619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    void pushLayerUpdate(HardwareLayer layer) {
297d72e0a339b54af0c4e731513bbad120dff694723John Reck        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
29819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    }
29919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
30019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    @Override
30119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    void flushLayerUpdates() {
30219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        // TODO: Figure out what this should do or remove it
30319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    }
30419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
30519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    @Override
30619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    void onLayerDestroyed(HardwareLayer layer) {
307d72e0a339b54af0c4e731513bbad120dff694723John Reck        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
308cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
309cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
310cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    @Override
311cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    void setName(String name) {
312cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
313cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
3144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    @Override
31528ad7b52e038ef0cdd89f753d9839444a434b299John Reck    void fence() {
31628ad7b52e038ef0cdd89f753d9839444a434b299John Reck        nFence(mNativeProxy);
31728ad7b52e038ef0cdd89f753d9839444a434b299John Reck    }
31828ad7b52e038ef0cdd89f753d9839444a434b299John Reck
31928ad7b52e038ef0cdd89f753d9839444a434b299John Reck    @Override
320a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    public void notifyFramePending() {
321a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        nNotifyFramePending(mNativeProxy);
322a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    }
323a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
324a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    @Override
3254f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    protected void finalize() throws Throwable {
3264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        try {
3274f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            nDeleteProxy(mNativeProxy);
3280ed751dd22a98f0c1f637570c5775b4f5e97d895John Reck            mNativeProxy = 0;
3294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        } finally {
3304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            super.finalize();
331cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck        }
332cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck    }
333cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
33484a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    static void startTrimMemory(int level) {
33584a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck        // TODO
33684a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    }
33784a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
33884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    static void endTrimMemory() {
33984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck        // TODO
34084a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    }
34184a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
34266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    private static class AtlasInitializer {
34366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        static AtlasInitializer sInstance = new AtlasInitializer();
34466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
34566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        private boolean mInitialized = false;
34666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
34766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        private AtlasInitializer() {}
34866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
34966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        synchronized void init() {
35066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            if (mInitialized) return;
35166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            IBinder binder = ServiceManager.getService("assetatlas");
35266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            if (binder == null) return;
35366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
35466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            IAssetAtlas atlas = IAssetAtlas.Stub.asInterface(binder);
35566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            try {
35666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                if (atlas.isCompatible(android.os.Process.myPpid())) {
35766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                    GraphicBuffer buffer = atlas.getBuffer();
35866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                    if (buffer != null) {
35966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        long[] map = atlas.getMap();
36066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        if (map != null) {
36166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                            nSetAtlas(buffer, map);
36266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                            mInitialized = true;
36366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        }
36466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        // If IAssetAtlas is not the same class as the IBinder
36566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        // we are using a remote service and we can safely
36666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        // destroy the graphic buffer
36766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        if (atlas.getClass() != binder.getClass()) {
36866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                            buffer.destroy();
36966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                        }
37066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                    }
37166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                }
37266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            } catch (RemoteException e) {
37366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck                Log.w(LOG_TAG, "Could not acquire atlas", e);
37466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            }
37566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        }
37666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
37766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
37884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    static native void setupShadersDiskCache(String cacheFile);
37984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck
38066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    private static native void nSetAtlas(GraphicBuffer buffer, long[] map);
381cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
382e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    private static native long nCreateRootRenderNode();
383e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
3844f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    private static native void nDeleteProxy(long nativeProxy);
385cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
38618f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    private static native void nSetFrameInterval(long nativeProxy, long frameIntervalNanos);
387e4280baaa709c74d86cf6a389a4674ca665f5af6John Reck    private static native boolean nLoadSystemProperties(long nativeProxy);
38818f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck
3894f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    private static native boolean nInitialize(long nativeProxy, Surface window);
3904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    private static native void nUpdateSurface(long nativeProxy, Surface window);
391f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    private static native void nPauseSurface(long nativeProxy, Surface window);
392797b95b26bbb7557678af78b9a2a61830158920fChris Craik    private static native void nSetup(long nativeProxy, int width, int height,
393797b95b26bbb7557678af78b9a2a61830158920fChris Craik            float lightX, float lightY, float lightZ, float lightRadius);
39463a06673253914510bbeebd500655008682dade1John Reck    private static native void nSetOpaque(long nativeProxy, boolean opaque);
395fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    private static native int nSyncAndDrawFrame(long nativeProxy,
396fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            long frameTimeNanos, long recordDuration, float density,
3974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
398fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
399fae904d63947fe1687d1d44be29234cc3d538f24John Reck    private static native void nDestroyCanvasAndSurface(long nativeProxy);
400cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck
4010d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
40219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
40319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
40419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    private static native long nCreateTextureLayer(long nativeProxy);
40519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
406d72e0a339b54af0c4e731513bbad120dff694723John Reck    private static native void nPushLayerUpdate(long nativeProxy, long layer);
407d72e0a339b54af0c4e731513bbad120dff694723John Reck    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
40828ad7b52e038ef0cdd89f753d9839444a434b299John Reck
409e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck    private static native void nFlushCaches(long nativeProxy, int flushMode);
410e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck
41128ad7b52e038ef0cdd89f753d9839444a434b299John Reck    private static native void nFence(long nativeProxy);
412a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    private static native void nNotifyFramePending(long nativeProxy);
413fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
414fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd);
415cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck}
416