ThreadedRenderer.java revision f666ad7046c0b1b255835f75aeb7d1391067df93
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.graphics.Bitmap;
20import android.graphics.Rect;
21import android.graphics.SurfaceTexture;
22import android.os.SystemClock;
23import android.os.Trace;
24import android.view.Surface.OutOfResourcesException;
25import android.view.View.AttachInfo;
26
27import java.io.PrintWriter;
28
29/**
30 * Hardware renderer that proxies the rendering to a render thread. Most calls
31 * are currently synchronous.
32 * TODO: Make draw() async.
33 * TODO: Figure out how to share the DisplayList between two threads (global lock?)
34 *
35 * The UI thread can block on the RenderThread, but RenderThread must never
36 * block on the UI thread.
37 *
38 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
39 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
40 * by the lifecycle of the RenderProxy.
41 *
42 * Note that although currently the EGL context & surfaces are created & managed
43 * by the render thread, the goal is to move that into a shared structure that can
44 * be managed by both threads. EGLSurface creation & deletion should ideally be
45 * done on the UI thread and not the RenderThread to avoid stalling the
46 * RenderThread with surface buffer allocation.
47 *
48 * @hide
49 */
50public class ThreadedRenderer extends HardwareRenderer {
51    private static final String LOGTAG = "ThreadedRenderer";
52
53    private static final Rect NULL_RECT = new Rect(-1, -1, -1, -1);
54
55    private int mWidth, mHeight;
56    private long mNativeProxy;
57
58    ThreadedRenderer(boolean translucent) {
59        mNativeProxy = nCreateProxy(translucent);
60        setEnabled(mNativeProxy != 0);
61    }
62
63    @Override
64    void destroy(boolean full) {
65        nDestroyCanvas(mNativeProxy);
66    }
67
68    @Override
69    boolean initialize(Surface surface) throws OutOfResourcesException {
70        return nInitialize(mNativeProxy, surface);
71    }
72
73    @Override
74    void updateSurface(Surface surface) throws OutOfResourcesException {
75        nUpdateSurface(mNativeProxy, surface);
76    }
77
78    @Override
79    void destroyHardwareResources(View view) {
80        destroyResources(view);
81        // TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
82    }
83
84    private static void destroyResources(View view) {
85        view.destroyHardwareResources();
86
87        if (view instanceof ViewGroup) {
88            ViewGroup group = (ViewGroup) view;
89
90            int count = group.getChildCount();
91            for (int i = 0; i < count; i++) {
92                destroyResources(group.getChildAt(i));
93            }
94        }
95    }
96
97    @Override
98    void invalidate(Surface surface) {
99        updateSurface(surface);
100    }
101
102    @Override
103    boolean safelyRun(Runnable action) {
104        nRunWithGlContext(mNativeProxy, action);
105        return true;
106    }
107
108    @Override
109    void setup(int width, int height) {
110        mWidth = width;
111        mHeight = height;
112        nSetup(mNativeProxy, width, height);
113    }
114
115    @Override
116    int getWidth() {
117        return mWidth;
118    }
119
120    @Override
121    int getHeight() {
122        return mHeight;
123    }
124
125    @Override
126    void dumpGfxInfo(PrintWriter pw) {
127        // TODO Auto-generated method stub
128    }
129
130    @Override
131    long getFrameCount() {
132        // TODO Auto-generated method stub
133        return 0;
134    }
135
136    @Override
137    boolean loadSystemProperties() {
138        return false;
139    }
140
141    /**
142     * TODO: Remove
143     * Temporary hack to allow RenderThreadTest prototype app to trigger
144     * replaying a DisplayList after modifying the displaylist properties
145     *
146     *  @hide */
147    public void repeatLastDraw() {
148    }
149
150    @Override
151    void setDisplayListData(long displayList, long newData) {
152        nSetDisplayListData(mNativeProxy, displayList, newData);
153    }
154
155    @Override
156    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
157        attachInfo.mIgnoreDirtyState = true;
158        attachInfo.mDrawingTime = SystemClock.uptimeMillis();
159        view.mPrivateFlags |= View.PFLAG_DRAWN;
160
161        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
162                == View.PFLAG_INVALIDATED;
163        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
164
165        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
166        RenderNode displayList = view.getDisplayList();
167        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
168
169        view.mRecreateDisplayList = false;
170
171        if (dirty == null) {
172            dirty = NULL_RECT;
173        }
174        nDrawDisplayList(mNativeProxy, displayList.getNativeDisplayList(),
175                dirty.left, dirty.top, dirty.right, dirty.bottom);
176    }
177
178    @Override
179    void detachFunctor(long functor) {
180        nDetachFunctor(mNativeProxy, functor);
181    }
182
183    @Override
184    void attachFunctor(AttachInfo attachInfo, long functor) {
185        nAttachFunctor(mNativeProxy, functor);
186    }
187
188    @Override
189    HardwareLayer createDisplayListLayer(int width, int height) {
190        long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
191        return HardwareLayer.adoptDisplayListLayer(this, layer);
192    }
193
194    @Override
195    HardwareLayer createTextureLayer() {
196        long layer = nCreateTextureLayer(mNativeProxy);
197        return HardwareLayer.adoptTextureLayer(this, layer);
198    }
199
200    @Override
201    SurfaceTexture createSurfaceTexture(final HardwareLayer layer) {
202        final SurfaceTexture[] ret = new SurfaceTexture[1];
203        nRunWithGlContext(mNativeProxy, new Runnable() {
204            @Override
205            public void run() {
206                ret[0] = layer.createSurfaceTexture();
207            }
208        });
209        return ret[0];
210    }
211
212    @Override
213    boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
214        return nCopyLayerInto(mNativeProxy,
215                layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
216    }
217
218    @Override
219    void pushLayerUpdate(HardwareLayer layer) {
220        // TODO: Remove this, it's not needed outside of GLRenderer
221    }
222
223    @Override
224    void onLayerCreated(HardwareLayer layer) {
225        // TODO: Is this actually useful?
226    }
227
228    @Override
229    void flushLayerUpdates() {
230        // TODO: Figure out what this should do or remove it
231    }
232
233    @Override
234    void onLayerDestroyed(HardwareLayer layer) {
235        nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater());
236    }
237
238    @Override
239    void setName(String name) {
240    }
241
242    @Override
243    protected void finalize() throws Throwable {
244        try {
245            nDeleteProxy(mNativeProxy);
246        } finally {
247            super.finalize();
248        }
249    }
250
251    /** @hide */
252    public static native void postToRenderThread(Runnable runnable);
253
254    private static native long nCreateProxy(boolean translucent);
255    private static native void nDeleteProxy(long nativeProxy);
256
257    private static native boolean nInitialize(long nativeProxy, Surface window);
258    private static native void nUpdateSurface(long nativeProxy, Surface window);
259    private static native void nSetup(long nativeProxy, int width, int height);
260    private static native void nSetDisplayListData(long nativeProxy, long displayList,
261            long newData);
262    private static native void nDrawDisplayList(long nativeProxy, long displayList,
263            int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
264    private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
265    private static native void nDestroyCanvas(long nativeProxy);
266
267    private static native void nAttachFunctor(long nativeProxy, long functor);
268    private static native void nDetachFunctor(long nativeProxy, long functor);
269
270    private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
271    private static native long nCreateTextureLayer(long nativeProxy);
272    private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
273    private static native void nDestroyLayer(long nativeProxy, long layer);
274}
275