ThreadedRenderer.java revision fc53ef27793a39e9effd829e9cae02a9ca14147e
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 destroyLayers(View view) {
80        throw new NoSuchMethodError();
81    }
82
83    @Override
84    void destroyHardwareResources(View view) {
85        // TODO: canvas.clearLayerUpdates()
86        destroyResources(view);
87        // TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
88    }
89
90    private static void destroyResources(View view) {
91        view.destroyHardwareResources();
92
93        if (view instanceof ViewGroup) {
94            ViewGroup group = (ViewGroup) view;
95
96            int count = group.getChildCount();
97            for (int i = 0; i < count; i++) {
98                destroyResources(group.getChildAt(i));
99            }
100        }
101    }
102
103    @Override
104    void invalidate(Surface surface) {
105        updateSurface(surface);
106    }
107
108    @Override
109    boolean validate() {
110        // TODO Remove users of this API
111        return false;
112    }
113
114    @Override
115    boolean safelyRun(Runnable action) {
116        nRunWithGlContext(mNativeProxy, action);
117        return true;
118    }
119
120    @Override
121    void setup(int width, int height) {
122        mWidth = width;
123        mHeight = height;
124        nSetup(mNativeProxy, width, height);
125    }
126
127    @Override
128    int getWidth() {
129        return mWidth;
130    }
131
132    @Override
133    int getHeight() {
134        return mHeight;
135    }
136
137    @Override
138    void dumpGfxInfo(PrintWriter pw) {
139        // TODO Auto-generated method stub
140    }
141
142    @Override
143    long getFrameCount() {
144        // TODO Auto-generated method stub
145        return 0;
146    }
147
148    @Override
149    boolean loadSystemProperties() {
150        return false;
151    }
152
153    @Override
154    void pushLayerUpdate(HardwareLayer layer) {
155        throw new NoSuchMethodError();
156    }
157
158    @Override
159    void onLayerCreated(HardwareLayer layer) {
160        throw new NoSuchMethodError();
161    }
162
163    @Override
164    void onLayerDestroyed(HardwareLayer layer) {
165        throw new NoSuchMethodError();
166    }
167
168    @Override
169    void flushLayerUpdates() {
170        throw new NoSuchMethodError();
171    }
172
173    /**
174     * TODO: Remove
175     * Temporary hack to allow RenderThreadTest prototype app to trigger
176     * replaying a DisplayList after modifying the displaylist properties
177     *
178     *  @hide */
179    public void repeatLastDraw() {
180    }
181
182    @Override
183    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
184        attachInfo.mIgnoreDirtyState = true;
185        attachInfo.mDrawingTime = SystemClock.uptimeMillis();
186        view.mPrivateFlags |= View.PFLAG_DRAWN;
187
188        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
189                == View.PFLAG_INVALIDATED;
190        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
191
192        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
193        DisplayList displayList = view.getDisplayList();
194        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
195
196        view.mRecreateDisplayList = false;
197
198        if (dirty == null) {
199            dirty = NULL_RECT;
200        }
201        nDrawDisplayList(mNativeProxy, displayList.getNativeDisplayList(),
202                dirty.left, dirty.top, dirty.right, dirty.bottom);
203    }
204
205    @Override
206    HardwareLayer createTextureLayer() {
207        throw new NoSuchMethodError();
208    }
209
210    @Override
211    HardwareLayer createDisplayListLayer(int width, int height) {
212        throw new NoSuchMethodError();
213    }
214
215    @Override
216    SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
217        throw new NoSuchMethodError();
218    }
219
220    @Override
221    boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
222        throw new NoSuchMethodError();
223    }
224
225    @Override
226    void detachFunctor(long functor) {
227        nDetachFunctor(mNativeProxy, functor);
228    }
229
230    @Override
231    void attachFunctor(AttachInfo attachInfo, long functor) {
232        nAttachFunctor(mNativeProxy, functor);
233    }
234
235    @Override
236    void setName(String name) {
237    }
238
239    @Override
240    protected void finalize() throws Throwable {
241        try {
242            nDeleteProxy(mNativeProxy);
243        } finally {
244            super.finalize();
245        }
246    }
247
248    /** @hide */
249    public static native void postToRenderThread(Runnable runnable);
250
251    private static native long nCreateProxy(boolean translucent);
252    private static native void nDeleteProxy(long nativeProxy);
253
254    private static native boolean nInitialize(long nativeProxy, Surface window);
255    private static native void nUpdateSurface(long nativeProxy, Surface window);
256    private static native void nSetup(long nativeProxy, int width, int height);
257    private static native void nDrawDisplayList(long nativeProxy, long displayList,
258            int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
259    private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
260    private static native void nDestroyCanvas(long nativeProxy);
261
262    private static native void nAttachFunctor(long nativeProxy, long functor);
263    private static native void nDetachFunctor(long nativeProxy, long functor);
264}
265