blob: 0bf99d3bb3e36f7f0547c0c7101b7b32a507ffb1 [file] [log] [blame]
John Reckcec24ae2013-11-05 13:27:50 -08001/*
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
John Reck04fc5832014-02-05 16:38:25 -080019import android.graphics.Bitmap;
John Reckcec24ae2013-11-05 13:27:50 -080020import android.graphics.Rect;
21import android.graphics.SurfaceTexture;
John Reckcec24ae2013-11-05 13:27:50 -080022import android.os.Trace;
John Reckcec24ae2013-11-05 13:27:50 -080023import android.view.Surface.OutOfResourcesException;
24import android.view.View.AttachInfo;
25
26import java.io.PrintWriter;
John Reckcec24ae2013-11-05 13:27:50 -080027
28/**
29 * Hardware renderer that proxies the rendering to a render thread. Most calls
John Reck4f02bf42014-01-03 18:09:17 -080030 * are currently synchronous.
31 * TODO: Make draw() async.
32 * TODO: Figure out how to share the DisplayList between two threads (global lock?)
John Reckcec24ae2013-11-05 13:27:50 -080033 *
34 * The UI thread can block on the RenderThread, but RenderThread must never
35 * block on the UI thread.
36 *
John Reck4f02bf42014-01-03 18:09:17 -080037 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
38 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
39 * by the lifecycle of the RenderProxy.
40 *
John Reckcec24ae2013-11-05 13:27:50 -080041 * Note that although currently the EGL context & surfaces are created & managed
42 * by the render thread, the goal is to move that into a shared structure that can
43 * be managed by both threads. EGLSurface creation & deletion should ideally be
44 * done on the UI thread and not the RenderThread to avoid stalling the
45 * RenderThread with surface buffer allocation.
46 *
47 * @hide
48 */
49public class ThreadedRenderer extends HardwareRenderer {
50 private static final String LOGTAG = "ThreadedRenderer";
51
John Recke45b1fd2014-04-15 09:50:16 -070052 private static final Rect NULL_RECT = new Rect();
John Reckcec24ae2013-11-05 13:27:50 -080053
John Reck18f16e62014-05-02 16:46:41 -070054 private static final long NANOS_PER_MS = 1000000;
55
John Reckf9be7792014-05-02 18:21:16 -070056 // Keep in sync with DrawFrameTask.h SYNC_* flags
57 // Nothing interesting to report
58 private static final int SYNC_OK = 0x0;
59 // Needs a ViewRoot invalidate
60 private static final int SYNC_INVALIDATE_REQUIRED = 0x1;
61
John Reckcec24ae2013-11-05 13:27:50 -080062 private int mWidth, mHeight;
John Reck4f02bf42014-01-03 18:09:17 -080063 private long mNativeProxy;
John Reckf7d9c1d2014-04-09 10:01:03 -070064 private boolean mInitialized = false;
John Reckbc0cc022014-04-11 16:08:14 -070065 private RenderNode mRootNode;
John Reck18f16e62014-05-02 16:46:41 -070066 private Choreographer mChoreographer;
John Reckcec24ae2013-11-05 13:27:50 -080067
John Reck3dfe19f2013-12-13 14:25:19 -080068 ThreadedRenderer(boolean translucent) {
John Recke45b1fd2014-04-15 09:50:16 -070069 long rootNodePtr = nCreateRootRenderNode();
70 mRootNode = RenderNode.adopt(rootNodePtr);
John Reckbc0cc022014-04-11 16:08:14 -070071 mRootNode.setClipToBounds(false);
John Recke45b1fd2014-04-15 09:50:16 -070072 mNativeProxy = nCreateProxy(translucent, rootNodePtr);
John Reck18f16e62014-05-02 16:46:41 -070073
74 // Setup timing
75 mChoreographer = Choreographer.getInstance();
76 nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos());
John Reckcec24ae2013-11-05 13:27:50 -080077 }
78
79 @Override
80 void destroy(boolean full) {
John Reckf7d9c1d2014-04-09 10:01:03 -070081 mInitialized = false;
82 updateEnabledState(null);
John Reckfae904d2014-04-14 11:01:57 -070083 nDestroyCanvasAndSurface(mNativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -080084 }
85
John Reckf7d9c1d2014-04-09 10:01:03 -070086 private void updateEnabledState(Surface surface) {
87 if (surface == null || !surface.isValid()) {
88 setEnabled(false);
89 } else {
90 setEnabled(mInitialized);
91 }
92 }
93
John Reckcec24ae2013-11-05 13:27:50 -080094 @Override
95 boolean initialize(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -070096 mInitialized = true;
97 updateEnabledState(surface);
John Reck4f02bf42014-01-03 18:09:17 -080098 return nInitialize(mNativeProxy, surface);
John Reckcec24ae2013-11-05 13:27:50 -080099 }
100
101 @Override
102 void updateSurface(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -0700103 updateEnabledState(surface);
John Reck4f02bf42014-01-03 18:09:17 -0800104 nUpdateSurface(mNativeProxy, surface);
John Reckcec24ae2013-11-05 13:27:50 -0800105 }
106
107 @Override
John Reckf7d9c1d2014-04-09 10:01:03 -0700108 void pauseSurface(Surface surface) {
109 nPauseSurface(mNativeProxy, surface);
110 }
111
112 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800113 void destroyHardwareResources(View view) {
John Reck4f02bf42014-01-03 18:09:17 -0800114 destroyResources(view);
115 // TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
116 }
117
118 private static void destroyResources(View view) {
119 view.destroyHardwareResources();
120
121 if (view instanceof ViewGroup) {
122 ViewGroup group = (ViewGroup) view;
123
124 int count = group.getChildCount();
125 for (int i = 0; i < count; i++) {
126 destroyResources(group.getChildAt(i));
127 }
128 }
John Reckcec24ae2013-11-05 13:27:50 -0800129 }
130
131 @Override
132 void invalidate(Surface surface) {
John Reck4f02bf42014-01-03 18:09:17 -0800133 updateSurface(surface);
John Reckcec24ae2013-11-05 13:27:50 -0800134 }
135
136 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800137 boolean safelyRun(Runnable action) {
John Reckfc53ef272014-02-11 10:40:25 -0800138 nRunWithGlContext(mNativeProxy, action);
139 return true;
John Reckcec24ae2013-11-05 13:27:50 -0800140 }
141
142 @Override
143 void setup(int width, int height) {
144 mWidth = width;
145 mHeight = height;
John Reckbc0cc022014-04-11 16:08:14 -0700146 mRootNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
John Reck4f02bf42014-01-03 18:09:17 -0800147 nSetup(mNativeProxy, width, height);
John Reckcec24ae2013-11-05 13:27:50 -0800148 }
149
150 @Override
151 int getWidth() {
152 return mWidth;
153 }
154
155 @Override
156 int getHeight() {
157 return mHeight;
158 }
159
160 @Override
161 void dumpGfxInfo(PrintWriter pw) {
162 // TODO Auto-generated method stub
163 }
164
165 @Override
166 long getFrameCount() {
167 // TODO Auto-generated method stub
168 return 0;
169 }
170
171 @Override
172 boolean loadSystemProperties() {
John Recke4280ba2014-05-05 16:39:37 -0700173 return nLoadSystemProperties(mNativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -0800174 }
175
John Reckbc0cc022014-04-11 16:08:14 -0700176 private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
John Reckcec24ae2013-11-05 13:27:50 -0800177 view.mPrivateFlags |= View.PFLAG_DRAWN;
178
179 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
180 == View.PFLAG_INVALIDATED;
181 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
182
183 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
John Reckbc0cc022014-04-11 16:08:14 -0700184 HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
John Reck05e85842014-04-23 14:48:28 -0700185 try {
186 callbacks.onHardwarePostDraw(canvas);
187 canvas.drawDisplayList(view.getDisplayList());
188 callbacks.onHardwarePostDraw(canvas);
189 } finally {
190 mRootNode.end(canvas);
191 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
192 }
John Reckcec24ae2013-11-05 13:27:50 -0800193
194 view.mRecreateDisplayList = false;
John Reckbc0cc022014-04-11 16:08:14 -0700195 }
196
197 @Override
198 void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
199 attachInfo.mIgnoreDirtyState = true;
John Reck18f16e62014-05-02 16:46:41 -0700200 long frameTimeNanos = mChoreographer.getFrameTimeNanos();
201 attachInfo.mDrawingTime = frameTimeNanos / NANOS_PER_MS;
John Reckbc0cc022014-04-11 16:08:14 -0700202
203 updateRootDisplayList(view, callbacks);
John Reckcec24ae2013-11-05 13:27:50 -0800204
John Reck6313b922014-04-16 18:59:21 -0700205 attachInfo.mIgnoreDirtyState = false;
206
John Reck4f02bf42014-01-03 18:09:17 -0800207 if (dirty == null) {
208 dirty = NULL_RECT;
209 }
John Reckf9be7792014-05-02 18:21:16 -0700210 int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
John Reck18f16e62014-05-02 16:46:41 -0700211 dirty.left, dirty.top, dirty.right, dirty.bottom);
John Reckf9be7792014-05-02 18:21:16 -0700212 if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
213 attachInfo.mViewRootImpl.invalidate();
214 }
John Reckcec24ae2013-11-05 13:27:50 -0800215 }
216
217 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000218 void detachFunctor(long functor) {
John Reckd3d8daf2014-04-10 15:00:13 -0700219 // no-op, we never attach functors to need to detach them
John Reckcec24ae2013-11-05 13:27:50 -0800220 }
221
222 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000223 void attachFunctor(AttachInfo attachInfo, long functor) {
John Reckd3d8daf2014-04-10 15:00:13 -0700224 invokeFunctor(functor, true);
John Reckcec24ae2013-11-05 13:27:50 -0800225 }
226
227 @Override
Bo Liuae738a72014-04-27 16:22:04 -0700228 void invokeFunctor(long functor, boolean waitForCompletion) {
John Reck0d1f6342014-03-28 20:30:27 -0700229 nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
230 }
231
232 @Override
John Reck19b6bcf2014-02-14 20:03:38 -0800233 HardwareLayer createDisplayListLayer(int width, int height) {
234 long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
235 return HardwareLayer.adoptDisplayListLayer(this, layer);
236 }
237
238 @Override
239 HardwareLayer createTextureLayer() {
240 long layer = nCreateTextureLayer(mNativeProxy);
241 return HardwareLayer.adoptTextureLayer(this, layer);
242 }
243
244 @Override
245 SurfaceTexture createSurfaceTexture(final HardwareLayer layer) {
246 final SurfaceTexture[] ret = new SurfaceTexture[1];
247 nRunWithGlContext(mNativeProxy, new Runnable() {
248 @Override
249 public void run() {
250 ret[0] = layer.createSurfaceTexture();
251 }
252 });
253 return ret[0];
254 }
255
256 @Override
257 boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
258 return nCopyLayerInto(mNativeProxy,
259 layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
260 }
261
262 @Override
263 void pushLayerUpdate(HardwareLayer layer) {
264 // TODO: Remove this, it's not needed outside of GLRenderer
265 }
266
267 @Override
268 void onLayerCreated(HardwareLayer layer) {
269 // TODO: Is this actually useful?
270 }
271
272 @Override
273 void flushLayerUpdates() {
274 // TODO: Figure out what this should do or remove it
275 }
276
277 @Override
278 void onLayerDestroyed(HardwareLayer layer) {
279 nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater());
280 }
281
282 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800283 void setName(String name) {
John Reckcec24ae2013-11-05 13:27:50 -0800284 }
285
John Reck4f02bf42014-01-03 18:09:17 -0800286 @Override
John Reck28ad7b52014-04-07 16:59:25 -0700287 void fence() {
288 nFence(mNativeProxy);
289 }
290
291 @Override
John Reck4f02bf42014-01-03 18:09:17 -0800292 protected void finalize() throws Throwable {
293 try {
294 nDeleteProxy(mNativeProxy);
John Reck0ed751d2014-04-08 14:10:17 -0700295 mNativeProxy = 0;
John Reck4f02bf42014-01-03 18:09:17 -0800296 } finally {
297 super.finalize();
John Reckcec24ae2013-11-05 13:27:50 -0800298 }
299 }
300
301 /** @hide */
302 public static native void postToRenderThread(Runnable runnable);
John Reck4f02bf42014-01-03 18:09:17 -0800303
John Recke45b1fd2014-04-15 09:50:16 -0700304 private static native long nCreateRootRenderNode();
305 private static native long nCreateProxy(boolean translucent, long rootRenderNode);
John Reck4f02bf42014-01-03 18:09:17 -0800306 private static native void nDeleteProxy(long nativeProxy);
307
John Reck18f16e62014-05-02 16:46:41 -0700308 private static native void nSetFrameInterval(long nativeProxy, long frameIntervalNanos);
John Recke4280ba2014-05-05 16:39:37 -0700309 private static native boolean nLoadSystemProperties(long nativeProxy);
John Reck18f16e62014-05-02 16:46:41 -0700310
John Reck4f02bf42014-01-03 18:09:17 -0800311 private static native boolean nInitialize(long nativeProxy, Surface window);
312 private static native void nUpdateSurface(long nativeProxy, Surface window);
John Reckf7d9c1d2014-04-09 10:01:03 -0700313 private static native void nPauseSurface(long nativeProxy, Surface window);
John Reck4f02bf42014-01-03 18:09:17 -0800314 private static native void nSetup(long nativeProxy, int width, int height);
John Reckbe34f2f2014-03-10 08:58:44 -0700315 private static native void nSetDisplayListData(long nativeProxy, long displayList,
John Reck44fd8d22014-02-26 11:00:11 -0800316 long newData);
John Reckf9be7792014-05-02 18:21:16 -0700317 private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos,
John Reck4f02bf42014-01-03 18:09:17 -0800318 int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
John Reckfc53ef272014-02-11 10:40:25 -0800319 private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
John Reckfae904d2014-04-14 11:01:57 -0700320 private static native void nDestroyCanvasAndSurface(long nativeProxy);
John Reck4f02bf42014-01-03 18:09:17 -0800321
John Reck0d1f6342014-03-28 20:30:27 -0700322 private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
John Reck19b6bcf2014-02-14 20:03:38 -0800323
324 private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
325 private static native long nCreateTextureLayer(long nativeProxy);
326 private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
327 private static native void nDestroyLayer(long nativeProxy, long layer);
John Reck28ad7b52014-04-07 16:59:25 -0700328
329 private static native void nFence(long nativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -0800330}