blob: 2ba1b8d3c187a3df914d9a58514bf5d1cde79bc1 [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
John Reck63a06672014-05-07 13:45:54 -0700151 void setOpaque(boolean opaque) {
152 nSetOpaque(mNativeProxy, opaque);
153 }
154
155 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800156 int getWidth() {
157 return mWidth;
158 }
159
160 @Override
161 int getHeight() {
162 return mHeight;
163 }
164
165 @Override
166 void dumpGfxInfo(PrintWriter pw) {
167 // TODO Auto-generated method stub
168 }
169
170 @Override
171 long getFrameCount() {
172 // TODO Auto-generated method stub
173 return 0;
174 }
175
176 @Override
177 boolean loadSystemProperties() {
John Recke4280ba2014-05-05 16:39:37 -0700178 return nLoadSystemProperties(mNativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -0800179 }
180
John Reckbc0cc022014-04-11 16:08:14 -0700181 private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
John Reckcec24ae2013-11-05 13:27:50 -0800182 view.mPrivateFlags |= View.PFLAG_DRAWN;
183
184 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
185 == View.PFLAG_INVALIDATED;
186 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
187
188 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
John Reckbc0cc022014-04-11 16:08:14 -0700189 HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
John Reck05e85842014-04-23 14:48:28 -0700190 try {
191 callbacks.onHardwarePostDraw(canvas);
192 canvas.drawDisplayList(view.getDisplayList());
193 callbacks.onHardwarePostDraw(canvas);
194 } finally {
195 mRootNode.end(canvas);
196 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
197 }
John Reckcec24ae2013-11-05 13:27:50 -0800198
199 view.mRecreateDisplayList = false;
John Reckbc0cc022014-04-11 16:08:14 -0700200 }
201
202 @Override
203 void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
204 attachInfo.mIgnoreDirtyState = true;
John Reck18f16e62014-05-02 16:46:41 -0700205 long frameTimeNanos = mChoreographer.getFrameTimeNanos();
206 attachInfo.mDrawingTime = frameTimeNanos / NANOS_PER_MS;
John Reckbc0cc022014-04-11 16:08:14 -0700207
208 updateRootDisplayList(view, callbacks);
John Reckcec24ae2013-11-05 13:27:50 -0800209
John Reck6313b922014-04-16 18:59:21 -0700210 attachInfo.mIgnoreDirtyState = false;
211
John Reck4f02bf42014-01-03 18:09:17 -0800212 if (dirty == null) {
213 dirty = NULL_RECT;
214 }
John Reckf9be7792014-05-02 18:21:16 -0700215 int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
John Reck18f16e62014-05-02 16:46:41 -0700216 dirty.left, dirty.top, dirty.right, dirty.bottom);
John Reckf9be7792014-05-02 18:21:16 -0700217 if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
218 attachInfo.mViewRootImpl.invalidate();
219 }
John Reckcec24ae2013-11-05 13:27:50 -0800220 }
221
222 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000223 void detachFunctor(long functor) {
John Reckd3d8daf2014-04-10 15:00:13 -0700224 // no-op, we never attach functors to need to detach them
John Reckcec24ae2013-11-05 13:27:50 -0800225 }
226
227 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000228 void attachFunctor(AttachInfo attachInfo, long functor) {
John Reckd3d8daf2014-04-10 15:00:13 -0700229 invokeFunctor(functor, true);
John Reckcec24ae2013-11-05 13:27:50 -0800230 }
231
232 @Override
Bo Liuae738a72014-04-27 16:22:04 -0700233 void invokeFunctor(long functor, boolean waitForCompletion) {
John Reck0d1f6342014-03-28 20:30:27 -0700234 nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
235 }
236
237 @Override
John Reck19b6bcf2014-02-14 20:03:38 -0800238 HardwareLayer createDisplayListLayer(int width, int height) {
239 long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
240 return HardwareLayer.adoptDisplayListLayer(this, layer);
241 }
242
243 @Override
244 HardwareLayer createTextureLayer() {
245 long layer = nCreateTextureLayer(mNativeProxy);
246 return HardwareLayer.adoptTextureLayer(this, layer);
247 }
248
249 @Override
250 SurfaceTexture createSurfaceTexture(final HardwareLayer layer) {
251 final SurfaceTexture[] ret = new SurfaceTexture[1];
252 nRunWithGlContext(mNativeProxy, new Runnable() {
253 @Override
254 public void run() {
255 ret[0] = layer.createSurfaceTexture();
256 }
257 });
258 return ret[0];
259 }
260
261 @Override
262 boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
263 return nCopyLayerInto(mNativeProxy,
264 layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
265 }
266
267 @Override
268 void pushLayerUpdate(HardwareLayer layer) {
269 // TODO: Remove this, it's not needed outside of GLRenderer
270 }
271
272 @Override
273 void onLayerCreated(HardwareLayer layer) {
274 // TODO: Is this actually useful?
275 }
276
277 @Override
278 void flushLayerUpdates() {
279 // TODO: Figure out what this should do or remove it
280 }
281
282 @Override
283 void onLayerDestroyed(HardwareLayer layer) {
284 nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater());
285 }
286
287 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800288 void setName(String name) {
John Reckcec24ae2013-11-05 13:27:50 -0800289 }
290
John Reck4f02bf42014-01-03 18:09:17 -0800291 @Override
John Reck28ad7b52014-04-07 16:59:25 -0700292 void fence() {
293 nFence(mNativeProxy);
294 }
295
296 @Override
John Reck4f02bf42014-01-03 18:09:17 -0800297 protected void finalize() throws Throwable {
298 try {
299 nDeleteProxy(mNativeProxy);
John Reck0ed751d2014-04-08 14:10:17 -0700300 mNativeProxy = 0;
John Reck4f02bf42014-01-03 18:09:17 -0800301 } finally {
302 super.finalize();
John Reckcec24ae2013-11-05 13:27:50 -0800303 }
304 }
305
306 /** @hide */
307 public static native void postToRenderThread(Runnable runnable);
John Reck4f02bf42014-01-03 18:09:17 -0800308
John Recke45b1fd2014-04-15 09:50:16 -0700309 private static native long nCreateRootRenderNode();
310 private static native long nCreateProxy(boolean translucent, long rootRenderNode);
John Reck4f02bf42014-01-03 18:09:17 -0800311 private static native void nDeleteProxy(long nativeProxy);
312
John Reck18f16e62014-05-02 16:46:41 -0700313 private static native void nSetFrameInterval(long nativeProxy, long frameIntervalNanos);
John Recke4280ba2014-05-05 16:39:37 -0700314 private static native boolean nLoadSystemProperties(long nativeProxy);
John Reck18f16e62014-05-02 16:46:41 -0700315
John Reck4f02bf42014-01-03 18:09:17 -0800316 private static native boolean nInitialize(long nativeProxy, Surface window);
317 private static native void nUpdateSurface(long nativeProxy, Surface window);
John Reckf7d9c1d2014-04-09 10:01:03 -0700318 private static native void nPauseSurface(long nativeProxy, Surface window);
John Reck4f02bf42014-01-03 18:09:17 -0800319 private static native void nSetup(long nativeProxy, int width, int height);
John Reck63a06672014-05-07 13:45:54 -0700320 private static native void nSetOpaque(long nativeProxy, boolean opaque);
John Reckbe34f2f2014-03-10 08:58:44 -0700321 private static native void nSetDisplayListData(long nativeProxy, long displayList,
John Reck44fd8d22014-02-26 11:00:11 -0800322 long newData);
John Reckf9be7792014-05-02 18:21:16 -0700323 private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos,
John Reck4f02bf42014-01-03 18:09:17 -0800324 int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
John Reckfc53ef272014-02-11 10:40:25 -0800325 private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
John Reckfae904d2014-04-14 11:01:57 -0700326 private static native void nDestroyCanvasAndSurface(long nativeProxy);
John Reck4f02bf42014-01-03 18:09:17 -0800327
John Reck0d1f6342014-03-28 20:30:27 -0700328 private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
John Reck19b6bcf2014-02-14 20:03:38 -0800329
330 private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
331 private static native long nCreateTextureLayer(long nativeProxy);
332 private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
333 private static native void nDestroyLayer(long nativeProxy, long layer);
John Reck28ad7b52014-04-07 16:59:25 -0700334
335 private static native void nFence(long nativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -0800336}